Merge branch 'iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (60 commits)
  dma-debug: make memory range checks more consistent
  dma-debug: warn of unmapping an invalid dma address
  dma-debug: fix dma_debug_add_bus() definition for !CONFIG_DMA_API_DEBUG
  dma-debug/x86: register pci bus for dma-debug leak detection
  dma-debug: add a check dma memory leaks
  dma-debug: add checks for kernel text and rodata
  dma-debug: print stacktrace of mapping path on unmap error
  dma-debug: Documentation update
  dma-debug: x86 architecture bindings
  dma-debug: add function to dump dma mappings
  dma-debug: add checks for sync_single_sg_*
  dma-debug: add checks for sync_single_range_*
  dma-debug: add checks for sync_single_*
  dma-debug: add checking for [alloc|free]_coherent
  dma-debug: add add checking for map/unmap_sg
  dma-debug: add checking for map/unmap_page/single
  dma-debug: add core checking functions
  dma-debug: add debugfs interface
  dma-debug: add kernel command line parameters
  dma-debug: add initialization code
  ...

Fix trivial conflicts due to whitespace changes in arch/x86/kernel/pci-nommu.c
diff --git a/Documentation/Smack.txt b/Documentation/Smack.txt
index 989c2fc..629c92e 100644
--- a/Documentation/Smack.txt
+++ b/Documentation/Smack.txt
@@ -184,14 +184,16 @@
 other than a letter or digit, are reserved for use by the Smack development
 team. Smack labels are unstructured, case sensitive, and the only operation
 ever performed on them is comparison for equality. Smack labels cannot
-contain unprintable characters or the "/" (slash) character.
+contain unprintable characters or the "/" (slash) character. Smack labels
+cannot begin with a '-', which is reserved for special options.
 
 There are some predefined labels:
 
-	_ Pronounced "floor", a single underscore character.
-	^ Pronounced "hat", a single circumflex character.
-	* Pronounced "star", a single asterisk character.
-	? Pronounced "huh", a single question mark character.
+	_ 	Pronounced "floor", a single underscore character.
+	^ 	Pronounced "hat", a single circumflex character.
+	* 	Pronounced "star", a single asterisk character.
+	? 	Pronounced "huh", a single question mark character.
+	@ 	Pronounced "Internet", a single at sign character.
 
 Every task on a Smack system is assigned a label. System tasks, such as
 init(8) and systems daemons, are run with the floor ("_") label. User tasks
@@ -412,6 +414,36 @@
 	A privileged program may set this to match the label of another
 	task with which it hopes to communicate.
 
+Smack Netlabel Exceptions
+
+You will often find that your labeled application has to talk to the outside,
+unlabeled world. To do this there's a special file /smack/netlabel where you can
+add some exceptions in the form of :
+@IP1	   LABEL1 or
+@IP2/MASK  LABEL2
+
+It means that your application will have unlabeled access to @IP1 if it has
+write access on LABEL1, and access to the subnet @IP2/MASK if it has write
+access on LABEL2.
+
+Entries in the /smack/netlabel file are matched by longest mask first, like in
+classless IPv4 routing.
+
+A special label '@' and an option '-CIPSO' can be used there :
+@      means Internet, any application with any label has access to it
+-CIPSO means standard CIPSO networking
+
+If you don't know what CIPSO is and don't plan to use it, you can just do :
+echo 127.0.0.1 -CIPSO > /smack/netlabel
+echo 0.0.0.0/0 @      > /smack/netlabel
+
+If you use CIPSO on your 192.168.0.0/16 local network and need also unlabeled
+Internet access, you can have :
+echo 127.0.0.1      -CIPSO > /smack/netlabel
+echo 192.168.0.0/16 -CIPSO > /smack/netlabel
+echo 0.0.0.0/0      @      > /smack/netlabel
+
+
 Writing Applications for Smack
 
 There are three sorts of applications that will run on a Smack system. How an
diff --git a/Documentation/arm/Samsung-S3C24XX/Suspend.txt b/Documentation/arm/Samsung-S3C24XX/Suspend.txt
index 0dab6e3..a30fe51 100644
--- a/Documentation/arm/Samsung-S3C24XX/Suspend.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Suspend.txt
@@ -40,13 +40,13 @@
 Machine Support
 ---------------
 
-  The machine specific functions must call the s3c2410_pm_init() function
+  The machine specific functions must call the s3c_pm_init() function
   to say that its bootloader is capable of resuming. This can be as
   simple as adding the following to the machine's definition:
 
-  INITMACHINE(s3c2410_pm_init)
+  INITMACHINE(s3c_pm_init)
 
-  A board can do its own setup before calling s3c2410_pm_init, if it
+  A board can do its own setup before calling s3c_pm_init, if it
   needs to setup anything else for power management support.
 
   There is currently no support for over-riding the default method of
@@ -74,7 +74,7 @@
 
 	enable_irq_wake(IRQ_EINT0);
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 
diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt
index dc60455..43cb100 100644
--- a/Documentation/arm/memory.txt
+++ b/Documentation/arm/memory.txt
@@ -29,7 +29,14 @@
 				CPU supports vector relocation (control
 				register V bit.)
 
-ffc00000	fffeffff	DMA memory mapping region.  Memory returned
+fffe0000	fffeffff	XScale cache flush area.  This is used
+				in proc-xscale.S to flush the whole data
+				cache.  Free for other usage on non-XScale.
+
+fff00000	fffdffff	Fixmap mapping region.  Addresses provided
+				by fix_to_virt() will be located here.
+
+ffc00000	ffefffff	DMA memory mapping region.  Memory returned
 				by the dma_alloc_xxx functions will be
 				dynamically mapped here.
 
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index f2e908d..2f21ecd 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -25,7 +25,7 @@
 		"tda10046lifeview", "av7110", "dec2000t", "dec2540t",
 		"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
-		"opera1");
+		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" );
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -37,8 +37,8 @@
 	$outfile = eval($cid);
 	die $@ if $@;
 	print STDERR <<EOF;
-Firmware $outfile extracted successfully.
-Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware
+Firmware(s) $outfile extracted successfully.
+Now copy it(they) to either /usr/lib/hotplug/firmware or /lib/firmware
 (depending on configuration of firmware hotplug).
 EOF
 	exit(0);
@@ -345,6 +345,85 @@
     $fwfile;
 }
 
+sub cx231xx {
+    my $fwfile = "v4l-cx231xx-avcore-01.fw";
+    my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
+    my $hash = "7d3bb956dc9df0eafded2b56ba57cc42";
+
+    checkstandard();
+
+    wgetfile($fwfile, $url);
+    verify($fwfile, $hash);
+
+    $fwfile;
+}
+
+sub cx18 {
+    my $url = "http://linuxtv.org/downloads/firmware/";
+
+    my %files = (
+	'v4l-cx23418-apu.fw' => '588f081b562f5c653a3db1ad8f65939a',
+	'v4l-cx23418-cpu.fw' => 'b6c7ed64bc44b1a6e0840adaeac39d79',
+	'v4l-cx23418-dig.fw' => '95bc688d3e7599fd5800161e9971cc55',
+    );
+
+    checkstandard();
+
+    my $allfiles;
+    foreach my $fwfile (keys %files) {
+	wgetfile($fwfile, "$url/$fwfile");
+	verify($fwfile, $files{$fwfile});
+	$allfiles .= " $fwfile";
+    }
+
+    $allfiles =~ s/^\s//;
+
+    $allfiles;
+}
+
+sub cx23885 {
+    my $url = "http://linuxtv.org/downloads/firmware/";
+
+    my %files = (
+	'v4l-cx23885-avcore-01.fw' => 'a9f8f5d901a7fb42f552e1ee6384f3bb',
+	'v4l-cx23885-enc.fw'       => 'a9f8f5d901a7fb42f552e1ee6384f3bb',
+    );
+
+    checkstandard();
+
+    my $allfiles;
+    foreach my $fwfile (keys %files) {
+	wgetfile($fwfile, "$url/$fwfile");
+	verify($fwfile, $files{$fwfile});
+	$allfiles .= " $fwfile";
+    }
+
+    $allfiles =~ s/^\s//;
+
+    $allfiles;
+}
+
+sub pvrusb2 {
+    my $url = "http://linuxtv.org/downloads/firmware/";
+
+    my %files = (
+	'v4l-cx25840.fw'           => 'dadb79e9904fc8af96e8111d9cb59320',
+    );
+
+    checkstandard();
+
+    my $allfiles;
+    foreach my $fwfile (keys %files) {
+	wgetfile($fwfile, "$url/$fwfile");
+	verify($fwfile, $files{$fwfile});
+	$allfiles .= " $fwfile";
+    }
+
+    $allfiles =~ s/^\s//;
+
+    $allfiles;
+}
+
 sub or51132_qam {
     my $fwfile = "dvb-fe-or51132-qam.fw";
     my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 02ea377..5e02b83 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -64,10 +64,10 @@
 
 ---------------------------
 
-What:	Video4Linux API 1 ioctls and video_decoder.h from Video devices.
-When:	December 2008
-Files:	include/linux/video_decoder.h include/linux/videodev.h
-Check:	include/linux/video_decoder.h include/linux/videodev.h
+What:	Video4Linux API 1 ioctls and from Video devices.
+When:	July 2009
+Files:	include/linux/videodev.h
+Check:	include/linux/videodev.h
 Why:	V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
 	series. The old API have lots of drawbacks and don't provide enough
 	means to work with all video and audio standards. The newer API is
@@ -340,7 +340,8 @@
 ---------------------------
 
 What:	i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
-When:	2.6.29 (ideally) or 2.6.30 (more likely)
+When:	2.6.30
+Check:	i2c_attach_client i2c_detach_client
 Why:	Deprecated by the new (standard) device driver binding model. Use
 	i2c_driver->probe() and ->remove() instead.
 Who:	Jean Delvare <khali@linux-fr.org>
@@ -355,17 +356,6 @@
 
 ---------------------------
 
-What:	SELinux "compat_net" functionality
-When:	2.6.30 at the earliest
-Why:	In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
-	network access control functionality of SELinux.  Secmark offers both
-	better performance and greater flexibility than the "compat_net"
-	mechanism.  Now that the major Linux distributions have moved to
-	Secmark, it is time to deprecate the older mechanism and start the
-	process of removing the old code.
-Who:	Paul Moore <paul.moore@hp.com>
----------------------------
-
 What:	sysfs ui for changing p4-clockmod parameters
 When:	September 2009
 Why:	See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index fae3495..9698c39 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -7,10 +7,14 @@
   * nForce3 250Gb MCP          10de:00E4 
   * nForce4 MCP                10de:0052
   * nForce4 MCP-04             10de:0034
-  * nForce4 MCP51              10de:0264
-  * nForce4 MCP55              10de:0368
-  * nForce4 MCP61              10de:03EB
-  * nForce4 MCP65              10de:0446
+  * nForce MCP51               10de:0264
+  * nForce MCP55               10de:0368
+  * nForce MCP61               10de:03EB
+  * nForce MCP65               10de:0446
+  * nForce MCP67               10de:0542
+  * nForce MCP73               10de:07D8
+  * nForce MCP78S              10de:0752
+  * nForce MCP79               10de:0AA2
 
 Datasheet: not publicly available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index ef1efa7..f889481 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -4,7 +4,7 @@
   * Intel 82371AB PIIX4 and PIIX4E
   * Intel 82443MX (440MX)
     Datasheet: Publicly available at the Intel website
-  * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
+  * ServerWorks OSB4, CSB5, CSB6, HT-1000 and HT-1100 southbridges
     Datasheet: Only available via NDA from ServerWorks
   * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges
     Datasheet: Not publicly available
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
new file mode 100644
index 0000000..b55ce57
--- /dev/null
+++ b/Documentation/i2c/instantiating-devices
@@ -0,0 +1,167 @@
+How to instantiate I2C devices
+==============================
+
+Unlike PCI or USB devices, I2C devices are not enumerated at the hardware
+level. Instead, the software must know which devices are connected on each
+I2C bus segment, and what address these devices are using. For this
+reason, the kernel code must instantiate I2C devices explicitly. There are
+several ways to achieve this, depending on the context and requirements.
+
+
+Method 1: Declare the I2C devices by bus number
+-----------------------------------------------
+
+This method is appropriate when the I2C bus is a system bus as is the case
+for many embedded systems. On such systems, each I2C bus has a number
+which is known in advance. It is thus possible to pre-declare the I2C
+devices which live on this bus. This is done with an array of struct
+i2c_board_info which is registered by calling i2c_register_board_info().
+
+Example (from omap2 h4):
+
+static struct i2c_board_info __initdata h4_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("isp1301_omap", 0x2d),
+		.irq		= OMAP_GPIO_IRQ(125),
+	},
+	{	/* EEPROM on mainboard */
+		I2C_BOARD_INFO("24c01", 0x52),
+		.platform_data	= &m24c01,
+	},
+	{	/* EEPROM on cpu card */
+		I2C_BOARD_INFO("24c01", 0x57),
+		.platform_data	= &m24c01,
+	},
+};
+
+static void __init omap_h4_init(void)
+{
+	(...)
+	i2c_register_board_info(1, h4_i2c_board_info,
+			ARRAY_SIZE(h4_i2c_board_info));
+	(...)
+}
+
+The above code declares 3 devices on I2C bus 1, including their respective
+addresses and custom data needed by their drivers. When the I2C bus in
+question is registered, the I2C devices will be instantiated automatically
+by i2c-core.
+
+The devices will be automatically unbound and destroyed when the I2C bus
+they sit on goes away (if ever.)
+
+
+Method 2: Instantiate the devices explicitly
+--------------------------------------------
+
+This method is appropriate when a larger device uses an I2C bus for
+internal communication. A typical case is TV adapters. These can have a
+tuner, a video decoder, an audio decoder, etc. usually connected to the
+main chip by the means of an I2C bus. You won't know the number of the I2C
+bus in advance, so the method 1 described above can't be used. Instead,
+you can instantiate your I2C devices explicitly. This is done by filling
+a struct i2c_board_info and calling i2c_new_device().
+
+Example (from the sfe4001 network driver):
+
+static struct i2c_board_info sfe4001_hwmon_info = {
+	I2C_BOARD_INFO("max6647", 0x4e),
+};
+
+int sfe4001_init(struct efx_nic *efx)
+{
+	(...)
+	efx->board_info.hwmon_client =
+		i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
+
+	(...)
+}
+
+The above code instantiates 1 I2C device on the I2C bus which is on the
+network adapter in question.
+
+A variant of this is when you don't know for sure if an I2C device is
+present or not (for example for an optional feature which is not present
+on cheap variants of a board but you have no way to tell them apart), or
+it may have different addresses from one board to the next (manufacturer
+changing its design without notice). In this case, you can call
+i2c_new_probed_device() instead of i2c_new_device().
+
+Example (from the pnx4008 OHCI driver):
+
+static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+
+static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+{
+	(...)
+	struct i2c_adapter *i2c_adap;
+	struct i2c_board_info i2c_info;
+
+	(...)
+	i2c_adap = i2c_get_adapter(2);
+	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
+	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
+						   normal_i2c);
+	i2c_put_adapter(i2c_adap);
+	(...)
+}
+
+The above code instantiates up to 1 I2C device on the I2C bus which is on
+the OHCI adapter in question. It first tries at address 0x2c, if nothing
+is found there it tries address 0x2d, and if still nothing is found, it
+simply gives up.
+
+The driver which instantiated the I2C device is responsible for destroying
+it on cleanup. This is done by calling i2c_unregister_device() on the
+pointer that was earlier returned by i2c_new_device() or
+i2c_new_probed_device().
+
+
+Method 3: Probe an I2C bus for certain devices
+----------------------------------------------
+
+Sometimes you do not have enough information about an I2C device, not even
+to call i2c_new_probed_device(). The typical case is hardware monitoring
+chips on PC mainboards. There are several dozen models, which can live
+at 25 different addresses. Given the huge number of mainboards out there,
+it is next to impossible to build an exhaustive list of the hardware
+monitoring chips being used. Fortunately, most of these chips have
+manufacturer and device ID registers, so they can be identified by
+probing.
+
+In that case, I2C devices are neither declared nor instantiated
+explicitly. Instead, i2c-core will probe for such devices as soon as their
+drivers are loaded, and if any is found, an I2C device will be
+instantiated automatically. In order to prevent any misbehavior of this
+mechanism, the following restrictions apply:
+* The I2C device driver must implement the detect() method, which
+  identifies a supported device by reading from arbitrary registers.
+* Only buses which are likely to have a supported device and agree to be
+  probed, will be probed. For example this avoids probing for hardware
+  monitoring chips on a TV adapter.
+
+Example:
+See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c
+
+I2C devices instantiated as a result of such a successful probe will be
+destroyed automatically when the driver which detected them is removed,
+or when the underlying I2C bus is itself destroyed, whichever happens
+first.
+
+Those of you familiar with the i2c subsystem of 2.4 kernels and early 2.6
+kernels will find out that this method 3 is essentially similar to what
+was done there. Two significant differences are:
+* Probing is only one way to instantiate I2C devices now, while it was the
+  only way back then. Where possible, methods 1 and 2 should be preferred.
+  Method 3 should only be used when there is no other way, as it can have
+  undesirable side effects.
+* I2C buses must now explicitly say which I2C driver classes can probe
+  them (by the means of the class bitfield), while all I2C buses were
+  probed by default back then. The default is an empty class which means
+  that no probing happens. The purpose of the class bitfield is to limit
+  the aforementioned undesirable side effects.
+
+Once again, method 3 should be avoided wherever possible. Explicit device
+instantiation (methods 1 and 2) is much preferred for it is safer and
+faster.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 6b9af7d..c1a06f9 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -207,15 +207,26 @@
 identify supported devices (returning 0 for supported ones and -ENODEV
 for unsupported ones), a list of addresses to probe, and a device type
 (or class) so that only I2C buses which may have that type of device
-connected (and not otherwise enumerated) will be probed.  The i2c
-core will then call you back as needed and will instantiate a device
-for you for every successful detection.
+connected (and not otherwise enumerated) will be probed.  For example,
+a driver for a hardware monitoring chip for which auto-detection is
+needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
+with a class including I2C_CLASS_HWMON would be probed by this driver.
+Note that the absence of matching classes does not prevent the use of
+a device of that type on the given I2C adapter.  All it prevents is
+auto-detection; explicit instantiation of devices is still possible.
 
 Note that this mechanism is purely optional and not suitable for all
 devices.  You need some reliable way to identify the supported devices
 (typically using device-specific, dedicated identification registers),
 otherwise misdetections are likely to occur and things can get wrong
-quickly.
+quickly.  Keep in mind that the I2C protocol doesn't include any
+standard way to detect the presence of a chip at a given address, let
+alone a standard way to identify devices.  Even worse is the lack of
+semantics associated to bus transfers, which means that the same
+transfer can be seen as a read operation by a chip and as a write
+operation by another chip.  For these reasons, explicit device
+instantiation should always be preferred to auto-detection where
+possible.
 
 
 Device Deletion
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index f1d6399..1f779a2 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -122,10 +122,8 @@
 'c'	00-7F	linux/coda.h		conflict!
 'c'	80-9F	arch/s390/include/asm/chsc.h
 'd'	00-FF	linux/char/drm/drm/h	conflict!
-'d'	00-DF	linux/video_decoder.h	conflict!
 'd'	F0-FF	linux/digi1.h
 'e'	all	linux/digi1.h		conflict!
-'e'	00-1F	linux/video_encoder.h	conflict!
 'e'	00-1F	net/irda/irtty.h	conflict!
 'f'	00-1F	linux/ext2_fs.h
 'h'	00-7F				Charon filesystem
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0122e5f..aeedb89 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -846,6 +846,12 @@
 			       If specified, z/VM IUCV HVC accepts connections
 			       from listed z/VM user IDs only.
 
+	i2c_bus=	[HW] Override the default board specific I2C bus speed
+			     or register an additional I2C bus that is not
+			     registered from board initialization code.
+			     Format:
+			     <bus_id>,<clkrate>
+
 	i8042.debug	[HW] Toggle i8042 debug mode
 	i8042.direct	[HW] Put keyboard port into non-translated mode
 	i8042.dumbkbd	[HW] Pretend that controller can only read data from
@@ -2034,15 +2040,6 @@
 			If enabled at boot time, /selinux/disable can be used
 			later to disable prior to initial policy load.
 
-	selinux_compat_net =
-			[SELINUX] Set initial selinux_compat_net flag value.
-                        Format: { "0" | "1" }
-                        0 -- use new secmark-based packet controls
-                        1 -- use legacy packet controls
-                        Default value is 0 (preferred).
-                        Value can be changed at runtime via
-                        /selinux/compat_net.
-
 	serialnumber	[BUGS=X86-32]
 
 	shapers=	[NET]
diff --git a/Documentation/powerpc/dts-bindings/fsl/dma.txt b/Documentation/powerpc/dts-bindings/fsl/dma.txt
index cc45311..0732cdd 100644
--- a/Documentation/powerpc/dts-bindings/fsl/dma.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/dma.txt
@@ -35,30 +35,30 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc8349-dma", "fsl,elo-dma";
-		reg = <82a8 4>;
-		ranges = <0 8100 1a4>;
+		reg = <0x82a8 4>;
+		ranges = <0 0x8100 0x1a4>;
 		interrupt-parent = <&ipic>;
-		interrupts = <47 8>;
+		interrupts = <71 8>;
 		cell-index = <0>;
 		dma-channel@0 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <0>;
-			reg = <0 80>;
+			reg = <0 0x80>;
 		};
 		dma-channel@80 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <1>;
-			reg = <80 80>;
+			reg = <0x80 0x80>;
 		};
 		dma-channel@100 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <2>;
-			reg = <100 80>;
+			reg = <0x100 0x80>;
 		};
 		dma-channel@180 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <3>;
-			reg = <180 80>;
+			reg = <0x180 0x80>;
 		};
 	};
 
@@ -93,36 +93,36 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc8540-dma", "fsl,eloplus-dma";
-		reg = <21300 4>;
-		ranges = <0 21100 200>;
+		reg = <0x21300 4>;
+		ranges = <0 0x21100 0x200>;
 		cell-index = <0>;
 		dma-channel@0 {
 			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <0 80>;
+			reg = <0 0x80>;
 			cell-index = <0>;
 			interrupt-parent = <&mpic>;
-			interrupts = <14 2>;
+			interrupts = <20 2>;
 		};
 		dma-channel@80 {
 			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <80 80>;
+			reg = <0x80 0x80>;
 			cell-index = <1>;
 			interrupt-parent = <&mpic>;
-			interrupts = <15 2>;
+			interrupts = <21 2>;
 		};
 		dma-channel@100 {
 			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <100 80>;
+			reg = <0x100 0x80>;
 			cell-index = <2>;
 			interrupt-parent = <&mpic>;
-			interrupts = <16 2>;
+			interrupts = <22 2>;
 		};
 		dma-channel@180 {
 			compatible = "fsl,mpc8540-dma-channel", "fsl,eloplus-dma-channel";
-			reg = <180 80>;
+			reg = <0x180 0x80>;
 			cell-index = <3>;
 			interrupt-parent = <&mpic>;
-			interrupts = <17 2>;
+			interrupts = <23 2>;
 		};
 	};
 
diff --git a/Documentation/powerpc/dts-bindings/fsl/esdhc.txt b/Documentation/powerpc/dts-bindings/fsl/esdhc.txt
new file mode 100644
index 0000000..6008465
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/esdhc.txt
@@ -0,0 +1,24 @@
+* Freescale Enhanced Secure Digital Host Controller (eSDHC)
+
+The Enhanced Secure Digital Host Controller provides an interface
+for MMC, SD, and SDIO types of memory cards.
+
+Required properties:
+  - compatible : should be
+    "fsl,<chip>-esdhc", "fsl,mpc8379-esdhc" for MPC83xx processors.
+    "fsl,<chip>-esdhc", "fsl,mpc8536-esdhc" for MPC85xx processors.
+  - reg : should contain eSDHC registers location and length.
+  - interrupts : should contain eSDHC interrupt.
+  - interrupt-parent : interrupt source phandle.
+  - clock-frequency : specifies eSDHC base clock frequency.
+
+Example:
+
+sdhci@2e000 {
+	compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+	reg = <0x2e000 0x1000>;
+	interrupts = <42 0x8>;
+	interrupt-parent = <&ipic>;
+	/* Filled in by U-Boot */
+	clock-frequency = <0>;
+};
diff --git a/Documentation/powerpc/dts-bindings/fsl/ssi.txt b/Documentation/powerpc/dts-bindings/fsl/ssi.txt
index a2d9639..5ff76c9 100644
--- a/Documentation/powerpc/dts-bindings/fsl/ssi.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/ssi.txt
@@ -4,44 +4,56 @@
 be programmed in AC97, I2S, left-justified, or right-justified modes.
 
 Required properties:
-- compatible	  : compatible list, containing "fsl,ssi"
-- cell-index	  : the SSI, <0> = SSI1, <1> = SSI2, and so on
-- reg		  : offset and length of the register set for the device
-- interrupts	  : <a b> where a is the interrupt number and b is a
-                     field that represents an encoding of the sense and
-		    level information for the interrupt.  This should be
-		    encoded based on the information in section 2)
-		    depending on the type of interrupt controller you
-		    have.
-- interrupt-parent : the phandle for the interrupt controller that
-                     services interrupts for this device.
-- fsl,mode	  : the operating mode for the SSI interface
-		    "i2s-slave" - I2S mode, SSI is clock slave
-		    "i2s-master" - I2S mode, SSI is clock master
-		    "lj-slave" - left-justified mode, SSI is clock slave
-		    "lj-master" - l.j. mode, SSI is clock master
-		    "rj-slave" - right-justified mode, SSI is clock slave
-		    "rj-master" - r.j., SSI is clock master
-		    "ac97-slave" - AC97 mode, SSI is clock slave
-		    "ac97-master" - AC97 mode, SSI is clock master
-- fsl,playback-dma: phandle to a node for the DMA channel to use for
+- compatible:       Compatible list, contains "fsl,ssi".
+- cell-index:       The SSI, <0> = SSI1, <1> = SSI2, and so on.
+- reg:              Offset and length of the register set for the device.
+- interrupts:       <a b> where a is the interrupt number and b is a
+                    field that represents an encoding of the sense and
+                    level information for the interrupt.  This should be
+                    encoded based on the information in section 2)
+                    depending on the type of interrupt controller you
+                    have.
+- interrupt-parent: The phandle for the interrupt controller that
+                    services interrupts for this device.
+- fsl,mode:         The operating mode for the SSI interface.
+                    "i2s-slave" - I2S mode, SSI is clock slave
+                    "i2s-master" - I2S mode, SSI is clock master
+                    "lj-slave" - left-justified mode, SSI is clock slave
+                    "lj-master" - l.j. mode, SSI is clock master
+                    "rj-slave" - right-justified mode, SSI is clock slave
+                    "rj-master" - r.j., SSI is clock master
+                    "ac97-slave" - AC97 mode, SSI is clock slave
+                    "ac97-master" - AC97 mode, SSI is clock master
+- fsl,playback-dma: Phandle to a node for the DMA channel to use for
                     playback of audio.  This is typically dictated by SOC
                     design.  See the notes below.
-- fsl,capture-dma:  phandle to a node for the DMA channel to use for
+- fsl,capture-dma:  Phandle to a node for the DMA channel to use for
                     capture (recording) of audio.  This is typically dictated
                     by SOC design.  See the notes below.
+- fsl,fifo-depth:   The number of elements in the transmit and receive FIFOs.
+                    This number is the maximum allowed value for SFCSR[TFWM0].
+- fsl,ssi-asynchronous:
+                    If specified, the SSI is to be programmed in asynchronous
+                    mode.  In this mode, pins SRCK, STCK, SRFS, and STFS must
+                    all be connected to valid signals.  In synchronous mode,
+                    SRCK and SRFS are ignored.  Asynchronous mode allows
+                    playback and capture to use different sample sizes and
+                    sample rates.  Some drivers may require that SRCK and STCK
+                    be connected together, and SRFS and STFS be connected
+                    together.  This would still allow different sample sizes,
+                    but not different sample rates.
 
 Optional properties:
-- codec-handle	  : phandle to a 'codec' node that defines an audio
-		    codec connected to this SSI.  This node is typically
-		    a child of an I2C or other control node.
+- codec-handle:     Phandle to a 'codec' node that defines an audio
+                    codec connected to this SSI.  This node is typically
+                    a child of an I2C or other control node.
 
 Child 'codec' node required properties:
-- compatible	  : compatible list, contains the name of the codec
+- compatible:       Compatible list, contains the name of the codec
 
 Child 'codec' node optional properties:
-- clock-frequency  : The frequency of the input clock, which typically
-                     comes from an on-board dedicated oscillator.
+- clock-frequency:  The frequency of the input clock, which typically comes
+                    from an on-board dedicated oscillator.
 
 Notes on fsl,playback-dma and fsl,capture-dma:
 
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index 0d93fa1..f11c583 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -135,7 +135,7 @@
 134 -> Adlink RTV24
 135 -> DViCO FusionHDTV 5 Lite                             [18ac:d500]
 136 -> Acorp Y878F                                         [9511:1540]
-137 -> Conceptronic CTVFMi v2
+137 -> Conceptronic CTVFMi v2                              [036e:109e]
 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E)
 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900
 140 -> Osprey 440                                          [0070:ff07]
@@ -154,3 +154,7 @@
 153 -> PHYTEC VD-012 (bt878)
 154 -> PHYTEC VD-012-X1 (bt878)
 155 -> PHYTEC VD-012-X2 (bt878)
+156 -> IVCE-8784                                           [0000:f050,0001:f050,0002:f050,0003:f050]
+157 -> Geovision GV-800(S) (master)                        [800a:763d]
+158 -> Geovision GV-800(S) (slave)                         [800b:763d,800c:763d,800d:763d]
+159 -> ProVideo PV183                                      [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540]
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index 35ea130..91aa3c0 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -12,3 +12,7 @@
  11 -> DViCO FusionHDTV DVB-T Dual Express                 [18ac:db78]
  12 -> Leadtek Winfast PxDVR3200 H                         [107d:6681]
  13 -> Compro VideoMate E650F                              [185b:e800]
+ 14 -> TurboSight TBS 6920                                 [6920:8888]
+ 15 -> TeVii S470                                          [d470:9022]
+ 16 -> DVBWorld DVB-S2 2005                                [0001:2005]
+ 17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 0d08f1e..71e9db0 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -77,3 +77,4 @@
  76 -> SATTRADE ST4200 DVB-S/S2                            [b200:4200]
  77 -> TBS 8910 DVB-S                                      [8910:8888]
  78 -> Prof 6200 DVB-S                                     [b022:3022]
+ 79 -> Terratec Cinergy HT PCI MKII                        [153b:1177]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 75bded8..78d0a6e 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -7,12 +7,12 @@
   6 -> Terratec Cinergy 200 USB                 (em2800)
   7 -> Leadtek Winfast USB II                   (em2800)        [0413:6023]
   8 -> Kworld USB2800                           (em2800)
-  9 -> Pinnacle Dazzle DVC 90/DVC 100           (em2820/em2840) [2304:0207,2304:021a]
+  9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a]
  10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
  11 -> Terratec Hybrid XS                       (em2880)        [0ccd:0042]
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
- 14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840)
+ 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
  15 -> V-Gear PocketTV                          (em2800)
  16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b]
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
@@ -30,7 +30,6 @@
  30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
  31 -> Usbgear VD204v9                          (em2821)
  32 -> Supercomp USB 2.0 TV                     (em2821)
- 33 -> SIIG AVTuner-PVR/Prolink PlayTV USB 2.0  (em2821)
  34 -> Terratec Cinergy A Hybrid XS             (em2860)        [0ccd:004f]
  35 -> Typhoon DVD Maker                        (em2860)
  36 -> NetGMBH Cam                              (em2860)
@@ -58,3 +57,7 @@
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
  60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]
  61 -> Pixelview PlayTV Box 4 USB 2.0           (em2820/em2840)
+ 62 -> Gadmei TVR200                            (em2820/em2840)
+ 63 -> Kaiomy TVnPC U2                          (em2860)        [eb1a:e303]
+ 64 -> Easy Cap Capture DC-60                   (em2860)
+ 65 -> IO-DATA GV-MVP/SZ                        (em2820/em2840) [04bb:0515]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index b8d4705..6dacf28 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -153,3 +153,5 @@
 152 -> Asus Tiger Rev:1.00                      [1043:4857]
 153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]
 154 -> Avermedia AVerTV GO 007 FM Plus          [1461:f31d]
+155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
+156 -> Hauppauge WinTV-HVR1110r3                [0070:6707,0070:6709,0070:670a]
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 295462b..0e89e76 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -401,8 +401,7 @@
    first set the correct norm. Well, it seems logically correct: TV
    standard is "more constant" for current country than geometry
    settings of a variety of TV capture cards which may work in ITU or
-   square pixel format. Remember that users now can lock the norm to
-   avoid any ambiguity.
+   square pixel format.
 --
 Please note that lavplay/lavrec are also included in the MJPEG-tools
 (http://mjpeg.sf.net/).
diff --git a/Documentation/video4linux/bttv/Insmod-options b/Documentation/video4linux/bttv/Insmod-options
index 5ef7578..bbe3ed6 100644
--- a/Documentation/video4linux/bttv/Insmod-options
+++ b/Documentation/video4linux/bttv/Insmod-options
@@ -81,16 +81,6 @@
 		pal=[bdgil]	select PAL variant (used for some tuners
 				only, important for the audio carrier).
 
-tvmixer.o
-	registers a mixer device for the TV card's volume/bass/treble
-	controls (requires a i2c audio control chip like the msp3400).
-
-	insmod args:
-		debug=1		print some debug info to the syslog.
-		devnr=n		allocate device #n (0 == /dev/mixer,
-				1 = /dev/mixer1, ...), default is to
-				use the first free one.
-
 tvaudio.o
 	new, experimental module which is supported to provide a single
 	driver for all simple i2c audio control chips (tda/tea*).
diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README
index 7ca2154..3a367cd 100644
--- a/Documentation/video4linux/bttv/README
+++ b/Documentation/video4linux/bttv/README
@@ -63,8 +63,8 @@
 yourself (patches very welcome of course...)  You know: The linux
 slogan is "Do it yourself".
 
-There is a mailing list: video4linux-list@redhat.com.
-https://listman.redhat.com/mailman/listinfo/video4linux-list
+There is a mailing list: linux-media@vger.kernel.org
+http://vger.kernel.org/vger-lists.html#linux-media
 
 If you have trouble with some specific TV card, try to ask there
 instead of mailing me directly.  The chance that someone with the
diff --git a/Documentation/video4linux/cx2341x/README.hm12 b/Documentation/video4linux/cx2341x/README.hm12
index 0e213ed..b36148e 100644
--- a/Documentation/video4linux/cx2341x/README.hm12
+++ b/Documentation/video4linux/cx2341x/README.hm12
@@ -32,6 +32,10 @@
 The width of a frame is always 720 pixels, regardless of the actual specified
 width.
 
+If the height is not a multiple of 32 lines, then the captured video is
+missing macroblocks at the end and is unusable. So the height must be a
+multiple of 32.
+
 --------------------------------------------------------------------------
 
 #include <stdio.h>
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 1c58a76..98529e0 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -32,6 +32,7 @@
 zc3xx		041e:4051	Creative Live!Cam Notebook Pro (VF0250)
 ov519		041e:4052	Creative Live! VISTA IM
 zc3xx		041e:4053	Creative Live!Cam Video IM
+vc032x		041e:405b	Creative Live! Cam Notebook Ultra (VC0130)
 ov519		041e:405f	Creative Live! VISTA VF0330
 ov519		041e:4060	Creative Live! VISTA VF0350
 ov519		041e:4061	Creative Live! VISTA VF0400
@@ -193,6 +194,7 @@
 spca500		08ca:0103	Aiptek PocketDV
 sunplus		08ca:0104	Aiptek PocketDVII 1.3
 sunplus		08ca:0106	Aiptek Pocket DV3100+
+mr97310a	08ca:0111	Aiptek PenCam VGA+
 sunplus		08ca:2008	Aiptek Mini PenCam 2 M
 sunplus		08ca:2010	Aiptek PocketCam 3M
 sunplus		08ca:2016	Aiptek PocketCam 2 Mega
@@ -215,6 +217,7 @@
 pac207		093a:2470	Genius GF112
 pac207		093a:2471	Genius VideoCam ge111
 pac207		093a:2472	Genius VideoCam ge110
+pac207		093a:2474	Genius iLook 111
 pac207		093a:2476	Genius e-Messenger 112
 pac7311		093a:2600	PAC7311 Typhoon
 pac7311		093a:2601	Philips SPC 610 NC
@@ -279,6 +282,7 @@
 zc3xx		10fd:8050	Typhoon Webshot II USB 300k
 ov534		1415:2000	Sony HD Eye for PS3 (SLEH 00201)
 pac207		145f:013a	Trust WB-1300N
+vc032x		15b8:6001	HP 2.0 Megapixel
 vc032x		15b8:6002	HP 2.0 Megapixel rz406aa
 spca501		1776:501c	Arowana 300K CMOS Camera
 t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
diff --git a/Documentation/video4linux/si470x.txt b/Documentation/video4linux/si470x.txt
index 49679e6..3a7823e 100644
--- a/Documentation/video4linux/si470x.txt
+++ b/Documentation/video4linux/si470x.txt
@@ -1,6 +1,6 @@
 Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers
 
-Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net>
+Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
 
 
 Information from Silicon Labs
@@ -41,7 +41,7 @@
 - 10c4:818a: Silicon Labs USB FM Radio Reference Design
 - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
 - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
-- 10c5:819a: DealExtreme USB Radio
+- 10c5:819a: Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear)
 
 
 Software
@@ -52,6 +52,7 @@
 - gradio - GTK FM radio tuner
 - kradio - Comfortable Radio Application for KDE
 - radio - ncurses-based radio application
+- mplayer - The Ultimate Movie Player For Linux
 
 There is also a library libv4l, which can be used. It's going to have a function
 for frequency seeking, either by using hardware functionality as in radio-si470x
@@ -69,7 +70,7 @@
 USB Audio is provided by the ALSA snd_usb_audio module. It is recommended to
 also select SND_USB_AUDIO, as this is required to get sound from the radio. For
 listing you have to redirect the sound, for example using one of the following
-commands.
+commands. Please adjust the audio devices to your needs (/dev/dsp* and hw:x,x).
 
 If you just want to test audio (very poor quality):
 cat /dev/dsp1 > /dev/dsp
@@ -80,6 +81,10 @@
 If you use arts try:
 arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
 
+If you use mplayer try:
+mplayer -radio adevice=hw=1.0:arate=96000 \
+	-rawaudio rate=96000 \
+	radio://<frequency>/capture
 
 Module Parameters
 =================
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index ff12437..a311773 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -47,7 +47,9 @@
 3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
    /dev/vtxX) and keeping track of device-node specific data.
 
-4) Filehandle-specific structs containing per-filehandle data.
+4) Filehandle-specific structs containing per-filehandle data;
+
+5) video buffer handling.
 
 This is a rough schematic of how it all relates:
 
@@ -82,12 +84,20 @@
 	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
 
 Registration will initialize the v4l2_device struct and link dev->driver_data
-to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from
-dev (driver name followed by the bus_id, to be precise). You may change the
-name after registration if you want.
+to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
+from dev (driver name followed by the bus_id, to be precise). If you set it
+up before calling v4l2_device_register then it will be untouched. If dev is
+NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
 
 The first 'dev' argument is normally the struct device pointer of a pci_dev,
-usb_device or platform_device.
+usb_device or platform_device. It is rare for dev to be NULL, but it happens
+with ISA devices or when one device creates multiple PCI devices, thus making
+it impossible to associate v4l2_dev with a particular parent.
+
+You can also supply a notify() callback that can be called by sub-devices to
+notify you of events. Whether you need to set this depends on the sub-device.
+Any notifications a sub-device supports must be defined in a header in
+include/media/<subdevice>.h.
 
 You unregister with:
 
@@ -95,6 +105,17 @@
 
 Unregistering will also automatically unregister all subdevs from the device.
 
+If you have a hotpluggable device (e.g. a USB device), then when a disconnect
+happens the parent device becomes invalid. Since v4l2_device has a pointer to
+that parent device it has to be cleared as well to mark that the parent is
+gone. To do this call:
+
+	v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
+
+This does *not* unregister the subdevs, so you still need to call the
+v4l2_device_unregister() function for that. If your driver is not hotpluggable,
+then there is no need to call v4l2_device_disconnect().
+
 Sometimes you need to iterate over all devices registered by a specific
 driver. This is usually the case if multiple device drivers use the same
 hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv
@@ -134,7 +155,7 @@
 
 static atomic_t drv_instance = ATOMIC_INIT(0);
 
-static int __devinit drv_probe(struct pci_dev *dev,
+static int __devinit drv_probe(struct pci_dev *pdev,
 				const struct pci_device_id *pci_id)
 {
 	...
@@ -218,7 +239,7 @@
 
 A sub-device driver initializes the v4l2_subdev struct using:
 
-	v4l2_subdev_init(subdev, &ops);
+	v4l2_subdev_init(sd, &ops);
 
 Afterwards you need to initialize subdev->name with a unique name and set the
 module owner. This is done for you if you use the i2c helper functions.
@@ -226,7 +247,7 @@
 A device (bridge) driver needs to register the v4l2_subdev with the
 v4l2_device:
 
-	int err = v4l2_device_register_subdev(device, subdev);
+	int err = v4l2_device_register_subdev(v4l2_dev, sd);
 
 This can fail if the subdev module disappeared before it could be registered.
 After this function was called successfully the subdev->dev field points to
@@ -234,17 +255,17 @@
 
 You can unregister a sub-device using:
 
-	v4l2_device_unregister_subdev(subdev);
+	v4l2_device_unregister_subdev(sd);
 
-Afterwards the subdev module can be unloaded and subdev->dev == NULL.
+Afterwards the subdev module can be unloaded and sd->dev == NULL.
 
 You can call an ops function either directly:
 
-	err = subdev->ops->core->g_chip_ident(subdev, &chip);
+	err = sd->ops->core->g_chip_ident(sd, &chip);
 
 but it is better and easier to use this macro:
 
-	err = v4l2_subdev_call(subdev, core, g_chip_ident, &chip);
+	err = v4l2_subdev_call(sd, core, g_chip_ident, &chip);
 
 The macro will to the right NULL pointer checks and returns -ENODEV if subdev
 is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is
@@ -252,19 +273,19 @@
 
 It is also possible to call all or a subset of the sub-devices:
 
-	v4l2_device_call_all(dev, 0, core, g_chip_ident, &chip);
+	v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip);
 
 Any subdev that does not support this ops is skipped and error results are
 ignored. If you want to check for errors use this:
 
-	err = v4l2_device_call_until_err(dev, 0, core, g_chip_ident, &chip);
+	err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip);
 
 Any error except -ENOIOCTLCMD will exit the loop with that error. If no
 errors (except -ENOIOCTLCMD) occured, then 0 is returned.
 
 The second argument to both calls is a group ID. If 0, then all subdevs are
 called. If non-zero, then only those whose group ID match that value will
-be called. Before a bridge driver registers a subdev it can set subdev->grp_id
+be called. Before a bridge driver registers a subdev it can set sd->grp_id
 to whatever value it wants (it's 0 by default). This value is owned by the
 bridge driver and the sub-device driver will never modify or use it.
 
@@ -276,6 +297,11 @@
 v4l2_device_call_all(). That ensures that it will only go to the subdev
 that needs it.
 
+If the sub-device needs to notify its v4l2_device parent of an event, then
+it can call v4l2_subdev_notify(sd, notification, arg). This macro checks
+whether there is a notify() callback defined and returns -ENODEV if not.
+Otherwise the result of the notify() call is returned.
+
 The advantage of using v4l2_subdev is that it is a generic struct and does
 not contain any knowledge about the underlying hardware. So a driver might
 contain several subdevs that use an I2C bus, but also a subdev that is
@@ -340,6 +366,12 @@
 is called. This will unregister the sub-device from the bridge driver. It is
 safe to call this even if the sub-device was never registered.
 
+You need to do this because when the bridge driver destroys the i2c adapter
+the remove() callbacks are called of the i2c devices on that adapter.
+After that the corresponding v4l2_subdev structures are invalid, so they
+have to be unregistered first. Calling v4l2_device_unregister_subdev(sd)
+from the remove() callback ensures that this is always done correctly.
+
 
 The bridge driver also has some helper functions it can use:
 
@@ -349,8 +381,8 @@
 calls i2c_new_device() with the given i2c_adapter and chip/address arguments.
 If all goes well, then it registers the subdev with the v4l2_device. It gets
 the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure
-that adapdata is set to v4l2_device when you setup the i2c_adapter in your
-driver.
+to call i2c_set_adapdata(adapter, v4l2_device) when you setup the i2c_adapter
+in your driver.
 
 You can also use v4l2_i2c_new_probed_subdev() which is very similar to
 v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses
@@ -358,6 +390,14 @@
 
 Both functions return NULL if something went wrong.
 
+Note that the chipid you pass to v4l2_i2c_new_(probed_)subdev() is usually
+the same as the module name. It allows you to specify a chip variant, e.g.
+"saa7114" or "saa7115". In general though the i2c driver autodetects this.
+The use of chipid is something that needs to be looked at more closely at a
+later date. It differs between i2c drivers and as such can be confusing.
+To see which chip variants are supported you can look in the i2c driver code
+for the i2c_device_id table. This lists all the possibilities.
+
 
 struct video_device
 -------------------
@@ -396,6 +436,15 @@
 - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
   (highly recommended to use this and it might become compulsory in the
   future!), then set this to your v4l2_ioctl_ops struct.
+- parent: you only set this if v4l2_device was registered with NULL as
+  the parent device struct. This only happens in cases where one hardware
+  device has multiple PCI devices that all share the same v4l2_device core.
+
+  The cx88 driver is an example of this: one core v4l2_device struct, but
+  it is used by both an raw video PCI device (cx8800) and a MPEG PCI device
+  (cx8802). Since the v4l2_device cannot be associated with a particular
+  PCI device it is setup without a parent device. But when the struct
+  video_device is setup you do know which parent PCI device to use.
 
 If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
 .ioctl to video_ioctl2 in your v4l2_file_operations struct.
@@ -499,8 +548,8 @@
 
 You can set/get driver private data in the video_device struct using:
 
-void *video_get_drvdata(struct video_device *dev);
-void video_set_drvdata(struct video_device *dev, void *data);
+void *video_get_drvdata(struct video_device *vdev);
+void video_set_drvdata(struct video_device *vdev, void *data);
 
 Note that you can safely call video_set_drvdata() before calling
 video_register_device().
@@ -519,3 +568,103 @@
 You can go from a video_device struct to the v4l2_device struct using:
 
 struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
+
+video buffer helper functions
+-----------------------------
+
+The v4l2 core API provides a standard method for dealing with video
+buffers. Those methods allow a driver to implement read(), mmap() and
+overlay() on a consistent way.
+
+There are currently methods for using video buffers on devices that
+supports DMA with scatter/gather method (videobuf-dma-sg), DMA with
+linear access (videobuf-dma-contig), and vmalloced buffers, mostly
+used on USB drivers (videobuf-vmalloc).
+
+Any driver using videobuf should provide operations (callbacks) for
+four handlers:
+
+ops->buf_setup   - calculates the size of the video buffers and avoid they
+		   to waste more than some maximum limit of RAM;
+ops->buf_prepare - fills the video buffer structs and calls
+		   videobuf_iolock() to alloc and prepare mmaped memory;
+ops->buf_queue   - advices the driver that another buffer were
+		   requested (by read() or by QBUF);
+ops->buf_release - frees any buffer that were allocated.
+
+In order to use it, the driver need to have a code (generally called at
+interrupt context) that will properly handle the buffer request lists,
+announcing that a new buffer were filled.
+
+The irq handling code should handle the videobuf task lists, in order
+to advice videobuf that a new frame were filled, in order to honor to a
+request. The code is generally like this one:
+	if (list_empty(&dma_q->active))
+		return;
+
+	buf = list_entry(dma_q->active.next, struct vbuffer, vb.queue);
+
+	if (!waitqueue_active(&buf->vb.done))
+		return;
+
+	/* Some logic to handle the buf may be needed here */
+
+	list_del(&buf->vb.queue);
+	do_gettimeofday(&buf->vb.ts);
+	wake_up(&buf->vb.done);
+
+Those are the videobuffer functions used on drivers, implemented on
+videobuf-core:
+
+- Videobuf init functions
+  videobuf_queue_sg_init()
+      Initializes the videobuf infrastructure. This function should be
+      called before any other videobuf function on drivers that uses DMA
+      Scatter/Gather buffers.
+
+  videobuf_queue_dma_contig_init
+      Initializes the videobuf infrastructure. This function should be
+      called before any other videobuf function on drivers that need DMA
+      contiguous buffers.
+
+  videobuf_queue_vmalloc_init()
+      Initializes the videobuf infrastructure. This function should be
+      called before any other videobuf function on USB (and other drivers)
+      that need a vmalloced type of videobuf.
+
+- videobuf_iolock()
+  Prepares the videobuf memory for the proper method (read, mmap, overlay).
+
+- videobuf_queue_is_busy()
+  Checks if a videobuf is streaming.
+
+- videobuf_queue_cancel()
+  Stops video handling.
+
+- videobuf_mmap_free()
+  frees mmap buffers.
+
+- videobuf_stop()
+  Stops video handling, ends mmap and frees mmap and other buffers.
+
+- V4L2 api functions. Those functions correspond to VIDIOC_foo ioctls:
+   videobuf_reqbufs(), videobuf_querybuf(), videobuf_qbuf(),
+   videobuf_dqbuf(), videobuf_streamon(), videobuf_streamoff().
+
+- V4L1 api function (corresponds to VIDIOCMBUF ioctl):
+   videobuf_cgmbuf()
+      This function is used to provide backward compatibility with V4L1
+      API.
+
+- Some help functions for read()/poll() operations:
+   videobuf_read_stream()
+      For continuous stream read()
+   videobuf_read_one()
+      For snapshot read()
+   videobuf_poll_stream()
+      polling help function
+
+The better way to understand it is to take a look at vivi driver. One
+of the main reasons for vivi is to be a videobuf usage example. the
+vivi_thread_tick() does the task that the IRQ callback would do on PCI
+drivers (or the irq callback on USB).
diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
index d6e70be..05769cf 100644
--- a/Documentation/video4linux/v4lgrab.c
+++ b/Documentation/video4linux/v4lgrab.c
@@ -105,8 +105,8 @@
   struct video_picture vpic;
 
   unsigned char *buffer, *src;
-  int bpp = 24, r, g, b;
-  unsigned int i, src_depth;
+  int bpp = 24, r = 0, g = 0, b = 0;
+  unsigned int i, src_depth = 16;
 
   if (fd < 0) {
     perror(VIDEO_DEV);
diff --git a/Documentation/video4linux/zr364xx.txt b/Documentation/video4linux/zr364xx.txt
index 5c81e3a..7f3d195 100644
--- a/Documentation/video4linux/zr364xx.txt
+++ b/Documentation/video4linux/zr364xx.txt
@@ -65,3 +65,4 @@
 0x06d6  0x003b   Trust           Powerc@m 970Z
 0x0a17  0x004e   Pentax          Optio 50
 0x041e  0x405d   Creative        DiVi CAM 516
+0x08ca  0x2102   Aiptek          DV T300
diff --git a/Documentation/x86/earlyprintk.txt b/Documentation/x86/earlyprintk.txt
new file mode 100644
index 0000000..607b1a0
--- /dev/null
+++ b/Documentation/x86/earlyprintk.txt
@@ -0,0 +1,101 @@
+
+Mini-HOWTO for using the earlyprintk=dbgp boot option with a
+USB2 Debug port key and a debug cable, on x86 systems.
+
+You need two computers, the 'USB debug key' special gadget and
+and two USB cables, connected like this:
+
+  [host/target] <-------> [USB debug key] <-------> [client/console]
+
+1. There are three specific hardware requirements:
+
+ a.) Host/target system needs to have USB debug port capability.
+
+ You can check this capability by looking at a 'Debug port' bit in
+ the lspci -vvv output:
+
+ # lspci -vvv
+ ...
+ 00:1d.7 USB Controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #1 (rev 03) (prog-if 20 [EHCI])
+         Subsystem: Lenovo ThinkPad T61
+         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
+         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+         Latency: 0
+         Interrupt: pin D routed to IRQ 19
+         Region 0: Memory at fe227000 (32-bit, non-prefetchable) [size=1K]
+         Capabilities: [50] Power Management version 2
+                 Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
+                 Status: D0 PME-Enable- DSel=0 DScale=0 PME+
+         Capabilities: [58] Debug port: BAR=1 offset=00a0
+                            ^^^^^^^^^^^ <==================== [ HERE ]
+	 Kernel driver in use: ehci_hcd
+         Kernel modules: ehci-hcd
+ ...
+
+( If your system does not list a debug port capability then you probably
+  wont be able to use the USB debug key. )
+
+ b.) You also need a Netchip USB debug cable/key:
+
+        http://www.plxtech.com/products/NET2000/NET20DC/default.asp
+
+     This is a small blue plastic connector with two USB connections,
+     it draws power from its USB connections.
+
+ c.) Thirdly, you need a second client/console system with a regular USB port.
+
+2. Software requirements:
+
+ a.) On the host/target system:
+
+    You need to enable the following kernel config option:
+
+      CONFIG_EARLY_PRINTK_DBGP=y
+
+    And you need to add the boot command line: "earlyprintk=dbgp".
+    (If you are using Grub, append it to the 'kernel' line in
+     /etc/grub.conf)
+
+    NOTE: normally earlyprintk console gets turned off once the
+    regular console is alive - use "earlyprintk=dbgp,keep" to keep
+    this channel open beyond early bootup. This can be useful for
+    debugging crashes under Xorg, etc.
+
+ b.) On the client/console system:
+
+    You should enable the following kernel config option:
+
+      CONFIG_USB_SERIAL_DEBUG=y
+
+    On the next bootup with the modified kernel you should
+    get a /dev/ttyUSBx device(s).
+
+    Now this channel of kernel messages is ready to be used: start
+    your favorite terminal emulator (minicom, etc.) and set
+    it up to use /dev/ttyUSB0 - or use a raw 'cat /dev/ttyUSBx' to
+    see the raw output.
+
+ c.) On Nvidia Southbridge based systems: the kernel will try to probe
+     and find out which port has debug device connected.
+
+3. Testing that it works fine:
+
+   You can test the output by using earlyprintk=dbgp,keep and provoking
+   kernel messages on the host/target system. You can provoke a harmless
+   kernel message by for example doing:
+
+     echo h > /proc/sysrq-trigger
+
+   On the host/target system you should see this help line in "dmesg" output:
+
+     SysRq : HELP : loglevel(0-9) reBoot Crashdump terminate-all-tasks(E) memory-full-oom-kill(F) kill-all-tasks(I) saK show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) Unmount show-blocked-tasks(W) dump-ftrace-buffer(Z)
+
+   On the client/console system do:
+
+       cat /dev/ttyUSB0
+
+   And you should see the help line above displayed shortly after you've
+   provoked it on the host system.
+
+If it does not work then please ask about it on the linux-kernel@vger.kernel.org
+mailing list or contact the x86 maintainers.
diff --git a/MAINTAINERS b/MAINTAINERS
index d8a4c8d..c5f4e9d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -502,6 +502,13 @@
 M:	rpurdie@rpsys.net
 S:	Maintained
 
+ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
+P:	Paulius Zaleckas
+M:	paulius.zaleckas@teltonika.lt
+L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+T:	git gitorious.org/linux-gemini/mainline.git
+S:	Maintained
+
 ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
 P:	Daniel Ribeiro
 M:	drwyrm@gmail.com
@@ -513,6 +520,12 @@
 W:	http://www.openezx.org/
 S:	Maintained
 
+ARM/FARADAY FA526 PORT
+P:	Paulius Zaleckas
+M:	paulius.zaleckas@teltonika.lt
+L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S:	Maintained
+
 ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
 P:	Sascha Hauer
 M:	kernel@pengutronix.de
@@ -622,7 +635,7 @@
 M:	dirk@opfer-online.de
 S:	Maintained
 
-ARM/PALMTX SUPPORT
+ARM/PALMTX,PALMT5,PALMLD SUPPORT
 P:	Marek Vasut
 M:	marek.vasut@gmail.com
 W:	http://hackndev.com
@@ -1050,7 +1063,6 @@
 P:	Mauro Carvalho Chehab
 M:	mchehab@infradead.org
 L:	linux-media@vger.kernel.org
-L:	video4linux-list@redhat.com
 W:	http://linuxtv.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:	Maintained
@@ -3570,6 +3582,22 @@
 L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 S:	Maintained
 
+PXA168 SUPPORT
+P:	Eric Miao
+M:	eric.miao@marvell.com
+P:	Jason Chagas
+M:	jason.chagas@marvell.com
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
+T:	git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
+S:	Supported
+
+PXA910 SUPPORT
+P:	Eric Miao
+M:	eric.miao@marvell.com
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
+T:	git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
+S:	Supported
+
 PXA MMCI DRIVER
 S:	Orphan
 
@@ -4806,7 +4834,6 @@
 P:	Mauro Carvalho Chehab
 M:	mchehab@infradead.org
 L:	linux-media@vger.kernel.org
-L:	video4linux-list@redhat.com
 W:	http://linuxtv.org
 T:	git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:	Maintained
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dbfdf87..e02b893 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,7 @@
 config ARCH_AT91
 	bool "Atmel AT91"
 	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
 	help
 	  This enables support for systems based on the Atmel AT91RM9200,
@@ -275,6 +276,14 @@
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
+config ARCH_GEMINI
+	bool "Cortina Systems Gemini"
+	select CPU_FA526
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Support for the Cortina Systems Gemini family SoCs
+
 config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select CPU_SA110
@@ -477,12 +486,29 @@
 	select HAVE_CLK
 	select COMMON_CLKDEV
 	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_CLK
+	select COMMON_CLKDEV
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select TICK_ONESHOT
+	select PLAT_PXA
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
+config ARCH_MMP
+	bool "Marvell PXA168/910"
+	depends on MMU
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select TICK_ONESHOT
+	select PLAT_PXA
+	help
+	  Support for Marvell's PXA168/910 processor line.
+
 config ARCH_RPC
 	bool "RiscPC"
 	select ARCH_ACORN
@@ -598,6 +624,8 @@
 
 source "arch/arm/mach-footbridge/Kconfig"
 
+source "arch/arm/mach-gemini/Kconfig"
+
 source "arch/arm/mach-integrator/Kconfig"
 
 source "arch/arm/mach-iop32x/Kconfig"
@@ -617,6 +645,9 @@
 source "arch/arm/mach-mv78xx0/Kconfig"
 
 source "arch/arm/mach-pxa/Kconfig"
+source "arch/arm/plat-pxa/Kconfig"
+
+source "arch/arm/mach-mmp/Kconfig"
 
 source "arch/arm/mach-sa1100/Kconfig"
 
@@ -686,12 +717,15 @@
 config PLAT_ORION
 	bool
 
+config PLAT_PXA
+	bool
+
 source arch/arm/mm/Kconfig
 
 config IWMMXT
 	bool "Enable iWMMXt support"
-	depends on CPU_XSCALE || CPU_XSC3
-	default y if PXA27x || PXA3xx
+	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
+	default y if PXA27x || PXA3xx || ARCH_MMP
 	help
 	  Enable support for iWMMXt context switching at run time if
 	  running on a CPU that supports it.
@@ -915,6 +949,23 @@
 	default "2"
 	depends on NEED_MULTIPLE_NODES
 
+config HIGHMEM
+	bool "High Memory Support (EXPERIMENTAL)"
+	depends on MMU && EXPERIMENTAL
+	help
+	  The address space of ARM processors is only 4 Gigabytes large
+	  and it has to accommodate user address space, kernel address
+	  space as well as some memory mapped IO. That means that, if you
+	  have a large amount of physical memory and/or IO, not all of the
+	  memory can be "permanently mapped" by the kernel. The physical
+	  memory that is not permanently mapped is called "high memory".
+
+	  Depending on the selected kernel/user memory split, minimum
+	  vmalloc space and actual amount of RAM, you may not need this
+	  option which should result in a slightly faster kernel.
+
+	  If unsure, say n.
+
 source "mm/Kconfig"
 
 config LEDS
@@ -1092,7 +1143,7 @@
 
 config CPU_FREQ_SA1100
 	bool
-	depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_H3800 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
+	depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
 	default y
 
 config CPU_FREQ_SA1110
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 192ee01..a71fd94 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -2,18 +2,29 @@
 
 source "lib/Kconfig.debug"
 
-# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
+# RMK wants arm kernels compiled with frame pointers or stack unwinding.
 # If you know what you are doing and are willing to live without stack
 # traces, you can get a slightly smaller kernel by setting this option to
 # n, but then RMK will have to kill you ;).
 config FRAME_POINTER
 	bool
-	default y
+	default y if !ARM_UNWIND
 	help
 	  If you say N here, the resulting kernel will be slightly smaller and
-	  faster. However, when a problem occurs with the kernel, the
-	  information that is reported is severely limited. Most people
-	  should say Y here.
+	  faster. However, if neither FRAME_POINTER nor ARM_UNWIND are enabled,
+	  when a problem occurs with the kernel, the information that is
+	  reported is severely limited.
+
+config ARM_UNWIND
+	bool "Enable stack unwinding support"
+	depends on AEABI && EXPERIMENTAL
+	default y
+	help
+	  This option enables stack unwinding support in the kernel
+	  using the information automatically generated by the
+	  compiler. The resulting kernel image is slightly bigger but
+	  the performance is not affected. Currently, this feature
+	  only works with EABI compilers. If unsure say Y.
 
 config DEBUG_USER
 	bool "Verbose user fault messages"
@@ -66,7 +77,7 @@
 	  Say Y here if you want the debug print routines to direct their
 	  output to the EmbeddedICE macrocell's DCC channel using
 	  co-processor 14. This is known to work on the ARM9 style ICE
-	  channel.
+	  channel and on the XScale with the PEEDI.
 
 	  It does include a timeout to ensure that the system does not
 	  totally freeze when there is nothing connected to read.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 24e0f01..e84729b 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -72,6 +72,7 @@
 tune-$(CONFIG_CPU_ARM922T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_FA526)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
 tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
@@ -85,6 +86,10 @@
 CFLAGS_ABI	:=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
 endif
 
+ifeq ($(CONFIG_ARM_UNWIND),y)
+CFLAGS_ABI	+=-funwind-tables
+endif
+
 # Need -Uarm for gcc < 3.x
 KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
 KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
@@ -105,8 +110,11 @@
  textofs-$(CONFIG_SA1111)	   := 0x00208000
 endif
  machine-$(CONFIG_ARCH_PXA)	   := pxa
+ machine-$(CONFIG_ARCH_MMP)	   := mmp
+    plat-$(CONFIG_PLAT_PXA)	   := pxa
  machine-$(CONFIG_ARCH_L7200)	   := l7200
  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
+ machine-$(CONFIG_ARCH_GEMINI)     := gemini
  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
  machine-$(CONFIG_ARCH_IOP32X)	   := iop32x
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 77d61423..b371fba 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -27,6 +27,12 @@
 		.macro	writeb, ch, rb
 		mcr	p14, 0, \ch, c0, c5, 0
 		.endm
+#elif defined(CONFIG_CPU_XSCALE)
+		.macro	loadsp, rb
+		.endm
+		.macro	writeb, ch, rb
+		mcr	p14, 0, \ch, c8, c0, 0
+		.endm
 #else
 		.macro	loadsp, rb
 		.endm
@@ -459,6 +465,20 @@
 		mcr	p15, 0, r0, c7, c5, 4	@ ISB
 		mov	pc, r12
 
+__fa526_cache_on:
+		mov	r12, lr
+		bl	__setup_mmu
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c7, 0	@ Invalidate whole cache
+		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
+		mcr	p15, 0, r0, c8, c7, 0	@ flush UTLB
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		orr	r0, r0, #0x1000		@ I-cache enable
+		bl	__common_mmu_cache_on
+		mov	r0, #0
+		mcr	p15, 0, r0, c8, c7, 0	@ flush UTLB
+		mov	pc, r12
+
 __arm6_mmu_cache_on:
 		mov	r12, lr
 		bl	__setup_mmu
@@ -630,12 +650,30 @@
 		b	__armv4_mmu_cache_off
 		b	__armv4_mmu_cache_flush
 
+		.word	0x56158000		@ PXA168
+		.word	0xfffff000
+		b __armv4_mmu_cache_on
+		b __armv4_mmu_cache_off
+		b __armv5tej_mmu_cache_flush
+
+		.word	0x56056930
+		.word	0xff0ffff0		@ PXA935
+		b	__armv4_mmu_cache_on
+		b	__armv4_mmu_cache_off
+		b	__armv4_mmu_cache_flush
+
 		.word	0x56050000		@ Feroceon
 		.word	0xff0f0000
 		b	__armv4_mmu_cache_on
 		b	__armv4_mmu_cache_off
 		b	__armv5tej_mmu_cache_flush
 
+		.word	0x66015261		@ FA526
+		.word	0xff01fff1
+		b	__fa526_cache_on
+		b	__armv4_mmu_cache_off
+		b	__fa526_cache_flush
+
 		@ These match on the architecture ID
 
 		.word	0x00020000		@ ARMv4T
@@ -775,6 +813,12 @@
 		mcr	p15, 0, ip, c7, c10, 4	@ drain WB
 		mov	pc, lr
 		
+__fa526_cache_flush:
+		mov	r1, #0
+		mcr	p15, 0, r1, c7, c14, 0	@ clean and invalidate D cache
+		mcr	p15, 0, r1, c7, c5, 0	@ flush I cache
+		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
+		mov	pc, lr
 
 __armv6_mmu_cache_flush:
 		mov	r1, #0
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 3fc0841..393c816 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -46,6 +46,21 @@
 
 	asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
 }
+#elif defined(CONFIG_CPU_XSCALE)
+
+static void icedcc_putc(int ch)
+{
+	int status, i = 0x4000000;
+
+	do {
+		if (--i < 0)
+			return;
+
+		asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
+	} while (status & (1 << 28));
+
+	asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
+}
 
 #else
 
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index 153a07e..a5924b9 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -11,6 +11,11 @@
 ENTRY(_start)
 SECTIONS
 {
+  /DISCARD/ : {
+    *(.ARM.exidx*)
+    *(.ARM.extab*)
+  }
+
   . = TEXT_START;
   _text = .;
 
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
index 1037bba..5589444 100644
--- a/arch/arm/common/clkdev.c
+++ b/arch/arm/common/clkdev.c
@@ -62,9 +62,8 @@
 	return clk;
 }
 
-struct clk *clk_get(struct device *dev, const char *con_id)
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
-	const char *dev_id = dev ? dev_name(dev) : NULL;
 	struct clk *clk;
 
 	mutex_lock(&clocks_mutex);
@@ -75,6 +74,14 @@
 
 	return clk ? clk : ERR_PTR(-ENOENT);
 }
+EXPORT_SYMBOL(clk_get_sys);
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+
+	return clk_get_sys(dev_id, con_id);
+}
 EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index f030f07..734ac91 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/page-flags.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
@@ -349,6 +350,12 @@
 
 	BUG_ON(!valid_dma_direction(dir));
 
+	if (PageHighMem(page)) {
+		dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
+			     "is not supported\n");
+		return ~0;
+	}
+
 	return map_single(dev, page_address(page) + offset, size, dir);
 }
 EXPORT_SYMBOL(dma_map_page);
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 697c649..7713a08 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -124,37 +124,6 @@
 	return 0;
 }
 
-unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
-{
-	unsigned short gpio_bit;
-	unsigned long flag;
-	struct scoop_dev *sdev = dev_get_drvdata(dev);
-
-	spin_lock_irqsave(&sdev->scoop_lock, flag);
-	gpio_bit = ioread16(sdev->base + SCOOP_GPWR) | bit;
-	iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
-	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
-
-	return gpio_bit;
-}
-
-unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
-{
-	unsigned short gpio_bit;
-	unsigned long flag;
-	struct scoop_dev *sdev = dev_get_drvdata(dev);
-
-	spin_lock_irqsave(&sdev->scoop_lock, flag);
-	gpio_bit = ioread16(sdev->base + SCOOP_GPWR) & ~bit;
-	iowrite16(gpio_bit, sdev->base + SCOOP_GPWR);
-	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
-
-	return gpio_bit;
-}
-
-EXPORT_SYMBOL(set_scoop_gpio);
-EXPORT_SYMBOL(reset_scoop_gpio);
-
 unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
 {
 	struct scoop_dev *sdev = dev_get_drvdata(dev);
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 780bbf7..140f1d7 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -29,8 +29,8 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/pm.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
+#include <mach/regs-rtc.h>
 #include <mach/sharpsl.h>
 #include <asm/hardware/sharpsl_pm.h>
 
diff --git a/arch/arm/configs/acs5k_defconfig b/arch/arm/configs/acs5k_defconfig
new file mode 100644
index 0000000..1cab4e7
--- /dev/null
+++ b/arch/arm/configs/acs5k_defconfig
@@ -0,0 +1,1233 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-simtec-micrel1
+# Tue Dec 16 13:31:34 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+CONFIG_ARCH_KS8695=y
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Kendin/Micrel KS8695 Implementations
+#
+CONFIG_MACH_KS8695=y
+CONFIG_MACH_DSM320=y
+CONFIG_MACH_ACS5K=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM922T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+CONFIG_PCI_DEBUG=y
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_KS8695_ETHER=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_PRISM54=m
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_NET_PCMCIA is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_KS8695=y
+CONFIG_SERIAL_KS8695_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_ACS5KCAN=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_KS8695_WATCHDOG=y
+# CONFIG_ALIM7101_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/acs5k_tiny_defconfig b/arch/arm/configs/acs5k_tiny_defconfig
new file mode 100644
index 0000000..8e3d084
--- /dev/null
+++ b/arch/arm/configs/acs5k_tiny_defconfig
@@ -0,0 +1,941 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-simtec-micrel1
+# Tue Jan  6 13:23:07 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+CONFIG_ARCH_KS8695=y
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Kendin/Micrel KS8695 Implementations
+#
+# CONFIG_MACH_KS8695 is not set
+# CONFIG_MACH_DSM320 is not set
+CONFIG_MACH_ACS5K=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM922T=y
+CONFIG_CPU_32v4T=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyAM0,115200 init=/bin/sh"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_KS8695_ETHER=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_KS8695=y
+CONFIG_SERIAL_KS8695_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_ACS5KCAN=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_KS8695_WATCHDOG=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig
index b1cd331..c66dd39 100644
--- a/arch/arm/configs/assabet_defconfig
+++ b/arch/arm/configs/assabet_defconfig
@@ -89,7 +89,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 80222fe..f264846 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -91,7 +91,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 CONFIG_SA1100_BADGE4=y
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig
index ee130b5..2b4c066 100644
--- a/arch/arm/configs/cerfcube_defconfig
+++ b/arch/arm/configs/cerfcube_defconfig
@@ -93,7 +93,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/xm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
similarity index 83%
rename from arch/arm/configs/xm_x2xx_defconfig
rename to arch/arm/configs/cm_x2xx_defconfig
index 1039f366..797b790 100644
--- a/arch/arm/configs/xm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc8
-# Sun Oct  5 11:05:36 2008
+# Linux kernel version: 2.6.29-rc2
+# Sun Feb  1 16:31:36 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,7 +22,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
 CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
@@ -47,12 +46,12 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -80,27 +79,21 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 # CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
-# CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -108,11 +101,9 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -129,6 +120,11 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -138,7 +134,6 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
@@ -165,17 +160,19 @@
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
-CONFIG_DMABOUNCE=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
 #
 # CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
@@ -185,7 +182,9 @@
 # CONFIG_ARCH_VIPER is not set
 # CONFIG_ARCH_PXA_ESERIES is not set
 # CONFIG_TRIZEPS_PXA is not set
-CONFIG_MACH_EM_X270=y
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
 # CONFIG_MACH_COLIBRI is not set
 # CONFIG_MACH_ZYLONITE is not set
 # CONFIG_MACH_LITTLETON is not set
@@ -204,14 +203,6 @@
 # CONFIG_PXA_PWM is not set
 
 #
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
 # Processor Type
 #
 CONFIG_CPU_32=y
@@ -232,6 +223,8 @@
 # CONFIG_OUTER_CACHE is not set
 CONFIG_IWMMXT=y
 CONFIG_XSCALE_PMU=y
+CONFIG_DMABOUNCE=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -242,6 +235,7 @@
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
 CONFIG_PCMCIA=m
@@ -287,14 +281,13 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -327,6 +320,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -345,6 +340,7 @@
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -389,6 +385,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -399,6 +396,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -420,8 +418,6 @@
 #
 # Bluetooth device drivers
 #
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
 # CONFIG_BT_HCIBTUSB is not set
 # CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
@@ -434,15 +430,15 @@
 # CONFIG_BT_HCIBTUART is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -467,6 +463,7 @@
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
@@ -521,9 +518,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x400000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 CONFIG_MTD_PXA2XX=y
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
@@ -535,6 +530,8 @@
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -563,6 +560,12 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -642,6 +645,8 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
@@ -756,26 +761,30 @@
 CONFIG_DM9000=y
 CONFIG_DM9000_DEBUGLEVEL=1
 # CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+# CONFIG_ENC28J60 is not set
 # CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
-CONFIG_8139TOO=y
+CONFIG_8139TOO=m
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
@@ -783,10 +792,12 @@
 # CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
@@ -797,8 +808,6 @@
 # CONFIG_WLAN_PRE80211 is not set
 CONFIG_WLAN_80211=y
 # CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
 CONFIG_LIBERTAS=m
 # CONFIG_LIBERTAS_USB is not set
 # CONFIG_LIBERTAS_CS is not set
@@ -811,10 +820,16 @@
 # CONFIG_PRISM54 is not set
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
 # CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_HOSTAP is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -879,22 +894,22 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
 # CONFIG_TOUCHSCREEN_PENMOUNT is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-CONFIG_TOUCHSCREEN_WM97XX=m
-# CONFIG_TOUCHSCREEN_WM9705 is not set
-CONFIG_TOUCHSCREEN_WM9712=y
-# CONFIG_TOUCHSCREEN_WM9713 is not set
-# CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set
+CONFIG_TOUCHSCREEN_UCB1400=m
+# CONFIG_TOUCHSCREEN_WM97XX is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -933,6 +948,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_IPMI_HANDLER is not set
@@ -1009,26 +1025,45 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PXA2XX=m
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
 # CONFIG_GPIO_SYSFS is not set
 
 #
+# Memory mapped GPIO expanders:
+#
+
+#
 # I2C GPIO expanders:
 #
 # CONFIG_GPIO_MAX732X is not set
@@ -1043,17 +1078,19 @@
 #
 # SPI GPIO expanders:
 #
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -1064,11 +1101,17 @@
 # CONFIG_MFD_ASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
-# CONFIG_UCB1400_CORE is not set
+CONFIG_UCB1400_CORE=m
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
@@ -1077,13 +1120,117 @@
 #
 # Multimedia core support
 #
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
 # CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
+CONFIG_VIDEO_MEDIA=m
 
 #
 # Multimedia drivers
 #
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+CONFIG_MEDIA_TUNER_CUSTOMIZE=y
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+CONFIG_SOC_CAMERA_MT9M111=m
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_VIDEO_PXA27x=m
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 
 #
@@ -1095,6 +1242,7 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1128,6 +1276,7 @@
 # CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
@@ -1138,13 +1287,17 @@
 # CONFIG_FB_PM3 is not set
 # CONFIG_FB_CARMINE is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
 # CONFIG_FB_PXA_SMARTPANEL is not set
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_FB_MBX=m
 # CONFIG_FB_W100 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
 
 #
 # Display device support
@@ -1167,6 +1320,7 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -1182,81 +1336,16 @@
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-# CONFIG_SND_AC97_POWER_SAVE is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
 CONFIG_SND_ARM=y
 CONFIG_SND_PXA2XX_PCM=m
+CONFIG_SND_PXA2XX_LIB=m
+CONFIG_SND_PXA2XX_LIB_AC97=y
 CONFIG_SND_PXA2XX_AC97=m
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_CAIAQ is not set
-CONFIG_SND_PCMCIA=y
-# CONFIG_SND_VXPOCKET is not set
-# CONFIG_SND_PDAUDIOCF is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+# CONFIG_SND_PCMCIA is not set
 # CONFIG_SND_SOC is not set
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
@@ -1269,9 +1358,37 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1291,12 +1408,15 @@
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
@@ -1306,6 +1426,8 @@
 # CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 # CONFIG_USB_MUSB_HDRC is not set
 
 #
@@ -1314,20 +1436,20 @@
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1355,6 +1477,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1371,13 +1494,20 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_UWB is not set
 CONFIG_MMC=m
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_BLOCK_BOUNCE=y
@@ -1385,11 +1515,12 @@
 # CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_PXA=m
 # CONFIG_MMC_SDHCI is not set
 # CONFIG_MMC_TIFM_SD is not set
+# CONFIG_MMC_SPI is not set
 # CONFIG_MMC_SDRICOH_CS is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_ACCESSIBILITY is not set
@@ -1400,8 +1531,7 @@
 # LED drivers
 #
 # CONFIG_LEDS_PCA9532 is not set
-# CONFIG_LEDS_GPIO is not set
-CONFIG_LEDS_CM_X270=y
+CONFIG_LEDS_GPIO=m
 # CONFIG_LEDS_PCA955X is not set
 
 #
@@ -1410,6 +1540,7 @@
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
@@ -1441,37 +1572,43 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 CONFIG_RTC_DRV_V3020=y
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_PXA is not set
 # CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
 # CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1483,14 +1620,16 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1520,15 +1659,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1548,6 +1685,7 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1567,6 +1705,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1678,19 +1817,29 @@
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 CONFIG_FRAME_POINTER=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1705,13 +1854,16 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
+# CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
@@ -1783,14 +1935,18 @@
 #
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
diff --git a/arch/arm/configs/colibri_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
similarity index 75%
rename from arch/arm/configs/colibri_defconfig
rename to arch/arm/configs/colibri_pxa270_defconfig
index 744086f..4cf3bde 100644
--- a/arch/arm/configs/colibri_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc3
-# Mon Dec  3 13:36:09 2007
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 16:18:17 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -12,6 +12,7 @@
 # CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,8 +22,8 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -42,22 +43,30 @@
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
 CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -70,29 +79,38 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -106,6 +124,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -115,9 +134,7 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
@@ -131,41 +148,58 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
 # CONFIG_ARCH_KS8695 is not set
 # CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
 # CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 CONFIG_ARCH_PXA=y
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
 #
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_MP900C is not set
 # CONFIG_ARCH_PXA_IDP is not set
 # CONFIG_PXA_SHARPSL is not set
-# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
 # CONFIG_MACH_EM_X270 is not set
 CONFIG_MACH_COLIBRI=y
+# CONFIG_MACH_COLIBRI300 is not set
 # CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_RAUMFELD_PROTO is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
 # CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_PXA_EZX is not set
 CONFIG_PXA27x=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+# CONFIG_PXA_PWM is not set
 
 #
 # Processor Type
@@ -174,6 +208,7 @@
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
 CONFIG_CPU_CP15=y
@@ -187,6 +222,7 @@
 # CONFIG_OUTER_CACHE is not set
 CONFIG_IWMMXT=y
 CONFIG_XSCALE_PMU=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -198,28 +234,33 @@
 #
 # Kernel Features
 #
-# CONFIG_TICK_ONESHOT is not set
+CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -232,6 +273,12 @@
 # CONFIG_KEXEC is not set
 
 #
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
 # Floating point emulation
 #
 
@@ -246,6 +293,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -253,21 +302,18 @@
 # Power management options
 #
 CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
 CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
 CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
 # CONFIG_APM_EMULATION is not set
-
-#
-# Networking
-#
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -275,6 +321,7 @@
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=y
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_INET=y
@@ -304,26 +351,26 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
 
 #
 # Core Netfilter Configuration
 #
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
 # CONFIG_NF_CONNTRACK is not set
 # CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
 
 #
 # IP: Netfilter Configuration
 #
+# CONFIG_NF_DEFRAG_IPV4 is not set
 CONFIG_IP_NF_QUEUE=m
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
@@ -332,7 +379,9 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -342,12 +391,14 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
 CONFIG_IRDA=m
 
 #
@@ -382,15 +433,6 @@
 # CONFIG_KS959_DONGLE is not set
 
 #
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
 # FIR device drivers
 #
 # CONFIG_USB_IRDA is not set
@@ -410,7 +452,6 @@
 #
 # Bluetooth device drivers
 #
-# CONFIG_BT_HCIUSB is not set
 # CONFIG_BT_HCIBTUSB is not set
 # CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
@@ -419,21 +460,20 @@
 # CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
 CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
 CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
 # CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -448,6 +488,8 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -457,9 +499,11 @@
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -510,9 +554,7 @@
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 CONFIG_MTD_PXA2XX=y
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
@@ -538,6 +580,7 @@
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
 # CONFIG_MTD_NAND_H1900 is not set
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_DISKONCHIP=y
 CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y
@@ -556,6 +599,11 @@
 # CONFIG_MTD_ONENAND_SIM is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -569,36 +617,41 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=8
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
 CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_PLATFORM is not set
-# CONFIG_IDE_ARM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -610,7 +663,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -631,6 +683,10 @@
 # CONFIG_SMSC_PHY is not set
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -638,11 +694,17 @@
 # CONFIG_AX88796 is not set
 # CONFIG_SMC91X is not set
 CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+# CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
 # CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -654,10 +716,15 @@
 CONFIG_WLAN_80211=y
 # CONFIG_LIBERTAS is not set
 # CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_IWLWIFI_LEDS is not set
 CONFIG_HOSTAP=y
 CONFIG_HOSTAP_FIRMWARE=y
 CONFIG_HOSTAP_FIRMWARE_NVRAM=y
-# CONFIG_ZD1211RW is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -670,7 +737,6 @@
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -710,6 +776,7 @@
 # CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 # CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_MOUSE_GPIO is not set
 # CONFIG_INPUT_JOYSTICK is not set
@@ -718,20 +785,25 @@
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
 # CONFIG_TOUCHSCREEN_PENMOUNT is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-CONFIG_TOUCHSCREEN_UCB1400=y
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 CONFIG_INPUT_MISC=y
 # CONFIG_INPUT_ATI_REMOTE is not set
 # CONFIG_INPUT_ATI_REMOTE2 is not set
 # CONFIG_INPUT_KEYSPAN_REMOTE is not set
 # CONFIG_INPUT_POWERMATE is not set
 # CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
 CONFIG_INPUT_UINPUT=m
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
 
 #
 # Hardware I/O ports
@@ -746,9 +818,11 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -764,45 +838,50 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+CONFIG_I2C_HELPER_AUTO=y
 
 #
 # I2C Hardware Bus support
 #
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
 # CONFIG_I2C_GPIO is not set
-# CONFIG_I2C_PXA is not set
 # CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PXA is not set
 # CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_TINY_USB is not set
 
 #
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
@@ -811,16 +890,35 @@
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# SPI support
+# Memory mapped GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
@@ -828,7 +926,10 @@
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
@@ -848,6 +949,7 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
@@ -856,6 +958,7 @@
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -863,9 +966,12 @@
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83793 is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -879,23 +985,46 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 CONFIG_DAB=y
 # CONFIG_USB_DABUSB is not set
 
@@ -907,6 +1036,7 @@
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -914,8 +1044,8 @@
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -928,13 +1058,20 @@
 # CONFIG_FB_UVESA is not set
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_GENERIC=y
 
 #
 # Display device support
@@ -964,12 +1101,7 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
-CONFIG_AC97_BUS=y
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
@@ -979,18 +1111,26 @@
 # USB Input Devices
 #
 # CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
 
 #
 # USB HID Boot Protocol drivers
 #
 # CONFIG_USB_KBD is not set
 # CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+# CONFIG_HID_APPLE is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
@@ -999,29 +1139,40 @@
 # CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_PERSIST is not set
 # CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_OHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 # CONFIG_USB_LIBUSUAL is not set
 
@@ -1029,19 +1180,14 @@
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_AIRCABLE is not set
-# CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ARK3116 is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_CH341 is not set
@@ -1059,6 +1205,7 @@
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
 # CONFIG_USB_SERIAL_GARMIN is not set
 # CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_KLSI is not set
@@ -1066,17 +1213,21 @@
 # CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_MOS7720 is not set
 # CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
 # CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
 # CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
 # CONFIG_USB_SERIAL_TI is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OPTION is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
 # CONFIG_USB_SERIAL_DEBUG is not set
 
 #
@@ -1085,7 +1236,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1101,30 +1252,29 @@
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 CONFIG_USB_GADGET=m
 # CONFIG_USB_GADGET_DEBUG is not set
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
 # CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
 CONFIG_USB_GADGET_SELECTED=y
-# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_AT91 is not set
 # CONFIG_USB_GADGET_ATMEL_USBA is not set
 # CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_GOKU is not set
 # CONFIG_USB_GADGET_LH7A40X is not set
 # CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
 # CONFIG_USB_GADGET_S3C2410 is not set
-# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
 CONFIG_USB_GADGET_DUMMY_HCD=y
 CONFIG_USB_DUMMY_HCD=m
 CONFIG_USB_GADGET_DUALSPEED=y
@@ -1134,21 +1284,32 @@
 # CONFIG_USB_FILE_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=y
 CONFIG_MMC_BLOCK_BOUNCE=y
 # CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 # CONFIG_MMC_PXA is not set
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
 # CONFIG_LEDS_CLASS is not set
 
@@ -1163,6 +1324,8 @@
 CONFIG_LEDS_TRIGGER_TIMER=y
 # CONFIG_LEDS_TRIGGER_IDE_DISK is not set
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
@@ -1190,6 +1353,9 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 CONFIG_RTC_DRV_PCF8583=m
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
@@ -1199,36 +1365,45 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
 # CONFIG_RTC_DRV_SA1100 is not set
+# CONFIG_RTC_DRV_PXA is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
 # CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
@@ -1254,15 +1429,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_ECRYPT_FS is not set
@@ -1283,9 +1456,13 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
@@ -1293,20 +1470,18 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
-CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1361,9 +1536,6 @@
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
@@ -1371,6 +1543,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
@@ -1378,9 +1551,12 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
@@ -1396,16 +1572,40 @@
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 CONFIG_FRAME_POINTER=y
-CONFIG_FORCED_INLINING=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
 
@@ -1415,58 +1615,114 @@
 CONFIG_KEYS=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 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_RNG2=y
 CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
 # CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
 CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
new file mode 100644
index 0000000..4774a36
--- /dev/null
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -0,0 +1,1156 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 16:13:20 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+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_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Supported PXA3xx Processor Variants
+#
+CONFIG_CPU_PXA300=y
+# CONFIG_CPU_PXA310 is not set
+# CONFIG_CPU_PXA320 is not set
+# CONFIG_CPU_PXA930 is not set
+# CONFIG_CPU_PXA935 is not set
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_MP900C is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
+CONFIG_MACH_COLIBRI300=y
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_RAUMFELD_PROTO is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_PXA_EZX is not set
+CONFIG_PXA3xx=y
+# CONFIG_PXA_PWM is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_XSC3L2=y
+CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="console=ttyS0,115200 rw"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_AX88796=y
+# CONFIG_AX88796_93CX6 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_SMARTPANEL is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index f7622e6..1aa6224 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -113,7 +113,6 @@
 CONFIG_SA1100_COLLIE=y
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/xm_x2xx_defconfig b/arch/arm/configs/em_x270_defconfig
similarity index 74%
copy from arch/arm/configs/xm_x2xx_defconfig
copy to arch/arm/configs/em_x270_defconfig
index 1039f366..e9955b7 100644
--- a/arch/arm/configs/xm_x2xx_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc8
-# Sun Oct  5 11:05:36 2008
+# Linux kernel version: 2.6.29-rc2
+# Sun Feb  1 16:43:31 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -22,8 +22,6 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
@@ -47,12 +45,12 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -80,27 +78,20 @@
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
 CONFIG_HAVE_CLK=y
-# CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -108,11 +99,9 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -129,6 +118,11 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -138,7 +132,6 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
@@ -165,17 +158,19 @@
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
-CONFIG_DMABOUNCE=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
 #
 # CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
@@ -185,33 +180,26 @@
 # CONFIG_ARCH_VIPER is not set
 # CONFIG_ARCH_PXA_ESERIES is not set
 # CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
 CONFIG_MACH_EM_X270=y
+CONFIG_MACH_EXEDA=y
 # CONFIG_MACH_COLIBRI is not set
 # CONFIG_MACH_ZYLONITE is not set
 # CONFIG_MACH_LITTLETON is not set
 # CONFIG_MACH_TAVOREVB is not set
 # CONFIG_MACH_SAAR is not set
-CONFIG_MACH_ARMCORE=y
+# CONFIG_MACH_ARMCORE is not set
 # CONFIG_MACH_CM_X300 is not set
 # CONFIG_MACH_MAGICIAN is not set
 # CONFIG_MACH_MIOA701 is not set
 # CONFIG_MACH_PCM027 is not set
 # CONFIG_ARCH_PXA_PALM is not set
 # CONFIG_PXA_EZX is not set
-CONFIG_PXA25x=y
 CONFIG_PXA27x=y
 CONFIG_PXA_SSP=y
 # CONFIG_PXA_PWM is not set
 
 #
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
 # Processor Type
 #
 CONFIG_CPU_32=y
@@ -232,36 +220,14 @@
 # CONFIG_OUTER_CACHE is not set
 CONFIG_IWMMXT=y
 CONFIG_XSCALE_PMU=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
 #
-CONFIG_PCI=y
-CONFIG_PCI_SYSCALL=y
-CONFIG_PCI_HOST_ITE8152=y
+# CONFIG_PCI_SYSCALL is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-CONFIG_PCCARD=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_PCMCIA=m
-CONFIG_PCMCIA_LOAD_CIS=y
-CONFIG_PCMCIA_IOCTL=y
-CONFIG_CARDBUS=y
-
-#
-# PC-card bridges
-#
-CONFIG_YENTA=m
-# CONFIG_YENTA_O2 is not set
-# CONFIG_YENTA_RICOH is not set
-CONFIG_YENTA_TI=y
-# CONFIG_YENTA_ENE_TUNE is not set
-# CONFIG_YENTA_TOSHIBA is not set
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-CONFIG_PCMCIA_PXA2XX=m
-CONFIG_PCCARD_NONSTATIC=m
+# CONFIG_PCCARD is not set
 
 #
 # Kernel Features
@@ -287,14 +253,12 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -309,7 +273,21 @@
 #
 # CPU Power Management
 #
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
 # CONFIG_CPU_IDLE is not set
 
 #
@@ -327,6 +305,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -338,13 +318,14 @@
 CONFIG_PM_SLEEP=y
 CONFIG_SUSPEND=y
 CONFIG_SUSPEND_FREEZER=y
-CONFIG_APM_EMULATION=m
+CONFIG_APM_EMULATION=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -389,6 +370,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -399,6 +381,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -420,29 +403,23 @@
 #
 # Bluetooth device drivers
 #
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
-# CONFIG_BT_HCIBTUSB is not set
+CONFIG_BT_HCIBTUSB=m
 # CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
 # CONFIG_BT_HCIBFUSB is not set
-# CONFIG_BT_HCIDTL1 is not set
-# CONFIG_BT_HCIBT3C is not set
-# CONFIG_BT_HCIBLUECARD is not set
-# CONFIG_BT_HCIBTUART is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
 # CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -467,6 +444,7 @@
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
@@ -521,20 +499,18 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x400000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 CONFIG_MTD_PXA2XX=y
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
 # CONFIG_MTD_SHARP_SL is not set
-# CONFIG_MTD_INTEL_VR_NOR is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
-# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -551,32 +527,31 @@
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
 # CONFIG_MTD_NAND_H1900 is not set
-CONFIG_MTD_NAND_GPIO=m
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_SHARPSL is not set
-# CONFIG_MTD_NAND_CAFE is not set
-CONFIG_MTD_NAND_CM_X270=y
 # CONFIG_MTD_NAND_NANDSIM is not set
 CONFIG_MTD_NAND_PLATFORM=y
 # CONFIG_MTD_ALAUDA is not set
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
@@ -625,117 +600,10 @@
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
+# CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
-CONFIG_ATA=m
-# CONFIG_ATA_NONSTANDARD is not set
-# CONFIG_SATA_PMP is not set
-# CONFIG_SATA_AHCI is not set
-# CONFIG_SATA_SIL24 is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-# CONFIG_PATA_ALI is not set
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-CONFIG_PATA_PCMCIA=m
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_SCH is not set
+# CONFIG_ATA is not set
 # CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -743,78 +611,47 @@
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
-# CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_AX88796 is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
 CONFIG_DM9000=y
 CONFIG_DM9000_DEBUGLEVEL=1
 # CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL is not set
+# CONFIG_ENC28J60 is not set
 # CONFIG_SMC911X is not set
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
+# CONFIG_SMSC911X is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-CONFIG_8139TOO=y
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_R6040 is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_SC92031 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_TR is not set
 
 #
 # Wireless LAN
 #
 # CONFIG_WLAN_PRE80211 is not set
 CONFIG_WLAN_80211=y
-# CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
 CONFIG_LIBERTAS=m
 # CONFIG_LIBERTAS_USB is not set
-# CONFIG_LIBERTAS_CS is not set
 CONFIG_LIBERTAS_SDIO=m
 # CONFIG_LIBERTAS_DEBUG is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-# CONFIG_PRISM54 is not set
 # CONFIG_USB_ZD1201 is not set
 # CONFIG_USB_NET_RNDIS_WLAN is not set
 # CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_HOSTAP is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -822,10 +659,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
-# CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
 CONFIG_PPP=m
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPP_FILTER=y
@@ -838,7 +672,6 @@
 # CONFIG_PPPOL2TP is not set
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
-# CONFIG_NET_FC is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -861,7 +694,7 @@
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
-# CONFIG_INPUT_APMPOWER is not set
+CONFIG_INPUT_APMPOWER=y
 
 #
 # Input Device Drivers
@@ -873,15 +706,18 @@
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_KEYBOARD_PXA27x=m
-# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_DA9034 is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
@@ -895,6 +731,7 @@
 # CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -902,7 +739,6 @@
 #
 CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
@@ -917,7 +753,6 @@
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -931,26 +766,16 @@
 CONFIG_SERIAL_PXA_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_CARDMAN_4000 is not set
-# CONFIG_CARDMAN_4040 is not set
-# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=m
@@ -961,24 +786,6 @@
 #
 
 #
-# PC SMBus host controller drivers
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VIA is not set
-# CONFIG_I2C_VIAPRO is not set
-
-#
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_GPIO is not set
@@ -995,11 +802,6 @@
 # CONFIG_I2C_TINY_USB is not set
 
 #
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
 # Other I2C/SMBus bus drivers
 #
 # CONFIG_I2C_PCA_PLATFORM is not set
@@ -1015,20 +817,39 @@
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PXA2XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
 # CONFIG_GPIO_SYSFS is not set
 
 #
+# Memory mapped GPIO expanders:
+#
+
+#
 # I2C GPIO expanders:
 #
 # CONFIG_GPIO_MAX732X is not set
@@ -1038,22 +859,29 @@
 #
 # PCI GPIO expanders:
 #
-# CONFIG_GPIO_BT8XX is not set
 
 #
 # SPI GPIO expanders:
 #
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_APM_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_BATTERY_DA9030=y
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -1065,10 +893,16 @@
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
+CONFIG_PMIC_DA903X=y
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
@@ -1077,24 +911,121 @@
 #
 # Multimedia core support
 #
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
 # CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
+CONFIG_VIDEO_MEDIA=m
 
 #
 # Multimedia drivers
 #
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+CONFIG_MEDIA_TUNER_CUSTOMIZE=y
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+CONFIG_SOC_CAMERA_MT9M111=m
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_VIDEO_PXA27x=m
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1113,38 +1044,27 @@
 #
 # Frame buffer hardware drivers
 #
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_VT8623 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_CARMINE is not set
 CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
 # CONFIG_FB_PXA_SMARTPANEL is not set
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_FB_MBX=m
+# CONFIG_FB_MBX_DEBUG is not set
 # CONFIG_FB_W100 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+CONFIG_LCD_TDO24M=y
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_DA903X=m
 
 #
 # Display device support
@@ -1167,6 +1087,7 @@
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
 CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -1182,82 +1103,21 @@
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
 CONFIG_SND_AC97_CODEC=m
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-# CONFIG_SND_AC97_POWER_SAVE is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_DRIVERS is not set
 CONFIG_SND_ARM=y
-CONFIG_SND_PXA2XX_PCM=m
-CONFIG_SND_PXA2XX_AC97=m
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_CAIAQ is not set
-CONFIG_SND_PCMCIA=y
-# CONFIG_SND_VXPOCKET is not set
-# CONFIG_SND_PDAUDIOCF is not set
-# CONFIG_SND_SOC is not set
+CONFIG_SND_PXA2XX_LIB=m
+CONFIG_SND_PXA2XX_LIB_AC97=y
+# CONFIG_SND_PXA2XX_AC97 is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_PXA2XX_SOC=m
+CONFIG_SND_PXA2XX_SOC_AC97=m
+CONFIG_SND_PXA2XX_SOC_EM_X270=m
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_WM9712=m
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
@@ -1269,13 +1129,41 @@
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
 # CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
@@ -1291,21 +1179,22 @@
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
-# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
 # CONFIG_USB_MUSB_HDRC is not set
 
 #
@@ -1314,20 +1203,20 @@
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1355,6 +1244,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1371,13 +1261,19 @@
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
 CONFIG_MMC=m
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_BLOCK_BOUNCE=y
@@ -1385,12 +1281,11 @@
 # CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_PXA=m
 # CONFIG_MMC_SDHCI is not set
-# CONFIG_MMC_TIFM_SD is not set
-# CONFIG_MMC_SDRICOH_CS is not set
+# CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
@@ -1401,8 +1296,8 @@
 #
 # CONFIG_LEDS_PCA9532 is not set
 # CONFIG_LEDS_GPIO is not set
-CONFIG_LEDS_CM_X270=y
 # CONFIG_LEDS_PCA955X is not set
+CONFIG_LEDS_DA903X=y
 
 #
 # LED Triggers
@@ -1410,6 +1305,7 @@
 CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
@@ -1441,37 +1337,48 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
 # CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 CONFIG_RTC_DRV_V3020=y
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_PXA is not set
 # CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
-# CONFIG_REGULATOR is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_DA903X=y
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1483,14 +1390,17 @@
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1520,15 +1430,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1548,6 +1456,7 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1567,6 +1476,7 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1652,7 +1562,7 @@
 CONFIG_FRAME_WARN=0
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
@@ -1678,19 +1588,29 @@
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 CONFIG_FRAME_POINTER=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1705,13 +1625,24 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
@@ -1731,7 +1662,7 @@
 # CONFIG_CRYPTO_CBC is not set
 # CONFIG_CRYPTO_CTR is not set
 # CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_ECB=m
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_PCBC is not set
 # CONFIG_CRYPTO_XTS is not set
@@ -1748,7 +1679,7 @@
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
 # CONFIG_CRYPTO_RMD128 is not set
 # CONFIG_CRYPTO_RMD160 is not set
 # CONFIG_CRYPTO_RMD256 is not set
@@ -1762,9 +1693,9 @@
 #
 # Ciphers
 #
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=m
 # CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
@@ -1783,14 +1714,18 @@
 #
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index 8f986e9..1502957 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -90,7 +90,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 CONFIG_SA1100_H3600=y
-# CONFIG_SA1100_H3800 is not set
 CONFIG_SA1100_H3XXX=y
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
@@ -100,7 +99,6 @@
 # CONFIG_SA1100_SHANNON is not set
 # CONFIG_SA1100_SIMPAD is not set
 # CONFIG_SA1100_SSP is not set
-# CONFIG_H3600_SLEEVE is not set
 
 #
 # Processor Type
diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig
index 1c8fb89..db0708d 100644
--- a/arch/arm/configs/hackkit_defconfig
+++ b/arch/arm/configs/hackkit_defconfig
@@ -91,7 +91,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 CONFIG_SA1100_HACKKIT=y
diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig
index 81fadaf..f3074e4 100644
--- a/arch/arm/configs/jornada720_defconfig
+++ b/arch/arm/configs/jornada720_defconfig
@@ -178,7 +178,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 CONFIG_SA1100_JORNADA720=y
 CONFIG_SA1100_JORNADA720_SSP=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 4bc3807..c367ae4 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -1,11 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc7
-# Thu Dec  4 15:27:39 2008
+# Linux kernel version: 2.6.29-rc5
+# Tue Mar  3 21:45:57 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
@@ -42,10 +42,19 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
+CONFIG_LOG_BUF_SHIFT=19
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
@@ -53,6 +62,7 @@
 # CONFIG_IPC_NS is not set
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
@@ -83,6 +93,7 @@
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
 # CONFIG_MARKERS is not set
 CONFIG_OPROFILE=y
 CONFIG_HAVE_OPROFILE=y
@@ -93,7 +104,6 @@
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -101,11 +111,9 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -121,7 +129,6 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
 # CONFIG_FREEZER is not set
 
 #
@@ -132,7 +139,6 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
@@ -159,11 +165,13 @@
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Marvell Kirkwood Implementations
@@ -171,14 +179,8 @@
 CONFIG_MACH_DB88F6281_BP=y
 CONFIG_MACH_RD88F6192_NAS=y
 CONFIG_MACH_RD88F6281=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+CONFIG_MACH_SHEEVAPLUG=y
+CONFIG_MACH_TS219=y
 CONFIG_PLAT_ORION=y
 
 #
@@ -214,6 +216,7 @@
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
 # CONFIG_PCCARD is not set
 
 #
@@ -242,7 +245,6 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
@@ -291,6 +293,7 @@
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -355,6 +358,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -368,12 +372,27 @@
 # CONFIG_AF_RXRPC is not set
 # CONFIG_PHONET is not set
 CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_NL80211 is not set
 CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -398,6 +417,7 @@
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
@@ -451,9 +471,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_IMPA7 is not set
 # CONFIG_MTD_INTEL_VR_NOR is not set
@@ -481,6 +499,7 @@
 # CONFIG_MTD_NAND_VERIFY_WRITE is not set
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_IDS=y
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_CAFE is not set
@@ -491,6 +510,12 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -568,6 +593,8 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
@@ -682,6 +709,9 @@
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -695,6 +725,7 @@
 # CONFIG_DM9000 is not set
 # CONFIG_ENC28J60 is not set
 # CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -710,7 +741,6 @@
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -720,6 +750,7 @@
 # CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
@@ -754,8 +785,39 @@
 # Wireless LAN
 #
 # CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+# CONFIG_LIBERTAS_USB is not set
+CONFIG_LIBERTAS_SDIO=y
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8180 is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_ATH5K is not set
+# CONFIG_ATH9K is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_IWLCORE is not set
 # CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_IWLAGN is not set
+# CONFIG_IWL3945 is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -791,13 +853,20 @@
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
 # Input Device Drivers
 #
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
@@ -807,7 +876,11 @@
 #
 # Hardware I/O ports
 #
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -839,11 +912,11 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -879,6 +952,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MV64XXX=y
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
@@ -905,8 +979,6 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
@@ -925,12 +997,12 @@
 # SPI Master Controller Drivers
 #
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 CONFIG_SPI_ORION=y
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
@@ -952,10 +1024,12 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
@@ -1012,11 +1086,9 @@
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
 CONFIG_HID_EZKEY=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_LOGITECH=y
@@ -1024,12 +1096,15 @@
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
 CONFIG_HID_MICROSOFT=y
 CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
 CONFIG_HID_PANTHERLORD=y
 # CONFIG_PANTHERLORD_FF is not set
 CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
 # CONFIG_THRUSTMASTER_FF is not set
 # CONFIG_ZEROPLUS_FF is not set
 CONFIG_USB_SUPPORT=y
@@ -1058,6 +1133,7 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 # CONFIG_USB_OHCI_HCD is not set
@@ -1087,7 +1163,6 @@
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 # CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
 # CONFIG_USB_STORAGE_USBAT is not set
 CONFIG_USB_STORAGE_SDDR09=y
 CONFIG_USB_STORAGE_SDDR55=y
@@ -1135,21 +1210,51 @@
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_UWB is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_MVSDIO=y
+# CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
-# CONFIG_LEDS_CLASS is not set
+CONFIG_LEDS_CLASS=y
 
 #
 # LED drivers
 #
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
 
 #
 # LED Triggers
 #
-# CONFIG_LEDS_TRIGGERS is not set
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1178,7 +1283,7 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
+CONFIG_RTC_DRV_S35390A=y
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
 
@@ -1227,6 +1332,7 @@
 # CONFIG_DMATEST is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -1238,16 +1344,14 @@
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 CONFIG_FILE_LOCKING=y
-CONFIG_XFS_FS=y
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_DEBUG is not set
+# CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1268,9 +1372,9 @@
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
@@ -1286,10 +1390,7 @@
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1309,6 +1410,7 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1393,7 +1495,7 @@
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
@@ -1416,6 +1518,7 @@
 # CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
@@ -1424,7 +1527,7 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1435,7 +1538,10 @@
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
 
 #
 # Tracers
@@ -1446,11 +1552,14 @@
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1464,19 +1573,22 @@
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_ASYNC_CORE=y
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
 # CONFIG_CRYPTO_FIPS is not set
-CONFIG_CRYPTO_ALGAPI=m
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=m
-CONFIG_CRYPTO_RNG=m
-CONFIG_CRYPTO_MANAGER=m
+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_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
@@ -1496,7 +1608,7 @@
 CONFIG_CRYPTO_CBC=m
 # CONFIG_CRYPTO_CTR is not set
 # CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_ECB=y
 # CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_XTS is not set
@@ -1510,7 +1622,7 @@
 #
 # Digest
 #
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=y
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
@@ -1527,9 +1639,9 @@
 #
 # Ciphers
 #
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_ARC4=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
@@ -1560,6 +1672,7 @@
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig
index a1cc34f..56ae568 100644
--- a/arch/arm/configs/lart_defconfig
+++ b/arch/arm/configs/lart_defconfig
@@ -87,7 +87,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
index 73ba62b..82428c2 100644
--- a/arch/arm/configs/magician_defconfig
+++ b/arch/arm/configs/magician_defconfig
@@ -1,9 +1,10 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc6
-# Sun Dec 30 13:02:54 2007
+# Linux kernel version: 2.6.29-rc3
+# Fri Jan 30 12:42:03 2009
 #
 CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
@@ -12,6 +13,7 @@
 # CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
@@ -21,8 +23,8 @@
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ZONE_DMA=y
 CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -41,16 +43,24 @@
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -65,31 +75,41 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -103,8 +123,7 @@
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_FREEZER=y
 
 #
 # System Type
@@ -114,9 +133,7 @@
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
@@ -130,41 +147,58 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
 # CONFIG_ARCH_KS8695 is not set
 # CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
 # CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_PNX4008 is not set
 CONFIG_ARCH_PXA=y
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Intel PXA2xx/PXA3xx Implementations
 #
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
 # CONFIG_ARCH_LUBBOCK is not set
 # CONFIG_MACH_LOGICPD_PXA270 is not set
 # CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_MP900C is not set
 # CONFIG_ARCH_PXA_IDP is not set
 # CONFIG_PXA_SHARPSL is not set
-# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_H5000 is not set
 # CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
 # CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
 # CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_CM_X300 is not set
 CONFIG_MACH_MAGICIAN=y
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_PXA_EZX is not set
 CONFIG_PXA27x=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
+CONFIG_PXA_SSP=y
+CONFIG_PXA_PWM=y
+CONFIG_PXA_HAVE_BOARD_IRQS=y
 
 #
 # Processor Type
@@ -173,6 +207,7 @@
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
 CONFIG_CPU_CP15=y
@@ -186,6 +221,7 @@
 # CONFIG_OUTER_CACHE is not set
 CONFIG_IWMMXT=y
 CONFIG_XSCALE_PMU=y
+CONFIG_COMMON_CLKDEV=y
 
 #
 # Bus support
@@ -197,28 +233,33 @@
 #
 # Kernel Features
 #
-# CONFIG_TICK_ONESHOT is not set
-# CONFIG_NO_HZ is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -229,9 +270,10 @@
 CONFIG_CMDLINE="keepinitrd"
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
 
 #
-# CPU Frequency scaling
+# CPU Power Management
 #
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
@@ -239,6 +281,7 @@
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
 # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
@@ -247,6 +290,7 @@
 # CONFIG_CPU_FREQ_GOV_USERSPACE is not set
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -263,6 +307,8 @@
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
@@ -270,21 +316,18 @@
 # Power management options
 #
 CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
 # CONFIG_PM_DEBUG is not set
 CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
 CONFIG_SUSPEND=y
-CONFIG_APM_EMULATION=y
-
-#
-# Networking
-#
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
 #
 # Networking options
 #
+CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -316,33 +359,15 @@
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK is not set
-# CONFIG_NF_CONNTRACK_ENABLED is not set
-# CONFIG_NF_CONNTRACK is not set
-# CONFIG_NETFILTER_XTABLES is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -353,6 +378,7 @@
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -390,20 +416,17 @@
 # Dongle support
 #
 # CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
 
 #
 # FIR device drivers
 #
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
 CONFIG_PXA_FICP=m
+# CONFIG_MCS_FIR is not set
 CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
@@ -417,17 +440,17 @@
 #
 # Bluetooth device drivers
 #
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTSDIO is not set
 # CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
 # CONFIG_BT_HCIVHCI is not set
 # CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -442,25 +465,28 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=0
+# CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
 #
-CONFIG_MTD_CHAR=m
-CONFIG_MTD_BLKDEVS=m
-CONFIG_MTD_BLOCK=m
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
@@ -473,6 +499,7 @@
 #
 CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
@@ -487,6 +514,7 @@
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
@@ -497,9 +525,7 @@
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x00000000
-CONFIG_MTD_PHYSMAP_LEN=0x04000000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
 # CONFIG_MTD_PXA2XX is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_SHARP_SL is not set
@@ -523,6 +549,12 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -531,10 +563,12 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -547,7 +581,6 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -563,6 +596,20 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
@@ -612,7 +659,26 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
 CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
 CONFIG_INPUT_UINPUT=m
 
 #
@@ -625,9 +691,11 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -642,6 +710,7 @@
 # CONFIG_SERIAL_PXA_CONSOLE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
@@ -649,37 +718,45 @@
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
-CONFIG_I2C=m
+CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+CONFIG_I2C_HELPER_AUTO=y
 
 #
 # I2C Hardware Bus support
 #
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
 # CONFIG_I2C_GPIO is not set
-CONFIG_I2C_PXA=m
-# CONFIG_I2C_PXA_SLAVE is not set
 # CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
 # CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
 # CONFIG_I2C_STUB is not set
 
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
@@ -688,19 +765,39 @@
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# SPI support
+# Memory mapped GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 CONFIG_W1=y
 
 #
 # 1-wire Bus Masters
 #
+# CONFIG_W1_MASTER_DS2490 is not set
 # CONFIG_W1_MASTER_DS2482 is not set
 CONFIG_W1_MASTER_DS1WM=y
+# CONFIG_W1_MASTER_GPIO is not set
 
 #
 # 1-wire Slaves
@@ -709,32 +806,56 @@
 # CONFIG_W1_SLAVE_SMEM is not set
 # CONFIG_W1_SLAVE_DS2433 is not set
 CONFIG_W1_SLAVE_DS2760=y
+# CONFIG_W1_SLAVE_BQ27000 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 CONFIG_PDA_POWER=y
-# CONFIG_APM_POWER is not set
 CONFIG_BATTERY_DS2760=y
+# CONFIG_BATTERY_BQ27x00 is not set
 # CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
 CONFIG_HTC_EGPIO=y
 CONFIG_HTC_PASIC3=y
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
@@ -745,6 +866,7 @@
 CONFIG_FB=y
 # CONFIG_FIRMWARE_EDID is not set
 # CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -752,8 +874,8 @@
 # CONFIG_FB_SYS_FILLRECT is not set
 # CONFIG_FB_SYS_COPYAREA is not set
 # CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -765,13 +887,21 @@
 #
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_PXA=y
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_SMARTPANEL is not set
 # CONFIG_FB_PXA_PARAMETERS is not set
 # CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CORGI=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
 
 #
 # Display device support
@@ -802,15 +932,8 @@
 # CONFIG_FONT_SUN12x22 is not set
 # CONFIG_FONT_10x18 is not set
 # CONFIG_LOGO is not set
-
-#
-# Sound
-#
 CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -824,53 +947,185 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
-
-#
-# ALSA ARM devices
-#
-# CONFIG_SND_PXA2XX_AC97 is not set
-
-#
-# System on Chip audio support
-#
+# CONFIG_SND_ARM is not set
+CONFIG_SND_PXA2XX_LIB=m
+# CONFIG_SND_USB is not set
 CONFIG_SND_SOC=m
 CONFIG_SND_PXA2XX_SOC=m
-
-#
-# SoC Audio support for SuperH
-#
-
-#
-# Open Sound System
-#
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
 # CONFIG_SOUND_PRIME is not set
 # CONFIG_HID_SUPPORT is not set
 CONFIG_HID=m
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+# CONFIG_USB_ETH_RNDIS is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=y
 CONFIG_MMC_BLOCK_BOUNCE=y
 CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_PXA=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -899,6 +1154,9 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
@@ -908,17 +1166,26 @@
 # Platform RTC drivers
 #
 # CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
 CONFIG_RTC_DRV_SA1100=y
+# CONFIG_RTC_DRV_PXA is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -927,19 +1194,18 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -965,15 +1231,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -997,9 +1261,13 @@
 # CONFIG_JFFS2_CMODE_SIZE is not set
 # CONFIG_JFFS2_CMODE_FAVOURLZO is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
@@ -1007,14 +1275,13 @@
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1076,6 +1343,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
@@ -1083,15 +1351,18 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
 # CONFIG_LOCK_STAT is not set
@@ -1100,17 +1371,41 @@
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 CONFIG_FRAME_POINTER=y
-CONFIG_FORCED_INLINING=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
 
@@ -1119,55 +1414,110 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
 CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
 CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_MD4 is not set
 # CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_ECB=m
-# CONFIG_CRYPTO_CBC is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
 # CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
 # CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
 # CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index 83c817f..b069872 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -165,6 +165,7 @@
 # Marvell MV78xx0 Implementations
 #
 CONFIG_MACH_DB78X00_BP=y
+CONFIG_MACH_RD78X00_MASA=y
 
 #
 # Boot options
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index d81ea21..36cd62e 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -91,7 +91,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig
new file mode 100644
index 0000000..8fb918d
--- /dev/null
+++ b/arch/arm/configs/omap_3430sdp_defconfig
@@ -0,0 +1,2061 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 14:17:01 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+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_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_OMAP_LDP=y
+CONFIG_MACH_OVERO=y
+CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_MACH_OMAP_3430SDP=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS2,115200 root=/dev/mmcblk0p3 rootwait debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+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
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_LL is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=m
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+CONFIG_LIBERTAS_SDIO=y
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+CONFIG_RTL8187=m
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_OMAP_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_AF9015 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+# CONFIG_DVB_TDA8261 is not set
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+# CONFIG_DVB_TUNER_CX24113 is not set
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_SI21XX is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+# CONFIG_DVB_LGDT3304 is not set
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DVB_LGS8GL5 is not set
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+# CONFIG_SND_OMAP_SOC_OVERO is not set
+CONFIG_SND_OMAP_SOC_SDP3430=y
+CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=y
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+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_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+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_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index a8ee698..020e6a8 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -481,7 +481,7 @@
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_CAFE is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_PLATFORM=y
 # CONFIG_MTD_ALAUDA is not set
 CONFIG_MTD_NAND_ORION=y
 # CONFIG_MTD_ONENAND is not set
@@ -1177,7 +1177,7 @@
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_M48T86=y
 # CONFIG_RTC_DRV_M48T59 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig
index a6b47ea..f2d2dda 100644
--- a/arch/arm/configs/pleb_defconfig
+++ b/arch/arm/configs/pleb_defconfig
@@ -88,7 +88,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
new file mode 100644
index 0000000..db5faea
--- /dev/null
+++ b/arch/arm/configs/pxa168_defconfig
@@ -0,0 +1,891 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc3
+# Fri Mar 20 13:43:13 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+CONFIG_ARCH_MMP=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_MACH_TAVOREVB is not set
+
+#
+# Marvell PXA168/910 Implmentations
+#
+CONFIG_MACH_ASPENITE=y
+CONFIG_MACH_ZYLONITE2=y
+# CONFIG_MACH_TTC_DKB is not set
+CONFIG_CPU_PXA168=y
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_MOHAWK=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+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_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+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_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
new file mode 100644
index 0000000..8c7e299
--- /dev/null
+++ b/arch/arm/configs/pxa910_defconfig
@@ -0,0 +1,891 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc3
+# Fri Mar 20 13:45:12 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+CONFIG_ARCH_MMP=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_MACH_TAVOREVB=y
+
+#
+# Marvell PXA168/910 Implmentations
+#
+# CONFIG_MACH_ASPENITE is not set
+# CONFIG_MACH_ZYLONITE2 is not set
+CONFIG_MACH_TTC_DKB=y
+CONFIG_CPU_PXA910=y
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_MOHAWK=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+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_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+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_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/rx51_defconfig b/arch/arm/configs/rx51_defconfig
new file mode 100644
index 0000000..593102da
--- /dev/null
+++ b/arch/arm/configs/rx51_defconfig
@@ -0,0 +1,1821 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc8
+# Fri Mar 13 15:28:56 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=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_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+CONFIG_MACH_NOKIA_RX51=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs rw console=ttyMTD5"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_SECURITY is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+CONFIG_MTD_OOPS=y
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_OMAP_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+CONFIG_MTD_ONENAND=y
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=m
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_USB_VIDEO_CLASS is not set
+# CONFIG_USB_GSPCA is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_WHITELIST=y
+CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+CONFIG_MMC_OMAP_HS=m
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGERS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=m
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+CONFIG_LOCK_STAT=y
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+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_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/shannon_defconfig b/arch/arm/configs/shannon_defconfig
index d052c8f..984f7096 100644
--- a/arch/arm/configs/shannon_defconfig
+++ b/arch/arm/configs/shannon_defconfig
@@ -87,7 +87,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig
index 9b6561d..90235bf 100644
--- a/arch/arm/configs/shark_defconfig
+++ b/arch/arm/configs/shark_defconfig
@@ -1,88 +1,174 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-git3
-# Sat Jul 16 15:21:47 2005
+# Linux kernel version: 2.6.28-git6
+# Thu Jan  8 17:14:47 2009
 #
 CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_GENERIC_GPIO is not set
+# CONFIG_GENERIC_TIME is not set
+# CONFIG_GENERIC_CLOCKEVENTS is not set
 CONFIG_MMU=y
-CONFIG_UID16=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # General setup
 #
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_FREEZER is not set
 
 #
 # System Type
 #
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 CONFIG_ARCH_SHARK=y
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
 
 #
 # Processor Type
@@ -91,14 +177,20 @@
 CONFIG_CPU_SA110=y
 CONFIG_CPU_32v4=y
 CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_V4WB=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
 CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
 
 #
 # Processor Features
 #
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
 
 #
 # Bus support
@@ -107,22 +199,40 @@
 CONFIG_ISA_DMA=y
 CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
 CONFIG_PCI_HOST_VIA82C505=y
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
 # CONFIG_PCCARD is not set
 
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 # CONFIG_PREEMPT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
 CONFIG_LEDS=y
 CONFIG_LEDS_TIMER=y
 # CONFIG_LEDS_CPU is not set
@@ -135,6 +245,12 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE=""
 # CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -143,13 +259,16 @@
 #
 # At least one emulation must be selected
 #
-# CONFIG_FPE_NWFPE is not set
-CONFIG_FPE_FASTFPE=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
 
 #
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
 # CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_ARTHUR is not set
@@ -158,6 +277,75 @@
 # Power management options
 #
 # CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -166,36 +354,27 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
 # CONFIG_PARPORT_1284 is not set
-
-#
-# Plug and Play support
-#
 # CONFIG_PNP is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
@@ -210,52 +389,78 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
 #
+CONFIG_IDE_ATAPI=y
 # CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
 CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
 
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
 CONFIG_IDE_ARM=y
-# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -275,17 +480,20 @@
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_7000FASST is not set
@@ -296,12 +504,18 @@
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -314,20 +528,15 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=m
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC395x is not set
@@ -336,123 +545,57 @@
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
 # CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
 # CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
+# CONFIG_VETH is not set
 # CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
+# CONFIG_AX88796 is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_SMC91X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
 # CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
 # CONFIG_NET_TULIP is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
@@ -462,56 +605,69 @@
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 CONFIG_CS89x0=y
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
+CONFIG_CS89x0_NOEEPROM=y
 # CONFIG_E100 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
 # CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
 # CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 # CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
-# CONFIG_SK98LIN is not set
+# CONFIG_SKY2 is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -519,18 +675,17 @@
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_ISDN is not set
 
 #
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -540,7 +695,6 @@
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
@@ -553,14 +707,25 @@
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_INPORT is not set
 # CONFIG_MOUSE_LOGIBM is not set
 # CONFIG_MOUSE_PC110PAD is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
@@ -580,16 +745,22 @@
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -599,90 +770,122 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
 # CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
 # CONFIG_NVRAM is not set
-CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
-# Misc devices
+# Sonics Silicon Backplane
 #
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
 
 #
 # Multimedia devices
 #
-# CONFIG_VIDEO_DEV is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia core support
 #
-# CONFIG_DVB is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 CONFIG_FB_CYBER2000=y
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
 # CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
 # CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
@@ -691,126 +894,132 @@
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
 CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
 # CONFIG_SND is not set
-
-#
-# Open Sound System
-#
 CONFIG_SOUND_PRIME=m
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_SOUND_OSS=m
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_AD1889 is not set
-# CONFIG_SOUND_SGALAXY is not set
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
 # CONFIG_SOUND_MSS is not set
 # CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_PAS is not set
 # CONFIG_SOUND_PSS is not set
 CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
 # CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMFPCI is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
 # CONFIG_SOUND_KAHLUA is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
 
 #
-# USB support
+# Special HID drivers
 #
+CONFIG_HID_COMPAT=y
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
-# USB Gadget Support
+# Enable Host or Gadget support to see Inventra options
 #
-# CONFIG_USB_GADGET is not set
 
 #
-# MMC/SD Card support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
+# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
 # CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
+# CONFIG_OCFS2_FS is not set
 CONFIG_DNOTIFY=y
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -834,14 +1043,12 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -855,22 +1062,27 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=m
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=m
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_SUNRPC=m
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -897,11 +1109,9 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
+# CONFIG_SYSV68_PARTITION is not set
 CONFIG_NLS=m
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
@@ -942,30 +1152,74 @@
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
+# CONFIG_DLM is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_LL is not set
 
 #
@@ -973,19 +1227,23 @@
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
 
 #
-# Hardware crypto devices
-#
-
-#
 # Library routines
 #
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig
index 03f783e..685d2b5 100644
--- a/arch/arm/configs/simpad_defconfig
+++ b/arch/arm/configs/simpad_defconfig
@@ -89,7 +89,6 @@
 # CONFIG_SA1100_COLLIE is not set
 # CONFIG_SA1100_H3100 is not set
 # CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
 # CONFIG_SA1100_BADGE4 is not set
 # CONFIG_SA1100_JORNADA720 is not set
 # CONFIG_SA1100_HACKKIT is not set
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 6cbd8fd..bb7d695 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -46,6 +46,14 @@
 # define MULTI_CACHE 1
 #endif
 
+#if defined(CONFIG_CPU_FA526)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE fa
+# endif
+#endif
+
 #if defined(CONFIG_CPU_ARM926T)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
@@ -94,6 +102,14 @@
 # endif
 #endif
 
+#if defined(CONFIG_CPU_MOHAWK)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE mohawk
+# endif
+#endif
+
 #if defined(CONFIG_CPU_FEROCEON)
 # define MULTI_CACHE 1
 #endif
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 22cb14e..ff46dfa 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -15,10 +15,20 @@
  * must not be used by drivers.
  */
 #ifndef __arch_page_to_dma
+
+#if !defined(CONFIG_HIGHMEM)
 static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
 {
 	return (dma_addr_t)__virt_to_bus((unsigned long)page_address(page));
 }
+#elif defined(__pfn_to_bus)
+static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+{
+	return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
+}
+#else
+#error "this machine class needs to define __arch_page_to_dma to use HIGHMEM"
+#endif
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
 {
@@ -57,6 +67,8 @@
  * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
  */
 extern void dma_cache_maint(const void *kaddr, size_t size, int rw);
+extern void dma_cache_maint_page(struct page *page, unsigned long offset,
+				 size_t size, int rw);
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -316,7 +328,7 @@
 	BUG_ON(!valid_dma_direction(dir));
 
 	if (!arch_is_coherent())
-		dma_cache_maint(page_address(page) + offset, size, dir);
+		dma_cache_maint_page(page, offset, size, dir);
 
 	return page_to_dma(dev, page) + offset;
 }
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index df5638f..7edf353 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -19,21 +19,17 @@
 #include <asm/system.h>
 #include <asm/scatterlist.h>
 
-typedef unsigned int dmach_t;
-
 #include <mach/isa-dma.h>
 
 /*
- * DMA modes
+ * The DMA modes reflect the settings for the ISA DMA controller
  */
-typedef unsigned int dmamode_t;
+#define DMA_MODE_MASK	 0xcc
 
-#define DMA_MODE_MASK	3
-
-#define DMA_MODE_READ	 0
-#define DMA_MODE_WRITE	 1
-#define DMA_MODE_CASCADE 2
-#define DMA_AUTOINIT	 4
+#define DMA_MODE_READ	 0x44
+#define DMA_MODE_WRITE	 0x48
+#define DMA_MODE_CASCADE 0xc0
+#define DMA_AUTOINIT	 0x10
 
 extern spinlock_t  dma_spin_lock;
 
@@ -52,44 +48,44 @@
 /* Clear the 'DMA Pointer Flip Flop'.
  * Write 0 for LSB/MSB, 1 for MSB/LSB access.
  */
-#define clear_dma_ff(channel)
+#define clear_dma_ff(chan)
 
 /* Set only the page register bits of the transfer address.
  *
  * NOTE: This is an architecture specific function, and should
  *       be hidden from the drivers
  */
-extern void set_dma_page(dmach_t channel, char pagenr);
+extern void set_dma_page(unsigned int chan, char pagenr);
 
 /* Request a DMA channel
  *
  * Some architectures may need to do allocate an interrupt
  */
-extern int  request_dma(dmach_t channel, const char * device_id);
+extern int  request_dma(unsigned int chan, const char * device_id);
 
 /* Free a DMA channel
  *
  * Some architectures may need to do free an interrupt
  */
-extern void free_dma(dmach_t channel);
+extern void free_dma(unsigned int chan);
 
 /* Enable DMA for this channel
  *
  * On some architectures, this may have other side effects like
  * enabling an interrupt and setting the DMA registers.
  */
-extern void enable_dma(dmach_t channel);
+extern void enable_dma(unsigned int chan);
 
 /* Disable DMA for this channel
  *
  * On some architectures, this may have other side effects like
  * disabling an interrupt or whatever.
  */
-extern void disable_dma(dmach_t channel);
+extern void disable_dma(unsigned int chan);
 
 /* Test whether the specified channel has an active DMA transfer
  */
-extern int dma_channel_active(dmach_t channel);
+extern int dma_channel_active(unsigned int chan);
 
 /* Set the DMA scatter gather list for this channel
  *
@@ -97,7 +93,7 @@
  * especially since some DMA architectures don't update the
  * DMA address immediately, but defer it to the enable_dma().
  */
-extern void set_dma_sg(dmach_t channel, struct scatterlist *sg, int nr_sg);
+extern void set_dma_sg(unsigned int chan, struct scatterlist *sg, int nr_sg);
 
 /* Set the DMA address for this channel
  *
@@ -105,9 +101,9 @@
  * especially since some DMA architectures don't update the
  * DMA address immediately, but defer it to the enable_dma().
  */
-extern void __set_dma_addr(dmach_t channel, void *addr);
-#define set_dma_addr(channel, addr)				\
-	__set_dma_addr(channel, bus_to_virt(addr))
+extern void __set_dma_addr(unsigned int chan, void *addr);
+#define set_dma_addr(chan, addr)				\
+	__set_dma_addr(chan, bus_to_virt(addr))
 
 /* Set the DMA byte count for this channel
  *
@@ -115,7 +111,7 @@
  * especially since some DMA architectures don't update the
  * DMA count immediately, but defer it to the enable_dma().
  */
-extern void set_dma_count(dmach_t channel, unsigned long count);
+extern void set_dma_count(unsigned int chan, unsigned long count);
 
 /* Set the transfer direction for this channel
  *
@@ -124,11 +120,11 @@
  * DMA transfer direction immediately, but defer it to the
  * enable_dma().
  */
-extern void set_dma_mode(dmach_t channel, dmamode_t mode);
+extern void set_dma_mode(unsigned int chan, unsigned int mode);
 
 /* Set the transfer speed for this channel
  */
-extern void set_dma_speed(dmach_t channel, int cycle_ns);
+extern void set_dma_speed(unsigned int chan, int cycle_ns);
 
 /* Get DMA residue count. After a DMA transfer, this
  * should return zero. Reading this while a DMA transfer is
@@ -136,7 +132,7 @@
  * If called before the channel has been used, it may return 1.
  * Otherwise, it returns the number of _bytes_ left to transfer.
  */
-extern int  get_dma_residue(dmach_t channel);
+extern int  get_dma_residue(unsigned int chan);
 
 #ifndef NO_DMA
 #define NO_DMA	255
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index a58378c..d7da19b 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -50,6 +50,8 @@
 #define R_ARM_ABS32	2
 #define R_ARM_CALL	28
 #define R_ARM_JUMP24	29
+#define R_ARM_V4BX	40
+#define R_ARM_PREL31	42
 
 /*
  * These are used to set parameters in the core dumps.
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
new file mode 100644
index 0000000..bbae919
--- /dev/null
+++ b/arch/arm/include/asm/fixmap.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+/*
+ * Nothing too fancy for now.
+ *
+ * On ARM we already have well known fixed virtual addresses imposed by
+ * the architecture such as the vector page which is located at 0xffff0000,
+ * therefore a second level page table is already allocated covering
+ * 0xfff00000 upwards.
+ *
+ * The cache flushing code in proc-xscale.S uses the virtual area between
+ * 0xfffe0000 and 0xfffeffff.
+ */
+
+#define FIXADDR_START		0xfff00000UL
+#define FIXADDR_TOP		0xfffe0000UL
+#define FIXADDR_SIZE		(FIXADDR_TOP - FIXADDR_START)
+
+#define FIX_KMAP_BEGIN		0
+#define FIX_KMAP_END		(FIXADDR_SIZE >> PAGE_SHIFT)
+
+#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);
+}
+
+#endif
diff --git a/arch/arm/include/asm/hardware/scoop.h b/arch/arm/include/asm/hardware/scoop.h
index dfb8330..46492a63 100644
--- a/arch/arm/include/asm/hardware/scoop.h
+++ b/arch/arm/include/asm/hardware/scoop.h
@@ -63,7 +63,5 @@
 extern struct scoop_pcmcia_config *platform_scoop_config;
 
 void reset_scoop(struct device *dev);
-unsigned short __deprecated set_scoop_gpio(struct device *dev, unsigned short bit);
-unsigned short __deprecated reset_scoop_gpio(struct device *dev, unsigned short bit);
 unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
 void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
new file mode 100644
index 0000000..7f36d00
--- /dev/null
+++ b/arch/arm/include/asm/highmem.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#include <asm/kmap_types.h>
+
+#define PKMAP_BASE		(PAGE_OFFSET - PMD_SIZE)
+#define LAST_PKMAP		PTRS_PER_PTE
+#define LAST_PKMAP_MASK		(LAST_PKMAP - 1)
+#define PKMAP_NR(virt)		(((virt) - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)		(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define kmap_prot		PAGE_KERNEL
+
+#define flush_cache_kmaps()	flush_cache_all()
+
+extern pte_t *pkmap_page_table;
+
+#define ARCH_NEEDS_KMAP_HIGH_GET
+
+extern void *kmap_high(struct page *page);
+extern void *kmap_high_get(struct page *page);
+extern void kunmap_high(struct page *page);
+
+extern void *kmap(struct page *page);
+extern void kunmap(struct page *page);
+extern void *kmap_atomic(struct page *page, enum km_type type);
+extern void kunmap_atomic(void *kvaddr, enum km_type type);
+extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+extern struct page *kmap_atomic_to_page(const void *ptr);
+
+#endif
diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h
index bda489f..f7bd52b 100644
--- a/arch/arm/include/asm/hwcap.h
+++ b/arch/arm/include/asm/hwcap.h
@@ -17,6 +17,8 @@
 #define HWCAP_CRUNCH	1024
 #define HWCAP_THUMBEE	2048
 #define HWCAP_NEON	4096
+#define HWCAP_VFPv3	8192
+#define HWCAP_VFPv3D16	16384
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 /*
diff --git a/arch/arm/include/asm/kmap_types.h b/arch/arm/include/asm/kmap_types.h
index 45def13..d16ec97 100644
--- a/arch/arm/include/asm/kmap_types.h
+++ b/arch/arm/include/asm/kmap_types.h
@@ -18,6 +18,7 @@
 	KM_IRQ1,
 	KM_SOFTIRQ0,
 	KM_SOFTIRQ1,
+	KM_L2_CACHE,
 	KM_TYPE_NR
 };
 
diff --git a/arch/arm/include/asm/mach/dma.h b/arch/arm/include/asm/mach/dma.h
index fc7278e..9e614a1 100644
--- a/arch/arm/include/asm/mach/dma.h
+++ b/arch/arm/include/asm/mach/dma.h
@@ -15,13 +15,13 @@
 typedef struct dma_struct dma_t;
 
 struct dma_ops {
-	int	(*request)(dmach_t, dma_t *);		/* optional */
-	void	(*free)(dmach_t, dma_t *);		/* optional */
-	void	(*enable)(dmach_t, dma_t *);		/* mandatory */
-	void 	(*disable)(dmach_t, dma_t *);		/* mandatory */
-	int	(*residue)(dmach_t, dma_t *);		/* optional */
-	int	(*setspeed)(dmach_t, dma_t *, int);	/* optional */
-	char	*type;
+	int	(*request)(unsigned int, dma_t *);		/* optional */
+	void	(*free)(unsigned int, dma_t *);			/* optional */
+	void	(*enable)(unsigned int, dma_t *);		/* mandatory */
+	void 	(*disable)(unsigned int, dma_t *);		/* mandatory */
+	int	(*residue)(unsigned int, dma_t *);		/* optional */
+	int	(*setspeed)(unsigned int, dma_t *, int);	/* optional */
+	const char *type;
 };
 
 struct dma_struct {
@@ -34,24 +34,21 @@
 	unsigned int	active:1;	/* Transfer active		*/
 	unsigned int	invalid:1;	/* Address/Count changed	*/
 
-	dmamode_t	dma_mode;	/* DMA mode			*/
+	unsigned int	dma_mode;	/* DMA mode			*/
 	int		speed;		/* DMA speed			*/
 
 	unsigned int	lock;		/* Device is allocated		*/
 	const char	*device_id;	/* Device name			*/
 
-	unsigned int	dma_base;	/* Controller base address	*/
-	int		dma_irq;	/* Controller IRQ		*/
-	struct scatterlist cur_sg;	/* Current controller buffer	*/
-	unsigned int	state;
-
-	struct dma_ops	*d_ops;
+	const struct dma_ops *d_ops;
 };
 
-/* Prototype: void arch_dma_init(dma)
- * Purpose  : Initialise architecture specific DMA
- * Params   : dma - pointer to array of DMA structures
+/*
+ * isa_dma_add - add an ISA-style DMA channel
  */
-extern void arch_dma_init(dma_t *dma);
+extern int isa_dma_add(unsigned int, dma_t *dma);
 
-extern void isa_init_dma(dma_t *dma);
+/*
+ * Add the ISA DMA controller.  Always takes channels 0-7.
+ */
+extern void isa_init_dma(void);
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index 39d949b..58cf91f 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -26,6 +26,7 @@
 #define MT_HIGH_VECTORS		8
 #define MT_MEMORY		9
 #define MT_ROM			10
+#define MT_MEMORY_NONCACHED	11
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 0202a7c..85763db 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -44,14 +44,21 @@
  * The module space lives between the addresses given by TASK_SIZE
  * and PAGE_OFFSET - it must be within 32MB of the kernel text.
  */
-#define MODULES_END		(PAGE_OFFSET)
-#define MODULES_VADDR		(MODULES_END - 16*1048576)
-
+#define MODULES_VADDR		(PAGE_OFFSET - 16*1024*1024)
 #if TASK_SIZE > MODULES_VADDR
 #error Top of user space clashes with start of module space
 #endif
 
 /*
+ * The highmem pkmap virtual space shares the end of the module area.
+ */
+#ifdef CONFIG_HIGHMEM
+#define MODULES_END		(PAGE_OFFSET - PMD_SIZE)
+#else
+#define MODULES_END		(PAGE_OFFSET)
+#endif
+
+/*
  * The XIP kernel gets mapped at the bottom of the module vm area.
  * Since we use sections to map it, this macro replaces the physical address
  * with its virtual address while keeping offset from the base section.
@@ -181,6 +188,7 @@
 #ifndef __virt_to_bus
 #define __virt_to_bus	__virt_to_phys
 #define __bus_to_virt	__phys_to_virt
+#define __pfn_to_bus(x)	((x) << PAGE_SHIFT)
 #endif
 
 static inline __deprecated unsigned long virt_to_bus(void *x)
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 24b168d..e4dfa69 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -1,15 +1,27 @@
 #ifndef _ASM_ARM_MODULE_H
 #define _ASM_ARM_MODULE_H
 
-struct mod_arch_specific
-{
-	int foo;
-};
-
 #define Elf_Shdr	Elf32_Shdr
 #define Elf_Sym		Elf32_Sym
 #define Elf_Ehdr	Elf32_Ehdr
 
+struct unwind_table;
+
+struct mod_arch_specific
+{
+#ifdef CONFIG_ARM_UNWIND
+	Elf_Shdr *unw_sec_init;
+	Elf_Shdr *unw_sec_devinit;
+	Elf_Shdr *unw_sec_core;
+	Elf_Shdr *sec_init_text;
+	Elf_Shdr *sec_devinit_text;
+	Elf_Shdr *sec_core_text;
+	struct unwind_table *unwind_init;
+	struct unwind_table *unwind_devinit;
+	struct unwind_table *unwind_core;
+#endif
+};
+
 /*
  * Include the ARM architecture version.
  */
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index f341c9d..e6eb8a6 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -76,6 +76,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_COPY_FA
+# ifdef _USER
+#  define MULTI_USER 1
+# else
+#  define _USER fa
+# endif
+#endif
+
 #ifdef CONFIG_CPU_SA1100
 # ifdef _USER
 #  define MULTI_USER 1
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index db80203..3976412 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -89,6 +89,14 @@
 #   define CPU_NAME cpu_arm922
 #  endif
 # endif
+# ifdef CONFIG_CPU_FA526
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_fa526
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM925T
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
@@ -185,6 +193,14 @@
 #   define CPU_NAME cpu_xsc3
 #  endif
 # endif
+# ifdef CONFIG_CPU_MOHAWK
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_mohawk
+#  endif
+# endif
 # ifdef CONFIG_CPU_FEROCEON
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 7319261..236a06b 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -27,6 +27,8 @@
 /* PTRACE_SYSCALL is 24 */
 #define PTRACE_GETCRUNCHREGS	25
 #define PTRACE_SETCRUNCHREGS	26
+#define PTRACE_GETVFPREGS	27
+#define PTRACE_SETVFPREGS	28
 
 /*
  * PSR bits
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h
index 503843d..c10d1aa 100644
--- a/arch/arm/include/asm/sizes.h
+++ b/arch/arm/include/asm/sizes.h
@@ -43,6 +43,7 @@
 #define SZ_8M                           0x00800000
 #define SZ_16M                          0x01000000
 #define SZ_32M                          0x02000000
+#define SZ_48M                          0x03000000
 #define SZ_64M                          0x04000000
 #define SZ_128M                         0x08000000
 #define SZ_256M                         0x10000000
diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h
new file mode 100644
index 0000000..4d0a164
--- /dev/null
+++ b/arch/arm/include/asm/stacktrace.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_STACKTRACE_H
+#define __ASM_STACKTRACE_H
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long sp;
+	unsigned long lr;
+	unsigned long pc;
+};
+
+extern int unwind_frame(struct stackframe *frame);
+extern void walk_stackframe(struct stackframe *frame,
+			    int (*fn)(struct stackframe *, void *), void *data);
+
+#endif	/* __ASM_STACKTRACE_H */
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 811be55..bd4dc8e 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -97,8 +97,8 @@
 extern int cpu_architecture(void);
 extern void cpu_init(void);
 
-void arm_machine_restart(char mode);
-extern void (*arm_pm_restart)(char str);
+void arm_machine_restart(char mode, const char *cmd);
+extern void (*arm_pm_restart)(char str, const char *cmd);
 
 #define UDBG_UNDEFINED	(1 << 0)
 #define UDBG_SYSCALL	(1 << 1)
@@ -125,6 +125,12 @@
 				    : : "r" (0) : "memory")
 #define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
 				    : : "r" (0) : "memory")
+#elif defined(CONFIG_CPU_FA526)
+#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
+				    : : "r" (0) : "memory")
+#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
+				    : : "r" (0) : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
 #else
 #define isb() __asm__ __volatile__ ("" : : : "memory")
 #define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 68b9ec8..4f88482 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -99,6 +99,8 @@
 
 #define thread_saved_pc(tsk)	\
 	((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
+#define thread_saved_sp(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.sp))
 #define thread_saved_fp(tsk)	\
 	((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
 
@@ -113,6 +115,8 @@
 extern void iwmmxt_task_release(struct thread_info *);
 extern void iwmmxt_task_switch(struct thread_info *);
 
+extern void vfp_sync_state(struct thread_info *thread);
+
 #endif
 
 /*
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index b543a05..a622180 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -39,6 +39,7 @@
 #define TLB_V6_D_ASID	(1 << 17)
 #define TLB_V6_I_ASID	(1 << 18)
 
+#define TLB_BTB		(1 << 28)
 #define TLB_L2CLEAN_FR	(1 << 29)		/* Feroceon */
 #define TLB_DCLEAN	(1 << 30)
 #define TLB_WB		(1 << 31)
@@ -53,6 +54,7 @@
  *	  v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
  *	  v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
  *	  fr    - Feroceon (v4wbi with non-outer-cacheable page table walks)
+ *	  fa    - Faraday (v4 with write buffer with UTLB and branch target buffer (BTB))
  *	  v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
  *	  v7wbi - identical to v6wbi
  */
@@ -89,6 +91,22 @@
 # define v4_always_flags	(-1UL)
 #endif
 
+#define fa_tlb_flags	(TLB_WB | TLB_BTB | TLB_DCLEAN | \
+			 TLB_V4_U_FULL | TLB_V4_U_PAGE)
+
+#ifdef CONFIG_CPU_TLB_FA
+# define fa_possible_flags	fa_tlb_flags
+# define fa_always_flags	fa_tlb_flags
+# ifdef _TLB
+#  define MULTI_TLB 1
+# else
+#  define _TLB fa
+# endif
+#else
+# define fa_possible_flags	0
+# define fa_always_flags	(-1UL)
+#endif
+
 #define v4wbi_tlb_flags	(TLB_WB | TLB_DCLEAN | \
 			 TLB_V4_I_FULL | TLB_V4_D_FULL | \
 			 TLB_V4_I_PAGE | TLB_V4_D_PAGE)
@@ -140,7 +158,7 @@
 # define v4wb_always_flags	(-1UL)
 #endif
 
-#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \
+#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
 			 TLB_V6_I_FULL | TLB_V6_D_FULL | \
 			 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
 			 TLB_V6_I_ASID | TLB_V6_D_ASID)
@@ -267,6 +285,7 @@
 				 v4wbi_possible_flags | \
 				 fr_possible_flags | \
 				 v4wb_possible_flags | \
+				 fa_possible_flags | \
 				 v6wbi_possible_flags | \
 				 v7wbi_possible_flags)
 
@@ -275,6 +294,7 @@
 				 v4wbi_always_flags & \
 				 fr_always_flags & \
 				 v4wb_always_flags & \
+				 fa_always_flags & \
 				 v6wbi_always_flags & \
 				 v7wbi_always_flags)
 
@@ -297,9 +317,7 @@
 	if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
 		asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 
-	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
-		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
-		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
@@ -334,9 +352,7 @@
 	if (tlb_flag(TLB_V6_I_ASID))
 		asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
 
-	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
-		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
-		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
@@ -374,9 +390,7 @@
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
 
-	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
-		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
-		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
@@ -411,9 +425,7 @@
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
 
-	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
-		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
-		     TLB_V6_I_ASID | TLB_V6_D_ASID)) {
+	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index aa399ae..491960b 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -25,5 +25,6 @@
 }
 
 extern void __init early_trap_init(void);
+extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 
 #endif
diff --git a/arch/arm/include/asm/unwind.h b/arch/arm/include/asm/unwind.h
new file mode 100644
index 0000000..a5edf42
--- /dev/null
+++ b/arch/arm/include/asm/unwind.h
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/include/asm/unwind.h
+ *
+ * Copyright (C) 2008 ARM Limited
+ *
+ * This program is free software; you can 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 __ASM_UNWIND_H
+#define __ASM_UNWIND_H
+
+#ifndef __ASSEMBLY__
+
+/* Unwind reason code according the the ARM EABI documents */
+enum unwind_reason_code {
+	URC_OK = 0,			/* operation completed successfully */
+	URC_CONTINUE_UNWIND = 8,
+	URC_FAILURE = 9			/* unspecified failure of some kind */
+};
+
+struct unwind_idx {
+	unsigned long addr;
+	unsigned long insn;
+};
+
+struct unwind_table {
+	struct list_head list;
+	struct unwind_idx *start;
+	struct unwind_idx *stop;
+	unsigned long begin_addr;
+	unsigned long end_addr;
+};
+
+extern struct unwind_table *unwind_table_add(unsigned long start,
+					     unsigned long size,
+					     unsigned long text_addr,
+					     unsigned long text_size);
+extern void unwind_table_del(struct unwind_table *tab);
+extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk);
+
+#ifdef CONFIG_ARM_UNWIND
+extern int __init unwind_init(void);
+#else
+static inline int __init unwind_init(void)
+{
+	return 0;
+}
+#endif
+
+#endif	/* !__ASSEMBLY__ */
+
+#ifdef CONFIG_ARM_UNWIND
+#define UNWIND(code...)		code
+#else
+#define UNWIND(code...)
+#endif
+
+#endif	/* __ASM_UNWIND_H */
diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h
index 825c1e7..df95e05 100644
--- a/arch/arm/include/asm/user.h
+++ b/arch/arm/include/asm/user.h
@@ -81,4 +81,13 @@
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
 
+/*
+ * User specific VFP registers. If only VFPv2 is present, registers 16 to 31
+ * are ignored by the ptrace system call.
+ */
+struct user_vfp {
+	unsigned long long fpregs[32];
+	unsigned long fpscr;
+};
+
 #endif /* _ARM_USER_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 4305345..11a5197 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,12 +29,14 @@
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
+obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
 
 obj-$(CONFIG_CPU_XSCALE)	+= xscale-cp0.o
 obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
+obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index f53c582..b121b60 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -49,6 +49,33 @@
 1002:
 		.endm
 
+#elif defined(CONFIG_CPU_XSCALE)
+
+		.macro	addruart, rx
+		.endm
+
+		.macro	senduart, rd, rx
+		mcr	p14, 0, \rd, c8, c0, 0
+		.endm
+
+		.macro	busyuart, rd, rx
+1001:
+		mrc	p14, 0, \rx, c14, c0, 0
+		tst	\rx, #0x10000000
+		beq	1001b
+		.endm
+
+		.macro	waituart, rd, rx
+		mov	\rd, #0x10000000
+1001:
+		subs	\rd, \rd, #1
+		bmi	1002f
+		mrc	p14, 0, \rx, c14, c0, 0
+		tst	\rx, #0x10000000
+		bne	1001b
+1002:
+		.endm
+
 #else
 
 		.macro	addruart, rx
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index 4a3a504..0e88e46 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -24,11 +24,6 @@
 #include <asm/dma.h>
 #include <asm/mach/dma.h>
 
-#define ISA_DMA_MODE_READ	0x44
-#define ISA_DMA_MODE_WRITE	0x48
-#define ISA_DMA_MODE_CASCADE	0xc0
-#define ISA_DMA_AUTOINIT	0x10
-
 #define ISA_DMA_MASK		0
 #define ISA_DMA_MODE		1
 #define ISA_DMA_CLRFF		2
@@ -49,38 +44,35 @@
 	{  0xd4,  0xd6,  0xd8,  0x48a,  0x08a,  0xcc, 0xce }
 };
 
-static int isa_get_dma_residue(dmach_t channel, dma_t *dma)
+static int isa_get_dma_residue(unsigned int chan, dma_t *dma)
 {
-	unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
+	unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT];
 	int count;
 
 	count = 1 + inb(io_port);
 	count |= inb(io_port) << 8;
 
-	return channel < 4 ? count : (count << 1);
+	return chan < 4 ? count : (count << 1);
 }
 
-static void isa_enable_dma(dmach_t channel, dma_t *dma)
+static void isa_enable_dma(unsigned int chan, dma_t *dma)
 {
 	if (dma->invalid) {
 		unsigned long address, length;
 		unsigned int mode;
 		enum dma_data_direction direction;
 
-		mode = channel & 3;
+		mode = (chan & 3) | dma->dma_mode;
 		switch (dma->dma_mode & DMA_MODE_MASK) {
 		case DMA_MODE_READ:
-			mode |= ISA_DMA_MODE_READ;
 			direction = DMA_FROM_DEVICE;
 			break;
 
 		case DMA_MODE_WRITE:
-			mode |= ISA_DMA_MODE_WRITE;
 			direction = DMA_TO_DEVICE;
 			break;
 
 		case DMA_MODE_CASCADE:
-			mode |= ISA_DMA_MODE_CASCADE;
 			direction = DMA_BIDIRECTIONAL;
 			break;
 
@@ -105,34 +97,31 @@
 		address = dma->buf.dma_address;
 		length  = dma->buf.length - 1;
 
-		outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]);
-		outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
+		outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]);
+		outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]);
 
-		if (channel >= 4) {
+		if (chan >= 4) {
 			address >>= 1;
 			length >>= 1;
 		}
 
-		outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]);
+		outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]);
 
-		outb(address, isa_dma_port[channel][ISA_DMA_ADDR]);
-		outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]);
+		outb(address, isa_dma_port[chan][ISA_DMA_ADDR]);
+		outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]);
 
-		outb(length, isa_dma_port[channel][ISA_DMA_COUNT]);
-		outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]);
+		outb(length, isa_dma_port[chan][ISA_DMA_COUNT]);
+		outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]);
 
-		if (dma->dma_mode & DMA_AUTOINIT)
-			mode |= ISA_DMA_AUTOINIT;
-
-		outb(mode, isa_dma_port[channel][ISA_DMA_MODE]);
+		outb(mode, isa_dma_port[chan][ISA_DMA_MODE]);
 		dma->invalid = 0;
 	}
-	outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
+	outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]);
 }
 
-static void isa_disable_dma(dmach_t channel, dma_t *dma)
+static void isa_disable_dma(unsigned int chan, dma_t *dma)
 {
-	outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
+	outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]);
 }
 
 static struct dma_ops isa_dma_ops = {
@@ -160,7 +149,12 @@
 	.end	= 0x048f
 } };
 
-void __init isa_init_dma(dma_t *dma)
+static dma_t isa_dma[8];
+
+/*
+ * ISA DMA always starts at channel 0
+ */
+void __init isa_init_dma(void)
 {
 	/*
 	 * Try to autodetect presence of an ISA DMA controller.
@@ -178,11 +172,11 @@
 	outb(0xaa, 0x00);
 
 	if (inb(0) == 0x55 && inb(0) == 0xaa) {
-		int channel, i;
+		unsigned int chan, i;
 
-		for (channel = 0; channel < 8; channel++) {
-			dma[channel].d_ops = &isa_dma_ops;
-			isa_disable_dma(channel, NULL);
+		for (chan = 0; chan < 8; chan++) {
+			isa_dma[chan].d_ops = &isa_dma_ops;
+			isa_disable_dma(chan, NULL);
 		}
 
 		outb(0x40, 0x0b);
@@ -217,5 +211,12 @@
 
 		for (i = 0; i < ARRAY_SIZE(dma_resources); i++)
 			request_resource(&ioport_resource, dma_resources + i);
+
+		for (chan = 0; chan < 8; chan++) {
+			int ret = isa_dma_add(chan, &isa_dma[chan]);
+			if (ret)
+				printk(KERN_ERR "ISADMA%u: unable to register: %d\n",
+					chan, ret);
+		}
 	}
 }
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index d006085..7d5b9fb 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/scatterlist.h>
 
 #include <asm/dma.h>
 
@@ -23,19 +24,40 @@
 DEFINE_SPINLOCK(dma_spin_lock);
 EXPORT_SYMBOL(dma_spin_lock);
 
-static dma_t dma_chan[MAX_DMA_CHANNELS];
+static dma_t *dma_chan[MAX_DMA_CHANNELS];
+
+static inline dma_t *dma_channel(unsigned int chan)
+{
+	if (chan >= MAX_DMA_CHANNELS)
+		return NULL;
+
+	return dma_chan[chan];
+}
+
+int __init isa_dma_add(unsigned int chan, dma_t *dma)
+{
+	if (!dma->d_ops)
+		return -EINVAL;
+
+	sg_init_table(&dma->buf, 1);
+
+	if (dma_chan[chan])
+		return -EBUSY;
+	dma_chan[chan] = dma;
+	return 0;
+}
 
 /*
  * Request DMA channel
  *
  * On certain platforms, we have to allocate an interrupt as well...
  */
-int request_dma(dmach_t channel, const char *device_id)
+int request_dma(unsigned int chan, const char *device_id)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 	int ret;
 
-	if (channel >= MAX_DMA_CHANNELS || !dma->d_ops)
+	if (!dma)
 		goto bad_dma;
 
 	if (xchg(&dma->lock, 1) != 0)
@@ -47,7 +69,7 @@
 
 	ret = 0;
 	if (dma->d_ops->request)
-		ret = dma->d_ops->request(channel, dma);
+		ret = dma->d_ops->request(chan, dma);
 
 	if (ret)
 		xchg(&dma->lock, 0);
@@ -55,7 +77,7 @@
 	return ret;
 
 bad_dma:
-	printk(KERN_ERR "dma: trying to allocate DMA%d\n", channel);
+	printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan);
 	return -EINVAL;
 
 busy:
@@ -68,42 +90,42 @@
  *
  * On certain platforms, we have to free interrupt as well...
  */
-void free_dma(dmach_t channel)
+void free_dma(unsigned int chan)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
-	if (channel >= MAX_DMA_CHANNELS || !dma->d_ops)
+	if (!dma)
 		goto bad_dma;
 
 	if (dma->active) {
-		printk(KERN_ERR "dma%d: freeing active DMA\n", channel);
-		dma->d_ops->disable(channel, dma);
+		printk(KERN_ERR "dma%d: freeing active DMA\n", chan);
+		dma->d_ops->disable(chan, dma);
 		dma->active = 0;
 	}
 
 	if (xchg(&dma->lock, 0) != 0) {
 		if (dma->d_ops->free)
-			dma->d_ops->free(channel, dma);
+			dma->d_ops->free(chan, dma);
 		return;
 	}
 
-	printk(KERN_ERR "dma%d: trying to free free DMA\n", channel);
+	printk(KERN_ERR "dma%d: trying to free free DMA\n", chan);
 	return;
 
 bad_dma:
-	printk(KERN_ERR "dma: trying to free DMA%d\n", channel);
+	printk(KERN_ERR "dma: trying to free DMA%d\n", chan);
 }
 EXPORT_SYMBOL(free_dma);
 
 /* Set DMA Scatter-Gather list
  */
-void set_dma_sg (dmach_t channel, struct scatterlist *sg, int nr_sg)
+void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (dma->active)
 		printk(KERN_ERR "dma%d: altering DMA SG while "
-		       "DMA active\n", channel);
+		       "DMA active\n", chan);
 
 	dma->sg = sg;
 	dma->sgcount = nr_sg;
@@ -115,13 +137,13 @@
  *
  * Copy address to the structure, and set the invalid bit
  */
-void __set_dma_addr (dmach_t channel, void *addr)
+void __set_dma_addr (unsigned int chan, void *addr)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (dma->active)
 		printk(KERN_ERR "dma%d: altering DMA address while "
-		       "DMA active\n", channel);
+		       "DMA active\n", chan);
 
 	dma->sg = NULL;
 	dma->addr = addr;
@@ -133,13 +155,13 @@
  *
  * Copy address to the structure, and set the invalid bit
  */
-void set_dma_count (dmach_t channel, unsigned long count)
+void set_dma_count (unsigned int chan, unsigned long count)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (dma->active)
 		printk(KERN_ERR "dma%d: altering DMA count while "
-		       "DMA active\n", channel);
+		       "DMA active\n", chan);
 
 	dma->sg = NULL;
 	dma->count = count;
@@ -149,13 +171,13 @@
 
 /* Set DMA direction mode
  */
-void set_dma_mode (dmach_t channel, dmamode_t mode)
+void set_dma_mode (unsigned int chan, unsigned int mode)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (dma->active)
 		printk(KERN_ERR "dma%d: altering DMA mode while "
-		       "DMA active\n", channel);
+		       "DMA active\n", chan);
 
 	dma->dma_mode = mode;
 	dma->invalid = 1;
@@ -164,42 +186,42 @@
 
 /* Enable DMA channel
  */
-void enable_dma (dmach_t channel)
+void enable_dma (unsigned int chan)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (!dma->lock)
 		goto free_dma;
 
 	if (dma->active == 0) {
 		dma->active = 1;
-		dma->d_ops->enable(channel, dma);
+		dma->d_ops->enable(chan, dma);
 	}
 	return;
 
 free_dma:
-	printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel);
+	printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan);
 	BUG();
 }
 EXPORT_SYMBOL(enable_dma);
 
 /* Disable DMA channel
  */
-void disable_dma (dmach_t channel)
+void disable_dma (unsigned int chan)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 
 	if (!dma->lock)
 		goto free_dma;
 
 	if (dma->active == 1) {
 		dma->active = 0;
-		dma->d_ops->disable(channel, dma);
+		dma->d_ops->disable(chan, dma);
 	}
 	return;
 
 free_dma:
-	printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel);
+	printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan);
 	BUG();
 }
 EXPORT_SYMBOL(disable_dma);
@@ -207,45 +229,38 @@
 /*
  * Is the specified DMA channel active?
  */
-int dma_channel_active(dmach_t channel)
+int dma_channel_active(unsigned int chan)
 {
-	return dma_chan[channel].active;
+	dma_t *dma = dma_channel(chan);
+	return dma->active;
 }
 EXPORT_SYMBOL(dma_channel_active);
 
-void set_dma_page(dmach_t channel, char pagenr)
+void set_dma_page(unsigned int chan, char pagenr)
 {
-	printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel);
+	printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan);
 }
 EXPORT_SYMBOL(set_dma_page);
 
-void set_dma_speed(dmach_t channel, int cycle_ns)
+void set_dma_speed(unsigned int chan, int cycle_ns)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 	int ret = 0;
 
 	if (dma->d_ops->setspeed)
-		ret = dma->d_ops->setspeed(channel, dma, cycle_ns);
+		ret = dma->d_ops->setspeed(chan, dma, cycle_ns);
 	dma->speed = ret;
 }
 EXPORT_SYMBOL(set_dma_speed);
 
-int get_dma_residue(dmach_t channel)
+int get_dma_residue(unsigned int chan)
 {
-	dma_t *dma = dma_chan + channel;
+	dma_t *dma = dma_channel(chan);
 	int ret = 0;
 
 	if (dma->d_ops->residue)
-		ret = dma->d_ops->residue(channel, dma);
+		ret = dma->d_ops->residue(chan, dma);
 
 	return ret;
 }
 EXPORT_SYMBOL(get_dma_residue);
-
-static int __init init_dma(void)
-{
-	arch_dma_init(dma_chan);
-	return 0;
-}
-
-core_initcall(init_dma);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 85040cf..d662a2f 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -20,6 +20,7 @@
 #include <asm/vfpmacros.h>
 #include <mach/entry-macro.S>
 #include <asm/thread_notify.h>
+#include <asm/unwind.h>
 
 #include "entry-header.S"
 
@@ -123,6 +124,8 @@
 #endif
 
 	.macro	svc_entry, stack_hole=0
+ UNWIND(.fnstart		)
+ UNWIND(.save {r0 - pc}		)
 	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole)
  SPFIX(	tst	sp, #4		)
  SPFIX(	bicne	sp, sp, #4	)
@@ -196,6 +199,7 @@
 	ldr	r0, [sp, #S_PSR]
 	msr	spsr_cxsf, r0
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ UNWIND(.fnend		)
 ENDPROC(__dabt_svc)
 
 	.align	5
@@ -228,6 +232,7 @@
 	bleq	trace_hardirqs_on
 #endif
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ UNWIND(.fnend		)
 ENDPROC(__irq_svc)
 
 	.ltorg
@@ -278,6 +283,7 @@
 	ldr	lr, [sp, #S_PSR]		@ Get SVC cpsr
 	msr	spsr_cxsf, lr
 	ldmia	sp, {r0 - pc}^			@ Restore SVC registers
+ UNWIND(.fnend		)
 ENDPROC(__und_svc)
 
 	.align	5
@@ -320,6 +326,7 @@
 	ldr	r0, [sp, #S_PSR]
 	msr	spsr_cxsf, r0
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ UNWIND(.fnend		)
 ENDPROC(__pabt_svc)
 
 	.align	5
@@ -343,6 +350,8 @@
 #endif
 
 	.macro	usr_entry
+ UNWIND(.fnstart	)
+ UNWIND(.cantunwind	)	@ don't unwind the user space
 	sub	sp, sp, #S_FRAME_SIZE
 	stmib	sp, {r1 - r12}
 
@@ -420,6 +429,7 @@
 	mov	r2, sp
 	adr	lr, ret_from_exception
 	b	do_DataAbort
+ UNWIND(.fnend		)
 ENDPROC(__dabt_usr)
 
 	.align	5
@@ -450,6 +460,7 @@
 
 	mov	why, #0
 	b	ret_to_user
+ UNWIND(.fnend		)
 ENDPROC(__irq_usr)
 
 	.ltorg
@@ -484,6 +495,7 @@
 #else
 	b	__und_usr_unknown
 #endif
+ UNWIND(.fnend		)
 ENDPROC(__und_usr)
 
 	@
@@ -671,14 +683,18 @@
 	enable_irq				@ Enable interrupts
 	mov	r1, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
+ UNWIND(.fnend		)
 	/* fall through */
 /*
  * This is the return code to user mode for abort handlers
  */
 ENTRY(ret_from_exception)
+ UNWIND(.fnstart	)
+ UNWIND(.cantunwind	)
 	get_thread_info tsk
 	mov	why, #0
 	b	ret_to_user
+ UNWIND(.fnend		)
 ENDPROC(__pabt_usr)
 ENDPROC(ret_from_exception)
 
@@ -688,6 +704,8 @@
  * previous and next are guaranteed not to be the same.
  */
 ENTRY(__switch_to)
+ UNWIND(.fnstart	)
+ UNWIND(.cantunwind	)
 	add	ip, r1, #TI_CPU_SAVE
 	ldr	r3, [r2, #TI_TP_VALUE]
 	stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
@@ -717,6 +735,7 @@
 	bl	atomic_notifier_call_chain
 	mov	r0, r5
 	ldmia	r4, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
+ UNWIND(.fnend		)
 ENDPROC(__switch_to)
 
 	__INIT
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 159d041..b55cb03 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -11,6 +11,7 @@
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
 #include <mach/entry-macro.S>
+#include <asm/unwind.h>
 
 #include "entry-header.S"
 
@@ -22,6 +23,8 @@
  * stack.
  */
 ret_fast_syscall:
+ UNWIND(.fnstart	)
+ UNWIND(.cantunwind	)
 	disable_irq				@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
@@ -38,6 +41,7 @@
 	mov	r0, r0
 	add	sp, sp, #S_FRAME_SIZE - S_PC
 	movs	pc, lr				@ return & move spsr_svc into cpsr
+ UNWIND(.fnend		)
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index dab48f2..d1731e3 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -22,6 +22,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/sections.h>
+#include <asm/unwind.h>
 
 #ifdef CONFIG_XIP_KERNEL
 /*
@@ -66,6 +67,24 @@
 			      char *secstrings,
 			      struct module *mod)
 {
+#ifdef CONFIG_ARM_UNWIND
+	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+
+	for (s = sechdrs; s < sechdrs_end; s++) {
+		if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_init = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_devinit = s;
+		else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_core = s;
+		else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_init_text = s;
+		else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_devinit_text = s;
+		else if (strcmp(".text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_core_text = s;
+	}
+#endif
 	return 0;
 }
 
@@ -104,6 +123,10 @@
 		loc = dstsec->sh_addr + rel->r_offset;
 
 		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_ARM_NONE:
+			/* ignore */
+			break;
+
 		case R_ARM_ABS32:
 			*(u32 *)loc += sym->st_value;
 			break;
@@ -132,6 +155,20 @@
 			*(u32 *)loc |= offset & 0x00ffffff;
 			break;
 
+	       case R_ARM_V4BX:
+		       /* Preserve Rm and the condition code. Alter
+			* other bits to re-code instruction as
+			* MOV PC,Rm.
+			*/
+		       *(u32 *)loc &= 0xf000000f;
+		       *(u32 *)loc |= 0x01a0f000;
+		       break;
+
+		case R_ARM_PREL31:
+			offset = *(u32 *)loc + sym->st_value - loc;
+			*(u32 *)loc = offset & 0x7fffffff;
+			break;
+
 		default:
 			printk(KERN_ERR "%s: unknown relocation: %u\n",
 			       module->name, ELF32_R_TYPE(rel->r_info));
@@ -150,14 +187,50 @@
 	return -ENOEXEC;
 }
 
+#ifdef CONFIG_ARM_UNWIND
+static void register_unwind_tables(struct module *mod)
+{
+	if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
+		mod->arch.unwind_init =
+			unwind_table_add(mod->arch.unw_sec_init->sh_addr,
+					 mod->arch.unw_sec_init->sh_size,
+					 mod->arch.sec_init_text->sh_addr,
+					 mod->arch.sec_init_text->sh_size);
+	if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
+		mod->arch.unwind_devinit =
+			unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
+					 mod->arch.unw_sec_devinit->sh_size,
+					 mod->arch.sec_devinit_text->sh_addr,
+					 mod->arch.sec_devinit_text->sh_size);
+	if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
+		mod->arch.unwind_core =
+			unwind_table_add(mod->arch.unw_sec_core->sh_addr,
+					 mod->arch.unw_sec_core->sh_size,
+					 mod->arch.sec_core_text->sh_addr,
+					 mod->arch.sec_core_text->sh_size);
+}
+
+static void unregister_unwind_tables(struct module *mod)
+{
+	unwind_table_del(mod->arch.unwind_init);
+	unwind_table_del(mod->arch.unwind_devinit);
+	unwind_table_del(mod->arch.unwind_core);
+}
+#else
+static inline void register_unwind_tables(struct module *mod) { }
+static inline void unregister_unwind_tables(struct module *mod) { }
+#endif
+
 int
 module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		struct module *module)
 {
+	register_unwind_tables(module);
 	return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
+	unregister_unwind_tables(mod);
 }
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index d3ea6fa..2de14e2 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -34,6 +34,7 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/thread_notify.h>
+#include <asm/stacktrace.h>
 #include <asm/mach/time.h>
 
 static const char *processor_modes[] = {
@@ -82,7 +83,7 @@
 __setup("nohlt", nohlt_setup);
 __setup("hlt", hlt_setup);
 
-void arm_machine_restart(char mode)
+void arm_machine_restart(char mode, const char *cmd)
 {
 	/*
 	 * Clean and disable cache, and turn off interrupts
@@ -99,7 +100,7 @@
 	/*
 	 * Now call the architecture specific reboot code.
 	 */
-	arch_reset(mode);
+	arch_reset(mode, cmd);
 
 	/*
 	 * Whoops - the architecture was unable to reboot.
@@ -119,7 +120,7 @@
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-void (*arm_pm_restart)(char str) = arm_machine_restart;
+void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
 EXPORT_SYMBOL_GPL(arm_pm_restart);
 
 
@@ -194,9 +195,9 @@
 		pm_power_off();
 }
 
-void machine_restart(char * __unused)
+void machine_restart(char *cmd)
 {
-	arm_pm_restart(reboot_mode);
+	arm_pm_restart(reboot_mode, cmd);
 }
 
 void __show_regs(struct pt_regs *regs)
@@ -372,23 +373,21 @@
 
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long fp, lr;
-	unsigned long stack_start, stack_end;
+	struct stackframe frame;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
-	stack_start = (unsigned long)end_of_stack(p);
-	stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-
-	fp = thread_saved_fp(p);
+	frame.fp = thread_saved_fp(p);
+	frame.sp = thread_saved_sp(p);
+	frame.lr = 0;			/* recovered from the stack */
+	frame.pc = thread_saved_pc(p);
 	do {
-		if (fp < stack_start || fp > stack_end)
+		int ret = unwind_frame(&frame);
+		if (ret < 0)
 			return 0;
-		lr = ((unsigned long *)fp)[-1];
-		if (!in_sched_functions(lr))
-			return lr;
-		fp = *(unsigned long *) (fp - 12);
+		if (!in_sched_functions(frame.pc))
+			return frame.pc;
 	} while (count ++ < 16);
 	return 0;
 }
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index df653ea..89882a1 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -653,6 +653,54 @@
 }
 #endif
 
+#ifdef CONFIG_VFP
+/*
+ * Get the child VFP state.
+ */
+static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
+{
+	struct thread_info *thread = task_thread_info(tsk);
+	union vfp_state *vfp = &thread->vfpstate;
+	struct user_vfp __user *ufp = data;
+
+	vfp_sync_state(thread);
+
+	/* copy the floating point registers */
+	if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
+			 sizeof(vfp->hard.fpregs)))
+		return -EFAULT;
+
+	/* copy the status and control register */
+	if (put_user(vfp->hard.fpscr, &ufp->fpscr))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Set the child VFP state.
+ */
+static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
+{
+	struct thread_info *thread = task_thread_info(tsk);
+	union vfp_state *vfp = &thread->vfpstate;
+	struct user_vfp __user *ufp = data;
+
+	vfp_sync_state(thread);
+
+	/* copy the floating point registers */
+	if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
+			   sizeof(vfp->hard.fpregs)))
+		return -EFAULT;
+
+	/* copy the status and control register */
+	if (get_user(vfp->hard.fpscr, &ufp->fpscr))
+		return -EFAULT;
+
+	return 0;
+}
+#endif
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
 	int ret;
@@ -775,6 +823,16 @@
 			break;
 #endif
 
+#ifdef CONFIG_VFP
+		case PTRACE_GETVFPREGS:
+			ret = ptrace_getvfpregs(child, (void __user *)data);
+			break;
+
+		case PTRACE_SETVFPREGS:
+			ret = ptrace_setvfpregs(child, (void __user *)data);
+			break;
+#endif
+
 		default:
 			ret = ptrace_request(child, request, addr, data);
 			break;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 68d6494..bc5e412 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -40,6 +40,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/traps.h>
+#include <asm/unwind.h>
 
 #include "compat.h"
 #include "atags.h"
@@ -685,6 +686,8 @@
 	struct machine_desc *mdesc;
 	char *from = default_command_line;
 
+	unwind_init();
+
 	setup_processor();
 	mdesc = setup_machine(machine_arch_type);
 	machine_name = mdesc->name;
@@ -780,6 +783,8 @@
 	"crunch",
 	"thumbee",
 	"neon",
+	"vfpv3",
+	"vfpv3d16",
 	NULL
 };
 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 55fa7ff..7801aac 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -93,6 +93,7 @@
 	pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
 	*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
 		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+	flush_pmd_entry(pmd);
 
 	/*
 	 * We need to tell the secondary core where to find
@@ -130,6 +131,7 @@
 	secondary_data.pgdir = 0;
 
 	*pmd = __pmd(0);
+	clean_pmd_entry(pmd);
 	pgd_free(&init_mm, pgd);
 
 	if (ret) {
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index fc650f6..9f444e5 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -2,34 +2,59 @@
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
 
-#include "stacktrace.h"
+#include <asm/stacktrace.h>
 
-int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
-		    int (*fn)(struct stackframe *, void *), void *data)
+#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
+/*
+ * Unwind the current stack frame and store the new register values in the
+ * structure passed as argument. Unwinding is equivalent to a function return,
+ * hence the new PC value rather than LR should be used for backtrace.
+ *
+ * With framepointer enabled, a simple function prologue looks like this:
+ *	mov	ip, sp
+ *	stmdb	sp!, {fp, ip, lr, pc}
+ *	sub	fp, ip, #4
+ *
+ * A simple function epilogue looks like this:
+ *	ldm	sp, {fp, sp, pc}
+ *
+ * Note that with framepointer enabled, even the leaf functions have the same
+ * prologue and epilogue, therefore we can ignore the LR value in this case.
+ */
+int unwind_frame(struct stackframe *frame)
 {
-	struct stackframe *frame;
+	unsigned long high, low;
+	unsigned long fp = frame->fp;
 
-	do {
-		/*
-		 * Check current frame pointer is within bounds
-		 */
-		if (fp < (low + 12) || fp + 4 >= high)
-			break;
+	/* only go to a higher address on the stack */
+	low = frame->sp;
+	high = ALIGN(low, THREAD_SIZE) + THREAD_SIZE;
 
-		frame = (struct stackframe *)(fp - 12);
+	/* check current frame pointer is within bounds */
+	if (fp < (low + 12) || fp + 4 >= high)
+		return -EINVAL;
+
+	/* restore the registers from the stack frame */
+	frame->fp = *(unsigned long *)(fp - 12);
+	frame->sp = *(unsigned long *)(fp - 8);
+	frame->pc = *(unsigned long *)(fp - 4);
+
+	return 0;
+}
+#endif
+
+void walk_stackframe(struct stackframe *frame,
+		     int (*fn)(struct stackframe *, void *), void *data)
+{
+	while (1) {
+		int ret;
 
 		if (fn(frame, data))
 			break;
-
-		/*
-		 * Update the low bound - the next frame must always
-		 * be at a higher address than the current frame.
-		 */
-		low = fp + 4;
-		fp = frame->fp;
-	} while (fp);
-
-	return 0;
+		ret = unwind_frame(frame);
+		if (ret < 0)
+			break;
+	}
 }
 EXPORT_SYMBOL(walk_stackframe);
 
@@ -44,7 +69,7 @@
 {
 	struct stack_trace_data *data = d;
 	struct stack_trace *trace = data->trace;
-	unsigned long addr = frame->lr;
+	unsigned long addr = frame->pc;
 
 	if (data->no_sched_functions && in_sched_functions(addr))
 		return 0;
@@ -61,11 +86,10 @@
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
 	struct stack_trace_data data;
-	unsigned long fp, base;
+	struct stackframe frame;
 
 	data.trace = trace;
 	data.skip = trace->skip;
-	base = (unsigned long)task_stack_page(tsk);
 
 	if (tsk != current) {
 #ifdef CONFIG_SMP
@@ -76,14 +100,22 @@
 		BUG();
 #else
 		data.no_sched_functions = 1;
-		fp = thread_saved_fp(tsk);
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		frame.lr = 0;		/* recovered from the stack */
+		frame.pc = thread_saved_pc(tsk);
 #endif
 	} else {
+		register unsigned long current_sp asm ("sp");
+
 		data.no_sched_functions = 0;
-		asm("mov %0, fp" : "=r" (fp));
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.lr = (unsigned long)__builtin_return_address(0);
+		frame.pc = (unsigned long)save_stack_trace_tsk;
 	}
 
-	walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
+	walk_stackframe(&frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
diff --git a/arch/arm/kernel/stacktrace.h b/arch/arm/kernel/stacktrace.h
deleted file mode 100644
index e9fd20c..0000000
--- a/arch/arm/kernel/stacktrace.h
+++ /dev/null
@@ -1,9 +0,0 @@
-struct stackframe {
-	unsigned long fp;
-	unsigned long sp;
-	unsigned long lr;
-	unsigned long pc;
-};
-
-int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
-		    int (*fn)(struct stackframe *, void *), void *data);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index c68b44a..4cdc4a0 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -33,6 +33,7 @@
 
 #include <asm/leds.h>
 #include <asm/thread_info.h>
+#include <asm/stacktrace.h>
 #include <asm/mach/time.h>
 
 /*
@@ -55,14 +56,22 @@
 #ifdef CONFIG_SMP
 unsigned long profile_pc(struct pt_regs *regs)
 {
-	unsigned long fp, pc = instruction_pointer(regs);
+	struct stackframe frame;
 
-	if (in_lock_functions(pc)) {
-		fp = regs->ARM_fp;
-		pc = ((unsigned long *)fp)[-1];
-	}
+	if (!in_lock_functions(regs->ARM_pc))
+		return regs->ARM_pc;
 
-	return pc;
+	frame.fp = regs->ARM_fp;
+	frame.sp = regs->ARM_sp;
+	frame.lr = regs->ARM_lr;
+	frame.pc = regs->ARM_pc;
+	do {
+		int ret = unwind_frame(&frame);
+		if (ret < 0)
+			return 0;
+	} while (in_lock_functions(frame.pc));
+
+	return frame.pc;
 }
 EXPORT_SYMBOL(profile_pc);
 #endif
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 79abc4d..57eb0f6 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -27,6 +27,7 @@
 #include <asm/system.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
+#include <asm/unwind.h>
 
 #include "ptrace.h"
 #include "signal.h"
@@ -61,6 +62,7 @@
 		dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
 }
 
+#ifndef CONFIG_ARM_UNWIND
 /*
  * Stack pointers should always be within the kernels view of
  * physical memory.  If it is not there, then we can't dump
@@ -74,6 +76,7 @@
 
 	return 0;
 }
+#endif
 
 /*
  * Dump out the contents of some memory nicely...
@@ -150,13 +153,33 @@
 	set_fs(fs);
 }
 
+#ifdef CONFIG_ARM_UNWIND
+static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+	unwind_backtrace(regs, tsk);
+}
+#else
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 {
-	unsigned int fp;
+	unsigned int fp, mode;
 	int ok = 1;
 
 	printk("Backtrace: ");
-	fp = regs->ARM_fp;
+
+	if (!tsk)
+		tsk = current;
+
+	if (regs) {
+		fp = regs->ARM_fp;
+		mode = processor_mode(regs);
+	} else if (tsk != current) {
+		fp = thread_saved_fp(tsk);
+		mode = 0x10;
+	} else {
+		asm("mov %0, fp" : "=r" (fp) : : "cc");
+		mode = 0x10;
+	}
+
 	if (!fp) {
 		printk("no frame pointer");
 		ok = 0;
@@ -168,29 +191,20 @@
 	printk("\n");
 
 	if (ok)
-		c_backtrace(fp, processor_mode(regs));
+		c_backtrace(fp, mode);
 }
+#endif
 
 void dump_stack(void)
 {
-	__backtrace();
+	dump_backtrace(NULL, NULL);
 }
 
 EXPORT_SYMBOL(dump_stack);
 
 void show_stack(struct task_struct *tsk, unsigned long *sp)
 {
-	unsigned long fp;
-
-	if (!tsk)
-		tsk = current;
-
-	if (tsk != current)
-		fp = thread_saved_fp(tsk);
-	else
-		asm("mov %0, fp" : "=r" (fp) : : "cc");
-
-	c_backtrace(fp, 0x10);
+	dump_backtrace(NULL, tsk);
 	barrier();
 }
 
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
new file mode 100644
index 0000000..1dedc2c
--- /dev/null
+++ b/arch/arm/kernel/unwind.c
@@ -0,0 +1,434 @@
+/*
+ * arch/arm/kernel/unwind.c
+ *
+ * Copyright (C) 2008 ARM Limited
+ *
+ * This program is free software; you can 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
+ *
+ *
+ * Stack unwinding support for ARM
+ *
+ * An ARM EABI version of gcc is required to generate the unwind
+ * tables. For information about the structure of the unwind tables,
+ * see "Exception Handling ABI for the ARM Architecture" at:
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#include <asm/stacktrace.h>
+#include <asm/traps.h>
+#include <asm/unwind.h>
+
+/* Dummy functions to avoid linker complaints */
+void __aeabi_unwind_cpp_pr0(void)
+{
+};
+EXPORT_SYMBOL(__aeabi_unwind_cpp_pr0);
+
+void __aeabi_unwind_cpp_pr1(void)
+{
+};
+EXPORT_SYMBOL(__aeabi_unwind_cpp_pr1);
+
+void __aeabi_unwind_cpp_pr2(void)
+{
+};
+EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
+
+struct unwind_ctrl_block {
+	unsigned long vrs[16];		/* virtual register set */
+	unsigned long *insn;		/* pointer to the current instructions word */
+	int entries;			/* number of entries left to interpret */
+	int byte;			/* current byte number in the instructions word */
+};
+
+enum regs {
+	FP = 11,
+	SP = 13,
+	LR = 14,
+	PC = 15
+};
+
+extern struct unwind_idx __start_unwind_idx[];
+extern struct unwind_idx __stop_unwind_idx[];
+
+static DEFINE_SPINLOCK(unwind_lock);
+static LIST_HEAD(unwind_tables);
+
+/* Convert a prel31 symbol to an absolute address */
+#define prel31_to_addr(ptr)				\
+({							\
+	/* sign-extend to 32 bits */			\
+	long offset = (((long)*(ptr)) << 1) >> 1;	\
+	(unsigned long)(ptr) + offset;			\
+})
+
+/*
+ * Binary search in the unwind index. The entries entries are
+ * guaranteed to be sorted in ascending order by the linker.
+ */
+static struct unwind_idx *search_index(unsigned long addr,
+				       struct unwind_idx *first,
+				       struct unwind_idx *last)
+{
+	pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last);
+
+	if (addr < first->addr) {
+		pr_warning("unwind: Unknown symbol address %08lx\n", addr);
+		return NULL;
+	} else if (addr >= last->addr)
+		return last;
+
+	while (first < last - 1) {
+		struct unwind_idx *mid = first + ((last - first + 1) >> 1);
+
+		if (addr < mid->addr)
+			last = mid;
+		else
+			first = mid;
+	}
+
+	return first;
+}
+
+static struct unwind_idx *unwind_find_idx(unsigned long addr)
+{
+	struct unwind_idx *idx = NULL;
+	unsigned long flags;
+
+	pr_debug("%s(%08lx)\n", __func__, addr);
+
+	if (core_kernel_text(addr))
+		/* main unwind table */
+		idx = search_index(addr, __start_unwind_idx,
+				   __stop_unwind_idx - 1);
+	else {
+		/* module unwind tables */
+		struct unwind_table *table;
+
+		spin_lock_irqsave(&unwind_lock, flags);
+		list_for_each_entry(table, &unwind_tables, list) {
+			if (addr >= table->begin_addr &&
+			    addr < table->end_addr) {
+				idx = search_index(addr, table->start,
+						   table->stop - 1);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&unwind_lock, flags);
+	}
+
+	pr_debug("%s: idx = %p\n", __func__, idx);
+	return idx;
+}
+
+static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
+{
+	unsigned long ret;
+
+	if (ctrl->entries <= 0) {
+		pr_warning("unwind: Corrupt unwind table\n");
+		return 0;
+	}
+
+	ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff;
+
+	if (ctrl->byte == 0) {
+		ctrl->insn++;
+		ctrl->entries--;
+		ctrl->byte = 3;
+	} else
+		ctrl->byte--;
+
+	return ret;
+}
+
+/*
+ * Execute the current unwind instruction.
+ */
+static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
+{
+	unsigned long insn = unwind_get_byte(ctrl);
+
+	pr_debug("%s: insn = %08lx\n", __func__, insn);
+
+	if ((insn & 0xc0) == 0x00)
+		ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
+	else if ((insn & 0xc0) == 0x40)
+		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;
+		if (mask == 0) {
+			pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n",
+				   insn);
+			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;
+	} 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;
+	} else if (insn == 0xb0) {
+		ctrl->vrs[PC] = ctrl->vrs[LR];
+		/* no further processing */
+		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",
+			       (insn << 8) | mask);
+			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;
+	} else if (insn == 0xb2) {
+		unsigned long uleb128 = unwind_get_byte(ctrl);
+
+		ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
+	} else {
+		pr_warning("unwind: Unhandled instruction %02lx\n", insn);
+		return -URC_FAILURE;
+	}
+
+	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;
+}
+
+/*
+ * Unwind a single frame starting with *sp for the symbol at *pc. It
+ * updates the *pc and *sp with the new values.
+ */
+int unwind_frame(struct stackframe *frame)
+{
+	unsigned long high, low;
+	struct unwind_idx *idx;
+	struct unwind_ctrl_block ctrl;
+
+	/* only go to a higher address on the stack */
+	low = frame->sp;
+	high = ALIGN(low, THREAD_SIZE) + THREAD_SIZE;
+
+	pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__,
+		 frame->pc, frame->lr, frame->sp);
+
+	if (!kernel_text_address(frame->pc))
+		return -URC_FAILURE;
+
+	idx = unwind_find_idx(frame->pc);
+	if (!idx) {
+		pr_warning("unwind: Index not found %08lx\n", frame->pc);
+		return -URC_FAILURE;
+	}
+
+	ctrl.vrs[FP] = frame->fp;
+	ctrl.vrs[SP] = frame->sp;
+	ctrl.vrs[LR] = frame->lr;
+	ctrl.vrs[PC] = 0;
+
+	if (idx->insn == 1)
+		/* can't unwind */
+		return -URC_FAILURE;
+	else if ((idx->insn & 0x80000000) == 0)
+		/* prel31 to the unwind table */
+		ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn);
+	else if ((idx->insn & 0xff000000) == 0x80000000)
+		/* only personality routine 0 supported in the index */
+		ctrl.insn = &idx->insn;
+	else {
+		pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n",
+			   idx->insn, idx);
+		return -URC_FAILURE;
+	}
+
+	/* check the personality routine */
+	if ((*ctrl.insn & 0xff000000) == 0x80000000) {
+		ctrl.byte = 2;
+		ctrl.entries = 1;
+	} else if ((*ctrl.insn & 0xff000000) == 0x81000000) {
+		ctrl.byte = 1;
+		ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16);
+	} else {
+		pr_warning("unwind: Unsupported personality routine %08lx at %p\n",
+			   *ctrl.insn, ctrl.insn);
+		return -URC_FAILURE;
+	}
+
+	while (ctrl.entries > 0) {
+		int urc;
+
+		if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
+			return -URC_FAILURE;
+		urc = unwind_exec_insn(&ctrl);
+		if (urc < 0)
+			return urc;
+	}
+
+	if (ctrl.vrs[PC] == 0)
+		ctrl.vrs[PC] = ctrl.vrs[LR];
+
+	frame->fp = ctrl.vrs[FP];
+	frame->sp = ctrl.vrs[SP];
+	frame->lr = ctrl.vrs[LR];
+	frame->pc = ctrl.vrs[PC];
+
+	return URC_OK;
+}
+
+void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+	struct stackframe frame;
+	unsigned long high, low;
+	register unsigned long current_sp asm ("sp");
+
+	pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
+
+	if (!tsk)
+		tsk = current;
+
+	if (regs) {
+		frame.fp = regs->ARM_fp;
+		frame.sp = regs->ARM_sp;
+		frame.lr = regs->ARM_lr;
+		frame.pc = regs->ARM_pc;
+	} else if (tsk == current) {
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.lr = (unsigned long)__builtin_return_address(0);
+		frame.pc = (unsigned long)unwind_backtrace;
+	} else {
+		/* task blocked in __switch_to */
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		/*
+		 * The function calling __switch_to cannot be a leaf function
+		 * so LR is recovered from the stack.
+		 */
+		frame.lr = 0;
+		frame.pc = thread_saved_pc(tsk);
+	}
+
+	low = frame.sp & ~(THREAD_SIZE - 1);
+	high = low + THREAD_SIZE;
+
+	while (1) {
+		int urc;
+		unsigned long where = frame.pc;
+
+		urc = unwind_frame(&frame);
+		if (urc < 0)
+			break;
+		dump_backtrace_entry(where, frame.pc, frame.sp - 4);
+	}
+}
+
+struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
+				      unsigned long text_addr,
+				      unsigned long text_size)
+{
+	unsigned long flags;
+	struct unwind_idx *idx;
+	struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
+
+	pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
+		 text_addr, text_size);
+
+	if (!tab)
+		return tab;
+
+	tab->start = (struct unwind_idx *)start;
+	tab->stop = (struct unwind_idx *)(start + size);
+	tab->begin_addr = text_addr;
+	tab->end_addr = text_addr + text_size;
+
+	/* Convert the symbol addresses to absolute values */
+	for (idx = tab->start; idx < tab->stop; idx++)
+		idx->addr = prel31_to_addr(&idx->addr);
+
+	spin_lock_irqsave(&unwind_lock, flags);
+	list_add_tail(&tab->list, &unwind_tables);
+	spin_unlock_irqrestore(&unwind_lock, flags);
+
+	return tab;
+}
+
+void unwind_table_del(struct unwind_table *tab)
+{
+	unsigned long flags;
+
+	if (!tab)
+		return;
+
+	spin_lock_irqsave(&unwind_lock, flags);
+	list_del(&tab->list);
+	spin_unlock_irqrestore(&unwind_lock, flags);
+
+	kfree(tab);
+}
+
+int __init unwind_init(void)
+{
+	struct unwind_idx *idx;
+
+	/* Convert the symbol addresses to absolute values */
+	for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
+		idx->addr = prel31_to_addr(&idx->addr);
+
+	pr_debug("unwind: ARM stack unwinding initialised\n");
+
+	return 0;
+}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 1602373..c90f272 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -82,6 +82,8 @@
 		EXIT_TEXT
 		EXIT_DATA
 		*(.exitcall.exit)
+		*(.ARM.exidx.exit.text)
+		*(.ARM.extab.exit.text)
 #ifndef CONFIG_MMU
 		*(.fixup)
 		*(__ex_table)
@@ -112,6 +114,23 @@
 
 	_etext = .;			/* End of text and rodata section */
 
+#ifdef CONFIG_ARM_UNWIND
+	/*
+	 * Stack unwinding tables
+	 */
+	. = ALIGN(8);
+	.ARM.unwind_idx : {
+		__start_unwind_idx = .;
+		*(.ARM.exidx*)
+		__stop_unwind_idx = .;
+	}
+	.ARM.unwind_tab : {
+		__start_unwind_tab = .;
+		*(.ARM.extab*)
+		__stop_unwind_tab = .;
+	}
+#endif
+
 #ifdef CONFIG_XIP_KERNEL
 	__data_loc = ALIGN(4);		/* location in binary */
 	. = PAGE_OFFSET + TEXT_OFFSET;
diff --git a/arch/arm/mach-aaec2000/include/mach/system.h b/arch/arm/mach-aaec2000/include/mach/system.h
index 8f4115d..fe08ca1 100644
--- a/arch/arm/mach-aaec2000/include/mach/system.h
+++ b/arch/arm/mach-aaec2000/include/mach/system.h
@@ -16,7 +16,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	cpu_reset(0);
 }
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 81439fe..438efbb 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -238,6 +238,10 @@
 	at91_add_device_i2c(NULL, 0);
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+	/* PCK0 provides MCLK to the WM8731 */
+	at91_set_B_periph(AT91_PIN_PC1, 0);
+	/* SSC (for WM8731) */
+	at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 7b9ce7a..b5daf7f 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -47,9 +47,6 @@
 #define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
 
 struct at91_gpio_bank {
-	unsigned chipbase;		/* bank's first GPIO number */
-	void __iomem *regbase;		/* base of register bank */
-	struct at91_gpio_bank *next;	/* bank sharing same IRQ/clock/... */
 	unsigned short id;		/* peripheral ID */
 	unsigned long offset;		/* offset from system peripheral base */
 	struct clk *clock;		/* associated clock */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 2f7d497..f2236f0 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -24,19 +24,59 @@
 #include <mach/at91_pio.h>
 #include <mach/gpio.h>
 
+#include <asm/gpio.h>
+
 #include "generic.h"
 
+struct at91_gpio_chip {
+	struct gpio_chip	chip;
+	struct at91_gpio_chip	*next;		/* Bank sharing same clock */
+	struct at91_gpio_bank	*bank;		/* Bank definition */
+	void __iomem		*regbase;	/* Base of register bank */
+};
 
-static struct at91_gpio_bank *gpio;
+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+
+static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
+static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
+static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
+static int at91_gpiolib_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int val);
+static int at91_gpiolib_direction_input(struct gpio_chip *chip,
+					unsigned offset);
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
+
+#define AT91_GPIO_CHIP(name, base_gpio, nr_gpio)			\
+	{								\
+		.chip = {						\
+			.label		  = name,			\
+			.request	  = at91_gpiolib_request,	\
+			.direction_input  = at91_gpiolib_direction_input, \
+			.direction_output = at91_gpiolib_direction_output, \
+			.get		  = at91_gpiolib_get,		\
+			.set		  = at91_gpiolib_set,		\
+			.dbg_show	  = at91_gpiolib_dbg_show,	\
+			.base		  = base_gpio,			\
+			.ngpio		  = nr_gpio,			\
+		},							\
+	}
+
+static struct at91_gpio_chip gpio_chip[] = {
+	AT91_GPIO_CHIP("A", 0x00 + PIN_BASE, 32),
+	AT91_GPIO_CHIP("B", 0x20 + PIN_BASE, 32),
+	AT91_GPIO_CHIP("C", 0x40 + PIN_BASE, 32),
+	AT91_GPIO_CHIP("D", 0x60 + PIN_BASE, 32),
+	AT91_GPIO_CHIP("E", 0x80 + PIN_BASE, 32),
+};
+
 static int gpio_banks;
 
-
 static inline void __iomem *pin_to_controller(unsigned pin)
 {
 	pin -= PIN_BASE;
 	pin /= 32;
 	if (likely(pin < gpio_banks))
-		return gpio[pin].regbase;
+		return gpio_chip[pin].regbase;
 
 	return NULL;
 }
@@ -197,39 +237,6 @@
 }
 EXPORT_SYMBOL(at91_set_multi_drive);
 
-/*--------------------------------------------------------------------------*/
-
-/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
- * called, and maybe at91_set_multi_drive() for putout pins.
- */
-
-int gpio_direction_input(unsigned pin)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
-		return -EINVAL;
-	__raw_writel(mask, pio + PIO_ODR);
-	return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned pin, int value)
-{
-	void __iomem	*pio = pin_to_controller(pin);
-	unsigned	mask = pin_to_mask(pin);
-
-	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
-		return -EINVAL;
-	__raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-	__raw_writel(mask, pio + PIO_OER);
-	return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*--------------------------------------------------------------------------*/
-
 /*
  * assuming the pin is muxed as a gpio output, set its value.
  */
@@ -282,7 +289,7 @@
 	else
 		wakeups[bank] &= ~mask;
 
-	set_irq_wake(gpio[bank].id, state);
+	set_irq_wake(gpio_chip[bank].bank->id, state);
 
 	return 0;
 }
@@ -292,14 +299,14 @@
 	int i;
 
 	for (i = 0; i < gpio_banks; i++) {
-		void __iomem	*pio = gpio[i].regbase;
+		void __iomem	*pio = gpio_chip[i].regbase;
 
 		backups[i] = __raw_readl(pio + PIO_IMR);
 		__raw_writel(backups[i], pio + PIO_IDR);
 		__raw_writel(wakeups[i], pio + PIO_IER);
 
 		if (!wakeups[i])
-			clk_disable(gpio[i].clock);
+			clk_disable(gpio_chip[i].bank->clock);
 		else {
 #ifdef CONFIG_PM_DEBUG
 			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
@@ -313,10 +320,10 @@
 	int i;
 
 	for (i = 0; i < gpio_banks; i++) {
-		void __iomem	*pio = gpio[i].regbase;
+		void __iomem	*pio = gpio_chip[i].regbase;
 
 		if (!wakeups[i])
-			clk_enable(gpio[i].clock);
+			clk_enable(gpio_chip[i].bank->clock);
 
 		__raw_writel(wakeups[i], pio + PIO_IDR);
 		__raw_writel(backups[i], pio + PIO_IER);
@@ -380,12 +387,12 @@
 {
 	unsigned	pin;
 	struct irq_desc	*gpio;
-	struct at91_gpio_bank *bank;
+	struct at91_gpio_chip *at91_gpio;
 	void __iomem	*pio;
 	u32		isr;
 
-	bank = get_irq_chip_data(irq);
-	pio = bank->regbase;
+	at91_gpio = get_irq_chip_data(irq);
+	pio = at91_gpio->regbase;
 
 	/* temporarily mask (level sensitive) parent IRQ */
 	desc->chip->ack(irq);
@@ -396,14 +403,14 @@
 		 */
 		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
 		if (!isr) {
-			if (!bank->next)
+			if (!at91_gpio->next)
 				break;
-			bank = bank->next;
-			pio = bank->regbase;
+			at91_gpio = at91_gpio->next;
+			pio = at91_gpio->regbase;
 			continue;
 		}
 
-		pin = bank->chipbase;
+		pin = at91_gpio->chip.base;
 		gpio = &irq_desc[pin];
 
 		while (isr) {
@@ -502,17 +509,17 @@
 void __init at91_gpio_irq_setup(void)
 {
 	unsigned		pioc, pin;
-	struct at91_gpio_bank	*this, *prev;
+	struct at91_gpio_chip	*this, *prev;
 
-	for (pioc = 0, pin = PIN_BASE, this = gpio, prev = NULL;
+	for (pioc = 0, pin = PIN_BASE, this = gpio_chip, prev = NULL;
 			pioc++ < gpio_banks;
 			prev = this, this++) {
-		unsigned	id = this->id;
+		unsigned	id = this->bank->id;
 		unsigned	i;
 
 		__raw_writel(~0, this->regbase + PIO_IDR);
 
-		for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
+		for (i = 0, pin = this->chip.base; i < 32; i++, pin++) {
 			lockdep_set_class(&irq_desc[pin].lock, &gpio_lock_class);
 
 			/*
@@ -537,32 +544,117 @@
 	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
 }
 
+/* gpiolib support */
+static int at91_gpiolib_direction_input(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;
+
+	__raw_writel(mask, pio + PIO_ODR);
+	return 0;
+}
+
+static int at91_gpiolib_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int val)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	__raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR));
+	__raw_writel(mask, pio + PIO_OER);
+	return 0;
+}
+
+static int at91_gpiolib_get(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 pdsr;
+
+	pdsr = __raw_readl(pio + PIO_PDSR);
+	return (pdsr & mask) != 0;
+}
+
+static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+
+	__raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR));
+}
+
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned pin = chip->base + offset;
+	void __iomem *pio = pin_to_controller(pin);
+	unsigned mask = pin_to_mask(pin);
+
+	/* Cannot request GPIOs that are in alternate function mode */
+	if (!(__raw_readl(pio + PIO_PSR) & mask))
+		return -EPERM;
+
+	return 0;
+}
+
+static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int i;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		unsigned pin = chip->base + i;
+		void __iomem *pio = pin_to_controller(pin);
+		unsigned mask = pin_to_mask(pin);
+		const char *gpio_label;
+
+		gpio_label = gpiochip_is_requested(chip, i);
+		if (gpio_label) {
+			seq_printf(s, "[%s] GPIO%s%d: ",
+				   gpio_label, chip->label, i);
+			if (__raw_readl(pio + PIO_PSR) & mask)
+				seq_printf(s, "[gpio] %s\n",
+					   at91_get_gpio_value(pin) ?
+					   "set" : "clear");
+			else
+				seq_printf(s, "[periph %s]\n",
+					   __raw_readl(pio + PIO_ABSR) &
+					   mask ? "B" : "A");
+		}
+	}
+}
+
 /*
  * Called from the processor-specific init to enable GPIO pin support.
  */
 void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
 {
 	unsigned		i;
-	struct at91_gpio_bank	*last;
+	struct at91_gpio_chip *at91_gpio, *last = NULL;
 
 	BUG_ON(nr_banks > MAX_GPIO_BANKS);
 
-	gpio = data;
 	gpio_banks = nr_banks;
 
-	for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) {
-		data->chipbase = PIN_BASE + i * 32;
-		data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
+	for (i = 0; i < nr_banks; i++) {
+		at91_gpio = &gpio_chip[i];
+
+		at91_gpio->bank = &data[i];
+		at91_gpio->chip.base = PIN_BASE + i * 32;
+		at91_gpio->regbase = at91_gpio->bank->offset +
+			(void __iomem *)AT91_VA_BASE_SYS;
 
 		/* enable PIO controller's clock */
-		clk_enable(data->clock);
+		clk_enable(at91_gpio->bank->clock);
 
-		/*
-		 * Some processors share peripheral ID between multiple GPIO banks.
-		 *  SAM9263 (PIOC, PIOD, PIOE)
-		 *  CAP9 (PIOA, PIOB, PIOC, PIOD)
-		 */
-		if (last && last->id == data->id)
-			last->next = data;
+		/* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
+		if (last && last->bank->id == at91_gpio->bank->id)
+			last->next = at91_gpio;
+		last = at91_gpio;
+
+		gpiochip_add(&at91_gpio->chip);
 	}
 }
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index bffa674..04c91e3 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -213,32 +213,12 @@
  */
 
 #include <asm/errno.h>
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return 0;
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-	might_sleep();
-}
-
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return at91_get_gpio_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	at91_set_gpio_value(gpio, value);
-}
-
 #include <asm-generic/gpio.h>		/* cansleep wrappers */
 
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+
 static inline int gpio_to_irq(unsigned gpio)
 {
 	return gpio;
diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h
index e712658..5268af3 100644
--- a/arch/arm/mach-at91/include/mach/system.h
+++ b/arch/arm/mach-at91/include/mach/system.h
@@ -43,7 +43,7 @@
 
 void (*at91_arch_reset)(void);
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/* call the CPU-specific reset function */
 	if (at91_arch_reset)
diff --git a/arch/arm/mach-clps711x/include/mach/system.h b/arch/arm/mach-clps711x/include/mach/system.h
index 24e9615..f916cd7 100644
--- a/arch/arm/mach-clps711x/include/mach/system.h
+++ b/arch/arm/mach-clps711x/include/mach/system.h
@@ -32,7 +32,7 @@
 	mov	r0, r0");
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	cpu_reset(0);
 }
diff --git a/arch/arm/mach-davinci/include/mach/system.h b/arch/arm/mach-davinci/include/mach/system.h
index 17ca41d..b7e7036 100644
--- a/arch/arm/mach-davinci/include/mach/system.h
+++ b/arch/arm/mach-davinci/include/mach/system.h
@@ -21,7 +21,7 @@
 	cpu_do_idle();
 }
 
-static void arch_reset(char mode)
+static void arch_reset(char mode, const char *cmd)
 {
 	davinci_watchdog_reset();
 }
diff --git a/arch/arm/mach-ebsa110/include/mach/system.h b/arch/arm/mach-ebsa110/include/mach/system.h
index 350a028..9a26245 100644
--- a/arch/arm/mach-ebsa110/include/mach/system.h
+++ b/arch/arm/mach-ebsa110/include/mach/system.h
@@ -34,6 +34,6 @@
 	asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc");
 }
 
-#define arch_reset(mode)	cpu_reset(0x80000000)
+#define arch_reset(mode, cmd)	cpu_reset(0x80000000)
 
 #endif
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 944e42d..9522e20 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for the linux kernel.
 #
-obj-y			:= core.o clock.o gpio.o
+obj-y			:= core.o clock.o dma-m2p.o gpio.o
 obj-m			:=
 obj-n			:=
 obj-			:=
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 9604928..e8ebeae 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -41,6 +41,56 @@
 	.enable_mask	= EP93XX_SYSCON_CLOCK_USH_EN,
 };
 
+/* DMA Clocks */
+static struct clk clk_m2p0 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00020000,
+};
+static struct clk clk_m2p1 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00010000,
+};
+static struct clk clk_m2p2 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00080000,
+};
+static struct clk clk_m2p3 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00040000,
+};
+static struct clk clk_m2p4 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00200000,
+};
+static struct clk clk_m2p5 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00100000,
+};
+static struct clk clk_m2p6 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00800000,
+};
+static struct clk clk_m2p7 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x00400000,
+};
+static struct clk clk_m2p8 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x02000000,
+};
+static struct clk clk_m2p9 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x01000000,
+};
+static struct clk clk_m2m0 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x04000000,
+};
+static struct clk clk_m2m1 = {
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= 0x08000000,
+};
+
 #define INIT_CK(dev,con,ck)					\
 	{ .dev_id = dev, .con_id = con, .clk = ck }
 
@@ -54,6 +104,18 @@
 	INIT_CK(NULL, "pclk", &clk_p),
 	INIT_CK(NULL, "pll2", &clk_pll2),
 	INIT_CK(NULL, "usb_host", &clk_usb_host),
+	INIT_CK(NULL, "m2p0", &clk_m2p0),
+	INIT_CK(NULL, "m2p1", &clk_m2p1),
+	INIT_CK(NULL, "m2p2", &clk_m2p2),
+	INIT_CK(NULL, "m2p3", &clk_m2p3),
+	INIT_CK(NULL, "m2p4", &clk_m2p4),
+	INIT_CK(NULL, "m2p5", &clk_m2p5),
+	INIT_CK(NULL, "m2p6", &clk_m2p6),
+	INIT_CK(NULL, "m2p7", &clk_m2p7),
+	INIT_CK(NULL, "m2p8", &clk_m2p8),
+	INIT_CK(NULL, "m2p9", &clk_m2p9),
+	INIT_CK(NULL, "m2m0", &clk_m2m0),
+	INIT_CK(NULL, "m2m1", &clk_m2m1),
 };
 
 
@@ -110,6 +172,22 @@
 	return (unsigned long)rate;
 }
 
+static void __init ep93xx_dma_clock_init(void)
+{
+	clk_m2p0.rate = clk_h.rate;
+	clk_m2p1.rate = clk_h.rate;
+	clk_m2p2.rate = clk_h.rate;
+	clk_m2p3.rate = clk_h.rate;
+	clk_m2p4.rate = clk_h.rate;
+	clk_m2p5.rate = clk_h.rate;
+	clk_m2p6.rate = clk_h.rate;
+	clk_m2p7.rate = clk_h.rate;
+	clk_m2p8.rate = clk_h.rate;
+	clk_m2p9.rate = clk_h.rate;
+	clk_m2m0.rate = clk_h.rate;
+	clk_m2m1.rate = clk_h.rate;
+}
+
 static int __init ep93xx_clock_init(void)
 {
 	u32 value;
@@ -124,6 +202,7 @@
 	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
 	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
 	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+	ep93xx_dma_clock_init();
 
 	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
 	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */
diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c
new file mode 100644
index 0000000..a2df5bb
--- /dev/null
+++ b/arch/arm/mach-ep93xx/dma-m2p.c
@@ -0,0 +1,408 @@
+/*
+ * arch/arm/mach-ep93xx/dma-m2p.c
+ * M2P DMA handling for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ *
+ * Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.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.
+ */
+
+/*
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ *	I2S	contains 3 Tx and 3 Rx DMA Channels
+ *	AAC	contains 3 Tx and 3 Rx DMA Channels
+ *	UART1	contains 1 Tx and 1 Rx DMA Channels
+ *	UART2	contains 1 Tx and 1 Rx DMA Channels
+ *	UART3	contains 1 Tx and 1 Rx DMA Channels
+ *	IrDA	contains 1 Tx and 1 Rx DMA Channels
+ *
+ * SSP and IDE use the Memory to Memory (M2M) channels and are not covered
+ * with this implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#define M2P_CONTROL			0x00
+#define  M2P_CONTROL_STALL_IRQ_EN	(1 << 0)
+#define  M2P_CONTROL_NFB_IRQ_EN		(1 << 1)
+#define  M2P_CONTROL_ERROR_IRQ_EN	(1 << 3)
+#define  M2P_CONTROL_ENABLE		(1 << 4)
+#define M2P_INTERRUPT			0x04
+#define  M2P_INTERRUPT_STALL		(1 << 0)
+#define  M2P_INTERRUPT_NFB		(1 << 1)
+#define  M2P_INTERRUPT_ERROR		(1 << 3)
+#define M2P_PPALLOC			0x08
+#define M2P_STATUS			0x0c
+#define M2P_REMAIN			0x14
+#define M2P_MAXCNT0			0x20
+#define M2P_BASE0			0x24
+#define M2P_MAXCNT1			0x30
+#define M2P_BASE1			0x34
+
+#define STATE_IDLE	0	/* Channel is inactive.  */
+#define STATE_STALL	1	/* Channel is active, no buffers pending.  */
+#define STATE_ON	2	/* Channel is active, one buffer pending.  */
+#define STATE_NEXT	3	/* Channel is active, two buffers pending.  */
+
+struct m2p_channel {
+	char				*name;
+	void __iomem			*base;
+	int				irq;
+
+	struct clk			*clk;
+	spinlock_t			lock;
+
+	void				*client;
+	unsigned			next_slot:1;
+	struct ep93xx_dma_buffer	*buffer_xfer;
+	struct ep93xx_dma_buffer	*buffer_next;
+	struct list_head		buffers_pending;
+};
+
+static struct m2p_channel m2p_rx[] = {
+	{"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
+	{"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
+	{"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
+	{"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
+	{"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
+	{NULL},
+};
+
+static struct m2p_channel m2p_tx[] = {
+	{"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
+	{"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
+	{"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
+	{"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
+	{"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
+	{NULL},
+};
+
+static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
+{
+	if (ch->next_slot == 0) {
+		writel(buf->size, ch->base + M2P_MAXCNT0);
+		writel(buf->bus_addr, ch->base + M2P_BASE0);
+	} else {
+		writel(buf->size, ch->base + M2P_MAXCNT1);
+		writel(buf->bus_addr, ch->base + M2P_BASE1);
+	}
+	ch->next_slot ^= 1;
+}
+
+static void choose_buffer_xfer(struct m2p_channel *ch)
+{
+	struct ep93xx_dma_buffer *buf;
+
+	ch->buffer_xfer = NULL;
+	if (!list_empty(&ch->buffers_pending)) {
+		buf = list_entry(ch->buffers_pending.next,
+				 struct ep93xx_dma_buffer, list);
+		list_del(&buf->list);
+		feed_buf(ch, buf);
+		ch->buffer_xfer = buf;
+	}
+}
+
+static void choose_buffer_next(struct m2p_channel *ch)
+{
+	struct ep93xx_dma_buffer *buf;
+
+	ch->buffer_next = NULL;
+	if (!list_empty(&ch->buffers_pending)) {
+		buf = list_entry(ch->buffers_pending.next,
+				 struct ep93xx_dma_buffer, list);
+		list_del(&buf->list);
+		feed_buf(ch, buf);
+		ch->buffer_next = buf;
+	}
+}
+
+static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
+{
+	/*
+	 * The control register must be read immediately after being written so
+	 * that the internal state machine is correctly updated. See the ep93xx
+	 * users' guide for details.
+	 */
+	writel(v, ch->base + M2P_CONTROL);
+	readl(ch->base + M2P_CONTROL);
+}
+
+static inline int m2p_channel_state(struct m2p_channel *ch)
+{
+	return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
+}
+
+static irqreturn_t m2p_irq(int irq, void *dev_id)
+{
+	struct m2p_channel *ch = dev_id;
+	struct ep93xx_dma_m2p_client *cl;
+	u32 irq_status, v;
+	int error = 0;
+
+	cl = ch->client;
+
+	spin_lock(&ch->lock);
+	irq_status = readl(ch->base + M2P_INTERRUPT);
+
+	if (irq_status & M2P_INTERRUPT_ERROR) {
+		writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
+		error = 1;
+	}
+
+	if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
+		spin_unlock(&ch->lock);
+		return IRQ_NONE;
+	}
+
+	switch (m2p_channel_state(ch)) {
+	case STATE_IDLE:
+		pr_crit("m2p_irq: dma interrupt without a dma buffer\n");
+		BUG();
+		break;
+
+	case STATE_STALL:
+		cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
+		if (ch->buffer_next != NULL) {
+			cl->buffer_finished(cl->cookie, ch->buffer_next,
+					    0, error);
+		}
+		choose_buffer_xfer(ch);
+		choose_buffer_next(ch);
+		if (ch->buffer_xfer != NULL)
+			cl->buffer_started(cl->cookie, ch->buffer_xfer);
+		break;
+
+	case STATE_ON:
+		cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
+		ch->buffer_xfer = ch->buffer_next;
+		choose_buffer_next(ch);
+		cl->buffer_started(cl->cookie, ch->buffer_xfer);
+		break;
+
+	case STATE_NEXT:
+		pr_crit("m2p_irq: dma interrupt while next\n");
+		BUG();
+		break;
+	}
+
+	v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
+					      M2P_CONTROL_NFB_IRQ_EN);
+	if (ch->buffer_xfer != NULL)
+		v |= M2P_CONTROL_STALL_IRQ_EN;
+	if (ch->buffer_next != NULL)
+		v |= M2P_CONTROL_NFB_IRQ_EN;
+	m2p_set_control(ch, v);
+
+	spin_unlock(&ch->lock);
+	return IRQ_HANDLED;
+}
+
+static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
+{
+	struct m2p_channel *ch;
+	int i;
+
+	if (cl->flags & EP93XX_DMA_M2P_RX)
+		ch = m2p_rx;
+	else
+		ch = m2p_tx;
+
+	for (i = 0; ch[i].base; i++) {
+		struct ep93xx_dma_m2p_client *client;
+
+		client = ch[i].client;
+		if (client != NULL) {
+			int port;
+
+			port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
+			if (port == (client->flags &
+				     EP93XX_DMA_M2P_PORT_MASK)) {
+				pr_warning("DMA channel already used by %s\n",
+					   cl->name ? : "unknown client");
+				return ERR_PTR(-EBUSY);
+			}
+		}
+	}
+
+	for (i = 0; ch[i].base; i++) {
+		if (ch[i].client == NULL)
+			return ch + i;
+	}
+
+	pr_warning("No free DMA channel for %s\n",
+		   cl->name ? : "unknown client");
+	return ERR_PTR(-ENODEV);
+}
+
+static void channel_enable(struct m2p_channel *ch)
+{
+	struct ep93xx_dma_m2p_client *cl = ch->client;
+	u32 v;
+
+	clk_enable(ch->clk);
+
+	v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
+	writel(v, ch->base + M2P_PPALLOC);
+
+	v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
+	v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
+	m2p_set_control(ch, v);
+}
+
+static void channel_disable(struct m2p_channel *ch)
+{
+	u32 v;
+
+	v = readl(ch->base + M2P_CONTROL);
+	v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
+	m2p_set_control(ch, v);
+
+	while (m2p_channel_state(ch) == STATE_ON)
+		cpu_relax();
+
+	m2p_set_control(ch, 0x0);
+
+	while (m2p_channel_state(ch) == STATE_STALL)
+		cpu_relax();
+
+	clk_disable(ch->clk);
+}
+
+int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
+{
+	struct m2p_channel *ch;
+	int err;
+
+	ch = find_free_channel(cl);
+	if (IS_ERR(ch))
+		return PTR_ERR(ch);
+
+	err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
+	if (err)
+		return err;
+
+	ch->client = cl;
+	ch->next_slot = 0;
+	ch->buffer_xfer = NULL;
+	ch->buffer_next = NULL;
+	INIT_LIST_HEAD(&ch->buffers_pending);
+
+	cl->channel = ch;
+
+	channel_enable(ch);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
+
+void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
+{
+	struct m2p_channel *ch = cl->channel;
+
+	channel_disable(ch);
+	free_irq(ch->irq, ch);
+	ch->client = NULL;
+}
+EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
+
+void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
+			   struct ep93xx_dma_buffer *buf)
+{
+	struct m2p_channel *ch = cl->channel;
+	unsigned long flags;
+	u32 v;
+
+	spin_lock_irqsave(&ch->lock, flags);
+	v = readl(ch->base + M2P_CONTROL);
+	if (ch->buffer_xfer == NULL) {
+		ch->buffer_xfer = buf;
+		feed_buf(ch, buf);
+		cl->buffer_started(cl->cookie, buf);
+
+		v |= M2P_CONTROL_STALL_IRQ_EN;
+		m2p_set_control(ch, v);
+
+	} else if (ch->buffer_next == NULL) {
+		ch->buffer_next = buf;
+		feed_buf(ch, buf);
+
+		v |= M2P_CONTROL_NFB_IRQ_EN;
+		m2p_set_control(ch, v);
+	} else {
+		list_add_tail(&buf->list, &ch->buffers_pending);
+	}
+	spin_unlock_irqrestore(&ch->lock, flags);
+}
+EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
+
+void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
+				     struct ep93xx_dma_buffer *buf)
+{
+	struct m2p_channel *ch = cl->channel;
+
+	list_add_tail(&buf->list, &ch->buffers_pending);
+}
+EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
+
+void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
+{
+	struct m2p_channel *ch = cl->channel;
+
+	channel_disable(ch);
+	ch->next_slot = 0;
+	ch->buffer_xfer = NULL;
+	ch->buffer_next = NULL;
+	INIT_LIST_HEAD(&ch->buffers_pending);
+	channel_enable(ch);
+}
+EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
+
+static int init_channel(struct m2p_channel *ch)
+{
+	ch->clk = clk_get(NULL, ch->name);
+	if (IS_ERR(ch->clk))
+		return PTR_ERR(ch->clk);
+
+	spin_lock_init(&ch->lock);
+	ch->client = NULL;
+
+	return 0;
+}
+
+static int __init ep93xx_dma_m2p_init(void)
+{
+	int i;
+	int ret;
+
+	for (i = 0; m2p_rx[i].base; i++) {
+		ret = init_channel(m2p_rx + i);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; m2p_tx[i].base; i++) {
+		ret = init_channel(m2p_tx + i);
+		if (ret)
+			return ret;
+	}
+
+	pr_info("M2P DMA subsystem initialized\n");
+	return 0;
+}
+arch_initcall(ep93xx_dma_m2p_init);
diff --git a/arch/arm/mach-ep93xx/edb9307a.c b/arch/arm/mach-ep93xx/edb9307a.c
index 5b5c22b..6171167 100644
--- a/arch/arm/mach-ep93xx/edb9307a.c
+++ b/arch/arm/mach-ep93xx/edb9307a.c
@@ -48,12 +48,24 @@
 	.phy_id		= 1,
 };
 
+static struct i2c_board_info __initdata edb9307a_i2c_data[] = {
+	{
+		/* On-board battery backed RTC */
+		I2C_BOARD_INFO("isl1208", 0x6f),
+	},
+	/*
+	 * The I2C signals are also routed to the Expansion Connector (J4)
+	 */
+};
+
 static void __init edb9307a_init_machine(void)
 {
 	ep93xx_init_devices();
 	platform_device_register(&edb9307a_flash);
 
 	ep93xx_register_eth(&edb9307a_eth_data, 1);
+
+	ep93xx_init_i2c(edb9307a_i2c_data, ARRAY_SIZE(edb9307a_i2c_data));
 }
 
 MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
new file mode 100644
index 0000000..ef6bd9d
--- /dev/null
+++ b/arch/arm/mach-ep93xx/include/mach/dma.h
@@ -0,0 +1,52 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+
+struct ep93xx_dma_buffer {
+	struct list_head	list;
+	u32			bus_addr;
+	u16			size;
+};
+
+struct ep93xx_dma_m2p_client {
+	char			*name;
+	u8			flags;
+	void			*cookie;
+	void			(*buffer_started)(void *cookie,
+					struct ep93xx_dma_buffer *buf);
+	void			(*buffer_finished)(void *cookie,
+					struct ep93xx_dma_buffer *buf,
+					int bytes, int error);
+
+	/* Internal to the DMA code.  */
+	void			*channel;
+};
+
+#define EP93XX_DMA_M2P_PORT_I2S1	0x00
+#define EP93XX_DMA_M2P_PORT_I2S2	0x01
+#define EP93XX_DMA_M2P_PORT_AAC1	0x02
+#define EP93XX_DMA_M2P_PORT_AAC2	0x03
+#define EP93XX_DMA_M2P_PORT_AAC3	0x04
+#define EP93XX_DMA_M2P_PORT_I2S3	0x05
+#define EP93XX_DMA_M2P_PORT_UART1	0x06
+#define EP93XX_DMA_M2P_PORT_UART2	0x07
+#define EP93XX_DMA_M2P_PORT_UART3	0x08
+#define EP93XX_DMA_M2P_PORT_IRDA	0x09
+#define EP93XX_DMA_M2P_PORT_MASK	0x0f
+#define EP93XX_DMA_M2P_TX		0x00
+#define EP93XX_DMA_M2P_RX		0x10
+#define EP93XX_DMA_M2P_ABORT_ON_ERROR	0x20
+#define EP93XX_DMA_M2P_IGNORE_ERROR	0x40
+#define EP93XX_DMA_M2P_ERROR_MASK	0x60
+
+int  ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
+void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
+void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
+			   struct ep93xx_dma_buffer *buf);
+void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
+				     struct ep93xx_dma_buffer *buf);
+void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
+
+#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index 22d6c9a..f66be12 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -58,7 +58,8 @@
 
 
 /* AHB peripherals */
-#define EP93XX_DMA_BASE			(EP93XX_AHB_VIRT_BASE + 0x00000000)
+#define EP93XX_DMA_BASE			((void __iomem *)		\
+					 (EP93XX_AHB_VIRT_BASE + 0x00000000))
 
 #define EP93XX_ETHERNET_BASE		(EP93XX_AHB_VIRT_BASE + 0x00010000)
 #define EP93XX_ETHERNET_PHYS_BASE	(EP93XX_AHB_PHYS_BASE + 0x00010000)
diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h
index 67789d0..ed8f35e 100644
--- a/arch/arm/mach-ep93xx/include/mach/system.h
+++ b/arch/arm/mach-ep93xx/include/mach/system.h
@@ -9,7 +9,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	u32 devicecfg;
 
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
index 4f35063..e2e0df8 100644
--- a/arch/arm/mach-footbridge/dma.c
+++ b/arch/arm/mach-footbridge/dma.c
@@ -21,16 +21,16 @@
 #include <asm/hardware/dec21285.h>
 
 #if 0
-static int fb_dma_request(dmach_t channel, dma_t *dma)
+static int fb_dma_request(unsigned int chan, dma_t *dma)
 {
 	return -EINVAL;
 }
 
-static void fb_dma_enable(dmach_t channel, dma_t *dma)
+static void fb_dma_enable(unsigned int chan, dma_t *dma)
 {
 }
 
-static void fb_dma_disable(dmach_t channel, dma_t *dma)
+static void fb_dma_disable(unsigned int chan, dma_t *dma)
 {
 }
 
@@ -42,7 +42,7 @@
 };
 #endif
 
-void __init arch_dma_init(dma_t *dma)
+static int __init fb_dma_init(void)
 {
 #if 0
 	dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
@@ -50,6 +50,8 @@
 #endif
 #ifdef CONFIG_ISA_DMA
 	if (footbridge_cfn_mode())
-		isa_init_dma(dma + _ISA_DMA(0));
+		isa_init_dma();
 #endif
+	return 0;
 }
+core_initcall(fb_dma_init);
diff --git a/arch/arm/mach-footbridge/include/mach/system.h b/arch/arm/mach-footbridge/include/mach/system.h
index 2db7f36..0b29315 100644
--- a/arch/arm/mach-footbridge/include/mach/system.h
+++ b/arch/arm/mach-footbridge/include/mach/system.h
@@ -18,7 +18,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	if (mode == 's') {
 		/*
diff --git a/arch/arm/mach-gemini/Kconfig b/arch/arm/mach-gemini/Kconfig
new file mode 100644
index 0000000..515b75c
--- /dev/null
+++ b/arch/arm/mach-gemini/Kconfig
@@ -0,0 +1,19 @@
+if ARCH_GEMINI
+
+menu "Cortina Systems Gemini Implementations"
+
+config MACH_RUT100
+	bool "Teltonika RUT100"
+	select GEMINI_MEM_SWAP
+	help
+	  Say Y here if you intend to run this kernel on a
+	  Teltonika 3G Router RUT100.
+
+endmenu
+
+config GEMINI_MEM_SWAP
+	bool "Gemini memory is swapped"
+	help
+	  Say Y here if Gemini memory is swapped by bootloader.
+
+endif
diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile
new file mode 100644
index 0000000..719505b
--- /dev/null
+++ b/arch/arm/mach-gemini/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y			:= irq.o mm.o time.o devices.o gpio.o
+
+# Board-specific support
+obj-$(CONFIG_MACH_RUT100)	+= board-rut1xx.o
diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot
new file mode 100644
index 0000000..22a52c2
--- /dev/null
+++ b/arch/arm/mach-gemini/Makefile.boot
@@ -0,0 +1,9 @@
+ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
+else
+   zreladdr-y	:= 0x10008000
+params_phys-y	:= 0x10000100
+initrd_phys-y	:= 0x10800000
+endif
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
new file mode 100644
index 0000000..e0de968
--- /dev/null
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -0,0 +1,95 @@
+/*
+ *  Support for Teltonika RUT1xx
+ *
+ *  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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+
+static struct gpio_keys_button rut1xx_keys[] = {
+	{
+		.code		= KEY_SETUP,
+		.gpio		= 60,
+		.active_low	= 1,
+		.desc		= "Reset to defaults",
+		.type		= EV_KEY,
+	},
+};
+
+static struct gpio_keys_platform_data rut1xx_keys_data = {
+	.buttons	= rut1xx_keys,
+	.nbuttons	= ARRAY_SIZE(rut1xx_keys),
+};
+
+static struct platform_device rut1xx_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &rut1xx_keys_data,
+	},
+};
+
+static struct gpio_led rut100_leds[] = {
+	{
+		.name			= "Power",
+		.default_trigger	= "heartbeat",
+		.gpio			= 17,
+	},
+	{
+		.name			= "GSM",
+		.default_trigger	= "default-on",
+		.gpio			= 7,
+		.active_low		= 1,
+	},
+};
+
+static struct gpio_led_platform_data rut100_leds_data = {
+	.num_leds	= ARRAY_SIZE(rut100_leds),
+	.leds		= rut100_leds,
+};
+
+static struct platform_device rut1xx_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &rut100_leds_data,
+	},
+};
+
+static struct sys_timer rut1xx_timer = {
+	.init	= gemini_timer_init,
+};
+
+static void __init rut1xx_init(void)
+{
+	gemini_gpio_init();
+	platform_register_uart();
+	platform_register_pflash(SZ_8M, NULL, 0);
+	platform_device_register(&rut1xx_leds);
+	platform_device_register(&rut1xx_keys_device);
+}
+
+MACHINE_START(RUT100, "Teltonika RUT100")
+	.phys_io	= 0x7fffc000,
+	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
+	.boot_params	= 0x100,
+	.map_io		= gemini_map_io,
+	.init_irq	= gemini_init_irq,
+	.timer		= &rut1xx_timer,
+	.init_machine	= rut1xx_init,
+MACHINE_END
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h
new file mode 100644
index 0000000..9392834
--- /dev/null
+++ b/arch/arm/mach-gemini/common.h
@@ -0,0 +1,28 @@
+/*
+ * Common Gemini architecture functions
+ *
+ * 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.
+ */
+
+#ifndef __GEMINI_COMMON_H__
+#define __GEMINI_COMMON_H__
+
+struct mtd_partition;
+
+extern void gemini_map_io(void);
+extern void gemini_init_irq(void);
+extern void gemini_timer_init(void);
+extern void gemini_gpio_init(void);
+
+/* Common platform devices registration functions */
+extern int platform_register_uart(void);
+extern int platform_register_pflash(unsigned int size,
+				    struct mtd_partition *parts,
+				    unsigned int nr_parts);
+
+#endif /* __GEMINI_COMMON_H__ */
diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c
new file mode 100644
index 0000000..6b52525
--- /dev/null
+++ b/arch/arm/mach-gemini/devices.c
@@ -0,0 +1,92 @@
+/*
+ * Common devices definition for Gemini
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/global_reg.h>
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.membase	= (void *)IO_ADDRESS(GEMINI_UART_BASE),
+		.mapbase	= GEMINI_UART_BASE,
+		.irq		= IRQ_UART,
+		.uartclk	= UART_CLK,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM,
+		.type		= PORT_16550A,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_FIXED_TYPE,
+	},
+	{},
+};
+
+static struct platform_device serial_device = {
+	.name	= "serial8250",
+	.id	= PLAT8250_DEV_PLATFORM,
+	.dev	= {
+		.platform_data = serial_platform_data,
+	},
+};
+
+int platform_register_uart(void)
+{
+	return platform_device_register(&serial_device);
+}
+
+static struct resource flash_resource = {
+	.start	= GEMINI_FLASH_BASE,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data pflash_platform_data = {};
+
+static struct platform_device pflash_device = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev 	= {
+		.platform_data = &pflash_platform_data,
+	},
+	.resource = &flash_resource,
+	.num_resources = 1,
+};
+
+int platform_register_pflash(unsigned int size, struct mtd_partition *parts,
+			     unsigned int nr_parts)
+{
+	unsigned int reg;
+
+	reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_STATUS);
+
+	if ((reg & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL)
+		return -ENXIO;
+
+	if (reg & FLASH_WIDTH_16BIT)
+		pflash_platform_data.width = 2;
+	else
+		pflash_platform_data.width = 1;
+
+	/* enable parallel flash pins and disable others */
+	reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL);
+	reg &= ~PFLASH_PADS_DISABLE;
+	reg |= SFLASH_PADS_DISABLE | NAND_PADS_DISABLE;
+	__raw_writel(reg, IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL);
+
+	flash_resource.end = flash_resource.start + size - 1;
+
+	pflash_platform_data.parts = parts;
+	pflash_platform_data.nr_parts = nr_parts;
+
+	return platform_device_register(&pflash_device);
+}
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c
new file mode 100644
index 0000000..e726385
--- /dev/null
+++ b/arch/arm/mach-gemini/gpio.c
@@ -0,0 +1,232 @@
+/*
+ * Gemini gpiochip and interrupt routines
+ *
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on plat-mxc/gpio.c:
+ *  MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
+ *  Copyright 2008 Juergen Beisert, kernel@pengutronix.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 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+#define GPIO_BASE(x)		IO_ADDRESS(GEMINI_GPIO_BASE(x))
+
+/* GPIO registers definition */
+#define GPIO_DATA_OUT		0x0
+#define GPIO_DATA_IN		0x4
+#define GPIO_DIR		0x8
+#define GPIO_DATA_SET		0x10
+#define GPIO_DATA_CLR		0x14
+#define GPIO_PULL_EN		0x18
+#define GPIO_PULL_TYPE		0x1C
+#define GPIO_INT_EN		0x20
+#define GPIO_INT_STAT		0x24
+#define GPIO_INT_MASK		0x2C
+#define GPIO_INT_CLR		0x30
+#define GPIO_INT_TYPE		0x34
+#define GPIO_INT_BOTH_EDGE	0x38
+#define GPIO_INT_LEVEL		0x3C
+#define GPIO_DEBOUNCE_EN	0x40
+#define GPIO_DEBOUNCE_PRESCALE	0x44
+
+#define GPIO_PORT_NUM		3
+
+static void _set_gpio_irqenable(unsigned int base, unsigned int index,
+				int enable)
+{
+	unsigned int reg;
+
+	reg = __raw_readl(base + GPIO_INT_EN);
+	reg = (reg & (~(1 << index))) | (!!enable << index);
+	__raw_writel(reg, base + GPIO_INT_EN);
+}
+
+static void gpio_ack_irq(unsigned int irq)
+{
+	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int base = GPIO_BASE(gpio / 32);
+
+	__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
+}
+
+static void gpio_mask_irq(unsigned int irq)
+{
+	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int base = GPIO_BASE(gpio / 32);
+
+	_set_gpio_irqenable(base, gpio % 32, 0);
+}
+
+static void gpio_unmask_irq(unsigned int irq)
+{
+	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int base = GPIO_BASE(gpio / 32);
+
+	_set_gpio_irqenable(base, gpio % 32, 1);
+}
+
+static int gpio_set_irq_type(unsigned int irq, unsigned int type)
+{
+	unsigned int gpio = irq_to_gpio(irq);
+	unsigned int gpio_mask = 1 << (gpio % 32);
+	unsigned int base = GPIO_BASE(gpio / 32);
+	unsigned int reg_both, reg_level, reg_type;
+
+	reg_type = __raw_readl(base + GPIO_INT_TYPE);
+	reg_level = __raw_readl(base + GPIO_INT_BOTH_EDGE);
+	reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_BOTH:
+		reg_type &= ~gpio_mask;
+		reg_both |= gpio_mask;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		reg_type &= ~gpio_mask;
+		reg_both &= ~gpio_mask;
+		reg_level &= ~gpio_mask;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		reg_type &= ~gpio_mask;
+		reg_both &= ~gpio_mask;
+		reg_level |= gpio_mask;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		reg_type |= gpio_mask;
+		reg_level &= ~gpio_mask;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		reg_type |= gpio_mask;
+		reg_level |= gpio_mask;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	__raw_writel(reg_type, base + GPIO_INT_TYPE);
+	__raw_writel(reg_level, base + GPIO_INT_BOTH_EDGE);
+	__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
+
+	gpio_ack_irq(irq);
+
+	return 0;
+}
+
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int gpio_irq_no, irq_stat;
+	unsigned int port = (unsigned int)get_irq_data(irq);
+
+	irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);
+
+	gpio_irq_no = GPIO_IRQ_BASE + port * 32;
+	for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
+
+		if ((irq_stat & 1) == 0)
+			continue;
+
+		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
+		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
+				&irq_desc[gpio_irq_no]);
+	}
+}
+
+static struct irq_chip gpio_irq_chip = {
+	.name = "GPIO",
+	.ack = gpio_ack_irq,
+	.mask = gpio_mask_irq,
+	.unmask = gpio_unmask_irq,
+	.set_type = gpio_set_irq_type,
+};
+
+static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
+				int dir)
+{
+	unsigned int base = GPIO_BASE(offset / 32);
+	unsigned int reg;
+
+	reg = __raw_readl(base + GPIO_DIR);
+	if (dir)
+		reg |= 1 << (offset % 32);
+	else
+		reg &= ~(1 << (offset % 32));
+	__raw_writel(reg, base + GPIO_DIR);
+}
+
+static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	unsigned int base = GPIO_BASE(offset / 32);
+
+	if (value)
+		__raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
+	else
+		__raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR);
+}
+
+static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned int base = GPIO_BASE(offset / 32);
+
+	return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
+}
+
+static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	_set_gpio_direction(chip, offset, 0);
+	return 0;
+}
+
+static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	_set_gpio_direction(chip, offset, 1);
+	gemini_gpio_set(chip, offset, value);
+	return 0;
+}
+
+static struct gpio_chip gemini_gpio_chip = {
+	.label			= "Gemini",
+	.direction_input	= gemini_gpio_direction_input,
+	.get			= gemini_gpio_get,
+	.direction_output	= gemini_gpio_direction_output,
+	.set			= gemini_gpio_set,
+	.base			= 0,
+	.ngpio			= GPIO_PORT_NUM * 32,
+};
+
+void __init gemini_gpio_init(void)
+{
+	int i, j;
+
+	for (i = 0; i < GPIO_PORT_NUM; i++) {
+		/* disable, unmask and clear all interrupts */
+		__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN);
+		__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK);
+		__raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR);
+
+		for (j = GPIO_IRQ_BASE + i * 32;
+		     j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
+			set_irq_chip(j, &gpio_irq_chip);
+			set_irq_handler(j, handle_edge_irq);
+			set_irq_flags(j, IRQF_VALID);
+		}
+
+		set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
+		set_irq_data(IRQ_GPIO(i), (void *)i);
+	}
+
+	BUG_ON(gpiochip_add(&gemini_gpio_chip));
+}
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
new file mode 100644
index 0000000..d04a6ea
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/debug-macro.S
@@ -0,0 +1,23 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <mach/hardware.h>
+
+	.macro	addruart,rx
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1					@ MMU enabled?
+	ldreq	\rx, =GEMINI_UART_BASE			@ physical
+	ldrne	\rx, =IO_ADDRESS(GEMINI_UART_BASE)	@ virtual
+	.endm
+
+#define UART_SHIFT	2
+#define FLOW_CONTROL
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-gemini/include/mach/entry-macro.S b/arch/arm/mach-gemini/include/mach/entry-macro.S
new file mode 100644
index 0000000..1624f91
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/entry-macro.S
@@ -0,0 +1,39 @@
+/*
+ * Low-level IRQ helper macros for Gemini platform.
+ *
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * 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 <mach/hardware.h>
+
+#define IRQ_STATUS	0x14
+
+	.macro  disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr     \irqstat, =IO_ADDRESS(GEMINI_INTERRUPT_BASE + IRQ_STATUS)
+	ldr     \irqnr, [\irqstat]
+	cmp     \irqnr, #0
+	beq     2313f
+	mov     \tmp, \irqnr
+	mov     \irqnr, #0
+2312:
+	tst     \tmp, #1
+	bne     2313f
+	add     \irqnr, \irqnr, #1
+	mov     \tmp, \tmp, lsr #1
+	cmp     \irqnr, #31
+	bcc     2312b
+2313:
+	.endm
diff --git a/arch/arm/mach-gemini/include/mach/global_reg.h b/arch/arm/mach-gemini/include/mach/global_reg.h
new file mode 100644
index 0000000..de7ff7e
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/global_reg.h
@@ -0,0 +1,278 @@
+/*
+ *  This file contains the hardware definitions for Gemini.
+ *
+ *  Copyright (C) 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.
+ */
+#ifndef __MACH_GLOBAL_REG_H
+#define __MACH_GLOBAL_REG_H
+
+/* Global Word ID Register*/
+#define GLOBAL_ID			0x00
+
+#define CHIP_ID(reg)			((reg) >> 8)
+#define CHIP_REVISION(reg)		((reg) & 0xFF)
+
+/* Global Status Register */
+#define GLOBAL_STATUS			0x04
+
+#define CPU_BIG_ENDIAN			(1 << 31)
+#define PLL_OSC_30M			(1 << 30)	/* else 60MHz */
+
+#define OPERATION_MODE_MASK		(0xF << 26)
+#define OPM_IDDQ			(0xF << 26)
+#define OPM_NAND			(0xE << 26)
+#define OPM_RING			(0xD << 26)
+#define OPM_DIRECT_BOOT			(0xC << 26)
+#define OPM_USB1_PHY_TEST		(0xB << 26)
+#define OPM_USB0_PHY_TEST		(0xA << 26)
+#define OPM_SATA1_PHY_TEST		(0x9 << 26)
+#define OPM_SATA0_PHY_TEST		(0x8 << 26)
+#define OPM_ICE_ARM			(0x7 << 26)
+#define OPM_ICE_FARADAY			(0x6 << 26)
+#define OPM_PLL_BYPASS			(0x5 << 26)
+#define OPM_DEBUG			(0x4 << 26)
+#define OPM_BURN_IN			(0x3 << 26)
+#define OPM_MBIST			(0x2 << 26)
+#define OPM_SCAN			(0x1 << 26)
+#define OPM_REAL			(0x0 << 26)
+
+#define FLASH_TYPE_MASK			(0x3 << 24)
+#define FLASH_TYPE_NAND_2K		(0x3 << 24)
+#define FLASH_TYPE_NAND_512		(0x2 << 24)
+#define FLASH_TYPE_PARALLEL		(0x1 << 24)
+#define FLASH_TYPE_SERIAL		(0x0 << 24)
+/* if parallel */
+#define FLASH_WIDTH_16BIT		(1 << 23)	/* else 8 bit */
+/* if serial */
+#define FLASH_ATMEL			(1 << 23)	/* else STM */
+
+#define FLASH_SIZE_MASK			(0x3 << 21)
+#define NAND_256M			(0x3 << 21)	/* and more */
+#define NAND_128M			(0x2 << 21)
+#define NAND_64M			(0x1 << 21)
+#define NAND_32M			(0x0 << 21)
+#define ATMEL_16M			(0x3 << 21)	/* and more */
+#define ATMEL_8M			(0x2 << 21)
+#define ATMEL_4M_2M			(0x1 << 21)
+#define ATMEL_1M			(0x0 << 21)	/* and less */
+#define STM_32M				(1 << 22)	/* and more */
+#define STM_16M				(0 << 22)	/* and less */
+
+#define FLASH_PARALLEL_HIGH_PIN_CNT	(1 << 20)	/* else low pin cnt */
+
+#define CPU_AHB_RATIO_MASK		(0x3 << 18)
+#define CPU_AHB_1_1			(0x0 << 18)
+#define CPU_AHB_3_2			(0x1 << 18)
+#define CPU_AHB_24_13			(0x2 << 18)
+#define CPU_AHB_2_1			(0x3 << 18)
+
+#define REG_TO_AHB_SPEED(reg)		((((reg) >> 15) & 0x7) * 10 + 130)
+#define AHB_SPEED_TO_REG(x)		((((x - 130)) / 10) << 15)
+
+/* it is posible to override some settings, use >> OVERRIDE_xxxx_SHIFT */
+#define OVERRIDE_FLASH_TYPE_SHIFT	16
+#define OVERRIDE_FLASH_WIDTH_SHIFT	16
+#define OVERRIDE_FLASH_SIZE_SHIFT	16
+#define OVERRIDE_CPU_AHB_RATIO_SHIFT	15
+#define OVERRIDE_AHB_SPEED_SHIFT	15
+
+/* Global PLL Control Register */
+#define GLOBAL_PLL_CTRL			0x08
+
+#define PLL_BYPASS			(1 << 31)
+#define PLL_POWER_DOWN			(1 << 8)
+#define PLL_CONTROL_Q			(0x1F << 0)
+
+/* Global Soft Reset Control Register */
+#define GLOBAL_RESET			0x0C
+
+#define RESET_GLOBAL			(1 << 31)
+#define RESET_CPU1			(1 << 30)
+#define RESET_TVE			(1 << 28)
+#define RESET_SATA1			(1 << 27)
+#define RESET_SATA0			(1 << 26)
+#define RESET_CIR			(1 << 25)
+#define RESET_EXT_DEV			(1 << 24)
+#define RESET_WD			(1 << 23)
+#define RESET_GPIO2			(1 << 22)
+#define RESET_GPIO1			(1 << 21)
+#define RESET_GPIO0			(1 << 20)
+#define RESET_SSP			(1 << 19)
+#define RESET_UART			(1 << 18)
+#define RESET_TIMER			(1 << 17)
+#define RESET_RTC			(1 << 16)
+#define RESET_INT1			(1 << 15)
+#define RESET_INT0			(1 << 14)
+#define RESET_LCD			(1 << 13)
+#define RESET_LPC			(1 << 12)
+#define RESET_APB			(1 << 11)
+#define RESET_DMA			(1 << 10)
+#define RESET_USB1			(1 << 9)
+#define RESET_USB0			(1 << 8)
+#define RESET_PCI			(1 << 7)
+#define RESET_GMAC1			(1 << 6)
+#define RESET_GMAC0			(1 << 5)
+#define RESET_SECURITY			(1 << 4)
+#define RESET_RAID			(1 << 3)
+#define RESET_IDE			(1 << 2)
+#define RESET_FLASH			(1 << 1)
+#define RESET_DRAM			(1 << 0)
+
+/* Global IO Pad Driving Capability Control Register */
+#define GLOBAL_IO_DRIVING_CTRL		0x10
+
+#define DRIVING_CURRENT_MASK		0x3
+
+/* here 00-4mA, 01-8mA, 10-12mA, 11-16mA */
+#define GPIO1_PADS_31_28_SHIFT		28
+#define GPIO0_PADS_31_16_SHIFT		26
+#define GPIO0_PADS_15_0_SHIFT		24
+#define PCI_AND_EXT_RESET_PADS_SHIFT	22
+#define IDE_PADS_SHIFT			20
+#define GMAC1_PADS_SHIFT		18
+#define GMAC0_PADS_SHIFT		16
+/* DRAM is not in mA and poorly documented */
+#define DRAM_CLOCK_PADS_SHIFT		8
+#define DRAM_DATA_PADS_SHIFT		4
+#define DRAM_CONTROL_PADS_SHIFT		0
+
+/* Global IO Pad Slew Rate Control Register */
+#define GLOBAL_IO_SLEW_RATE_CTRL	0x14
+
+#define GPIO1_PADS_31_28_SLOW		(1 << 10)
+#define GPIO0_PADS_31_16_SLOW		(1 << 9)
+#define GPIO0_PADS_15_0_SLOW		(1 << 8)
+#define PCI_PADS_SLOW			(1 << 7)
+#define IDE_PADS_SLOW			(1 << 6)
+#define GMAC1_PADS_SLOW			(1 << 5)
+#define GMAC0_PADS_SLOW			(1 << 4)
+#define DRAM_CLOCK_PADS_SLOW		(1 << 1)
+#define DRAM_IO_PADS_SLOW		(1 << 0)
+
+/*
+ * General skew control defines
+ * 16 steps, each step is around 0.2ns
+ */
+#define SKEW_MASK			0xF
+
+/* Global IDE PAD Skew Control Register */
+#define GLOBAL_IDE_SKEW_CTRL		0x18
+
+#define IDE1_HOST_STROBE_DELAY_SHIFT	28
+#define IDE1_DEVICE_STROBE_DELAY_SHIFT	24
+#define IDE1_OUTPUT_IO_SKEW_SHIFT	20
+#define IDE1_INPUT_IO_SKEW_SHIFT	16
+#define IDE0_HOST_STROBE_DELAY_SHIFT	12
+#define IDE0_DEVICE_STROBE_DELAY_SHIFT	8
+#define IDE0_OUTPUT_IO_SKEW_SHIFT	4
+#define IDE0_INPUT_IO_SKEW_SHIFT	0
+
+/* Global GMAC Control Pad Skew Control Register */
+#define GLOBAL_GMAC_CTRL_SKEW_CTRL	0x1C
+
+#define GMAC1_TXC_SKEW_SHIFT		28
+#define GMAC1_TXEN_SKEW_SHIFT		24
+#define GMAC1_RXC_SKEW_SHIFT		20
+#define GMAC1_RXDV_SKEW_SHIFT		16
+#define GMAC0_TXC_SKEW_SHIFT		12
+#define GMAC0_TXEN_SKEW_SHIFT		8
+#define GMAC0_RXC_SKEW_SHIFT		4
+#define GMAC0_RXDV_SKEW_SHIFT		0
+
+/* Global GMAC0 Data PAD Skew Control Register */
+#define GLOBAL_GMAC0_DATA_SKEW_CTRL	0x20
+/* Global GMAC1 Data PAD Skew Control Register */
+#define GLOBAL_GMAC1_DATA_SKEW_CTRL	0x24
+
+#define GMAC_TXD_SKEW_SHIFT(x)		(((x) * 4) + 16)
+#define GMAC_RXD_SKEW_SHIFT(x)		((x) * 4)
+
+/* CPU has two AHB busses. */
+
+/* Global Arbitration0 Control Register */
+#define GLOBAL_ARBITRATION0_CTRL	0x28
+
+#define BOOT_CONTROLLER_HIGH_PRIO	(1 << 3)
+#define DMA_BUS1_HIGH_PRIO		(1 << 2)
+#define CPU0_HIGH_PRIO			(1 << 0)
+
+/* Global Arbitration1 Control Register */
+#define GLOBAL_ARBITRATION1_CTRL	0x2C
+
+#define TVE_HIGH_PRIO			(1 << 9)
+#define PCI_HIGH_PRIO			(1 << 8)
+#define USB1_HIGH_PRIO			(1 << 7)
+#define USB0_HIGH_PRIO			(1 << 6)
+#define GMAC1_HIGH_PRIO			(1 << 5)
+#define GMAC0_HIGH_PRIO			(1 << 4)
+#define SECURITY_HIGH_PRIO		(1 << 3)
+#define RAID_HIGH_PRIO			(1 << 2)
+#define IDE_HIGH_PRIO			(1 << 1)
+#define DMA_BUS2_HIGH_PRIO		(1 << 0)
+
+/* Common bits for both arbitration registers */
+#define BURST_LENGTH_SHIFT		16
+#define BURST_LENGTH_MASK		(0x3F << 16)
+
+/* Miscellaneous Control Register */
+#define GLOBAL_MISC_CTRL		0x30
+
+#define MEMORY_SPACE_SWAP		(1 << 31)
+#define USB1_PLUG_MINIB			(1 << 30) /* else plug is mini-A */
+#define USB0_PLUG_MINIB			(1 << 29)
+#define GMAC_GMII			(1 << 28)
+#define GMAC_1_ENABLE			(1 << 27)
+/* TODO: define ATA/SATA bits */
+#define USB1_VBUS_ON			(1 << 23)
+#define USB0_VBUS_ON			(1 << 22)
+#define APB_CLKOUT_ENABLE		(1 << 21)
+#define TVC_CLKOUT_ENABLE		(1 << 20)
+#define EXT_CLKIN_ENABLE		(1 << 19)
+#define PCI_66MHZ			(1 << 18) /* else 33 MHz */
+#define PCI_CLKOUT_ENABLE		(1 << 17)
+#define LPC_CLKOUT_ENABLE		(1 << 16)
+#define USB1_WAKEUP_ON			(1 << 15)
+#define USB0_WAKEUP_ON			(1 << 14)
+/* TODO: define PCI idle detect bits */
+#define TVC_PADS_ENABLE			(1 << 9)
+#define SSP_PADS_ENABLE			(1 << 8)
+#define LCD_PADS_ENABLE			(1 << 7)
+#define LPC_PADS_ENABLE			(1 << 6)
+#define PCI_PADS_ENABLE			(1 << 5)
+#define IDE_PADS_ENABLE			(1 << 4)
+#define DRAM_PADS_POWER_DOWN		(1 << 3)
+#define NAND_PADS_DISABLE		(1 << 2)
+#define PFLASH_PADS_DISABLE		(1 << 1)
+#define SFLASH_PADS_DISABLE		(1 << 0)
+
+/* Global Clock Control Register */
+#define GLOBAL_CLOCK_CTRL		0x34
+
+#define POWER_STATE_G0			(1 << 31)
+#define POWER_STATE_S1			(1 << 30) /* else it is S3/S4 state */
+#define SECURITY_APB_AHB		(1 << 29)
+/* else Security APB clk will be 0.75xAHB */
+/* TODO: TVC clock divider */
+#define PCI_CLKRUN_ENABLE		(1 << 16)
+#define BOOT_CLK_DISABLE		(1 << 13)
+#define TVC_CLK_DISABLE			(1 << 12)
+#define FLASH_CLK_DISABLE		(1 << 11)
+#define DDR_CLK_DISABLE			(1 << 10)
+#define PCI_CLK_DISABLE			(1 << 9)
+#define IDE_CLK_DISABLE			(1 << 8)
+#define USB1_CLK_DISABLE		(1 << 7)
+#define USB0_CLK_DISABLE		(1 << 6)
+#define SATA1_CLK_DISABLE		(1 << 5)
+#define SATA0_CLK_DISABLE		(1 << 4)
+#define GMAC1_CLK_DISABLE		(1 << 3)
+#define GMAC0_CLK_DISABLE		(1 << 2)
+#define SECURITY_CLK_DISABLE		(1 << 1)
+
+/* TODO: other registers definitions if needed */
+
+#endif /* __MACH_GLOBAL_REG_H */
diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h
new file mode 100644
index 0000000..3bc2c70
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/gpio.h
@@ -0,0 +1,25 @@
+/*
+ * Gemini gpiolib specific defines
+ *
+ * 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.
+ */
+
+#ifndef __MACH_GPIO_H__
+#define __MACH_GPIO_H__
+
+#include <mach/irqs.h>
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+
+#define gpio_to_irq(x)	((x) + GPIO_IRQ_BASE)
+#define irq_to_gpio(x)	((x) - GPIO_IRQ_BASE)
+
+#endif /* __MACH_GPIO_H__ */
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
new file mode 100644
index 0000000..de67526
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/hardware.h
@@ -0,0 +1,75 @@
+/*
+ *  This file contains the hardware definitions for Gemini.
+ *
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#ifndef __MACH_HARDWARE_H
+#define __MACH_HARDWARE_H
+
+/*
+ * Memory Map definitions
+ */
+/* FIXME: Does it really swap SRAM like this? */
+#ifdef CONFIG_GEMINI_MEM_SWAP
+# define GEMINI_DRAM_BASE	0x00000000
+# define GEMINI_SRAM_BASE	0x20000000
+#else
+# define GEMINI_SRAM_BASE	0x00000000
+# define GEMINI_DRAM_BASE	0x10000000
+#endif
+#define GEMINI_FLASH_BASE	0x30000000
+#define GEMINI_GLOBAL_BASE	0x40000000
+#define GEMINI_WAQTCHDOG_BASE	0x41000000
+#define GEMINI_UART_BASE	0x42000000
+#define GEMINI_TIMER_BASE	0x43000000
+#define GEMINI_LCD_BASE		0x44000000
+#define GEMINI_RTC_BASE		0x45000000
+#define GEMINI_SATA_BASE	0x46000000
+#define GEMINI_LPC_HOST_BASE	0x47000000
+#define GEMINI_LPC_IO_BASE	0x47800000
+#define GEMINI_INTERRUPT_BASE	0x48000000
+/* TODO: Different interrupt controlers when SMP
+ * #define GEMINI_INTERRUPT0_BASE	0x48000000
+ * #define GEMINI_INTERRUPT1_BASE	0x49000000
+ */
+#define GEMINI_SSP_CTRL_BASE	0x4A000000
+#define GEMINI_POWER_CTRL_BASE	0x4B000000
+#define GEMINI_CIR_BASE		0x4C000000
+#define GEMINI_GPIO_BASE(x)	(0x4D000000 + (x) * 0x1000000)
+#define GEMINI_PCI_IO_BASE	0x50000000
+#define GEMINI_PCI_MEM_BASE	0x58000000
+#define GEMINI_TOE_BASE		0x60000000
+#define GEMINI_GMAC0_BASE	0x6000A000
+#define GEMINI_GMAC1_BASE	0x6000E000
+#define GEMINI_SECURITY_BASE	0x62000000
+#define GEMINI_IDE0_BASE	0x63000000
+#define GEMINI_IDE1_BASE	0x63400000
+#define GEMINI_RAID_BASE	0x64000000
+#define GEMINI_FLASH_CTRL_BASE	0x65000000
+#define GEMINI_DRAM_CTRL_BASE	0x66000000
+#define GEMINI_GENERAL_DMA_BASE	0x67000000
+#define GEMINI_USB0_BASE	0x68000000
+#define GEMINI_USB1_BASE	0x69000000
+#define GEMINI_BIG_ENDIAN_BASE	0x80000000
+
+#define GEMINI_TIMER1_BASE	GEMINI_TIMER_BASE
+#define GEMINI_TIMER2_BASE	(GEMINI_TIMER_BASE + 0x10)
+#define GEMINI_TIMER3_BASE	(GEMINI_TIMER_BASE + 0x20)
+
+/*
+ * UART Clock when System clk is 150MHz
+ */
+#define UART_CLK	48000000
+
+/*
+ * macro to get at IO space when running virtually
+ */
+#define IO_ADDRESS(x)	((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
+
+#endif
diff --git a/arch/arm/mach-gemini/include/mach/io.h b/arch/arm/mach-gemini/include/mach/io.h
new file mode 100644
index 0000000..c548056
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/io.h
@@ -0,0 +1,18 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define IO_SPACE_LIMIT	0xffffffff
+
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif /* __MACH_IO_H */
diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h
new file mode 100644
index 0000000..06bc47e
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/irqs.h
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+
+#ifndef __MACH_IRQS_H__
+#define __MACH_IRQS_H__
+
+#define IRQ_SERIRQ1	31
+#define IRQ_SERIRQ0	30
+#define IRQ_PCID	29
+#define IRQ_PCIC	28
+#define IRQ_PCIB	27
+#define IRQ_PWR		26
+#define IRQ_CIR		25
+#define IRQ_GPIO(x)	(22 + (x))
+#define IRQ_SSP		21
+#define IRQ_LPC		20
+#define IRQ_LCD		19
+#define IRQ_UART	18
+#define IRQ_RTC		17
+#define IRQ_TIMER3	16
+#define IRQ_TIMER2	15
+#define IRQ_TIMER1	14
+#define IRQ_FLASH	12
+#define IRQ_USB1	11
+#define IRQ_USB0	10
+#define IRQ_DMA		9
+#define IRQ_PCI		8
+#define IRQ_IPSEC	7
+#define IRQ_RAID	6
+#define IRQ_IDE1	5
+#define IRQ_IDE0	4
+#define IRQ_WATCHDOG	3
+#define IRQ_GMAC1	2
+#define IRQ_GMAC0	1
+#define IRQ_IPI		0
+
+#define NORMAL_IRQ_NUM	32
+
+#define GPIO_IRQ_BASE	NORMAL_IRQ_NUM
+#define GPIO_IRQ_NUM	(3 * 32)
+
+#define ARCH_TIMER_IRQ	IRQ_TIMER2
+
+#define NR_IRQS		(NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
+
+#endif /* __MACH_IRQS_H__ */
diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h
new file mode 100644
index 0000000..2d14d5b
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/memory.h
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#ifndef __MACH_MEMORY_H
+#define __MACH_MEMORY_H
+
+#ifdef CONFIG_GEMINI_MEM_SWAP
+# define PHYS_OFFSET	UL(0x00000000)
+#else
+# define PHYS_OFFSET	UL(0x10000000)
+#endif
+
+#endif /* __MACH_MEMORY_H */
diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/include/mach/system.h
new file mode 100644
index 0000000..bbbd727
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/system.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#ifndef __MACH_SYSTEM_H
+#define __MACH_SYSTEM_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/global_reg.h>
+
+static inline void arch_idle(void)
+{
+	/*
+	 * Because of broken hardware we have to enable interrupts or the CPU
+	 * will never wakeup... Acctualy it is not very good to enable
+	 * interrupts here since scheduler can miss a tick, but there is
+	 * no other way around this. Platforms that needs it for power saving
+	 * should call enable_hlt() in init code, since by default it is
+	 * disabled.
+	 */
+	local_irq_enable();
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	__raw_writel(RESET_GLOBAL | RESET_CPU1,
+		     IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
+}
+
+#endif /* __MACH_SYSTEM_H */
diff --git a/arch/arm/mach-gemini/include/mach/timex.h b/arch/arm/mach-gemini/include/mach/timex.h
new file mode 100644
index 0000000..dc5690b
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/timex.h
@@ -0,0 +1,13 @@
+/*
+ * 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-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h
new file mode 100644
index 0000000..59c5df7
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/uncompress.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on mach-pxa/include/mach/uncompress.h:
+ * Copyright:	(C) 2001 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#include <linux/serial_reg.h>
+#include <mach/hardware.h>
+
+static volatile unsigned long *UART = (unsigned long *)GEMINI_UART_BASE;
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ */
+static inline void putc(char c)
+{
+	while (!(UART[UART_LSR] & UART_LSR_THRE))
+		barrier();
+	UART[UART_TX] = c;
+}
+
+#define flush() do { } while (0)
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif /* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-gemini/include/mach/vmalloc.h b/arch/arm/mach-gemini/include/mach/vmalloc.h
new file mode 100644
index 0000000..83e536d
--- /dev/null
+++ b/arch/arm/mach-gemini/include/mach/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ *  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.
+ */
+
+#define VMALLOC_END	0xF0000000
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c
new file mode 100644
index 0000000..9e613ca
--- /dev/null
+++ b/arch/arm/mach-gemini/irq.c
@@ -0,0 +1,102 @@
+/*
+ *  Interrupt routines for Gemini
+ *
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/stddef.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+
+#define IRQ_SOURCE(base_addr)	(base_addr + 0x00)
+#define IRQ_MASK(base_addr)	(base_addr + 0x04)
+#define IRQ_CLEAR(base_addr)	(base_addr + 0x08)
+#define IRQ_TMODE(base_addr)	(base_addr + 0x0C)
+#define IRQ_TLEVEL(base_addr)	(base_addr + 0x10)
+#define IRQ_STATUS(base_addr)	(base_addr + 0x14)
+#define FIQ_SOURCE(base_addr)	(base_addr + 0x20)
+#define FIQ_MASK(base_addr)	(base_addr + 0x24)
+#define FIQ_CLEAR(base_addr)	(base_addr + 0x28)
+#define FIQ_TMODE(base_addr)	(base_addr + 0x2C)
+#define FIQ_LEVEL(base_addr)	(base_addr + 0x30)
+#define FIQ_STATUS(base_addr)	(base_addr + 0x34)
+
+static void gemini_ack_irq(unsigned int irq)
+{
+	__raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+}
+
+static void gemini_mask_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+	mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+	mask &= ~(1 << irq);
+	__raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+}
+
+static void gemini_unmask_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+	mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+	mask |= (1 << irq);
+	__raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+}
+
+static struct irq_chip gemini_irq_chip = {
+	.name	= "INTC",
+	.ack	= gemini_ack_irq,
+	.mask	= gemini_mask_irq,
+	.unmask	= gemini_unmask_irq,
+};
+
+static struct resource irq_resource = {
+	.name	= "irq_handler",
+	.start	= IO_ADDRESS(GEMINI_INTERRUPT_BASE),
+	.end	= IO_ADDRESS(FIQ_STATUS(GEMINI_INTERRUPT_BASE)) + 4,
+};
+
+void __init gemini_init_irq(void)
+{
+	unsigned int i, mode = 0, level = 0;
+
+	/*
+	 * Disable arch_idle() by default since it is buggy
+	 * For more info see arch/arm/mach-gemini/include/mach/system.h
+	 */
+	disable_hlt();
+
+	request_resource(&iomem_resource, &irq_resource);
+
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &gemini_irq_chip);
+		if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) {
+			set_irq_handler(i, handle_edge_irq);
+			mode |= 1 << i;
+			level |= 1 << i;
+		} else {			
+			set_irq_handler(i, handle_level_irq);
+		}
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Disable all interrupts */
+	__raw_writel(0, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+	__raw_writel(0, FIQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+
+	/* Set interrupt mode */
+	__raw_writel(mode, IRQ_TMODE(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+	__raw_writel(level, IRQ_TLEVEL(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
+}
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
new file mode 100644
index 0000000..5194824
--- /dev/null
+++ b/arch/arm/mach-gemini/mm.c
@@ -0,0 +1,82 @@
+/*
+ *  Static mappings for Gemini
+ *
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+
+/* Page table mapping for I/O region */
+static struct map_desc gemini_io_desc[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(GEMINI_GLOBAL_BASE),
+		.pfn		=__phys_to_pfn(GEMINI_GLOBAL_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_UART_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_UART_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_TIMER_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_TIMER_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_INTERRUPT_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_INTERRUPT_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_POWER_CTRL_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(0)),
+		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(0)),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(1)),
+		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(1)),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_GPIO_BASE(2)),
+		.pfn		= __phys_to_pfn(GEMINI_GPIO_BASE(2)),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_DRAM_CTRL_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual	= IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
+		.pfn		= __phys_to_pfn(GEMINI_GENERAL_DMA_BASE),
+		.length		= SZ_512K,
+		.type 		= MT_DEVICE,
+	},
+};
+
+void __init gemini_map_io(void)
+{
+	iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc));
+}
diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c
new file mode 100644
index 0000000..21dc5a8
--- /dev/null
+++ b/arch/arm/mach-gemini/time.c
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2001-2006 Storlink, Corp.
+ *  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.
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/global_reg.h>
+#include <asm/mach/time.h>
+
+/*
+ * Register definitions for the timers
+ */
+#define TIMER_COUNT(BASE_ADDR)		(BASE_ADDR  + 0x00)
+#define TIMER_LOAD(BASE_ADDR)		(BASE_ADDR  + 0x04)
+#define TIMER_MATCH1(BASE_ADDR)		(BASE_ADDR  + 0x08)
+#define TIMER_MATCH2(BASE_ADDR)		(BASE_ADDR  + 0x0C)
+#define TIMER_CR(BASE_ADDR)		(BASE_ADDR  + 0x30)
+
+#define TIMER_1_CR_ENABLE		(1 << 0)
+#define TIMER_1_CR_CLOCK		(1 << 1)
+#define TIMER_1_CR_INT			(1 << 2)
+#define TIMER_2_CR_ENABLE		(1 << 3)
+#define TIMER_2_CR_CLOCK		(1 << 4)
+#define TIMER_2_CR_INT			(1 << 5)
+#define TIMER_3_CR_ENABLE		(1 << 6)
+#define TIMER_3_CR_CLOCK		(1 << 7)
+#define TIMER_3_CR_INT			(1 << 8)
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
+{
+	timer_tick();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction gemini_timer_irq = {
+	.name		= "Gemini Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= gemini_timer_interrupt,
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init gemini_timer_init(void)
+{
+	unsigned int tick_rate, reg_v;
+
+	reg_v = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
+	tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000;
+
+	printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
+
+	tick_rate /= 6;		/* APB bus run AHB*(1/6) */
+
+	switch(reg_v & CPU_AHB_RATIO_MASK) {
+	case CPU_AHB_1_1:
+		printk(KERN_CONT "(1/1)\n");
+		break;
+	case CPU_AHB_3_2:
+		printk(KERN_CONT "(3/2)\n");
+		break;
+	case CPU_AHB_24_13:
+		printk(KERN_CONT "(24/13)\n");
+		break;
+	case CPU_AHB_2_1:
+		printk(KERN_CONT "(2/1)\n");
+		break;
+	}
+
+	/*
+	 * Make irqs happen for the system timer
+	 */
+	setup_irq(IRQ_TIMER2, &gemini_timer_irq);
+	/* Start the timer */
+	__raw_writel(tick_rate / HZ, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+	__raw_writel(tick_rate / HZ, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+	__raw_writel(TIMER_2_CR_ENABLE | TIMER_2_CR_INT, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+}
diff --git a/arch/arm/mach-h720x/include/mach/system.h b/arch/arm/mach-h720x/include/mach/system.h
index e4a7c76..a708d24 100644
--- a/arch/arm/mach-h720x/include/mach/system.h
+++ b/arch/arm/mach-h720x/include/mach/system.h
@@ -25,7 +25,7 @@
 }
 
 
-static __inline__ void arch_reset(char mode)
+static __inline__ void arch_reset(char mode, const char *cmd)
 {
 	CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET;
 }
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 887cb21..05f1739 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -29,7 +29,6 @@
 #include <linux/string.h>
 
 #include <asm/errno.h>
-#include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/imx-regs.h>
 
@@ -245,43 +244,8 @@
 	imx_mmc_device.dev.platform_data = info;
 }
 
-static struct imx_fb_platform_data imx_fb_info;
-
-void __init set_imx_fb_info(struct imx_fb_platform_data *hard_imx_fb_info)
-{
-	memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imx_fb_platform_data));
-}
-
-static struct resource imxfb_resources[] = {
-	[0] = {
-		.start	= 0x00205000,
-		.end	= 0x002050FF,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= LCDC_INT,
-		.end	= LCDC_INT,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 fb_dma_mask = ~(u64)0;
-
-static struct platform_device imxfb_device = {
-	.name		= "imx-fb",
-	.id		= 0,
-	.dev		= {
- 		.platform_data	= &imx_fb_info,
-		.dma_mask	= &fb_dma_mask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(imxfb_resources),
-	.resource	= imxfb_resources,
-};
-
 static struct platform_device *devices[] __initdata = {
 	&imx_mmc_device,
-	&imxfb_device,
 };
 
 static struct map_desc imx_io_desc[] __initdata = {
diff --git a/arch/arm/mach-imx/include/mach/system.h b/arch/arm/mach-imx/include/mach/system.h
index adee7e5..46d4ca9 100644
--- a/arch/arm/mach-imx/include/mach/system.h
+++ b/arch/arm/mach-imx/include/mach/system.h
@@ -32,7 +32,7 @@
 }
 
 static inline void
-arch_reset(char mode)
+arch_reset(char mode, const char *cmd)
 {
 	cpu_reset(0);
 }
diff --git a/arch/arm/mach-integrator/include/mach/system.h b/arch/arm/mach-integrator/include/mach/system.h
index c485345..e1551b8 100644
--- a/arch/arm/mach-integrator/include/mach/system.h
+++ b/arch/arm/mach-integrator/include/mach/system.h
@@ -32,7 +32,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * To reset, we hit the on-board reset register
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index e012bf1..42ae29b 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -59,7 +59,10 @@
 	})
 
 #define __arch_page_to_dma(dev, page)					\
-	__arch_virt_to_dma(dev, page_address(page))
+	({								\
+		/* __is_lbus_virt() can never be true for RAM pages */	\
+		(dma_addr_t)page_to_phys(page);				\
+	})
 
 #endif /* CONFIG_ARCH_IOP13XX */
 #endif /* !ASSEMBLY */
diff --git a/arch/arm/mach-iop13xx/include/mach/system.h b/arch/arm/mach-iop13xx/include/mach/system.h
index c7127f4..d0c66ef 100644
--- a/arch/arm/mach-iop13xx/include/mach/system.h
+++ b/arch/arm/mach-iop13xx/include/mach/system.h
@@ -13,7 +13,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * Reset the internal bus (warning both cores are reset)
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index 673b0db..4873f26 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -1026,8 +1026,10 @@
 		which_atu = 0;
 	}
 
-	if (!which_atu)
+	if (!which_atu) {
+		kfree(res);
 		return 0;
+	}
 
 	switch(which_atu) {
 	case IOP13XX_INIT_ATU_ATUX:
@@ -1074,6 +1076,7 @@
 		sys->map_irq = iop13xx_pcie_map_irq;
 		break;
 	default:
+		kfree(res);
 		return 0;
 	}
 
diff --git a/arch/arm/mach-iop32x/include/mach/system.h b/arch/arm/mach-iop32x/include/mach/system.h
index 32d9e5b..a4b808f 100644
--- a/arch/arm/mach-iop32x/include/mach/system.h
+++ b/arch/arm/mach-iop32x/include/mach/system.h
@@ -16,7 +16,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	local_irq_disable();
 
diff --git a/arch/arm/mach-iop33x/include/mach/system.h b/arch/arm/mach-iop33x/include/mach/system.h
index 0cb3ad8..f192a34 100644
--- a/arch/arm/mach-iop33x/include/mach/system.h
+++ b/arch/arm/mach-iop33x/include/mach/system.h
@@ -14,7 +14,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	*IOP3XX_PCSR = 0x30;
 
diff --git a/arch/arm/mach-ixp2000/include/mach/system.h b/arch/arm/mach-ixp2000/include/mach/system.h
index 2e9c68f..de37099 100644
--- a/arch/arm/mach-ixp2000/include/mach/system.h
+++ b/arch/arm/mach-ixp2000/include/mach/system.h
@@ -17,7 +17,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	local_irq_disable();
 
diff --git a/arch/arm/mach-ixp23xx/include/mach/system.h b/arch/arm/mach-ixp23xx/include/mach/system.h
index d57c3fc..8920ff2 100644
--- a/arch/arm/mach-ixp23xx/include/mach/system.h
+++ b/arch/arm/mach-ixp23xx/include/mach/system.h
@@ -19,7 +19,7 @@
 #endif
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/* First try machine specific support */
 	if (machine_is_ixdp2351()) {
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index d816c51..70afcfe 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -366,7 +366,7 @@
 }
 
 void __init ixp4xx_pci_preinit(void)
-{  
+{
 	unsigned long cpuid = read_cpuid_id();
 
 	/*
@@ -386,17 +386,17 @@
 
 	pr_debug("setup PCI-AHB(inbound) and AHB-PCI(outbound) address mappings\n");
 
-	/* 
+	/*
 	 * We use identity AHB->PCI address translation
 	 * in the 0x48000000 to 0x4bffffff address space
 	 */
 	*PCI_PCIMEMBASE = 0x48494A4B;
 
-	/* 
+	/*
 	 * We also use identity PCI->AHB address translation
 	 * in 4 16MB BARs that begin at the physical memory start
 	 */
-	*PCI_AHBMEMBASE = (PHYS_OFFSET & 0xFF000000) + 
+	*PCI_AHBMEMBASE = (PHYS_OFFSET & 0xFF000000) +
 		((PHYS_OFFSET & 0xFF000000) >> 8) +
 		((PHYS_OFFSET & 0xFF000000) >> 16) +
 		((PHYS_OFFSET & 0xFF000000) >> 24) +
@@ -408,18 +408,19 @@
 		pr_debug("setup BARs in controller\n");
 
 		/*
-		 * We configure the PCI inbound memory windows to be 
+		 * We configure the PCI inbound memory windows to be
 		 * 1:1 mapped to SDRAM
 		 */
-		local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET + 0x00000000);
-		local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + 0x01000000);
-		local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + 0x02000000);
-		local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + 0x03000000);
+		local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET);
+		local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M);
+		local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M);
+		local_write_config(PCI_BASE_ADDRESS_3, 4, PHYS_OFFSET + SZ_48M);
 
 		/*
-		 * Enable CSR window at 0xff000000.
+		 * Enable CSR window at 64 MiB to allow PCI masters
+		 * to continue prefetching past 64 MiB boundary.
 		 */
-		local_write_config(PCI_BASE_ADDRESS_4, 4, 0xff000008);
+		local_write_config(PCI_BASE_ADDRESS_4, 4, PHYS_OFFSET + SZ_64M);
 
 		/*
 		 * Enable the IO window to be way up high, at 0xfffffc00
@@ -500,7 +501,7 @@
 	return 1;
 }
 
-struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys)
+struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys)
 {
 	return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys);
 }
diff --git a/arch/arm/mach-ixp4xx/include/mach/cpu.h b/arch/arm/mach-ixp4xx/include/mach/cpu.h
index 51bd69c..def7773 100644
--- a/arch/arm/mach-ixp4xx/include/mach/cpu.h
+++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h
@@ -17,26 +17,31 @@
 #include <asm/cputype.h>
 
 /* Processor id value in CP15 Register 0 */
-#define IXP425_PROCESSOR_ID_VALUE	0x690541c0
-#define IXP435_PROCESSOR_ID_VALUE	0x69054040
-#define IXP465_PROCESSOR_ID_VALUE	0x69054200
-#define IXP4XX_PROCESSOR_ID_MASK	0xfffffff0
+#define IXP42X_PROCESSOR_ID_VALUE	0x690541c0 /* including unused 0x690541Ex */
+#define IXP42X_PROCESSOR_ID_MASK	0xffffffc0
 
-#define cpu_is_ixp42x()	((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \
-			  IXP425_PROCESSOR_ID_VALUE)
-#define cpu_is_ixp43x()	((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \
-			  IXP435_PROCESSOR_ID_VALUE)
-#define cpu_is_ixp46x()	((read_cpuid_id() & IXP4XX_PROCESSOR_ID_MASK) == \
-			  IXP465_PROCESSOR_ID_VALUE)
+#define IXP43X_PROCESSOR_ID_VALUE	0x69054040
+#define IXP43X_PROCESSOR_ID_MASK	0xfffffff0
+
+#define IXP46X_PROCESSOR_ID_VALUE	0x69054200 /* including IXP455 */
+#define IXP46X_PROCESSOR_ID_MASK	0xfffffff0
+
+#define cpu_is_ixp42x()	((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
+			 IXP42X_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp43x()	((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
+			 IXP43X_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp46x()	((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \
+			 IXP46X_PROCESSOR_ID_VALUE)
 
 static inline u32 ixp4xx_read_feature_bits(void)
 {
 	unsigned int val = ~*IXP4XX_EXP_CFG2;
-	val &= ~IXP4XX_FEATURE_RESERVED;
-	if (!cpu_is_ixp46x())
-		val &= ~IXP4XX_FEATURE_IXP46X_ONLY;
 
-	return val;
+	if (cpu_is_ixp42x())
+		return val & IXP42X_FEATURE_MASK;
+	if (cpu_is_ixp43x())
+		return val & IXP43X_FEATURE_MASK;
+	return val & IXP46X_FEATURE_MASK;
 }
 
 static inline void ixp4xx_write_feature_bits(u32 value)
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
index ad9c888..97c530f 100644
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -604,6 +604,7 @@
 #define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
 
 /* "fuse" bits of IXP_EXP_CFG2 */
+/* All IXP4xx CPUs */
 #define IXP4XX_FEATURE_RCOMP		(1 << 0)
 #define IXP4XX_FEATURE_USB_DEVICE	(1 << 1)
 #define IXP4XX_FEATURE_HASH		(1 << 2)
@@ -619,20 +620,41 @@
 #define IXP4XX_FEATURE_RESET_NPEB	(1 << 12)
 #define IXP4XX_FEATURE_RESET_NPEC	(1 << 13)
 #define IXP4XX_FEATURE_PCI		(1 << 14)
-#define IXP4XX_FEATURE_ECC_TIMESYNC	(1 << 15)
 #define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT	(3 << 16)
+#define IXP4XX_FEATURE_XSCALE_MAX_FREQ	(3 << 22)
+#define IXP42X_FEATURE_MASK		(IXP4XX_FEATURE_RCOMP            | \
+					 IXP4XX_FEATURE_USB_DEVICE       | \
+					 IXP4XX_FEATURE_HASH             | \
+					 IXP4XX_FEATURE_AES              | \
+					 IXP4XX_FEATURE_DES              | \
+					 IXP4XX_FEATURE_HDLC             | \
+					 IXP4XX_FEATURE_AAL              | \
+					 IXP4XX_FEATURE_HSS              | \
+					 IXP4XX_FEATURE_UTOPIA           | \
+					 IXP4XX_FEATURE_NPEB_ETH0        | \
+					 IXP4XX_FEATURE_NPEC_ETH         | \
+					 IXP4XX_FEATURE_RESET_NPEA       | \
+					 IXP4XX_FEATURE_RESET_NPEB       | \
+					 IXP4XX_FEATURE_RESET_NPEC       | \
+					 IXP4XX_FEATURE_PCI              | \
+					 IXP4XX_FEATURE_UTOPIA_PHY_LIMIT | \
+					 IXP4XX_FEATURE_XSCALE_MAX_FREQ)
+
+
+/* IXP43x/46x CPUs */
+#define IXP4XX_FEATURE_ECC_TIMESYNC	(1 << 15)
 #define IXP4XX_FEATURE_USB_HOST		(1 << 18)
 #define IXP4XX_FEATURE_NPEA_ETH		(1 << 19)
+#define IXP43X_FEATURE_MASK		(IXP42X_FEATURE_MASK             | \
+					 IXP4XX_FEATURE_ECC_TIMESYNC     | \
+					 IXP4XX_FEATURE_USB_HOST         | \
+					 IXP4XX_FEATURE_NPEA_ETH)
+
+/* IXP46x CPU (including IXP455) only */
 #define IXP4XX_FEATURE_NPEB_ETH_1_TO_3	(1 << 20)
 #define IXP4XX_FEATURE_RSA		(1 << 21)
-#define IXP4XX_FEATURE_XSCALE_MAX_FREQ	(3 << 22)
-#define IXP4XX_FEATURE_RESERVED		(0xFF << 24)
-
-#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC |	\
-				    IXP4XX_FEATURE_USB_HOST |		\
-				    IXP4XX_FEATURE_NPEA_ETH |		\
-				    IXP4XX_FEATURE_NPEB_ETH_1_TO_3 |	\
-				    IXP4XX_FEATURE_RSA |		\
-				    IXP4XX_FEATURE_XSCALE_MAX_FREQ)
+#define IXP46X_FEATURE_MASK		(IXP43X_FEATURE_MASK             | \
+					 IXP4XX_FEATURE_NPEB_ETH_1_TO_3  | \
+					 IXP4XX_FEATURE_RSA)
 
 #endif
diff --git a/arch/arm/mach-ixp4xx/include/mach/system.h b/arch/arm/mach-ixp4xx/include/mach/system.h
index 92a7e8d..d2aa26f 100644
--- a/arch/arm/mach-ixp4xx/include/mach/system.h
+++ b/arch/arm/mach-ixp4xx/include/mach/system.h
@@ -20,7 +20,7 @@
 }
 
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	if ( 1 && mode == 's') {
 		/* Jump into ROM at address 0 */
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index c73a94d..2523102 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -575,8 +575,8 @@
 		for (i = 0; i < image->size; i++)
 			image->data[i] = swab32(image->data[i]);
 
-	if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) {
-		print_npe(KERN_INFO, npe, "IXP46x firmware ignored on "
+	if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
+		print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
 			  "IXP42x\n");
 		goto err;
 	}
@@ -596,7 +596,7 @@
 		  "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
 		  (image->id >> 8) & 0xFF, image->id & 0xFF);
 
-	if (!cpu_is_ixp46x()) {
+	if (cpu_is_ixp42x()) {
 		if (!npe->id)
 			instr_size = NPE_A_42X_INSTR_SIZE;
 		else
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 3600cd9..b5421cc 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -20,6 +20,18 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell RD-88F6281 Reference Board.
 
+config MACH_SHEEVAPLUG
+	bool "Marvell SheevaPlug Reference Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell SheevaPlug Reference Board.
+
+config MACH_TS219
+	bool "QNAP TS-119 and TS-219 Turbo NAS"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  QNAP TS-119 and TS-219 Turbo NAS devices.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index b96c55d..8f03c9b 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -1,5 +1,7 @@
-obj-y				+= common.o addr-map.o irq.o pcie.o
+obj-y				+= common.o addr-map.o irq.o pcie.o mpp.o
 
 obj-$(CONFIG_MACH_DB88F6281_BP)		+= db88f6281-bp-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
+obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
+obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 0d2074f..3d2fae8 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -14,6 +14,7 @@
 #include <linux/serial_8250.h>
 #include <linux/mbus.h>
 #include <linux/mv643xx_eth.h>
+#include <linux/mv643xx_i2c.h>
 #include <linux/ata_platform.h>
 #include <linux/spi/orion_spi.h>
 #include <net/dsa.h>
@@ -24,6 +25,7 @@
 #include <mach/kirkwood.h>
 #include <plat/cache-feroceon-l2.h>
 #include <plat/ehci-orion.h>
+#include <plat/mvsdio.h>
 #include <plat/mv_xor.h>
 #include <plat/orion_nand.h>
 #include <plat/time.h>
@@ -257,7 +259,7 @@
 	.flags	= IORESOURCE_MEM,
 };
 
-void __init kirkwood_rtc_init(void)
+static void __init kirkwood_rtc_init(void)
 {
 	platform_device_register_simple("rtc-mv", -1, &kirkwood_rtc_resource, 1);
 }
@@ -299,6 +301,50 @@
 
 
 /*****************************************************************************
+ * SD/SDIO/MMC
+ ****************************************************************************/
+static struct resource mvsdio_resources[] = {
+	[0] = {
+		.start	= SDIO_PHYS_BASE,
+		.end	= SDIO_PHYS_BASE + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_KIRKWOOD_SDIO,
+		.end	= IRQ_KIRKWOOD_SDIO,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 mvsdio_dmamask = 0xffffffffUL;
+
+static struct platform_device kirkwood_sdio = {
+	.name		= "mvsdio",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &mvsdio_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(mvsdio_resources),
+	.resource	= mvsdio_resources,
+};
+
+void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
+{
+	u32 dev, rev;
+
+	kirkwood_pcie_id(&dev, &rev);
+	if (rev == 0)  /* catch all Kirkwood Z0's */
+		mvsdio_data->clock = 100000000;
+	else
+		mvsdio_data->clock = 200000000;
+	mvsdio_data->dram = &kirkwood_mbus_dram_info;
+	kirkwood_sdio.dev.platform_data = mvsdio_data;
+	platform_device_register(&kirkwood_sdio);
+}
+
+
+/*****************************************************************************
  * SPI
  ****************************************************************************/
 static struct orion_spi_info kirkwood_spi_plat_data = {
@@ -329,6 +375,45 @@
 
 
 /*****************************************************************************
+ * I2C
+ ****************************************************************************/
+static struct mv64xxx_i2c_pdata kirkwood_i2c_pdata = {
+	.freq_m		= 8, /* assumes 166 MHz TCLK */
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource kirkwood_i2c_resources[] = {
+	{
+		.name	= "i2c",
+		.start	= I2C_PHYS_BASE,
+		.end	= I2C_PHYS_BASE + 0x1f,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "i2c",
+		.start	= IRQ_KIRKWOOD_TWSI,
+		.end	= IRQ_KIRKWOOD_TWSI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device kirkwood_i2c = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(kirkwood_i2c_resources),
+	.resource	= kirkwood_i2c_resources,
+	.dev		= {
+		.platform_data	= &kirkwood_i2c_pdata,
+	},
+};
+
+void __init kirkwood_i2c_init(void)
+{
+	platform_device_register(&kirkwood_i2c);
+}
+
+
+/*****************************************************************************
  * UART0
  ****************************************************************************/
 static struct plat_serial8250_port kirkwood_uart0_data[] = {
@@ -505,7 +590,7 @@
 	},
 };
 
-void __init kirkwood_xor0_init(void)
+static void __init kirkwood_xor0_init(void)
 {
 	platform_device_register(&kirkwood_xor0_shared);
 
@@ -603,7 +688,7 @@
 	},
 };
 
-void __init kirkwood_xor1_init(void)
+static void __init kirkwood_xor1_init(void)
 {
 	platform_device_register(&kirkwood_xor1_shared);
 
@@ -711,4 +796,9 @@
 #ifdef CONFIG_CACHE_FEROCEON_L2
 	kirkwood_l2_init();
 #endif
+
+	/* internal devices that every board has */
+	kirkwood_rtc_init();
+	kirkwood_xor0_init();
+	kirkwood_xor1_init();
 }
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index fe367c1..6ee8840 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -14,6 +14,7 @@
 struct dsa_platform_data;
 struct mv643xx_eth_platform_data;
 struct mv_sata_platform_data;
+struct mvsdio_platform_data;
 
 /*
  * Basic Kirkwood init functions used early by machine-setup.
@@ -33,14 +34,14 @@
 void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data);
 void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
 void kirkwood_pcie_init(void);
-void kirkwood_rtc_init(void);
 void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
+void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
 void kirkwood_spi_init(void);
+void kirkwood_i2c_init(void);
 void kirkwood_uart0_init(void);
 void kirkwood_uart1_init(void);
-void kirkwood_xor0_init(void);
-void kirkwood_xor1_init(void);
 
+extern int kirkwood_tclk;
 extern struct sys_timer kirkwood_timer;
 
 
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index a14c294..5505d58 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -11,18 +11,59 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
-#include <linux/timer.h>
+#include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
 #include <mach/kirkwood.h>
+#include <plat/orion_nand.h>
+#include <plat/mvsdio.h>
 #include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition db88f6281_nand_parts[] = {
+	{
+		.name = "u-boot",
+		.offset = 0,
+		.size = SZ_1M
+	}, {
+		.name = "uImage",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = SZ_4M
+	}, {
+		.name = "root",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = MTDPART_SIZ_FULL
+	},
+};
+
+static struct resource db88f6281_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
+	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
+			  KIRKWOOD_NAND_MEM_SIZE - 1,
+};
+
+static struct orion_nand_data db88f6281_nand_data = {
+	.parts		= db88f6281_nand_parts,
+	.nr_parts	= ARRAY_SIZE(db88f6281_nand_parts),
+	.cle		= 0,
+	.ale		= 1,
+	.width		= 8,
+	.chip_delay	= 25,
+};
+
+static struct platform_device db88f6281_nand_flash = {
+	.name		= "orion_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &db88f6281_nand_data,
+	},
+	.resource	= &db88f6281_nand_resource,
+	.num_resources	= 1,
+};
 
 static struct mv643xx_eth_platform_data db88f6281_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
@@ -32,18 +73,32 @@
 	.n_ports	= 2,
 };
 
+static struct mvsdio_platform_data db88f6281_mvsdio_data = {
+	.gpio_write_protect	= 37,
+	.gpio_card_detect	= 38,
+};
+
+static unsigned int db88f6281_mpp_config[] __initdata = {
+	MPP37_GPIO,
+	MPP38_GPIO,
+	0
+};
+
 static void __init db88f6281_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
 	kirkwood_init();
+	kirkwood_mpp_conf(db88f6281_mpp_config);
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&db88f6281_ge00_data);
-	kirkwood_rtc_init();
 	kirkwood_sata_init(&db88f6281_sata_data);
 	kirkwood_uart0_init();
+	kirkwood_sdio_init(&db88f6281_mvsdio_data);
+	
+	platform_device_register(&db88f6281_nand_flash);
 }
 
 static int __init db88f6281_pci_init(void)
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index ada480c..38c9868 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -93,6 +93,7 @@
 #define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
 #define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0300)
 #define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0600)
+#define  I2C_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x1000)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
 #define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2000)
 #define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2100)
@@ -116,5 +117,7 @@
 
 #define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x80000)
 
+#define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x90000)
+
 
 #endif
diff --git a/arch/arm/mach-kirkwood/include/mach/system.h b/arch/arm/mach-kirkwood/include/mach/system.h
index 8510f6c..23a1914 100644
--- a/arch/arm/mach-kirkwood/include/mach/system.h
+++ b/arch/arm/mach-kirkwood/include/mach/system.h
@@ -17,7 +17,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * Enable soft reset to assert RSTOUTn.
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
new file mode 100644
index 0000000..63c4493
--- /dev/null
+++ b/arch/arm/mach-kirkwood/mpp.c
@@ -0,0 +1,97 @@
+/*
+ * arch/arm/mach-kirkwood/mpp.c
+ *
+ * MPP functions for Marvell Kirkwood SoCs
+ *
+ * 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/mbus.h>
+#include <linux/io.h>
+#include <asm/gpio.h>
+#include <mach/hardware.h>
+#include "common.h"
+#include "mpp.h"
+
+static unsigned int __init kirkwood_variant(void)
+{
+	u32 dev, rev;
+
+	kirkwood_pcie_id(&dev, &rev);
+
+	if (dev == MV88F6281_DEV_ID && rev >= MV88F6281_REV_A0)
+		return MPP_F6281_MASK;
+	if (dev == MV88F6192_DEV_ID && rev >= MV88F6192_REV_A0)
+		return MPP_F6192_MASK;
+	if (dev == MV88F6180_DEV_ID)
+		return MPP_F6180_MASK;
+
+	printk(KERN_ERR "MPP setup: unknown kirkwood variant "
+			"(dev %#x rev %#x)\n", dev, rev);
+	return 0;
+}
+
+#define MPP_CTRL(i)	(DEV_BUS_VIRT_BASE + (i) * 4)
+#define MPP_NR_REGS	(1 + MPP_MAX/8)
+
+void __init kirkwood_mpp_conf(unsigned int *mpp_list)
+{
+	u32 mpp_ctrl[MPP_NR_REGS];
+	unsigned int variant_mask;
+	int i;
+
+	variant_mask = kirkwood_variant();
+	if (!variant_mask)
+		return;
+
+	printk(KERN_DEBUG "initial MPP regs:");
+	for (i = 0; i < MPP_NR_REGS; i++) {
+		mpp_ctrl[i] = readl(MPP_CTRL(i));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+
+	while (*mpp_list) {
+		unsigned int num = MPP_NUM(*mpp_list);
+		unsigned int sel = MPP_SEL(*mpp_list);
+		int shift, gpio_mode;
+
+		if (num > MPP_MAX) {
+			printk(KERN_ERR "kirkwood_mpp_conf: invalid MPP "
+					"number (%u)\n", num);
+			continue;
+		}
+		if (!(*mpp_list & variant_mask)) {
+			printk(KERN_WARNING
+			       "kirkwood_mpp_conf: requested MPP%u config "
+			       "unavailable on this hardware\n", num);
+			continue;
+		}
+
+		shift = (num & 7) << 2;
+		mpp_ctrl[num / 8] &= ~(0xf << shift);
+		mpp_ctrl[num / 8] |= sel << shift;
+
+		gpio_mode = 0;
+		if (*mpp_list & MPP_INPUT_MASK)
+			gpio_mode |= GPIO_INPUT_OK;
+		if (*mpp_list & MPP_OUTPUT_MASK)
+			gpio_mode |= GPIO_OUTPUT_OK;
+		if (sel != 0)
+			gpio_mode = 0;
+		orion_gpio_set_valid(num, gpio_mode);
+
+		mpp_list++;
+	}
+
+	printk(KERN_DEBUG "  final MPP regs:");
+	for (i = 0; i < MPP_NR_REGS; i++) {
+		writel(mpp_ctrl[i], MPP_CTRL(i));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+}
diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
new file mode 100644
index 0000000..e021a80
--- /dev/null
+++ b/arch/arm/mach-kirkwood/mpp.h
@@ -0,0 +1,303 @@
+/*
+ * linux/arch/arm/mach-kirkwood/mpp.h -- Multi Purpose Pins
+ *
+ * Copyright 2009: Marvell Technology Group 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 __KIRKWOOD_MPP_H
+#define __KIRKWOOD_MPP_H
+
+#define MPP(_num, _sel, _in, _out, _F6180, _F6190, _F6192, _F6281) ( \
+	/* MPP number */		((_num) & 0xff) | \
+	/* MPP select value */		(((_sel) & 0xf) << 8) | \
+	/* may be input signal */	((!!(_in)) << 12) | \
+	/* may be output signal */	((!!(_out)) << 13) | \
+	/* available on F6180 */	((!!(_F6180)) << 14) | \
+	/* available on F6190 */	((!!(_F6190)) << 15) | \
+	/* available on F6192 */	((!!(_F6192)) << 16) | \
+	/* available on F6281 */	((!!(_F6281)) << 17))
+
+#define MPP_NUM(x)	((x) & 0xff)
+#define MPP_SEL(x)	(((x) >> 8) & 0xf)
+
+				/*   num sel  i  o  6180 6190 6192 6281 */
+
+#define MPP_INPUT_MASK		MPP(  0, 0x0, 1, 0, 0,   0,   0,   0    )
+#define MPP_OUTPUT_MASK		MPP(  0, 0x0, 0, 1, 0,   0,   0,   0    )
+
+#define MPP_F6180_MASK		MPP(  0, 0x0, 0, 0, 1,   0,   0,   0    )
+#define MPP_F6190_MASK		MPP(  0, 0x0, 0, 0, 0,   1,   0,   0    )
+#define MPP_F6192_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   1,   0    )
+#define MPP_F6281_MASK		MPP(  0, 0x0, 0, 0, 0,   0,   0,   1    )
+
+#define MPP0_GPIO		MPP(  0, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP0_NF_IO2		MPP(  0, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP0_SPI_SCn		MPP(  0, 0x2, 0, 1, 1,   1,   1,   1    )
+
+#define MPP1_GPO		MPP(  1, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP1_NF_IO3		MPP(  1, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP1_SPI_MOSI		MPP(  1, 0x2, 0, 1, 1,   1,   1,   1    )
+
+#define MPP2_GPO		MPP(  2, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP2_NF_IO4		MPP(  2, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP2_SPI_SCK		MPP(  2, 0x2, 0, 1, 1,   1,   1,   1    )
+
+#define MPP3_GPO		MPP(  3, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP3_NF_IO5		MPP(  3, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP3_SPI_MISO		MPP(  3, 0x2, 1, 0, 1,   1,   1,   1    )
+
+#define MPP4_GPIO		MPP(  4, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP4_NF_IO6		MPP(  4, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP4_UART0_RXD		MPP(  4, 0x2, 1, 0, 1,   1,   1,   1    )
+#define MPP4_SATA1_ACTn		MPP(  4, 0x5, 0, 1, 0,   0,   1,   1    )
+#define MPP4_PTP_CLK		MPP(  4, 0xd, 1, 0, 1,   1,   1,   1    )
+
+#define MPP5_GPO		MPP(  5, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP5_NF_IO7		MPP(  5, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP5_UART0_TXD		MPP(  5, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP5_PTP_TRIG_GEN	MPP(  5, 0x4, 0, 1, 1,   1,   1,   1    )
+#define MPP5_SATA0_ACTn		MPP(  5, 0x5, 0, 1, 0,   1,   1,   1    )
+
+#define MPP6_SYSRST_OUTn	MPP(  6, 0x1, 0, 1, 1,   1,   1,   1    )
+#define MPP6_SPI_MOSI		MPP(  6, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP6_PTP_TRIG_GEN	MPP(  6, 0x3, 0, 1, 1,   1,   1,   1    )
+
+#define MPP7_GPO		MPP(  7, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP7_PEX_RST_OUTn	MPP(  7, 0x1, 0, 1, 1,   1,   1,   1    )
+#define MPP7_SPI_SCn		MPP(  7, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP7_PTP_TRIG_GEN	MPP(  7, 0x3, 0, 1, 1,   1,   1,   1    )
+
+#define MPP8_GPIO		MPP(  8, 0x0, 1, 1, 1,    1,  1,   1    )
+#define MPP8_TW_SDA		MPP(  8, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP8_UART0_RTS		MPP(  8, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP8_UART1_RTS		MPP(  8, 0x3, 0, 1, 1,   1,   1,   1    )
+#define MPP8_MII0_RXERR		MPP(  8, 0x4, 1, 0, 0,   1,   1,   1    )
+#define MPP8_SATA1_PRESENTn	MPP(  8, 0x5, 0, 1, 0,   0,   1,   1    )
+#define MPP8_PTP_CLK		MPP(  8, 0xc, 1, 0, 1,   1,   1,   1    )
+#define MPP8_MII0_COL		MPP(  8, 0xd, 1, 0, 1,   1,   1,   1    )
+
+#define MPP9_GPIO		MPP(  9, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP9_TW_SCK		MPP(  9, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP9_UART0_CTS		MPP(  9, 0x2, 1, 0, 1,   1,   1,   1    )
+#define MPP9_UART1_CTS		MPP(  9, 0x3, 1, 0, 1,   1,   1,   1    )
+#define MPP9_SATA0_PRESENTn	MPP(  9, 0x5, 0, 1, 0,   1,   1,   1    )
+#define MPP9_PTP_EVENT_REQ	MPP(  9, 0xc, 1, 0, 1,   1,   1,   1    )
+#define MPP9_MII0_CRS		MPP(  9, 0xd, 1, 0, 1,   1,   1,   1    )
+
+#define MPP10_GPO		MPP( 10, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP10_SPI_SCK		MPP( 10, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP10_UART0_TXD		MPP( 10, 0X3, 0, 1, 1,   1,   1,   1    )
+#define MPP10_SATA1_ACTn	MPP( 10, 0x5, 0, 1, 0,   0,   1,   1    )
+#define MPP10_PTP_TRIG_GEN	MPP( 10, 0xc, 0, 1, 1,   1,   1,   1    )
+
+#define MPP11_GPIO		MPP( 11, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP11_SPI_MISO		MPP( 11, 0x2, 1, 0, 1,   1,   1,   1    )
+#define MPP11_UART0_RXD		MPP( 11, 0x3, 1, 0, 1,   1,   1,   1    )
+#define MPP11_PTP_EVENT_REQ	MPP( 11, 0x4, 1, 0, 1,   1,   1,   1    )
+#define MPP11_PTP_TRIG_GEN	MPP( 11, 0xc, 0, 1, 1,   1,   1,   1    )
+#define MPP11_PTP_CLK		MPP( 11, 0xd, 1, 0, 1,   1,   1,   1    )
+#define MPP11_SATA0_ACTn	MPP( 11, 0x5, 0, 1, 0,   1,   1,   1    )
+
+#define MPP12_GPO		MPP( 12, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP12_SD_CLK		MPP( 12, 0x1, 0, 1, 1,   1,   1,   1    )
+
+#define MPP13_GPIO		MPP( 13, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP13_SD_CMD		MPP( 13, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP13_UART1_TXD		MPP( 13, 0x3, 0, 1, 1,   1,   1,   1    )
+
+#define MPP14_GPIO		MPP( 14, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP14_SD_D0		MPP( 14, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP14_UART1_RXD		MPP( 14, 0x3, 1, 0, 1,   1,   1,   1    )
+#define MPP14_SATA1_PRESENTn	MPP( 14, 0x4, 0, 1, 0,   0,   1,   1    )
+#define MPP14_MII0_COL		MPP( 14, 0xd, 1, 0, 1,   1,   1,   1    )
+
+#define MPP15_GPIO		MPP( 15, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP15_SD_D1		MPP( 15, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP15_UART0_RTS		MPP( 15, 0x2, 0, 1, 1,   1,   1,   1    )
+#define MPP15_UART1_TXD		MPP( 15, 0x3, 0, 1, 1,   1,   1,   1    )
+#define MPP15_SATA0_ACTn	MPP( 15, 0x4, 0, 1, 0,   1,   1,   1    )
+
+#define MPP16_GPIO		MPP( 16, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP16_SD_D2		MPP( 16, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP16_UART0_CTS		MPP( 16, 0x2, 1, 0, 1,   1,   1,   1    )
+#define MPP16_UART1_RXD		MPP( 16, 0x3, 1, 0, 1,   1,   1,   1    )
+#define MPP16_SATA1_ACTn	MPP( 16, 0x4, 0, 1, 0,   0,   1,   1    )
+#define MPP16_MII0_CRS		MPP( 16, 0xd, 1, 0, 1,   1,   1,   1    )
+
+#define MPP17_GPIO		MPP( 17, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP17_SD_D3		MPP( 17, 0x1, 1, 1, 1,   1,   1,   1    )
+#define MPP17_SATA0_PRESENTn	MPP( 17, 0x4, 0, 1, 0,   1,   1,   1    )
+
+#define MPP18_GPO		MPP( 18, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP18_NF_IO0		MPP( 18, 0x1, 1, 1, 1,   1,   1,   1    )
+
+#define MPP19_GPO		MPP( 19, 0x0, 0, 1, 1,   1,   1,   1    )
+#define MPP19_NF_IO1		MPP( 19, 0x1, 1, 1, 1,   1,   1,   1    )
+
+#define MPP20_GPIO		MPP( 20, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP20_TSMP0		MPP( 20, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP20_TDM_CH0_TX_QL	MPP( 20, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP20_GE1_0		MPP( 20, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP20_AUDIO_SPDIFI	MPP( 20, 0x4, 1, 0, 0,   0,   1,   1    )
+#define MPP20_SATA1_ACTn	MPP( 20, 0x5, 0, 1, 0,   0,   1,   1    )
+
+#define MPP21_GPIO		MPP( 21, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP21_TSMP1		MPP( 21, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP21_TDM_CH0_RX_QL	MPP( 21, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP21_GE1_1		MPP( 21, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP21_AUDIO_SPDIFO	MPP( 21, 0x4, 0, 1, 0,   0,   1,   1    )
+#define MPP21_SATA0_ACTn	MPP( 21, 0x5, 0, 1, 0,   1,   1,   1    )
+
+#define MPP22_GPIO		MPP( 22, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP22_TSMP2		MPP( 22, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP22_TDM_CH2_TX_QL	MPP( 22, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP22_GE1_2		MPP( 22, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP22_AUDIO_SPDIFRMKCLK	MPP( 22, 0x4, 0, 1, 0,   0,   1,   1    )
+#define MPP22_SATA1_PRESENTn	MPP( 22, 0x5, 0, 1, 0,   0,   1,   1    )
+
+#define MPP23_GPIO		MPP( 23, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP23_TSMP3		MPP( 23, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP23_TDM_CH2_RX_QL	MPP( 23, 0x2, 1, 0, 0,   0,   1,   1    )
+#define MPP23_GE1_3		MPP( 23, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP23_AUDIO_I2SBCLK	MPP( 23, 0x4, 0, 1, 0,   0,   1,   1    )
+#define MPP23_SATA0_PRESENTn	MPP( 23, 0x5, 0, 1, 0,   1,   1,   1    )
+
+#define MPP24_GPIO		MPP( 24, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP24_TSMP4		MPP( 24, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP24_TDM_SPI_CS0	DEV( 24, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP24_GE1_4		MPP( 24, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP24_AUDIO_I2SDO	MPP( 24, 0x4, 0, 1, 0,   0,   1,   1    )
+
+#define MPP25_GPIO		MPP( 25, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP25_TSMP5		MPP( 25, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP25_TDM_SPI_SCK	MPP( 25, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP25_GE1_5		MPP( 25, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP25_AUDIO_I2SLRCLK	MPP( 25, 0x4, 0, 1, 0,   0,   1,   1    )
+
+#define MPP26_GPIO		MPP( 26, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP26_TSMP6		MPP( 26, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP26_TDM_SPI_MISO	MPP( 26, 0x2, 1, 0, 0,   0,   1,   1    )
+#define MPP26_GE1_6		MPP( 26, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP26_AUDIO_I2SMCLK	MPP( 26, 0x4, 0, 1, 0,   0,   1,   1    )
+
+#define MPP27_GPIO		MPP( 27, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP27_TSMP7		MPP( 27, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP27_TDM_SPI_MOSI	MPP( 27, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP27_GE1_7		MPP( 27, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP27_AUDIO_I2SDI	MPP( 27, 0x4, 1, 0, 0,   0,   1,   1    )
+
+#define MPP28_GPIO		MPP( 28, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP28_TSMP8		MPP( 28, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP28_TDM_CODEC_INTn	MPP( 28, 0x2, 0, 0, 0,   0,   1,   1    )
+#define MPP28_GE1_8		MPP( 28, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP28_AUDIO_EXTCLK	MPP( 28, 0x4, 1, 0, 0,   0,   1,   1    )
+
+#define MPP29_GPIO		MPP( 29, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP29_TSMP9		MPP( 29, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP29_TDM_CODEC_RSTn	MPP( 29, 0x2, 0, 0, 0,   0,   1,   1    )
+#define MPP29_GE1_9		MPP( 29, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP30_GPIO		MPP( 30, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP30_TSMP10		MPP( 30, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP30_TDM_PCLK		MPP( 30, 0x2, 1, 1, 0,   0,   1,   1    )
+#define MPP30_GE1_10		MPP( 30, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP31_GPIO		MPP( 31, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP31_TSMP11		MPP( 31, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP31_TDM_FS		MPP( 31, 0x2, 1, 1, 0,   0,   1,   1    )
+#define MPP31_GE1_11		MPP( 31, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP32_GPIO		MPP( 32, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP32_TSMP12		MPP( 32, 0x1, 1, 1, 0,   0,   1,   1    )
+#define MPP32_TDM_DRX		MPP( 32, 0x2, 1, 0, 0,   0,   1,   1    )
+#define MPP32_GE1_12		MPP( 32, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP33_GPIO		MPP( 33, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP33_TDM_DTX		MPP( 33, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP33_GE1_13		MPP( 33, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP34_GPIO		MPP( 34, 0x0, 1, 1, 0,   1,   1,   1    )
+#define MPP34_TDM_SPI_CS1	MPP( 34, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP34_GE1_14		MPP( 34, 0x3, 0, 0, 0,   1,   1,   1    )
+
+#define MPP35_GPIO		MPP( 35, 0x0, 1, 1, 1,   1,   1,   1    )
+#define MPP35_TDM_CH0_TX_QL	MPP( 35, 0x2, 0, 1, 0,   0,   1,   1    )
+#define MPP35_GE1_15		MPP( 35, 0x3, 0, 0, 0,   1,   1,   1    )
+#define MPP35_SATA0_ACTn	MPP( 35, 0x5, 0, 1, 0,   1,   1,   1    )
+#define MPP35_MII0_RXERR	MPP( 35, 0xc, 1, 0, 1,   1,   1,   1    )
+
+#define MPP36_GPIO		MPP( 36, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP36_TSMP0		MPP( 36, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP36_TDM_SPI_CS1	MPP( 36, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP36_AUDIO_SPDIFI	MPP( 36, 0x4, 1, 0, 1,   0,   0,   1    )
+
+#define MPP37_GPIO		MPP( 37, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP37_TSMP1		MPP( 37, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP37_TDM_CH2_TX_QL	MPP( 37, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP37_AUDIO_SPDIFO	MPP( 37, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP38_GPIO		MPP( 38, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP38_TSMP2		MPP( 38, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP38_TDM_CH2_RX_QL	MPP( 38, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP38_AUDIO_SPDIFRMLCLK	MPP( 38, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP39_GPIO		MPP( 39, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP39_TSMP3		MPP( 39, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP39_TDM_SPI_CS0	MPP( 39, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP39_AUDIO_I2SBCLK	MPP( 39, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP40_GPIO		MPP( 40, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP40_TSMP4		MPP( 40, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP40_TDM_SPI_SCK	MPP( 40, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP40_AUDIO_I2SDO	MPP( 40, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP41_GPIO		MPP( 41, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP41_TSMP5		MPP( 41, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP41_TDM_SPI_MISO	MPP( 41, 0x2, 1, 0, 0,   0,   0,   1    )
+#define MPP41_AUDIO_I2SLRC	MPP( 41, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP42_GPIO		MPP( 42, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP42_TSMP6		MPP( 42, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP42_TDM_SPI_MOSI	MPP( 42, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP42_AUDIO_I2SMCLK	MPP( 42, 0x4, 0, 1, 1,   0,   0,   1    )
+
+#define MPP43_GPIO		MPP( 43, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP43_TSMP7		MPP( 43, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP43_TDM_CODEC_INTn	MPP( 43, 0x2, 0, 0, 0,   0,   0,   1    )
+#define MPP43_AUDIO_I2SDI	MPP( 43, 0x4, 1, 0, 1,   0,   0,   1    )
+
+#define MPP44_GPIO		MPP( 44, 0x0, 1, 1, 1,   0,   0,   1    )
+#define MPP44_TSMP8		MPP( 44, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP44_TDM_CODEC_RSTn	MPP( 44, 0x2, 0, 0, 0,   0,   0,   1    )
+#define MPP44_AUDIO_EXTCLK	MPP( 44, 0x4, 1, 0, 1,   0,   0,   1    )
+
+#define MPP45_GPIO		MPP( 45, 0x0, 1, 1, 0,   0,   0,   1    )
+#define MPP45_TSMP9		MPP( 45, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP45_TDM_PCLK		MPP( 45, 0x2, 1, 1, 0,   0,   0,   1    )
+
+#define MPP46_GPIO		MPP( 46, 0x0, 1, 1, 0,   0,   0,   1    )
+#define MPP46_TSMP10		MPP( 46, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP46_TDM_FS		MPP( 46, 0x2, 1, 1, 0,   0,   0,   1    )
+
+#define MPP47_GPIO		MPP( 47, 0x0, 1, 1, 0,   0,   0,   1    )
+#define MPP47_TSMP11		MPP( 47, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP47_TDM_DRX		MPP( 47, 0x2, 1, 0, 0,   0,   0,   1    )
+
+#define MPP48_GPIO		MPP( 48, 0x0, 1, 1, 0,   0,   0,   1    )
+#define MPP48_TSMP12		MPP( 48, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP48_TDM_DTX		MPP( 48. 0x2, 0, 1, 0,   0,   0,   1    )
+
+#define MPP49_GPIO		MPP( 49, 0x0, 1, 1, 0,   0,   0,   1    )
+#define MPP49_TSMP9		MPP( 49, 0x1, 1, 1, 0,   0,   0,   1    )
+#define MPP49_TDM_CH0_RX_QL	MPP( 49, 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP49_PTP_CLK		MPP( 49, 0x5, 1, 0, 0,   0,   0,   1    )
+
+#define MPP_MAX			49
+
+void kirkwood_mpp_conf(unsigned int *mpp_list);
+
+#endif
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index b1d1a87..2f0e4ef 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -11,11 +11,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
-#include <linux/timer.h>
+#include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/spi/flash.h>
@@ -23,7 +20,6 @@
 #include <linux/spi/orion_spi.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/pci.h>
 #include <mach/kirkwood.h>
 #include "common.h"
 
@@ -61,14 +57,11 @@
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&rd88f6192_ge00_data);
-	kirkwood_rtc_init();
 	kirkwood_sata_init(&rd88f6192_sata_data);
 	spi_register_board_info(rd88F6192_spi_slave_info,
 				ARRAY_SIZE(rd88F6192_spi_slave_info));
 	kirkwood_spi_init();
 	kirkwood_uart0_init();
-	kirkwood_xor0_init();
-	kirkwood_xor1_init();
 }
 
 static int __init rd88f6192_pci_init(void)
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index e1c0516..31e996d 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -11,21 +11,20 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pci.h>
 #include <linux/irq.h>
-#include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
-#include <linux/timer.h>
+#include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ethtool.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 <plat/mvsdio.h>
 #include <plat/orion_nand.h>
 #include "common.h"
+#include "mpp.h"
 
 static struct mtd_partition rd88f6281_nand_parts[] = {
 	{
@@ -96,6 +95,15 @@
 	.n_ports	= 2,
 };
 
+static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
+	.gpio_card_detect = 28,
+};
+
+static unsigned int rd88f6281_mpp_config[] __initdata = {
+	MPP28_GPIO,
+	0
+};
+
 static void __init rd88f6281_init(void)
 {
 	u32 dev, rev;
@@ -104,6 +112,7 @@
 	 * Basic setup. Needs to be called early.
 	 */
 	kirkwood_init();
+	kirkwood_mpp_conf(rd88f6281_mpp_config);
 
 	kirkwood_ehci_init();
 
@@ -117,8 +126,8 @@
 	}
 	kirkwood_ge00_switch_init(&rd88f6281_switch_plat_data, NO_IRQ);
 
-	kirkwood_rtc_init();
 	kirkwood_sata_init(&rd88f6281_sata_data);
+	kirkwood_sdio_init(&rd88f6281_mvsdio_data);
 	kirkwood_uart0_init();
 
 	platform_device_register(&rd88f6281_nand_flash);
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
new file mode 100644
index 0000000..831e4a5
--- /dev/null
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -0,0 +1,136 @@
+/*
+ * arch/arm/mach-kirkwood/sheevaplug-setup.c
+ *
+ * Marvell SheevaPlug Reference 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/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include <plat/orion_nand.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition sheevaplug_nand_parts[] = {
+	{
+		.name = "u-boot",
+		.offset = 0,
+		.size = SZ_1M
+	}, {
+		.name = "uImage",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = SZ_4M
+	}, {
+		.name = "root",
+		.offset = MTDPART_OFS_NXTBLK,
+		.size = MTDPART_SIZ_FULL
+	},
+};
+
+static struct resource sheevaplug_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= KIRKWOOD_NAND_MEM_PHYS_BASE,
+	.end		= KIRKWOOD_NAND_MEM_PHYS_BASE +
+			  KIRKWOOD_NAND_MEM_SIZE - 1,
+};
+
+static struct orion_nand_data sheevaplug_nand_data = {
+	.parts		= sheevaplug_nand_parts,
+	.nr_parts	= ARRAY_SIZE(sheevaplug_nand_parts),
+	.cle		= 0,
+	.ale		= 1,
+	.width		= 8,
+	.chip_delay	= 25,
+};
+
+static struct platform_device sheevaplug_nand_flash = {
+	.name		= "orion_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &sheevaplug_nand_data,
+	},
+	.resource	= &sheevaplug_nand_resource,
+	.num_resources	= 1,
+};
+
+static struct mv643xx_eth_platform_data sheevaplug_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
+	// unfortunately the CD signal has not been connected */
+};
+
+static struct gpio_led sheevaplug_led_pins[] = {
+	{
+		.name			= "plug:green:health",
+		.default_trigger	= "default-on",
+		.gpio			= 49,
+		.active_low		= 1,
+	},
+};
+
+static struct gpio_led_platform_data sheevaplug_led_data = {
+	.leds		= sheevaplug_led_pins,
+	.num_leds	= ARRAY_SIZE(sheevaplug_led_pins),
+};
+
+static struct platform_device sheevaplug_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &sheevaplug_led_data,
+	}
+};
+
+static unsigned int sheevaplug_mpp_config[] __initdata = {
+	MPP29_GPIO,	/* USB Power Enable */
+	MPP49_GPIO,	/* LED */
+	0
+};
+
+static void __init sheevaplug_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(sheevaplug_mpp_config);
+
+	kirkwood_uart0_init();
+
+	if (gpio_request(29, "USB Power Enable") != 0 ||
+	    gpio_direction_output(29, 1) != 0)
+		printk(KERN_ERR "can't set up GPIO 29 (USB Power Enable)\n");
+	kirkwood_ehci_init();
+
+	kirkwood_ge00_init(&sheevaplug_ge00_data);
+	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
+
+	platform_device_register(&sheevaplug_nand_flash);
+	platform_device_register(&sheevaplug_leds);
+}
+
+MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
+	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= sheevaplug_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
new file mode 100644
index 0000000..dda5743
--- /dev/null
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -0,0 +1,220 @@
+/*
+ *
+ * QNAP TS-119/TS-219 Turbo NAS Board Setup
+ *
+ * Copyright (C) 2009  Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2008  Byron Bradley <byron.bbradley@gmail.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/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <linux/i2c.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/timex.h>
+#include <linux/serial_reg.h>
+#include <linux/pci.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+/****************************************************************************
+ * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the
+ *     partitions on the device because we want to keep compatability with
+ *     the QNAP firmware.
+ * Layout as used by QNAP:
+ *  0x00000000-0x00080000 : "U-Boot"
+ *  0x00200000-0x00400000 : "Kernel"
+ *  0x00400000-0x00d00000 : "RootFS"
+ *  0x00d00000-0x01000000 : "RootFS2"
+ *  0x00080000-0x000c0000 : "U-Boot Config"
+ *  0x000c0000-0x00200000 : "NAS Config"
+ *
+ * We'll use "RootFS1" instead of "RootFS" to stay compatible with the layout
+ * used by the QNAP TS-109/TS-209.
+ *
+ ***************************************************************************/
+
+static struct mtd_partition qnap_ts219_partitions[] = {
+	{
+		.name		= "U-Boot",
+		.size		= 0x00080000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "Kernel",
+		.size		= 0x00200000,
+		.offset		= 0x00200000,
+	}, {
+		.name		= "RootFS1",
+		.size		= 0x00900000,
+		.offset		= 0x00400000,
+	}, {
+		.name		= "RootFS2",
+		.size		= 0x00300000,
+		.offset		= 0x00d00000,
+	}, {
+		.name		= "U-Boot Config",
+		.size		= 0x00040000,
+		.offset		= 0x00080000,
+	}, {
+		.name		= "NAS Config",
+		.size		= 0x00140000,
+		.offset		= 0x000c0000,
+	},
+};
+
+static const struct flash_platform_data qnap_ts219_flash = {
+	.type		= "m25p128",
+	.name		= "spi_flash",
+	.parts		= qnap_ts219_partitions,
+	.nr_parts	= ARRAY_SIZE(qnap_ts219_partitions),
+};
+
+static struct spi_board_info __initdata qnap_ts219_spi_slave_info[] = {
+	{
+		.modalias	= "m25p80",
+		.platform_data	= &qnap_ts219_flash,
+		.irq		= -1,
+		.max_speed_hz	= 20000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+	},
+};
+
+static struct i2c_board_info __initdata qnap_ts219_i2c_rtc = {
+	I2C_BOARD_INFO("s35390a", 0x30),
+};
+
+static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv_sata_platform_data qnap_ts219_sata_data = {
+	.n_ports	= 2,
+};
+
+static struct gpio_keys_button qnap_ts219_buttons[] = {
+	{
+		.code		= KEY_COPY,
+		.gpio		= 15,
+		.desc		= "USB Copy",
+		.active_low	= 1,
+	},
+	{
+		.code		= KEY_RESTART,
+		.gpio		= 16,
+		.desc		= "Reset",
+		.active_low	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data qnap_ts219_button_data = {
+	.buttons	= qnap_ts219_buttons,
+	.nbuttons	= ARRAY_SIZE(qnap_ts219_buttons),
+};
+
+static struct platform_device qnap_ts219_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &qnap_ts219_button_data,
+	}
+};
+
+static unsigned int qnap_ts219_mpp_config[] __initdata = {
+	MPP0_SPI_SCn,
+	MPP1_SPI_MOSI,
+	MPP2_SPI_SCK,
+	MPP3_SPI_MISO,
+	MPP8_TW_SDA,
+	MPP9_TW_SCK,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP13_UART1_TXD,	/* PIC controller */
+	MPP14_UART1_RXD,	/* PIC controller */
+	MPP15_GPIO,		/* USB Copy button */
+	MPP16_GPIO,		/* Reset button */
+	MPP20_SATA1_ACTn,
+	MPP21_SATA0_ACTn,
+	MPP22_SATA1_PRESENTn,
+	MPP23_SATA0_PRESENTn,
+	0
+};
+
+
+/*****************************************************************************
+ * QNAP TS-x19 specific power off method via UART1-attached PIC
+ ****************************************************************************/
+
+#define UART1_REG(x)	(UART1_VIRT_BASE + ((UART_##x) << 2))
+
+void qnap_ts219_power_off(void)
+{
+	/* 19200 baud divisor */
+	const unsigned divisor = ((kirkwood_tclk + (8 * 19200)) / (16 * 19200));
+
+	pr_info("%s: triggering power-off...\n", __func__);
+
+	/* hijack UART1 and reset into sane state (19200,8n1) */
+	writel(0x83, UART1_REG(LCR));
+	writel(divisor & 0xff, UART1_REG(DLL));
+	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
+	writel(0x03, UART1_REG(LCR));
+	writel(0x00, UART1_REG(IER));
+	writel(0x00, UART1_REG(FCR));
+	writel(0x00, UART1_REG(MCR));
+
+	/* send the power-off command 'A' to PIC */
+	writel('A', UART1_REG(TX));
+}
+
+static void __init qnap_ts219_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(qnap_ts219_mpp_config);
+
+	kirkwood_uart0_init();
+	kirkwood_uart1_init(); /* A PIC controller is connected here. */
+	spi_register_board_info(qnap_ts219_spi_slave_info,
+				ARRAY_SIZE(qnap_ts219_spi_slave_info));
+	kirkwood_spi_init();
+	kirkwood_i2c_init();
+	i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
+	kirkwood_ge00_init(&qnap_ts219_ge00_data);
+	kirkwood_sata_init(&qnap_ts219_sata_data);
+	kirkwood_ehci_init();
+	platform_device_register(&qnap_ts219_button_device);
+
+	pm_power_off = qnap_ts219_power_off;
+
+}
+
+MACHINE_START(TS219, "QNAP TS-119/TS-219")
+	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= qnap_ts219_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
index 2754daa..fe0c82e 100644
--- a/arch/arm/mach-ks8695/Kconfig
+++ b/arch/arm/mach-ks8695/Kconfig
@@ -14,6 +14,12 @@
 	  Say 'Y' here if you want your kernel to run on the D-Link
 	  DSM-320 Wireless Media Player.
 
+config MACH_ACS5K
+	bool "Brivo Systems LLC, ACS-5000 Master board"
+	help
+	  say 'Y' here if you want your kernel to run on the Brivo
+	  Systems LLC, ACS-5000 Master board.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index f735d2c..7e3e816 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -17,3 +17,4 @@
 # Board-specific support
 obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o
 obj-$(CONFIG_MACH_DSM320)	+= board-dsm320.o
+obj-$(CONFIG_MACH_ACS5K)	+= board-acs5k.o
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
new file mode 100644
index 0000000..9e3e5a6
--- /dev/null
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -0,0 +1,233 @@
+/*
+ * arch/arm/mach-ks8695/board-acs5k.c
+ *
+ * Brivo Systems LLC, ACS-5000 Master Board
+ *
+ * Copyright 2008 Simtec Electronics
+ *		  Daniel Silverstone <dsilvers@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c-gpio.h>
+#include <linux/i2c/pca953x.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/devices.h>
+#include <mach/gpio.h>
+
+#include "generic.h"
+
+static struct i2c_gpio_platform_data acs5k_i2c_device_platdata = {
+	.sda_pin	= 4,
+	.scl_pin	= 5,
+	.udelay		= 10,
+};
+
+static struct platform_device acs5k_i2c_device = {
+	.name		= "i2c-gpio",
+	.id		= -1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev		= {
+		.platform_data	= &acs5k_i2c_device_platdata,
+	},
+};
+
+static int acs5k_pca9555_setup(struct i2c_client *client,
+			       unsigned gpio_base, unsigned ngpio,
+			       void *context)
+{
+	static int acs5k_gpio_value[] = {
+		-1, -1, -1, -1, -1, -1, -1, 0, 1, 1, -1, 0, 1, 0, -1, -1
+	};
+	int n;
+
+	for (n = 0; n < ARRAY_SIZE(acs5k_gpio_value); ++n) {
+		gpio_request(gpio_base + n, "ACS-5000 GPIO Expander");
+		if (acs5k_gpio_value[n] < 0)
+			gpio_direction_input(gpio_base + n);
+		else
+			gpio_direction_output(gpio_base + n,
+					      acs5k_gpio_value[n]);
+		gpio_export(gpio_base + n, 0); /* Export, direction locked down */
+	}
+
+	return 0;
+}
+
+static struct pca953x_platform_data acs5k_i2c_pca9555_platdata = {
+	.gpio_base	= 16, /* Start directly after the CPU's GPIO */
+	.invert		= 0, /* Do not invert */
+	.setup		= acs5k_pca9555_setup,
+};
+
+static struct i2c_board_info acs5k_i2c_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+	{
+		I2C_BOARD_INFO("pca9555", 0x20),
+		.platform_data = &acs5k_i2c_pca9555_platdata,
+	},
+};
+
+static void __devinit acs5k_i2c_init(void)
+{
+	/* The gpio interface */
+	platform_device_register(&acs5k_i2c_device);
+	/* I2C devices */
+	i2c_register_board_info(0, acs5k_i2c_devs,
+				ARRAY_SIZE(acs5k_i2c_devs));
+}
+
+static struct mtd_partition acs5k_nor_partitions[] = {
+	[0] = {
+		.name	= "Boot Agent and config",
+		.size	= SZ_256K,
+		.offset	= 0,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+		.name	= "Kernel",
+		.size	= SZ_1M,
+		.offset	= SZ_256K,
+	},
+	[2] = {
+		.name	= "SquashFS1",
+		.size	= SZ_2M,
+		.offset	= SZ_256K + SZ_1M,
+	},
+	[3] = {
+		.name	= "SquashFS2",
+		.size	= SZ_4M + SZ_2M,
+		.offset	= SZ_256K + SZ_1M + SZ_2M,
+	},
+	[4] = {
+		.name	= "Data",
+		.size	= SZ_16M + SZ_4M + SZ_2M + SZ_512K, /* 22.5 MB */
+		.offset	= SZ_256K + SZ_8M + SZ_1M,
+	}
+};
+
+static struct physmap_flash_data acs5k_nor_pdata = {
+	.width		= 4,
+	.nr_parts	= ARRAY_SIZE(acs5k_nor_partitions),
+	.parts		= acs5k_nor_partitions,
+};
+
+static struct resource acs5k_nor_resource[] = {
+	[0] = {
+		.start = SZ_32M, /* We expect the bootloader to map
+				  * the flash here.
+				  */
+		.end   = SZ_32M + SZ_16M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = SZ_32M + SZ_16M,
+		.end   = SZ_32M + SZ_32M - SZ_256K - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device acs5k_device_nor = {
+	.name		= "physmap-flash",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(acs5k_nor_resource),
+	.resource	= acs5k_nor_resource,
+	.dev		= {
+		.platform_data = &acs5k_nor_pdata,
+	},
+};
+
+static void __init acs5k_register_nor(void)
+{
+	int ret;
+
+	if (acs5k_nor_partitions[0].mask_flags == 0)
+		printk(KERN_WARNING "Warning: Unprotecting bootloader and configuration partition\n");
+
+	ret = platform_device_register(&acs5k_device_nor);
+	if (ret < 0)
+		printk(KERN_ERR "failed to register physmap-flash device\n");
+}
+
+static int __init acs5k_protection_setup(char *s)
+{
+	/* We can't allocate anything here but we should be able
+	 * to trivially parse s and decide if we can protect the
+	 * bootloader partition or not
+	 */
+	if (strcmp(s, "no") == 0)
+		acs5k_nor_partitions[0].mask_flags = 0;
+
+	return 1;
+}
+
+__setup("protect_bootloader=", acs5k_protection_setup);
+
+static void __init acs5k_init_gpio(void)
+{
+	int i;
+
+	ks8695_register_gpios();
+	for (i = 0; i < 4; ++i)
+		gpio_request(i, "ACS5K IRQ");
+	gpio_request(7, "ACS5K KS_FRDY");
+	for (i = 8; i < 16; ++i)
+		gpio_request(i, "ACS5K Unused");
+
+	gpio_request(3, "ACS5K CAN Control");
+	gpio_request(6, "ACS5K Heartbeat");
+	gpio_direction_output(3, 1); /* Default CAN_RESET high */
+	gpio_direction_output(6, 0); /* Default KS8695_ACTIVE low */
+	gpio_export(3, 0); /* export CAN_RESET as output only */
+	gpio_export(6, 0); /* export KS8695_ACTIVE as output only */
+}
+
+static void __init acs5k_init(void)
+{
+	acs5k_init_gpio();
+
+	/* Network device */
+	ks8695_add_device_lan();	/* eth0 = LAN */
+	ks8695_add_device_wan();	/* ethX = WAN */
+
+	/* NOR devices */
+	acs5k_register_nor();
+
+	/* I2C bus */
+	acs5k_i2c_init();
+}
+
+MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
+	/* Maintainer: Simtec Electronics. */
+	.phys_io	= KS8695_IO_PA,
+	.io_pg_offst	= (KS8695_IO_VA >> 18) & 0xfffc,
+	.boot_params	= KS8695_SDRAM_PA + 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= acs5k_init,
+	.timer		= &ks8695_timer,
+MACHINE_END
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
index 6d5887c..76e5308 100644
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ b/arch/arm/mach-ks8695/include/mach/memory.h
@@ -35,7 +35,11 @@
 					__phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)	({ is_lbus_device(dev) ? \
 					(dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_page_to_dma(dev, x)	__arch_virt_to_dma(dev, page_address(x))
+#define __arch_page_to_dma(dev, x)	\
+	({ dma_addr_t __dma = page_to_phys(page); \
+	   if (!is_lbus_device(dev)) \
+		__dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
+	   __dma; })
 
 #endif
 
diff --git a/arch/arm/mach-ks8695/include/mach/system.h b/arch/arm/mach-ks8695/include/mach/system.h
index 5a9b032..fb1dda9 100644
--- a/arch/arm/mach-ks8695/include/mach/system.h
+++ b/arch/arm/mach-ks8695/include/mach/system.h
@@ -27,7 +27,7 @@
 
 }
 
-static void arch_reset(char mode)
+static void arch_reset(char mode, const char *cmd)
 {
 	unsigned int reg;
 
diff --git a/arch/arm/mach-l7200/include/mach/system.h b/arch/arm/mach-l7200/include/mach/system.h
index 5272abe..e0dd3b6 100644
--- a/arch/arm/mach-l7200/include/mach/system.h
+++ b/arch/arm/mach-l7200/include/mach/system.h
@@ -19,7 +19,7 @@
 	*(unsigned long *)(IO_BASE + 0x50004) = 1;	/* idle mode */
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	if (mode == 's') {
 		cpu_reset(0);
diff --git a/arch/arm/mach-lh7a40x/include/mach/system.h b/arch/arm/mach-lh7a40x/include/mach/system.h
index fa46bb1e..45a56d3 100644
--- a/arch/arm/mach-lh7a40x/include/mach/system.h
+++ b/arch/arm/mach-lh7a40x/include/mach/system.h
@@ -13,7 +13,7 @@
 	cpu_do_idle ();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	cpu_reset (0);
 }
diff --git a/arch/arm/mach-loki/include/mach/system.h b/arch/arm/mach-loki/include/mach/system.h
index 8db1147..c1de36f 100644
--- a/arch/arm/mach-loki/include/mach/system.h
+++ b/arch/arm/mach-loki/include/mach/system.h
@@ -17,7 +17,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * Enable soft reset to assert RSTOUTn.
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
new file mode 100644
index 0000000..c6a564f
--- /dev/null
+++ b/arch/arm/mach-mmp/Kconfig
@@ -0,0 +1,47 @@
+if ARCH_MMP
+
+menu "Marvell PXA168/910 Implmentations"
+
+config MACH_ASPENITE
+	bool "Marvell's PXA168 Aspenite Development Board"
+	select CPU_PXA168
+	help
+	  Say 'Y' here if you want to support the Marvell PXA168-based
+	  Aspenite Development Board.
+
+config MACH_ZYLONITE2
+	bool "Marvell's PXA168 Zylonite2 Development Board"
+	select CPU_PXA168
+	help
+	  Say 'Y' here if you want to support the Marvell PXA168-based
+	  Zylonite2 Development Board.
+
+config MACH_TAVOREVB
+	bool "Marvell's PXA910 TavorEVB Development Board"
+	select CPU_PXA910
+	help
+	  Say 'Y' here if you want to support the Marvell PXA910-based
+	  TavorEVB Development Board.
+
+config MACH_TTC_DKB
+	bool "Marvell's PXA910 TavorEVB Development Board"
+	select CPU_PXA910
+	help
+	  Say 'Y' here if you want to support the Marvell PXA910-based
+	  TTC_DKB Development Board.
+
+endmenu
+
+config CPU_PXA168
+	bool
+	select CPU_MOHAWK
+	help
+	  Select code specific to PXA168
+
+config CPU_PXA910
+	bool
+	select CPU_MOHAWK
+	help
+	  Select code specific to PXA910
+
+endif
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
new file mode 100644
index 0000000..6883e65
--- /dev/null
+++ b/arch/arm/mach-mmp/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for Marvell's PXA168 processors line
+#
+
+obj-y				+= common.o clock.o devices.o irq.o time.o
+
+# SoC support
+obj-$(CONFIG_CPU_PXA168)	+= pxa168.o
+obj-$(CONFIG_CPU_PXA910)	+= pxa910.o
+
+# board support
+obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
+obj-$(CONFIG_MACH_ZYLONITE2)	+= aspenite.o
+obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
+obj-$(CONFIG_MACH_TTC_DKB)	+= ttc_dkb.o
diff --git a/arch/arm/mach-mmp/Makefile.boot b/arch/arm/mach-mmp/Makefile.boot
new file mode 100644
index 0000000..574a4aa
--- /dev/null
+++ b/arch/arm/mach-mmp/Makefile.boot
@@ -0,0 +1 @@
+   zreladdr-y	:= 0x00008000
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
new file mode 100644
index 0000000..4562452
--- /dev/null
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -0,0 +1,117 @@
+/*
+ *  linux/arch/arm/mach-mmp/aspenite.c
+ *
+ *  Support for the Marvell PXA168-based Aspenite and Zylonite2
+ *  Development Platform.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/pxa168.h>
+#include <mach/gpio.h>
+
+#include "common.h"
+
+static unsigned long common_pin_config[] __initdata = {
+	/* Data Flash Interface */
+	GPIO0_DFI_D15,
+	GPIO1_DFI_D14,
+	GPIO2_DFI_D13,
+	GPIO3_DFI_D12,
+	GPIO4_DFI_D11,
+	GPIO5_DFI_D10,
+	GPIO6_DFI_D9,
+	GPIO7_DFI_D8,
+	GPIO8_DFI_D7,
+	GPIO9_DFI_D6,
+	GPIO10_DFI_D5,
+	GPIO11_DFI_D4,
+	GPIO12_DFI_D3,
+	GPIO13_DFI_D2,
+	GPIO14_DFI_D1,
+	GPIO15_DFI_D0,
+
+	/* Static Memory Controller */
+	GPIO18_SMC_nCS0,
+	GPIO34_SMC_nCS1,
+	GPIO23_SMC_nLUA,
+	GPIO25_SMC_nLLA,
+	GPIO28_SMC_RDY,
+	GPIO29_SMC_SCLK,
+	GPIO35_SMC_BE1,
+	GPIO36_SMC_BE2,
+	GPIO27_GPIO,	/* Ethernet IRQ */
+
+	/* UART1 */
+	GPIO107_UART1_RXD,
+	GPIO108_UART1_TXD,
+};
+
+static struct smc91x_platdata smc91x_info = {
+	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= SMC_CS1_PHYS_BASE + 0x300,
+		.end	= SMC_CS1_PHYS_BASE + 0xfffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(27),
+		.end	= gpio_to_irq(27),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &smc91x_info,
+	},
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static void __init common_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(common_pin_config));
+
+	/* on-chip devices */
+	pxa168_add_uart(1);
+
+	/* off-chip devices */
+	platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = pxa168_init_irq,
+	.timer          = &pxa168_timer,
+	.init_machine   = common_init,
+MACHINE_END
+
+MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = pxa168_init_irq,
+	.timer          = &pxa168_timer,
+	.init_machine   = common_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/clock.c b/arch/arm/mach-mmp/clock.c
new file mode 100644
index 0000000..2d9cc5a
--- /dev/null
+++ b/arch/arm/mach-mmp/clock.c
@@ -0,0 +1,83 @@
+/*
+ *  linux/arch/arm/mach-mmp/clock.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/regs-apbc.h>
+#include "clock.h"
+
+static void apbc_clk_enable(struct clk *clk)
+{
+	uint32_t clk_rst;
+
+	clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(clk->fnclksel);
+	__raw_writel(clk_rst, clk->clk_rst);
+}
+
+static void apbc_clk_disable(struct clk *clk)
+{
+	__raw_writel(0, clk->clk_rst);
+}
+
+struct clkops apbc_clk_ops = {
+	.enable		= apbc_clk_enable,
+	.disable	= apbc_clk_disable,
+};
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (clk->enabled++ == 0)
+		clk->ops->enable(clk);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	WARN_ON(clk->enabled == 0);
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	if (--clk->enabled == 0)
+		clk->ops->disable(clk);
+	spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+
+	if (clk->ops->getrate)
+		rate = clk->ops->getrate(clk);
+	else
+		rate = clk->rate;
+
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clks_register(struct clk_lookup *clks, size_t num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		clkdev_add(&clks[i]);
+}
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h
new file mode 100644
index 0000000..ed967e7
--- /dev/null
+++ b/arch/arm/mach-mmp/clock.h
@@ -0,0 +1,71 @@
+/*
+ *  linux/arch/arm/mach-mmp/clock.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.
+ */
+
+#include <asm/clkdev.h>
+
+struct clkops {
+	void			(*enable)(struct clk *);
+	void			(*disable)(struct clk *);
+	unsigned long		(*getrate)(struct clk *);
+};
+
+struct clk {
+	const struct clkops	*ops;
+
+	void __iomem	*clk_rst;	/* clock reset control register */
+	int		fnclksel;	/* functional clock select (APBC) */
+	uint32_t	enable_val;	/* value for clock enable (APMU) */
+	unsigned long	rate;
+	int		enabled;
+};
+
+extern struct clkops apbc_clk_ops;
+
+#define APBC_CLK(_name, _reg, _fnclksel, _rate)			\
+struct clk clk_##_name = {					\
+		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.fnclksel	= _fnclksel,			\
+		.rate		= _rate,			\
+		.ops		= &apbc_clk_ops,		\
+}
+
+#define APBC_CLK_OPS(_name, _reg, _fnclksel, _rate, _ops)	\
+struct clk clk_##_name = {					\
+		.clk_rst	= (void __iomem *)APBC_##_reg,	\
+		.fnclksel	= _fnclksel,			\
+		.rate		= _rate,			\
+		.ops		= _ops,				\
+}
+
+#define APMU_CLK(_name, _reg, _eval, _rate)			\
+struct clk clk_##_name = {					\
+		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.enable_val	= _eval,			\
+		.rate		= _rate,			\
+		.ops		= &apmu_clk_ops,		\
+}
+
+#define APMU_CLK_OPS(_name, _reg, _eval, _rate, _ops)		\
+struct clk clk_##_name = {					\
+		.clk_rst	= (void __iomem *)APMU_##_reg,	\
+		.enable_val	= _eval,			\
+		.rate		= _rate,			\
+		.ops		= _ops,				\
+}
+
+#define INIT_CLKREG(_clk, _devname, _conname)			\
+	{							\
+		.clk		= _clk,				\
+		.dev_id		= _devname,			\
+		.con_id		= _conname,			\
+	}
+
+extern struct clk clk_pxa168_gpio;
+extern struct clk clk_pxa168_timers;
+
+extern void clks_register(struct clk_lookup *, size_t);
diff --git a/arch/arm/mach-mmp/common.c b/arch/arm/mach-mmp/common.c
new file mode 100644
index 0000000..e1e66c1
--- /dev/null
+++ b/arch/arm/mach-mmp/common.c
@@ -0,0 +1,37 @@
+/*
+ *  linux/arch/arm/mach-mmp/common.c
+ *
+ *  Code common to PXA168 processor lines
+ *
+ * This program is free software; you can 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/kernel.h>
+
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <mach/addr-map.h>
+
+#include "common.h"
+
+static struct map_desc standard_io_desc[] __initdata = {
+	{
+		.pfn		= __phys_to_pfn(APB_PHYS_BASE),
+		.virtual	= APB_VIRT_BASE,
+		.length		= APB_PHYS_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.pfn		= __phys_to_pfn(AXI_PHYS_BASE),
+		.virtual	= AXI_VIRT_BASE,
+		.length		= AXI_PHYS_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init pxa_map_io(void)
+{
+	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
new file mode 100644
index 0000000..c33fbbc
--- /dev/null
+++ b/arch/arm/mach-mmp/common.h
@@ -0,0 +1,13 @@
+#define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
+
+struct sys_timer;
+
+extern void timer_init(int irq);
+
+extern struct sys_timer pxa168_timer;
+extern struct sys_timer pxa910_timer;
+extern void __init pxa168_init_irq(void);
+extern void __init pxa910_init_irq(void);
+
+extern void __init icu_init_irq(void);
+extern void __init pxa_map_io(void);
diff --git a/arch/arm/mach-mmp/devices.c b/arch/arm/mach-mmp/devices.c
new file mode 100644
index 0000000..191d9de
--- /dev/null
+++ b/arch/arm/mach-mmp/devices.c
@@ -0,0 +1,69 @@
+/*
+ * linux/arch/arm/mach-mmp/devices.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/irq.h>
+#include <mach/devices.h>
+
+int __init pxa_register_device(struct pxa_device_desc *desc,
+				void *data, size_t size)
+{
+	struct platform_device *pdev;
+	struct resource res[2 + MAX_RESOURCE_DMA];
+	int i, ret = 0, nres = 0;
+
+	pdev = platform_device_alloc(desc->drv_name, desc->id);
+	if (pdev == NULL)
+		return -ENOMEM;
+
+	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	memset(res, 0, sizeof(res));
+
+	if (desc->start != -1ul && desc->size > 0) {
+		res[nres].start	= desc->start;
+		res[nres].end	= desc->start + desc->size - 1;
+		res[nres].flags	= IORESOURCE_MEM;
+		nres++;
+	}
+
+	if (desc->irq != NO_IRQ) {
+		res[nres].start	= desc->irq;
+		res[nres].end	= desc->irq;
+		res[nres].flags	= IORESOURCE_IRQ;
+		nres++;
+	}
+
+	for (i = 0; i < MAX_RESOURCE_DMA; i++, nres++) {
+		if (desc->dma[i] == 0)
+			break;
+
+		res[nres].start	= desc->dma[i];
+		res[nres].end	= desc->dma[i];
+		res[nres].flags	= IORESOURCE_DMA;
+	}
+
+	ret = platform_device_add_resources(pdev, res, nres);
+	if (ret) {
+		platform_device_put(pdev);
+		return ret;
+	}
+
+	if (data && size) {
+		ret = platform_device_add_data(pdev, data, size);
+		if (ret) {
+			platform_device_put(pdev);
+			return ret;
+		}
+	}
+
+	return platform_device_add(pdev);
+}
diff --git a/arch/arm/mach-mmp/include/mach/addr-map.h b/arch/arm/mach-mmp/include/mach/addr-map.h
new file mode 100644
index 0000000..3254089
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/addr-map.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/addr-map.h
+ *
+ *   Common address map 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_MACH_ADDR_MAP_H
+#define __ASM_MACH_ADDR_MAP_H
+
+/* APB - Application Subsystem Peripheral Bus
+ *
+ * NOTE: the DMA controller registers are actually on the AXI fabric #1
+ * slave port to AHB/APB bridge, due to its close relationship to those
+ * peripherals on APB, let's count it into the ABP mapping area.
+ */
+#define APB_PHYS_BASE		0xd4000000
+#define APB_VIRT_BASE		0xfe000000
+#define APB_PHYS_SIZE		0x00200000
+
+#define AXI_PHYS_BASE		0xd4200000
+#define AXI_VIRT_BASE		0xfe200000
+#define AXI_PHYS_SIZE		0x00200000
+
+/* Static Memory Controller - Chip Select 0 and 1 */
+#define SMC_CS0_PHYS_BASE	0x80000000
+#define SMC_CS0_PHYS_SIZE	0x10000000
+#define SMC_CS1_PHYS_BASE	0x90000000
+#define SMC_CS1_PHYS_SIZE	0x10000000
+
+#endif /* __ASM_MACH_ADDR_MAP_H */
diff --git a/arch/arm/mach-mmp/include/mach/clkdev.h b/arch/arm/mach-mmp/include/mach/clkdev.h
new file mode 100644
index 0000000..2fb354e
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h
new file mode 100644
index 0000000..25e797b
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/cputype.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_CPUTYPE_H
+#define __ASM_MACH_CPUTYPE_H
+
+#include <asm/cputype.h>
+
+/*
+ *  CPU   Stepping   OLD_ID       CPU_ID      CHIP_ID
+ *
+ * PXA168    A0    0x41159263   0x56158400   0x00A0A333
+ * PXA910    Y0    0x41159262   0x56158000   0x00F0C910
+ */
+
+#ifdef CONFIG_CPU_PXA168
+#  define __cpu_is_pxa168(id)	\
+	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x84; })
+#else
+#  define __cpu_is_pxa168(id)	(0)
+#endif
+
+#ifdef CONFIG_CPU_PXA910
+#  define __cpu_is_pxa910(id)	\
+	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x80; })
+#else
+#  define __cpu_is_pxa910(id)	(0)
+#endif
+
+#define cpu_is_pxa168()		({ __cpu_is_pxa168(read_cpuid_id()); })
+#define cpu_is_pxa910()		({ __cpu_is_pxa910(read_cpuid_id()); })
+
+#endif /* __ASM_MACH_CPUTYPE_H */
diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S
new file mode 100644
index 0000000..a850f87
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/debug-macro.S
@@ -0,0 +1,23 @@
+/* arch/arm/mach-mmp/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copied from arch/arm/mach-pxa/include/mach/debug.S
+ *
+ * This program is free software; you can 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 <mach/addr-map.h>
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1				@ MMU enabled?
+		ldreq	\rx, =APB_PHYS_BASE		@ physical
+		ldrne	\rx, =APB_VIRT_BASE		@ virtual
+		orr	\rx, \rx, #0x00017000
+		.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h
new file mode 100644
index 0000000..2458539
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/devices.h
@@ -0,0 +1,37 @@
+#include <linux/types.h>
+
+#define MAX_RESOURCE_DMA	2
+
+/* structure for describing the on-chip devices */
+struct pxa_device_desc {
+	const char	*dev_name;
+	const char	*drv_name;
+	int		id;
+	int		irq;
+	unsigned long	start;
+	unsigned long	size;
+	int		dma[MAX_RESOURCE_DMA];
+};
+
+#define PXA168_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...)	\
+struct pxa_device_desc pxa168_device_##_name __initdata = {		\
+	.dev_name	= "pxa168-" #_name,				\
+	.drv_name	= _drv,						\
+	.id		= _id,						\
+	.irq		= IRQ_PXA168_##_irq,				\
+	.start		= _start,					\
+	.size		= _size,					\
+	.dma		= { _dma },					\
+};
+
+#define PXA910_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...)	\
+struct pxa_device_desc pxa910_device_##_name __initdata = {		\
+	.dev_name	= "pxa910-" #_name,				\
+	.drv_name	= _drv,						\
+	.id		= _id,						\
+	.irq		= IRQ_PXA910_##_irq,				\
+	.start		= _start,					\
+	.size		= _size,					\
+	.dma		= { _dma },					\
+};
+extern int pxa_register_device(struct pxa_device_desc *, void *, size_t);
diff --git a/arch/arm/mach-mmp/include/mach/dma.h b/arch/arm/mach-mmp/include/mach/dma.h
new file mode 100644
index 0000000..1d69145
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/dma.h
@@ -0,0 +1,13 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/dma.h
+ */
+
+#ifndef __ASM_MACH_DMA_H
+#define __ASM_MACH_DMA_H
+
+#include <mach/addr-map.h>
+
+#define DMAC_REGS_VIRT	(APB_VIRT_BASE + 0x00000)
+
+#include <plat/dma.h>
+#endif /* __ASM_MACH_DMA_H */
diff --git a/arch/arm/mach-mmp/include/mach/entry-macro.S b/arch/arm/mach-mmp/include/mach/entry-macro.S
new file mode 100644
index 0000000..6d3cd35
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/entry-macro.S
@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/entry-macro.S
+ *
+ * This program is free software; you can 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 <mach/regs-icu.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =ICU_AP_IRQ_SEL_INT_NUM
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\tmp, [\base, #0]
+	and	\irqnr, \tmp, #0x3f
+	tst	\tmp, #(1 << 6)
+	.endm
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
new file mode 100644
index 0000000..ab26d13
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/gpio.h
@@ -0,0 +1,36 @@
+#ifndef __ASM_MACH_GPIO_H
+#define __ASM_MACH_GPIO_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+#include <asm-generic/gpio.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
+
+#define NR_BUILTIN_GPIO	(128)
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+#define gpio_to_irq(gpio)	(IRQ_GPIO_START + (gpio))
+#define irq_to_gpio(irq)	((irq) - IRQ_GPIO_START)
+
+
+#define __gpio_is_inverted(gpio)	(0)
+#define __gpio_is_occupied(gpio)	(0)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio.h>
+#endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-mmp/include/mach/hardware.h b/arch/arm/mach-mmp/include/mach/hardware.h
new file mode 100644
index 0000000..99264a5
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/hardware.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_MACH_HARDWARE_H
+#define __ASM_MACH_HARDWARE_H
+
+#endif /* __ASM_MACH_HARDWARE_H */
diff --git a/arch/arm/mach-mmp/include/mach/io.h b/arch/arm/mach-mmp/include/mach/io.h
new file mode 100644
index 0000000..e7adf3d
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/io.h
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/io.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_MACH_IO_H
+#define __ASM_MACH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif /* __ASM_MACH_IO_H */
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
new file mode 100644
index 0000000..e83e45e
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -0,0 +1,119 @@
+#ifndef __ASM_MACH_IRQS_H
+#define __ASM_MACH_IRQS_H
+
+/*
+ * Interrupt numbers for PXA168
+ */
+#define IRQ_PXA168_NONE			(-1)
+#define IRQ_PXA168_SSP3			0
+#define IRQ_PXA168_SSP2			1
+#define IRQ_PXA168_SSP1			2
+#define IRQ_PXA168_SSP0			3
+#define IRQ_PXA168_PMIC_INT		4
+#define IRQ_PXA168_RTC_INT		5
+#define IRQ_PXA168_RTC_ALARM		6
+#define IRQ_PXA168_TWSI0		7
+#define IRQ_PXA168_GPU			8
+#define IRQ_PXA168_KEYPAD		9
+#define IRQ_PXA168_ONEWIRE		12
+#define IRQ_PXA168_TIMER1		13
+#define IRQ_PXA168_TIMER2		14
+#define IRQ_PXA168_TIMER3		15
+#define IRQ_PXA168_CMU			16
+#define IRQ_PXA168_SSP4			17
+#define IRQ_PXA168_MSP_WAKEUP		19
+#define IRQ_PXA168_CF_WAKEUP		20
+#define IRQ_PXA168_XD_WAKEUP		21
+#define IRQ_PXA168_MFU			22
+#define IRQ_PXA168_MSP			23
+#define IRQ_PXA168_CF			24
+#define IRQ_PXA168_XD			25
+#define IRQ_PXA168_DDR_INT		26
+#define IRQ_PXA168_UART1		27
+#define IRQ_PXA168_UART2		28
+#define IRQ_PXA168_WDT			35
+#define IRQ_PXA168_FRQ_CHANGE		38
+#define IRQ_PXA168_SDH1			39
+#define IRQ_PXA168_SDH2			40
+#define IRQ_PXA168_LCD			41
+#define IRQ_PXA168_CI			42
+#define IRQ_PXA168_USB1			44
+#define IRQ_PXA168_NAND			45
+#define IRQ_PXA168_HIFI_DMA		46
+#define IRQ_PXA168_DMA_INT0		47
+#define IRQ_PXA168_DMA_INT1		48
+#define IRQ_PXA168_GPIOX		49
+#define IRQ_PXA168_USB2			51
+#define IRQ_PXA168_AC97			57
+#define IRQ_PXA168_TWSI1		58
+#define IRQ_PXA168_PMU			60
+#define IRQ_PXA168_SM_INT		63
+
+/*
+ * Interrupt numbers for PXA910
+ */
+#define IRQ_PXA910_AIRQ			0
+#define IRQ_PXA910_SSP3			1
+#define IRQ_PXA910_SSP2			2
+#define IRQ_PXA910_SSP1			3
+#define IRQ_PXA910_PMIC_INT		4
+#define IRQ_PXA910_RTC_INT		5
+#define IRQ_PXA910_RTC_ALARM		6
+#define IRQ_PXA910_TWSI0		7
+#define IRQ_PXA910_GPU			8
+#define IRQ_PXA910_KEYPAD		9
+#define IRQ_PXA910_ROTARY		10
+#define IRQ_PXA910_TRACKBALL		11
+#define IRQ_PXA910_ONEWIRE		12
+#define IRQ_PXA910_AP1_TIMER1		13
+#define IRQ_PXA910_AP1_TIMER2		14
+#define IRQ_PXA910_AP1_TIMER3		15
+#define IRQ_PXA910_IPC_AP0		16
+#define IRQ_PXA910_IPC_AP1		17
+#define IRQ_PXA910_IPC_AP2		18
+#define IRQ_PXA910_IPC_AP3		19
+#define IRQ_PXA910_IPC_AP4		20
+#define IRQ_PXA910_IPC_CP0		21
+#define IRQ_PXA910_IPC_CP1		22
+#define IRQ_PXA910_IPC_CP2		23
+#define IRQ_PXA910_IPC_CP3		24
+#define IRQ_PXA910_IPC_CP4		25
+#define IRQ_PXA910_L2_DDR		26
+#define IRQ_PXA910_UART2		27
+#define IRQ_PXA910_UART3		28
+#define IRQ_PXA910_AP2_TIMER1		29
+#define IRQ_PXA910_AP2_TIMER2		30
+#define IRQ_PXA910_CP2_TIMER1		31
+#define IRQ_PXA910_CP2_TIMER2		32
+#define IRQ_PXA910_CP2_TIMER3		33
+#define IRQ_PXA910_GSSP			34
+#define IRQ_PXA910_CP2_WDT		35
+#define IRQ_PXA910_MAIN_PMU		36
+#define IRQ_PXA910_CP_FREQ_CHG		37
+#define IRQ_PXA910_AP_FREQ_CHG		38
+#define IRQ_PXA910_MMC			39
+#define IRQ_PXA910_AEU			40
+#define IRQ_PXA910_LCD			41
+#define IRQ_PXA910_CCIC			42
+#define IRQ_PXA910_IRE			43
+#define IRQ_PXA910_USB1			44
+#define IRQ_PXA910_NAND			45
+#define IRQ_PXA910_HIFI_DMA		46
+#define IRQ_PXA910_DMA_INT0		47
+#define IRQ_PXA910_DMA_INT1		48
+#define IRQ_PXA910_AP_GPIO		49
+#define IRQ_PXA910_AP2_TIMER3		50
+#define IRQ_PXA910_USB2			51
+#define IRQ_PXA910_TWSI1		54
+#define IRQ_PXA910_CP_GPIO		55
+#define IRQ_PXA910_UART1		59	/* Slow UART */
+#define IRQ_PXA910_AP_PMU		60
+#define IRQ_PXA910_SM_INT		63	/* from PinMux */
+
+#define IRQ_GPIO_START			64
+#define IRQ_GPIO_NUM			128
+#define IRQ_GPIO(x)			(IRQ_GPIO_START + (x))
+
+#define NR_IRQS		(IRQ_GPIO_START + IRQ_GPIO_NUM)
+
+#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h
new file mode 100644
index 0000000..bdb21d7
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/memory.h
@@ -0,0 +1,14 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/memory.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_MACH_MEMORY_H
+#define __ASM_MACH_MEMORY_H
+
+#define PHYS_OFFSET	UL(0x00000000)
+
+#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
new file mode 100644
index 0000000..d0bdb6e
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -0,0 +1,258 @@
+#ifndef __ASM_MACH_MFP_PXA168_H
+#define __ASM_MACH_MFP_PXA168_H
+
+#include <mach/mfp.h>
+
+/* GPIO */
+#define GPIO0_GPIO		MFP_CFG(GPIO0, AF5)
+#define GPIO1_GPIO		MFP_CFG(GPIO1, AF5)
+#define GPIO2_GPIO		MFP_CFG(GPIO2, AF5)
+#define GPIO3_GPIO		MFP_CFG(GPIO3, AF5)
+#define GPIO4_GPIO		MFP_CFG(GPIO4, AF5)
+#define GPIO5_GPIO		MFP_CFG(GPIO5, AF5)
+#define GPIO6_GPIO		MFP_CFG(GPIO6, AF5)
+#define GPIO7_GPIO		MFP_CFG(GPIO7, AF5)
+#define GPIO8_GPIO		MFP_CFG(GPIO8, AF5)
+#define GPIO9_GPIO		MFP_CFG(GPIO9, AF5)
+#define GPIO10_GPIO		MFP_CFG(GPIO10, AF5)
+#define GPIO11_GPIO		MFP_CFG(GPIO11, AF5)
+#define GPIO12_GPIO		MFP_CFG(GPIO12, AF5)
+#define GPIO13_GPIO		MFP_CFG(GPIO13, AF5)
+#define GPIO14_GPIO		MFP_CFG(GPIO14, AF5)
+#define GPIO15_GPIO		MFP_CFG(GPIO15, AF5)
+#define GPIO16_GPIO		MFP_CFG(GPIO16, AF0)
+#define GPIO17_GPIO		MFP_CFG(GPIO17, AF5)
+#define GPIO18_GPIO		MFP_CFG(GPIO18, AF0)
+#define GPIO19_GPIO		MFP_CFG(GPIO19, AF5)
+#define GPIO20_GPIO		MFP_CFG(GPIO20, AF0)
+#define GPIO21_GPIO		MFP_CFG(GPIO21, AF5)
+#define GPIO22_GPIO		MFP_CFG(GPIO22, AF5)
+#define GPIO23_GPIO		MFP_CFG(GPIO23, AF5)
+#define GPIO24_GPIO		MFP_CFG(GPIO24, AF5)
+#define GPIO25_GPIO		MFP_CFG(GPIO25, AF5)
+#define GPIO26_GPIO		MFP_CFG(GPIO26, AF0)
+#define GPIO27_GPIO		MFP_CFG(GPIO27, AF5)
+#define GPIO28_GPIO		MFP_CFG(GPIO28, AF5)
+#define GPIO29_GPIO		MFP_CFG(GPIO29, AF5)
+#define GPIO30_GPIO		MFP_CFG(GPIO30, AF5)
+#define GPIO31_GPIO		MFP_CFG(GPIO31, AF5)
+#define GPIO32_GPIO		MFP_CFG(GPIO32, AF5)
+#define GPIO33_GPIO		MFP_CFG(GPIO33, AF5)
+#define GPIO34_GPIO		MFP_CFG(GPIO34, AF0)
+#define GPIO35_GPIO		MFP_CFG(GPIO35, AF0)
+#define GPIO36_GPIO		MFP_CFG(GPIO36, AF0)
+#define GPIO37_GPIO		MFP_CFG(GPIO37, AF0)
+#define GPIO38_GPIO		MFP_CFG(GPIO38, AF0)
+#define GPIO39_GPIO		MFP_CFG(GPIO39, AF0)
+#define GPIO40_GPIO		MFP_CFG(GPIO40, AF0)
+#define GPIO41_GPIO		MFP_CFG(GPIO41, AF0)
+#define GPIO42_GPIO		MFP_CFG(GPIO42, AF0)
+#define GPIO43_GPIO		MFP_CFG(GPIO43, AF0)
+#define GPIO44_GPIO		MFP_CFG(GPIO44, AF0)
+#define GPIO45_GPIO		MFP_CFG(GPIO45, AF0)
+#define GPIO46_GPIO		MFP_CFG(GPIO46, AF0)
+#define GPIO47_GPIO		MFP_CFG(GPIO47, AF0)
+#define GPIO48_GPIO		MFP_CFG(GPIO48, AF0)
+#define GPIO49_GPIO		MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO		MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO		MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO		MFP_CFG(GPIO52, AF0)
+#define GPIO53_GPIO		MFP_CFG(GPIO53, AF0)
+#define GPIO54_GPIO		MFP_CFG(GPIO54, AF0)
+#define GPIO55_GPIO		MFP_CFG(GPIO55, AF0)
+#define GPIO56_GPIO		MFP_CFG(GPIO56, AF0)
+#define GPIO57_GPIO		MFP_CFG(GPIO57, AF0)
+#define GPIO58_GPIO		MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO		MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO		MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO		MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO		MFP_CFG(GPIO62, AF0)
+#define GPIO63_GPIO		MFP_CFG(GPIO63, AF0)
+#define GPIO64_GPIO		MFP_CFG(GPIO64, AF0)
+#define GPIO65_GPIO		MFP_CFG(GPIO65, AF0)
+#define GPIO66_GPIO		MFP_CFG(GPIO66, AF0)
+#define GPIO67_GPIO		MFP_CFG(GPIO67, AF0)
+#define GPIO68_GPIO		MFP_CFG(GPIO68, AF0)
+#define GPIO69_GPIO		MFP_CFG(GPIO69, AF0)
+#define GPIO70_GPIO		MFP_CFG(GPIO70, AF0)
+#define GPIO71_GPIO		MFP_CFG(GPIO71, AF0)
+#define GPIO72_GPIO		MFP_CFG(GPIO72, AF0)
+#define GPIO73_GPIO		MFP_CFG(GPIO73, AF0)
+#define GPIO74_GPIO		MFP_CFG(GPIO74, AF0)
+#define GPIO75_GPIO		MFP_CFG(GPIO75, AF0)
+#define GPIO76_GPIO		MFP_CFG(GPIO76, AF0)
+#define GPIO77_GPIO		MFP_CFG(GPIO77, AF0)
+#define GPIO78_GPIO		MFP_CFG(GPIO78, AF0)
+#define GPIO79_GPIO		MFP_CFG(GPIO79, AF0)
+#define GPIO80_GPIO		MFP_CFG(GPIO80, AF0)
+#define GPIO81_GPIO		MFP_CFG(GPIO81, AF0)
+#define GPIO82_GPIO		MFP_CFG(GPIO82, AF0)
+#define GPIO83_GPIO		MFP_CFG(GPIO83, AF0)
+#define GPIO84_GPIO		MFP_CFG(GPIO84, AF0)
+#define GPIO85_GPIO		MFP_CFG(GPIO85, AF0)
+#define GPIO86_GPIO		MFP_CFG(GPIO86, AF0)
+#define GPIO87_GPIO		MFP_CFG(GPIO87, AF0)
+#define GPIO88_GPIO		MFP_CFG(GPIO88, AF0)
+#define GPIO89_GPIO		MFP_CFG(GPIO89, AF0)
+#define GPIO90_GPIO		MFP_CFG(GPIO90, AF0)
+#define GPIO91_GPIO		MFP_CFG(GPIO91, AF0)
+#define GPIO92_GPIO		MFP_CFG(GPIO92, AF0)
+#define GPIO93_GPIO		MFP_CFG(GPIO93, AF0)
+#define GPIO94_GPIO		MFP_CFG(GPIO94, AF0)
+#define GPIO95_GPIO		MFP_CFG(GPIO95, AF0)
+#define GPIO96_GPIO		MFP_CFG(GPIO96, AF0)
+#define GPIO97_GPIO		MFP_CFG(GPIO97, AF0)
+#define GPIO98_GPIO		MFP_CFG(GPIO98, AF0)
+#define GPIO99_GPIO		MFP_CFG(GPIO99, AF0)
+#define GPIO100_GPIO		MFP_CFG(GPIO100, AF0)
+#define GPIO101_GPIO		MFP_CFG(GPIO101, AF0)
+#define GPIO102_GPIO		MFP_CFG(GPIO102, AF0)
+#define GPIO103_GPIO		MFP_CFG(GPIO103, AF0)
+#define GPIO104_GPIO		MFP_CFG(GPIO104, AF0)
+#define GPIO105_GPIO		MFP_CFG(GPIO105, AF0)
+#define GPIO106_GPIO		MFP_CFG(GPIO106, AF0)
+#define GPIO107_GPIO		MFP_CFG(GPIO107, AF0)
+#define GPIO108_GPIO		MFP_CFG(GPIO108, AF0)
+#define GPIO109_GPIO		MFP_CFG(GPIO109, AF0)
+#define GPIO110_GPIO		MFP_CFG(GPIO110, AF0)
+#define GPIO111_GPIO		MFP_CFG(GPIO111, AF0)
+#define GPIO112_GPIO		MFP_CFG(GPIO112, AF0)
+#define GPIO113_GPIO		MFP_CFG(GPIO113, AF0)
+#define GPIO114_GPIO		MFP_CFG(GPIO114, AF0)
+#define GPIO115_GPIO		MFP_CFG(GPIO115, AF0)
+#define GPIO116_GPIO		MFP_CFG(GPIO116, AF0)
+#define GPIO117_GPIO		MFP_CFG(GPIO117, AF0)
+#define GPIO118_GPIO		MFP_CFG(GPIO118, AF0)
+#define GPIO119_GPIO		MFP_CFG(GPIO119, AF0)
+#define GPIO120_GPIO		MFP_CFG(GPIO120, AF0)
+#define GPIO121_GPIO		MFP_CFG(GPIO121, AF0)
+#define GPIO122_GPIO		MFP_CFG(GPIO122, AF0)
+
+/* DFI */
+#define GPIO0_DFI_D15		MFP_CFG(GPIO0, AF0)
+#define GPIO1_DFI_D14		MFP_CFG(GPIO1, AF0)
+#define GPIO2_DFI_D13		MFP_CFG(GPIO2, AF0)
+#define GPIO3_DFI_D12		MFP_CFG(GPIO3, AF0)
+#define GPIO4_DFI_D11		MFP_CFG(GPIO4, AF0)
+#define GPIO5_DFI_D10		MFP_CFG(GPIO5, AF0)
+#define GPIO6_DFI_D9		MFP_CFG(GPIO6, AF0)
+#define GPIO7_DFI_D8		MFP_CFG(GPIO7, AF0)
+#define GPIO8_DFI_D7		MFP_CFG(GPIO8, AF0)
+#define GPIO9_DFI_D6		MFP_CFG(GPIO9, AF0)
+#define GPIO10_DFI_D5		MFP_CFG(GPIO10, AF0)
+#define GPIO11_DFI_D4		MFP_CFG(GPIO11, AF0)
+#define GPIO12_DFI_D3		MFP_CFG(GPIO12, AF0)
+#define GPIO13_DFI_D2		MFP_CFG(GPIO13, AF0)
+#define GPIO14_DFI_D1		MFP_CFG(GPIO14, AF0)
+#define GPIO15_DFI_D0		MFP_CFG(GPIO15, AF0)
+
+#define GPIO30_DFI_ADDR0	MFP_CFG(GPIO30, AF0)
+#define GPIO31_DFI_ADDR1	MFP_CFG(GPIO31, AF0)
+#define GPIO32_DFI_ADDR2	MFP_CFG(GPIO32, AF0)
+#define GPIO33_DFI_ADDR3	MFP_CFG(GPIO33, AF0)
+
+/* NAND */
+#define GPIO16_ND_nCS0		MFP_CFG(GPIO16, AF1)
+#define GPIO17_ND_nWE		MFP_CFG(GPIO17, AF0)
+#define GPIO21_ND_ALE		MFP_CFG(GPIO21, AF0)
+#define GPIO22_ND_CLE		MFP_CFG(GPIO22, AF0)
+#define GPIO24_ND_nRE		MFP_CFG(GPIO24, AF0)
+#define GPIO26_ND_RnB1		MFP_CFG(GPIO26, AF1)
+#define GPIO27_ND_RnB2		MFP_CFG(GPIO27, AF1)
+
+/* Static Memory Controller */
+#define GPIO18_SMC_nCS0		MFP_CFG(GPIO18, AF3)
+#define GPIO18_SMC_nCS1		MFP_CFG(GPIO18, AF2)
+#define GPIO16_SMC_nCS0		MFP_CFG(GPIO16, AF2)
+#define GPIO16_SMC_nCS1		MFP_CFG(GPIO16, AF3)
+#define GPIO19_SMC_nCS0		MFP_CFG(GPIO19, AF0)
+#define GPIO20_SMC_nCS1		MFP_CFG(GPIO20, AF2)
+#define GPIO23_SMC_nLUA		MFP_CFG(GPIO23, AF0)
+#define GPIO25_SMC_nLLA		MFP_CFG(GPIO25, AF0)
+#define GPIO27_SMC_IRQ		MFP_CFG(GPIO27, AF0)
+#define GPIO28_SMC_RDY		MFP_CFG(GPIO28, AF0)
+#define GPIO29_SMC_SCLK		MFP_CFG(GPIO29, AF0)
+#define GPIO34_SMC_nCS1		MFP_CFG(GPIO34, AF2)
+#define GPIO35_SMC_BE1		MFP_CFG(GPIO35, AF2)
+#define GPIO36_SMC_BE2		MFP_CFG(GPIO36, AF2)
+
+/* Compact Flash */
+#define GPIO19_CF_nCE1		MFP_CFG(GPIO19, AF3)
+#define GPIO20_CF_nCE2		MFP_CFG(GPIO20, AF3)
+#define GPIO23_CF_nALE		MFP_CFG(GPIO23, AF3)
+#define GPIO25_CF_nRESET	MFP_CFG(GPIO25, AF3)
+#define GPIO28_CF_RDY		MFP_CFG(GPIO28, AF3)
+#define GPIO29_CF_STSCH		MFP_CFG(GPIO29, AF3)
+#define GPIO30_CF_nREG		MFP_CFG(GPIO30, AF3)
+#define GPIO31_CF_nIOIS16	MFP_CFG(GPIO31, AF3)
+#define GPIO32_CF_nCD1		MFP_CFG(GPIO32, AF3)
+#define GPIO33_CF_nCD2		MFP_CFG(GPIO33, AF3)
+
+/* UART1 */
+#define GPIO107_UART1_TXD	MFP_CFG_DRV(GPIO107, AF1, FAST)
+#define GPIO107_UART1_RXD	MFP_CFG_DRV(GPIO107, AF2, FAST)
+#define GPIO108_UART1_RXD	MFP_CFG_DRV(GPIO108, AF1, FAST)
+#define GPIO108_UART1_TXD	MFP_CFG_DRV(GPIO108, AF2, FAST)
+#define GPIO109_UART1_CTS	MFP_CFG(GPIO109, AF1)
+#define GPIO109_UART1_RTS	MFP_CFG(GPIO109, AF2)
+#define GPIO110_UART1_RTS	MFP_CFG(GPIO110, AF1)
+#define GPIO110_UART1_CTS	MFP_CFG(GPIO110, AF2)
+#define GPIO111_UART1_RI	MFP_CFG(GPIO111, AF1)
+#define GPIO111_UART1_DSR	MFP_CFG(GPIO111, AF2)
+#define GPIO112_UART1_DTR	MFP_CFG(GPIO111, AF1)
+#define GPIO112_UART1_DCD	MFP_CFG(GPIO112, AF2)
+
+/* MMC1 */
+#define GPIO37_MMC1_DAT7	MFP_CFG(GPIO37, AF1)
+#define GPIO38_MMC1_DAT6	MFP_CFG(GPIO38, AF1)
+#define GPIO54_MMC1_DAT5	MFP_CFG(GPIO54, AF1)
+#define GPIO48_MMC1_DAT4	MFP_CFG(GPIO48, AF1)
+#define GPIO51_MMC1_DAT3	MFP_CFG(GPIO51, AF1)
+#define GPIO52_MMC1_DAT2	MFP_CFG(GPIO52, AF1)
+#define GPIO40_MMC1_DAT1	MFP_CFG(GPIO40, AF1)
+#define GPIO41_MMC1_DAT0	MFP_CFG(GPIO41, AF1)
+#define GPIO49_MMC1_CMD		MFP_CFG(GPIO49, AF1)
+#define GPIO43_MMC1_CLK		MFP_CFG(GPIO43, AF1)
+#define GPIO53_MMC1_CD		MFP_CFG(GPIO53, AF1)
+#define GPIO46_MMC1_WP		MFP_CFG(GPIO46, AF1)
+
+/* LCD */
+#define GPIO84_LCD_CS		MFP_CFG(GPIO84, AF1)
+#define GPIO60_LCD_DD0		MFP_CFG(GPIO60, AF1)
+#define GPIO61_LCD_DD1		MFP_CFG(GPIO61, AF1)
+#define GPIO70_LCD_DD10		MFP_CFG(GPIO70, AF1)
+#define GPIO71_LCD_DD11		MFP_CFG(GPIO71, AF1)
+#define GPIO72_LCD_DD12		MFP_CFG(GPIO72, AF1)
+#define GPIO73_LCD_DD13		MFP_CFG(GPIO73, AF1)
+#define GPIO74_LCD_DD14		MFP_CFG(GPIO74, AF1)
+#define GPIO75_LCD_DD15		MFP_CFG(GPIO75, AF1)
+#define GPIO76_LCD_DD16		MFP_CFG(GPIO76, AF1)
+#define GPIO77_LCD_DD17		MFP_CFG(GPIO77, AF1)
+#define GPIO78_LCD_DD18		MFP_CFG(GPIO78, AF1)
+#define GPIO79_LCD_DD19		MFP_CFG(GPIO79, AF1)
+#define GPIO62_LCD_DD2		MFP_CFG(GPIO62, AF1)
+#define GPIO80_LCD_DD20		MFP_CFG(GPIO80, AF1)
+#define GPIO81_LCD_DD21		MFP_CFG(GPIO81, AF1)
+#define GPIO82_LCD_DD22		MFP_CFG(GPIO82, AF1)
+#define GPIO83_LCD_DD23		MFP_CFG(GPIO83, AF1)
+#define GPIO63_LCD_DD3		MFP_CFG(GPIO63, AF1)
+#define GPIO64_LCD_DD4		MFP_CFG(GPIO64, AF1)
+#define GPIO65_LCD_DD5		MFP_CFG(GPIO65, AF1)
+#define GPIO66_LCD_DD6		MFP_CFG(GPIO66, AF1)
+#define GPIO67_LCD_DD7		MFP_CFG(GPIO67, AF1)
+#define GPIO68_LCD_DD8		MFP_CFG(GPIO68, AF1)
+#define GPIO69_LCD_DD9		MFP_CFG(GPIO69, AF1)
+#define GPIO59_LCD_DENA_BIAS	MFP_CFG(GPIO59, AF1)
+#define GPIO56_LCD_FCLK_RD	MFP_CFG(GPIO56, AF1)
+#define GPIO57_LCD_LCLK_A0	MFP_CFG(GPIO57, AF1)
+#define GPIO58_LCD_PCLK_WR	MFP_CFG(GPIO58, AF1)
+#define GPIO85_LCD_VSYNC	MFP_CFG(GPIO85, AF1)
+
+/* I2S */
+#define GPIO113_I2S_MCLK	MFP_CFG(GPIO113,AF6)
+#define GPIO114_I2S_FRM		MFP_CFG(GPIO114,AF1)
+#define GPIO115_I2S_BCLK	MFP_CFG(GPIO115,AF1)
+#define GPIO116_I2S_RXD		MFP_CFG(GPIO116,AF2)
+#define GPIO117_I2S_TXD		MFP_CFG(GPIO117,AF2)
+
+#endif /* __ASM_MACH_MFP_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa910.h b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
new file mode 100644
index 0000000..48a1cbc
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa910.h
@@ -0,0 +1,157 @@
+#ifndef __ASM_MACH_MFP_PXA910_H
+#define __ASM_MACH_MFP_PXA910_H
+
+#include <mach/mfp.h>
+
+/* UART2 */
+#define GPIO47_UART2_RXD	MFP_CFG(GPIO47, AF6)
+#define GPIO48_UART2_TXD	MFP_CFG(GPIO48, AF6)
+
+/* UART3 */
+#define GPIO31_UART3_RXD	MFP_CFG(GPIO31, AF4)
+#define GPIO32_UART3_TXD	MFP_CFG(GPIO32, AF4)
+
+/*IRDA*/
+#define GPIO51_IRDA_SHDN	MFP_CFG(GPIO51, AF0)
+
+/* SMC */
+#define SM_nCS0_nCS0		MFP_CFG(SM_nCS0, AF0)
+#define SM_ADV_SM_ADV		MFP_CFG(SM_ADV, AF0)
+#define SM_SCLK_SM_SCLK		MFP_CFG(SM_SCLK, AF0)
+#define SM_SCLK_SM_SCLK		MFP_CFG(SM_SCLK, AF0)
+#define SM_BE0_SM_BE0		MFP_CFG(SM_BE0, AF1)
+#define SM_BE1_SM_BE1		MFP_CFG(SM_BE1, AF1)
+
+/* I2C */
+#define GPIO53_CI2C_SCL		MFP_CFG(GPIO53, AF2)
+#define GPIO54_CI2C_SDA		MFP_CFG(GPIO54, AF2)
+
+/* SSP1 (I2S) */
+#define GPIO24_SSP1_SDATA_IN	MFP_CFG_DRV(GPIO24, AF1, MEDIUM)
+#define GPIO21_SSP1_BITCLK	MFP_CFG_DRV(GPIO21, AF1, MEDIUM)
+#define GPIO20_SSP1_SYSCLK	MFP_CFG_DRV(GPIO20, AF1, MEDIUM)
+#define GPIO22_SSP1_SYNC	MFP_CFG_DRV(GPIO22, AF1, MEDIUM)
+#define GPIO23_SSP1_DATA_OUT	MFP_CFG_DRV(GPIO23, AF1, MEDIUM)
+#define GPIO124_MN_CLK_OUT	MFP_CFG_DRV(GPIO124, AF1, MEDIUM)
+#define GPIO123_CLK_REQ		MFP_CFG_DRV(GPIO123, AF0, MEDIUM)
+
+/* DFI */
+#define DF_IO0_ND_IO0		MFP_CFG(DF_IO0, AF0)
+#define DF_IO1_ND_IO1		MFP_CFG(DF_IO1, AF0)
+#define DF_IO2_ND_IO2		MFP_CFG(DF_IO2, AF0)
+#define DF_IO3_ND_IO3		MFP_CFG(DF_IO3, AF0)
+#define DF_IO4_ND_IO4		MFP_CFG(DF_IO4, AF0)
+#define DF_IO5_ND_IO5		MFP_CFG(DF_IO5, AF0)
+#define DF_IO6_ND_IO6		MFP_CFG(DF_IO6, AF0)
+#define DF_IO7_ND_IO7		MFP_CFG(DF_IO7, AF0)
+#define DF_IO8_ND_IO8		MFP_CFG(DF_IO8, AF0)
+#define DF_IO9_ND_IO9		MFP_CFG(DF_IO9, AF0)
+#define DF_IO10_ND_IO10		MFP_CFG(DF_IO10, AF0)
+#define DF_IO11_ND_IO11		MFP_CFG(DF_IO11, AF0)
+#define DF_IO12_ND_IO12		MFP_CFG(DF_IO12, AF0)
+#define DF_IO13_ND_IO13		MFP_CFG(DF_IO13, AF0)
+#define DF_IO14_ND_IO14		MFP_CFG(DF_IO14, AF0)
+#define DF_IO15_ND_IO15		MFP_CFG(DF_IO15, AF0)
+#define DF_nCS0_SM_nCS2_nCS0	MFP_CFG(DF_nCS0_SM_nCS2, AF0)
+#define DF_ALE_SM_WEn_ND_ALE	MFP_CFG(DF_ALE_SM_WEn, AF1)
+#define DF_CLE_SM_OEn_ND_CLE	MFP_CFG(DF_CLE_SM_OEn, AF0)
+#define DF_WEn_DF_WEn		MFP_CFG(DF_WEn, AF1)
+#define DF_REn_DF_REn		MFP_CFG(DF_REn, AF1)
+#define DF_RDY0_DF_RDY0		MFP_CFG(DF_RDY0, AF0)
+
+/*keypad*/
+#define GPIO00_KP_MKIN0		MFP_CFG(GPIO0, AF1)
+#define GPIO01_KP_MKOUT0	MFP_CFG(GPIO1, AF1)
+#define GPIO02_KP_MKIN1		MFP_CFG(GPIO2, AF1)
+#define GPIO03_KP_MKOUT1	MFP_CFG(GPIO3, AF1)
+#define GPIO04_KP_MKIN2		MFP_CFG(GPIO4, AF1)
+#define GPIO05_KP_MKOUT2	MFP_CFG(GPIO5, AF1)
+#define GPIO06_KP_MKIN3		MFP_CFG(GPIO6, AF1)
+#define GPIO07_KP_MKOUT3	MFP_CFG(GPIO7, AF1)
+#define GPIO08_KP_MKIN4		MFP_CFG(GPIO8, AF1)
+#define GPIO09_KP_MKOUT4	MFP_CFG(GPIO9, AF1)
+#define GPIO10_KP_MKIN5		MFP_CFG(GPIO10, AF1)
+#define GPIO11_KP_MKOUT5	MFP_CFG(GPIO11, AF1)
+#define GPIO12_KP_MKIN6		MFP_CFG(GPIO12, AF1)
+#define GPIO13_KP_MKOUT6	MFP_CFG(GPIO13, AF1)
+#define GPIO14_KP_MKIN7		MFP_CFG(GPIO14, AF1)
+#define GPIO15_KP_MKOUT7	MFP_CFG(GPIO15, AF1)
+#define GPIO16_KP_DKIN0		MFP_CFG(GPIO16, AF1)
+#define GPIO17_KP_DKIN1		MFP_CFG(GPIO17, AF1)
+#define GPIO18_KP_DKIN2		MFP_CFG(GPIO18, AF1)
+#define GPIO19_KP_DKIN3		MFP_CFG(GPIO19, AF1)
+
+/* LCD */
+#define GPIO81_LCD_FCLK		MFP_CFG(GPIO81, AF1)
+#define GPIO82_LCD_LCLK		MFP_CFG(GPIO82, AF1)
+#define GPIO83_LCD_PCLK		MFP_CFG(GPIO83, AF1)
+#define GPIO84_LCD_DENA		MFP_CFG(GPIO84, AF1)
+#define GPIO85_LCD_DD0		MFP_CFG(GPIO85, AF1)
+#define GPIO86_LCD_DD1		MFP_CFG(GPIO86, AF1)
+#define GPIO87_LCD_DD2		MFP_CFG(GPIO87, AF1)
+#define GPIO88_LCD_DD3		MFP_CFG(GPIO88, AF1)
+#define GPIO89_LCD_DD4		MFP_CFG(GPIO89, AF1)
+#define GPIO90_LCD_DD5		MFP_CFG(GPIO90, AF1)
+#define GPIO91_LCD_DD6		MFP_CFG(GPIO91, AF1)
+#define GPIO92_LCD_DD7		MFP_CFG(GPIO92, AF1)
+#define GPIO93_LCD_DD8		MFP_CFG(GPIO93, AF1)
+#define GPIO94_LCD_DD9		MFP_CFG(GPIO94, AF1)
+#define GPIO95_LCD_DD10		MFP_CFG(GPIO95, AF1)
+#define GPIO96_LCD_DD11		MFP_CFG(GPIO96, AF1)
+#define GPIO97_LCD_DD12		MFP_CFG(GPIO97, AF1)
+#define GPIO98_LCD_DD13		MFP_CFG(GPIO98, AF1)
+#define GPIO100_LCD_DD14	MFP_CFG(GPIO100, AF1)
+#define GPIO101_LCD_DD15	MFP_CFG(GPIO101, AF1)
+#define GPIO102_LCD_DD16	MFP_CFG(GPIO102, AF1)
+#define GPIO103_LCD_DD17	MFP_CFG(GPIO103, AF1)
+#define GPIO104_LCD_DD18	MFP_CFG(GPIO104, AF1)
+#define GPIO105_LCD_DD19	MFP_CFG(GPIO105, AF1)
+#define GPIO106_LCD_DD20	MFP_CFG(GPIO106, AF1)
+#define GPIO107_LCD_DD21	MFP_CFG(GPIO107, AF1)
+#define GPIO108_LCD_DD22	MFP_CFG(GPIO108, AF1)
+#define GPIO109_LCD_DD23	MFP_CFG(GPIO109, AF1)
+
+#define GPIO104_LCD_SPIDOUT	MFP_CFG(GPIO104, AF3)
+#define GPIO105_LCD_SPIDIN	MFP_CFG(GPIO105, AF3)
+#define GPIO107_LCD_CS1 	MFP_CFG(GPIO107, AF3)
+#define GPIO108_LCD_DCLK	MFP_CFG(GPIO108, AF3)
+
+#define GPIO106_LCD_RESET	MFP_CFG(GPIO106, AF0)
+
+/*smart panel*/
+#define GPIO82_LCD_A0		MFP_CFG(GPIO82, AF0)
+#define GPIO83_LCD_WR		MFP_CFG(GPIO83, AF0)
+#define GPIO103_LCD_CS		MFP_CFG(GPIO103, AF0)
+
+/*1wire*/
+#define GPIO106_1WIRE		MFP_CFG(GPIO106, AF3)
+
+/*CCIC*/
+#define GPIO67_CCIC_IN7		MFP_CFG_DRV(GPIO67, AF1, MEDIUM)
+#define GPIO68_CCIC_IN6		MFP_CFG_DRV(GPIO68, AF1, MEDIUM)
+#define GPIO69_CCIC_IN5		MFP_CFG_DRV(GPIO69, AF1, MEDIUM)
+#define GPIO70_CCIC_IN4		MFP_CFG_DRV(GPIO70, AF1, MEDIUM)
+#define GPIO71_CCIC_IN3		MFP_CFG_DRV(GPIO71, AF1, MEDIUM)
+#define GPIO72_CCIC_IN2		MFP_CFG_DRV(GPIO72, AF1, MEDIUM)
+#define GPIO73_CCIC_IN1		MFP_CFG_DRV(GPIO73, AF1, MEDIUM)
+#define GPIO74_CCIC_IN0		MFP_CFG_DRV(GPIO74, AF1, MEDIUM)
+#define GPIO75_CAM_HSYNC	MFP_CFG_DRV(GPIO75, AF1, MEDIUM)
+#define GPIO76_CAM_VSYNC	MFP_CFG_DRV(GPIO76, AF1, MEDIUM)
+#define GPIO77_CAM_MCLK		MFP_CFG_DRV(GPIO77, AF1, MEDIUM)
+#define GPIO78_CAM_PCLK		MFP_CFG_DRV(GPIO78, AF1, MEDIUM)
+
+/* MMC1 */
+#define MMC1_DAT7_MMC1_DAT7	MFP_CFG_DRV(MMC1_DAT7, AF0, MEDIUM)
+#define MMC1_DAT6_MMC1_DAT6	MFP_CFG_DRV(MMC1_DAT6, AF0, MEDIUM)
+#define MMC1_DAT5_MMC1_DAT5	MFP_CFG_DRV(MMC1_DAT5, AF0, MEDIUM)
+#define MMC1_DAT4_MMC1_DAT4	MFP_CFG_DRV(MMC1_DAT4, AF0, MEDIUM)
+#define MMC1_DAT3_MMC1_DAT3	MFP_CFG_DRV(MMC1_DAT3, AF0, MEDIUM)
+#define MMC1_DAT2_MMC1_DAT2	MFP_CFG_DRV(MMC1_DAT2, AF0, MEDIUM)
+#define MMC1_DAT1_MMC1_DAT1	MFP_CFG_DRV(MMC1_DAT1, AF0, MEDIUM)
+#define MMC1_DAT0_MMC1_DAT0	MFP_CFG_DRV(MMC1_DAT0, AF0, MEDIUM)
+#define MMC1_CMD_MMC1_CMD	MFP_CFG_DRV(MMC1_CMD, AF0, MEDIUM)
+#define MMC1_CLK_MMC1_CLK	MFP_CFG_DRV(MMC1_CLK, AF0, MEDIUM)
+#define MMC1_CD_MMC1_CD		MFP_CFG_DRV(MMC1_CD, AF0, MEDIUM)
+#define MMC1_WP_MMC1_WP		MFP_CFG_DRV(MMC1_WP, AF0, MEDIUM)
+
+#endif /* __ASM_MACH MFP_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp.h b/arch/arm/mach-mmp/include/mach/mfp.h
new file mode 100644
index 0000000..277ea4c
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp.h
@@ -0,0 +1,37 @@
+#ifndef __ASM_MACH_MFP_H
+#define __ASM_MACH_MFP_H
+
+#include <plat/mfp.h>
+
+/*
+ * NOTE: the MFPR register bit definitions on PXA168 processor lines are a
+ * bit different from those on PXA3xx.  Bit [7:10] are now reserved, which
+ * were SLEEP_OE_N, SLEEP_DATA, SLEEP_SEL and the LSB of DRIVE bits.
+ *
+ * To cope with this difference and re-use the pxa3xx mfp code as much as
+ * possible, we make the following compromise:
+ *
+ * 1. SLEEP_OE_N will always be programmed to '1' (by MFP_LPM_FLOAT)
+ * 2. DRIVE strength definitions redefined to include the reserved bit10
+ * 3. Override MFP_CFG() and MFP_CFG_DRV()
+ * 4. Drop the use of MFP_CFG_LPM() and MFP_CFG_X()
+ */
+
+#define MFP_DRIVE_VERY_SLOW	(0x0 << 13)
+#define MFP_DRIVE_SLOW		(0x2 << 13)
+#define MFP_DRIVE_MEDIUM	(0x4 << 13)
+#define MFP_DRIVE_FAST		(0x8 << 13)
+
+#undef MFP_CFG
+#undef MFP_CFG_DRV
+#undef MFP_CFG_LPM
+#undef MFP_CFG_X
+#undef MFP_CFG_DEFAULT
+
+#define MFP_CFG(pin, af)		\
+	(MFP_LPM_FLOAT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_MEDIUM)
+
+#define MFP_CFG_DRV(pin, af, drv)	\
+	(MFP_LPM_FLOAT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_##drv)
+
+#endif /* __ASM_MACH_MFP_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
new file mode 100644
index 0000000..ef0a8a2
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_MACH_PXA168_H
+#define __ASM_MACH_PXA168_H
+
+#include <mach/devices.h>
+
+extern struct pxa_device_desc pxa168_device_uart1;
+extern struct pxa_device_desc pxa168_device_uart2;
+
+static inline int pxa168_add_uart(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa168_device_uart1; break;
+	case 2: d = &pxa168_device_uart2; break;
+	}
+
+	if (d == NULL)
+		return -EINVAL;
+
+	return pxa_register_device(d, NULL, 0);
+}
+#endif /* __ASM_MACH_PXA168_H */
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
new file mode 100644
index 0000000..b7aeaf5
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_MACH_PXA910_H
+#define __ASM_MACH_PXA910_H
+
+#include <mach/devices.h>
+
+extern struct pxa_device_desc pxa910_device_uart1;
+extern struct pxa_device_desc pxa910_device_uart2;
+
+static inline int pxa910_add_uart(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &pxa910_device_uart1; break;
+	case 2: d = &pxa910_device_uart2; break;
+	}
+
+	if (d == NULL)
+		return -EINVAL;
+
+	return pxa_register_device(d, NULL, 0);
+}
+#endif /* __ASM_MACH_PXA910_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
new file mode 100644
index 0000000..c6b8c9d
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -0,0 +1,78 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/regs-apbc.h
+ *
+ *   Application Peripheral Bus Clock Unit
+ *
+ * This program is free software; you can 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_MACH_REGS_APBC_H
+#define __ASM_MACH_REGS_APBC_H
+
+#include <mach/addr-map.h>
+
+#define APBC_VIRT_BASE	(APB_VIRT_BASE + 0x015000)
+#define APBC_REG(x)	(APBC_VIRT_BASE + (x))
+
+/*
+ * APB clock register offsets for PXA168
+ */
+#define APBC_PXA168_UART1	APBC_REG(0x000)
+#define APBC_PXA168_UART2	APBC_REG(0x004)
+#define APBC_PXA168_GPIO	APBC_REG(0x008)
+#define APBC_PXA168_PWM0	APBC_REG(0x00c)
+#define APBC_PXA168_PWM1	APBC_REG(0x010)
+#define APBC_PXA168_SSP1	APBC_REG(0x01c)
+#define APBC_PXA168_SSP2	APBC_REG(0x020)
+#define APBC_PXA168_RTC		APBC_REG(0x028)
+#define APBC_PXA168_TWSI0	APBC_REG(0x02c)
+#define APBC_PXA168_KPC		APBC_REG(0x030)
+#define APBC_PXA168_TIMERS	APBC_REG(0x034)
+#define APBC_PXA168_AIB		APBC_REG(0x03c)
+#define APBC_PXA168_SW_JTAG	APBC_REG(0x040)
+#define APBC_PXA168_ONEWIRE	APBC_REG(0x048)
+#define APBC_PXA168_SSP3	APBC_REG(0x04c)
+#define APBC_PXA168_ASFAR	APBC_REG(0x050)
+#define APBC_PXA168_ASSAR	APBC_REG(0x054)
+#define APBC_PXA168_SSP4	APBC_REG(0x058)
+#define APBC_PXA168_SSP5	APBC_REG(0x05c)
+#define APBC_PXA168_TWSI1	APBC_REG(0x06c)
+#define APBC_PXA168_UART3	APBC_REG(0x070)
+#define APBC_PXA168_AC97	APBC_REG(0x084)
+
+/*
+ * APB Clock register offsets for PXA910
+ */
+#define APBC_PXA910_UART0	APBC_REG(0x000)
+#define APBC_PXA910_UART1	APBC_REG(0x004)
+#define APBC_PXA910_GPIO	APBC_REG(0x008)
+#define APBC_PXA910_PWM0	APBC_REG(0x00c)
+#define APBC_PXA910_PWM1	APBC_REG(0x010)
+#define APBC_PXA910_PWM2	APBC_REG(0x014)
+#define APBC_PXA910_PWM3	APBC_REG(0x018)
+#define APBC_PXA910_SSP1	APBC_REG(0x01c)
+#define APBC_PXA910_SSP2	APBC_REG(0x020)
+#define APBC_PXA910_IPC		APBC_REG(0x024)
+#define APBC_PXA910_TWSI0	APBC_REG(0x02c)
+#define APBC_PXA910_KPC		APBC_REG(0x030)
+#define APBC_PXA910_TIMERS	APBC_REG(0x034)
+#define APBC_PXA910_TBROT	APBC_REG(0x038)
+#define APBC_PXA910_AIB		APBC_REG(0x03c)
+#define APBC_PXA910_SW_JTAG	APBC_REG(0x040)
+#define APBC_PXA910_TIMERS1	APBC_REG(0x044)
+#define APBC_PXA910_ONEWIRE	APBC_REG(0x048)
+#define APBC_PXA910_SSP3	APBC_REG(0x04c)
+#define APBC_PXA910_ASFAR	APBC_REG(0x050)
+#define APBC_PXA910_ASSAR	APBC_REG(0x054)
+
+/* Common APB clock register bit definitions */
+#define APBC_APBCLK	(1 << 0)  /* APB Bus Clock Enable */
+#define APBC_FNCLK	(1 << 1)  /* Functional Clock Enable */
+#define APBC_RST	(1 << 2)  /* Reset Generation */
+
+/* Functional Clock Selection Mask */
+#define APBC_FNCLKSEL(x)	(((x) & 0xf) << 4)
+
+#endif /* __ASM_MACH_REGS_APBC_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
new file mode 100644
index 0000000..9190305
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/regs-apmu.h
+ *
+ *   Application Subsystem Power Management Unit
+ *
+ * This program is free software; you can 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_MACH_REGS_APMU_H
+#define __ASM_MACH_REGS_APMU_H
+
+#include <mach/addr-map.h>
+
+#define APMU_VIRT_BASE	(AXI_VIRT_BASE + 0x82800)
+#define APMU_REG(x)	(APMU_VIRT_BASE + (x))
+
+/* Clock Reset Control */
+#define APMU_IRE	APMU_REG(0x048)
+#define APMU_LCD	APMU_REG(0x04c)
+#define APMU_CCIC	APMU_REG(0x050)
+#define APMU_SDH0	APMU_REG(0x054)
+#define APMU_SDH1	APMU_REG(0x058)
+#define APMU_USB	APMU_REG(0x05c)
+#define APMU_NAND	APMU_REG(0x060)
+#define APMU_DMA	APMU_REG(0x064)
+#define APMU_GEU	APMU_REG(0x068)
+#define APMU_BUS	APMU_REG(0x06c)
+
+#define APMU_FNCLK_EN	(1 << 4)
+#define APMU_AXICLK_EN	(1 << 3)
+#define APMU_FNRST_DIS	(1 << 1)
+#define APMU_AXIRST_DIS	(1 << 0)
+
+#endif /* __ASM_MACH_REGS_APMU_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-icu.h b/arch/arm/mach-mmp/include/mach/regs-icu.h
new file mode 100644
index 0000000..e5f0872
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-icu.h
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/regs-icu.h
+ *
+ *   Interrupt Control Unit
+ *
+ * This program is free software; you can 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_MACH_ICU_H
+#define __ASM_MACH_ICU_H
+
+#include <mach/addr-map.h>
+
+#define ICU_VIRT_BASE	(AXI_VIRT_BASE + 0x82000)
+#define ICU_REG(x)	(ICU_VIRT_BASE + (x))
+
+#define ICU_INT_CONF(n)		ICU_REG((n) << 2)
+#define ICU_INT_CONF_AP_INT	(1 << 6)
+#define ICU_INT_CONF_CP_INT	(1 << 5)
+#define ICU_INT_CONF_IRQ	(1 << 4)
+#define ICU_INT_CONF_MASK	(0xf)
+
+#define ICU_AP_FIQ_SEL_INT_NUM	ICU_REG(0x108)	/* AP FIQ Selected Interrupt */
+#define ICU_AP_IRQ_SEL_INT_NUM	ICU_REG(0x10C)	/* AP IRQ Selected Interrupt */
+#define ICU_AP_GBL_IRQ_MSK	ICU_REG(0x114)	/* AP Global Interrupt Mask */
+#define ICU_INT_STATUS_0	ICU_REG(0x128)	/* Interrupt Stuats 0 */
+#define ICU_INT_STATUS_1	ICU_REG(0x12C)	/* Interrupt Status 1 */
+
+#endif /* __ASM_MACH_ICU_H */
diff --git a/arch/arm/mach-mmp/include/mach/regs-timers.h b/arch/arm/mach-mmp/include/mach/regs-timers.h
new file mode 100644
index 0000000..45589fe
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-timers.h
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/regs-timers.h
+ *
+ *   Timers Module
+ *
+ * This program is free software; you can 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_MACH_REGS_TIMERS_H
+#define __ASM_MACH_REGS_TIMERS_H
+
+#include <mach/addr-map.h>
+
+#define TIMERS1_VIRT_BASE	(APB_VIRT_BASE + 0x14000)
+#define TIMERS2_VIRT_BASE	(APB_VIRT_BASE + 0x16000)
+
+#define TMR_CCR		(0x0000)
+#define TMR_TN_MM(n, m)	(0x0004 + ((n) << 3) + (((n) + (m)) << 2))
+#define TMR_CR(n)	(0x0028 + ((n) << 2))
+#define TMR_SR(n)	(0x0034 + ((n) << 2))
+#define TMR_IER(n)	(0x0040 + ((n) << 2))
+#define TMR_PLVR(n)	(0x004c + ((n) << 2))
+#define TMR_PLCR(n)	(0x0058 + ((n) << 2))
+#define TMR_WMER	(0x0064)
+#define TMR_WMR		(0x0068)
+#define TMR_WVR		(0x006c)
+#define TMR_WSR		(0x0070)
+#define TMR_ICR(n)	(0x0074 + ((n) << 2))
+#define TMR_WICR	(0x0080)
+#define TMR_CER		(0x0084)
+#define TMR_CMR		(0x0088)
+#define TMR_ILR(n)	(0x008c + ((n) << 2))
+#define TMR_WCR		(0x0098)
+#define TMR_WFAR	(0x009c)
+#define TMR_WSAR	(0x00A0)
+#define TMR_CVWR(n)	(0x00A4 + ((n) << 2))
+
+#define TMR_CCR_CS_0(x)	(((x) & 0x3) << 0)
+#define TMR_CCR_CS_1(x)	(((x) & 0x7) << 2)
+#define TMR_CCR_CS_2(x)	(((x) & 0x3) << 5)
+
+#endif /* __ASM_MACH_REGS_TIMERS_H */
diff --git a/arch/arm/mach-mmp/include/mach/system.h b/arch/arm/mach-mmp/include/mach/system.h
new file mode 100644
index 0000000..001edfe
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/system.h
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/system.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_MACH_SYSTEM_H
+#define __ASM_MACH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	cpu_reset(0);
+}
+#endif /* __ASM_MACH_SYSTEM_H */
diff --git a/arch/arm/mach-mmp/include/mach/timex.h b/arch/arm/mach-mmp/include/mach/timex.h
new file mode 100644
index 0000000..6cebbd0
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/timex.h
@@ -0,0 +1,9 @@
+/*
+ * 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.
+ */
+
+#define CLOCK_TICK_RATE		3250000
diff --git a/arch/arm/mach-mmp/include/mach/uncompress.h b/arch/arm/mach-mmp/include/mach/uncompress.h
new file mode 100644
index 0000000..c93d5fa
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/uncompress.h
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-mmp/include/mach/uncompress.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.
+ */
+
+#include <linux/serial_reg.h>
+#include <mach/addr-map.h>
+
+#define UART1_BASE	(APB_PHYS_BASE + 0x36000)
+#define UART2_BASE	(APB_PHYS_BASE + 0x17000)
+#define UART3_BASE	(APB_PHYS_BASE + 0x18000)
+
+static inline void putc(char c)
+{
+	volatile unsigned long *UART = (unsigned long *)UART2_BASE;
+
+	/* UART enabled? */
+	if (!(UART[UART_IER] & UART_IER_UUE))
+		return;
+
+	while (!(UART[UART_LSR] & UART_LSR_THRE))
+		barrier();
+
+	UART[UART_TX] = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-mmp/include/mach/vmalloc.h b/arch/arm/mach-mmp/include/mach/vmalloc.h
new file mode 100644
index 0000000..b60ccaf
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/vmalloc.h
@@ -0,0 +1,5 @@
+/*
+ * linux/arch/arm/mach-mmp/include/mach/vmalloc.h
+ */
+
+#define VMALLOC_END	0xfe000000
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c
new file mode 100644
index 0000000..52ff2f0
--- /dev/null
+++ b/arch/arm/mach-mmp/irq.c
@@ -0,0 +1,55 @@
+/*
+ *  linux/arch/arm/mach-mmp/irq.c
+ *
+ *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
+ *
+ *  Author:	Bin Yang <bin.yang@marvell.com>
+ *  Created:	Sep 30, 2008
+ *  Copyright:	Marvell International Ltd.
+ *
+ *  This program is free software; you can 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/irq.h>
+#include <linux/io.h>
+
+#include <mach/regs-icu.h>
+
+#include "common.h"
+
+#define IRQ_ROUTE_TO_AP		(ICU_INT_CONF_AP_INT | ICU_INT_CONF_IRQ)
+
+#define PRIORITY_DEFAULT	0x1
+#define PRIORITY_NONE		0x0	/* means IRQ disabled */
+
+static void icu_mask_irq(unsigned int irq)
+{
+	__raw_writel(PRIORITY_NONE, ICU_INT_CONF(irq));
+}
+
+static void icu_unmask_irq(unsigned int irq)
+{
+	__raw_writel(IRQ_ROUTE_TO_AP | PRIORITY_DEFAULT, ICU_INT_CONF(irq));
+}
+
+static struct irq_chip icu_irq_chip = {
+	.name	= "icu_irq",
+	.ack	= icu_mask_irq,
+	.mask	= icu_mask_irq,
+	.unmask	= icu_unmask_irq,
+};
+
+void __init icu_init_irq(void)
+{
+	int irq;
+
+	for (irq = 0; irq < 64; irq++) {
+		icu_mask_irq(irq);
+		set_irq_chip(irq, &icu_irq_chip);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
new file mode 100644
index 0000000..ae92446
--- /dev/null
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -0,0 +1,111 @@
+/*
+ *  linux/arch/arm/mach-mmp/pxa168.c
+ *
+ *  Code specific to PXA168
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <asm/mach/time.h>
+#include <mach/addr-map.h>
+#include <mach/cputype.h>
+#include <mach/regs-apbc.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <mach/dma.h>
+#include <mach/devices.h>
+#include <mach/mfp.h>
+
+#include "common.h"
+#include "clock.h"
+
+#define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
+
+static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata =
+{
+	MFP_ADDR_X(GPIO0,   GPIO36,  0x04c),
+	MFP_ADDR_X(GPIO37,  GPIO55,  0x000),
+	MFP_ADDR_X(GPIO56,  GPIO123, 0x0e0),
+	MFP_ADDR_X(GPIO124, GPIO127, 0x0f4),
+
+	MFP_ADDR_END,
+};
+
+#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
+
+static void __init pxa168_init_gpio(void)
+{
+	int i;
+
+	/* enable GPIO clock */
+	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO);
+
+	/* unmask GPIO edge detection for all 4 banks - APMASKx */
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xffffffff, APMASK(i));
+
+	pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL);
+}
+
+void __init pxa168_init_irq(void)
+{
+	icu_init_irq();
+	pxa168_init_gpio();
+}
+
+/* APB peripheral clocks */
+static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
+static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
+
+/* device and clock bindings */
+static struct clk_lookup pxa168_clkregs[] = {
+	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
+	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+};
+
+static int __init pxa168_init(void)
+{
+	if (cpu_is_pxa168()) {
+		mfp_init_base(MFPR_VIRT_BASE);
+		mfp_init_addr(pxa168_mfp_addr_map);
+		pxa_init_dma(IRQ_PXA168_DMA_INT0, 32);
+		clks_register(ARRAY_AND_SIZE(pxa168_clkregs));
+	}
+
+	return 0;
+}
+postcore_initcall(pxa168_init);
+
+/* system timer - clock enabled, 3.25MHz */
+#define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
+
+static void __init pxa168_timer_init(void)
+{
+	/* this is early, we have to initialize the CCU registers by
+	 * ourselves instead of using clk_* API. Clock rate is defined
+	 * by APBC_TIMERS_CLK_RST (3.25MHz) and enabled free-running
+	 */
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA168_TIMERS);
+
+	/* 3.25MHz, bus/functional clock enabled, release reset */
+	__raw_writel(TIMER_CLK_RST, APBC_PXA168_TIMERS);
+
+	timer_init(IRQ_PXA168_TIMER1);
+}
+
+struct sys_timer pxa168_timer = {
+	.init	= pxa168_timer_init,
+};
+
+/* on-chip devices */
+PXA168_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4017000, 0x30, 21, 22);
+PXA168_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4018000, 0x30, 23, 24);
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
new file mode 100644
index 0000000..453f8f7
--- /dev/null
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -0,0 +1,158 @@
+/*
+ *  linux/arch/arm/mach-mmp/pxa910.c
+ *
+ *  Code specific to PXA910
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/addr-map.h>
+#include <mach/regs-apbc.h>
+#include <mach/regs-apmu.h>
+#include <mach/cputype.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <mach/dma.h>
+#include <mach/mfp.h>
+#include <mach/devices.h>
+
+#include "common.h"
+#include "clock.h"
+
+#define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
+
+static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata =
+{
+	MFP_ADDR_X(GPIO0, GPIO54, 0xdc),
+	MFP_ADDR_X(GPIO67, GPIO98, 0x1b8),
+	MFP_ADDR_X(GPIO100, GPIO109, 0x238),
+
+	MFP_ADDR(GPIO123, 0xcc),
+	MFP_ADDR(GPIO124, 0xd0),
+
+	MFP_ADDR(DF_IO0, 0x40),
+	MFP_ADDR(DF_IO1, 0x3c),
+	MFP_ADDR(DF_IO2, 0x38),
+	MFP_ADDR(DF_IO3, 0x34),
+	MFP_ADDR(DF_IO4, 0x30),
+	MFP_ADDR(DF_IO5, 0x2c),
+	MFP_ADDR(DF_IO6, 0x28),
+	MFP_ADDR(DF_IO7, 0x24),
+	MFP_ADDR(DF_IO8, 0x20),
+	MFP_ADDR(DF_IO9, 0x1c),
+	MFP_ADDR(DF_IO10, 0x18),
+	MFP_ADDR(DF_IO11, 0x14),
+	MFP_ADDR(DF_IO12, 0x10),
+	MFP_ADDR(DF_IO13, 0xc),
+	MFP_ADDR(DF_IO14, 0x8),
+	MFP_ADDR(DF_IO15, 0x4),
+
+	MFP_ADDR(DF_nCS0_SM_nCS2, 0x44),
+	MFP_ADDR(DF_nCS1_SM_nCS3, 0x48),
+	MFP_ADDR(SM_nCS0, 0x4c),
+	MFP_ADDR(SM_nCS1, 0x50),
+	MFP_ADDR(DF_WEn, 0x54),
+	MFP_ADDR(DF_REn, 0x58),
+	MFP_ADDR(DF_CLE_SM_OEn, 0x5c),
+	MFP_ADDR(DF_ALE_SM_WEn, 0x60),
+	MFP_ADDR(SM_SCLK, 0x64),
+	MFP_ADDR(DF_RDY0, 0x68),
+	MFP_ADDR(SM_BE0, 0x6c),
+	MFP_ADDR(SM_BE1, 0x70),
+	MFP_ADDR(SM_ADV, 0x74),
+	MFP_ADDR(DF_RDY1, 0x78),
+	MFP_ADDR(SM_ADVMUX, 0x7c),
+	MFP_ADDR(SM_RDY, 0x80),
+
+	MFP_ADDR_X(MMC1_DAT7, MMC1_WP, 0x84),
+
+	MFP_ADDR_END,
+};
+
+#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
+
+static void __init pxa910_init_gpio(void)
+{
+	int i;
+
+	/* enable GPIO clock */
+	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO);
+
+	/* unmask GPIO edge detection for all 4 banks - APMASKx */
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xffffffff, APMASK(i));
+
+	pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL);
+}
+
+void __init pxa910_init_irq(void)
+{
+	icu_init_irq();
+	pxa910_init_gpio();
+}
+
+/* APB peripheral clocks */
+static APBC_CLK(uart1, PXA910_UART0, 1, 14745600);
+static APBC_CLK(uart2, PXA910_UART1, 1, 14745600);
+
+/* device and clock bindings */
+static struct clk_lookup pxa910_clkregs[] = {
+	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
+	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+};
+
+static int __init pxa910_init(void)
+{
+	if (cpu_is_pxa910()) {
+		mfp_init_base(MFPR_VIRT_BASE);
+		mfp_init_addr(pxa910_mfp_addr_map);
+		pxa_init_dma(IRQ_PXA910_DMA_INT0, 32);
+		clks_register(ARRAY_AND_SIZE(pxa910_clkregs));
+	}
+
+	return 0;
+}
+postcore_initcall(pxa910_init);
+
+/* system timer - clock enabled, 3.25MHz */
+#define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
+
+static void __init pxa910_timer_init(void)
+{
+	/* reset and configure */
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_PXA910_TIMERS);
+	__raw_writel(TIMER_CLK_RST, APBC_PXA910_TIMERS);
+
+	timer_init(IRQ_PXA910_AP1_TIMER1);
+}
+
+struct sys_timer pxa910_timer = {
+	.init	= pxa910_timer_init,
+};
+
+/* on-chip devices */
+
+/* NOTE: there are totally 3 UARTs on PXA910:
+ *
+ *   UART1   - Slow UART (can be used both by AP and CP)
+ *   UART2/3 - Fast UART
+ *
+ * To be backward compatible with the legacy FFUART/BTUART/STUART sequence,
+ * they are re-ordered as:
+ *
+ *   pxa910_device_uart1 - UART2 as FFUART
+ *   pxa910_device_uart2 - UART3 as BTUART
+ *
+ * UART1 is not used by AP for the moment.
+ */
+PXA910_DEVICE(uart1, "pxa2xx-uart", 0, UART2, 0xd4017000, 0x30, 21, 22);
+PXA910_DEVICE(uart2, "pxa2xx-uart", 1, UART3, 0xd4018000, 0x30, 23, 24);
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
new file mode 100644
index 0000000..0e0c922
--- /dev/null
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -0,0 +1,109 @@
+/*
+ *  linux/arch/arm/mach-mmp/tavorevb.c
+ *
+ *  Support for the Marvell PXA910-based TavorEVB Development Platform.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa910.h>
+#include <mach/pxa910.h>
+#include <mach/gpio.h>
+
+#include "common.h"
+
+static unsigned long tavorevb_pin_config[] __initdata = {
+	/* UART2 */
+	GPIO47_UART2_RXD,
+	GPIO48_UART2_TXD,
+
+	/* SMC */
+	SM_nCS0_nCS0,
+	SM_ADV_SM_ADV,
+	SM_SCLK_SM_SCLK,
+	SM_SCLK_SM_SCLK,
+	SM_BE0_SM_BE0,
+	SM_BE1_SM_BE1,
+
+	/* DFI */
+	DF_IO0_ND_IO0,
+	DF_IO1_ND_IO1,
+	DF_IO2_ND_IO2,
+	DF_IO3_ND_IO3,
+	DF_IO4_ND_IO4,
+	DF_IO5_ND_IO5,
+	DF_IO6_ND_IO6,
+	DF_IO7_ND_IO7,
+	DF_IO8_ND_IO8,
+	DF_IO9_ND_IO9,
+	DF_IO10_ND_IO10,
+	DF_IO11_ND_IO11,
+	DF_IO12_ND_IO12,
+	DF_IO13_ND_IO13,
+	DF_IO14_ND_IO14,
+	DF_IO15_ND_IO15,
+	DF_nCS0_SM_nCS2_nCS0,
+	DF_ALE_SM_WEn_ND_ALE,
+	DF_CLE_SM_OEn_ND_CLE,
+	DF_WEn_DF_WEn,
+	DF_REn_DF_REn,
+	DF_RDY0_DF_RDY0,
+};
+
+static struct smc91x_platdata tavorevb_smc91x_info = {
+	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= SMC_CS1_PHYS_BASE + 0x300,
+		.end	= SMC_CS1_PHYS_BASE + 0xfffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(80),
+		.end	= gpio_to_irq(80),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &tavorevb_smc91x_info,
+	},
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static void __init tavorevb_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(tavorevb_pin_config));
+
+	/* on-chip devices */
+	pxa910_add_uart(1);
+
+	/* off-chip devices */
+	platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = pxa910_init_irq,
+	.timer          = &pxa910_timer,
+	.init_machine   = tavorevb_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
new file mode 100644
index 0000000..b03a6ed
--- /dev/null
+++ b/arch/arm/mach-mmp/time.c
@@ -0,0 +1,199 @@
+/*
+ * linux/arch/arm/mach-mmp/time.c
+ *
+ *   Support for clocksource and clockevents
+ *
+ * Copyright (C) 2008 Marvell International Ltd.
+ * All rights reserved.
+ *
+ *   2008-04-11: Jason Chagas <Jason.chagas@marvell.com>
+ *   2008-10-08: Bin Yang <bin.yang@marvell.com>
+ *
+ * The timers module actually includes three timers, each timer with upto
+ * three match comparators. Timer #0 is used here in free-running mode as
+ * the clock source, and match comparator #1 used as clock event device.
+ *
+ * This program is free software; you can 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/cnt32_to_63.h>
+
+#include <mach/addr-map.h>
+#include <mach/regs-timers.h>
+#include <mach/irqs.h>
+
+#include "clock.h"
+
+#define TIMERS_VIRT_BASE	TIMERS1_VIRT_BASE
+
+#define MAX_DELTA		(0xfffffffe)
+#define MIN_DELTA		(16)
+
+#define TCR2NS_SCALE_FACTOR	10
+
+static unsigned long tcr2ns_scale;
+
+static void __init set_tcr2ns_scale(unsigned long tcr_rate)
+{
+	unsigned long long v = 1000000000ULL << TCR2NS_SCALE_FACTOR;
+	do_div(v, tcr_rate);
+	tcr2ns_scale = v;
+	/*
+	 * We want an even value to automatically clear the top bit
+	 * returned by cnt32_to_63() without an additional run time
+	 * instruction. So if the LSB is 1 then round it up.
+	 */
+	if (tcr2ns_scale & 1)
+		tcr2ns_scale++;
+}
+
+/*
+ * FIXME: the timer needs some delay to stablize the counter capture
+ */
+static inline uint32_t timer_read(void)
+{
+	int delay = 100;
+
+	__raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(0));
+
+	while (delay--)
+		cpu_relax();
+
+	return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0));
+}
+
+unsigned long long sched_clock(void)
+{
+	unsigned long long v = cnt32_to_63(timer_read());
+	return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR;
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *c = dev_id;
+
+	/* disable and clear pending interrupt status */
+	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
+	__raw_writel(0x1, TIMERS_VIRT_BASE + TMR_ICR(0));
+	c->event_handler(c);
+	return IRQ_HANDLED;
+}
+
+static int timer_set_next_event(unsigned long delta,
+				struct clock_event_device *dev)
+{
+	unsigned long flags, next;
+
+	local_irq_save(flags);
+
+	/* clear pending interrupt status and enable */
+	__raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0));
+	__raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0));
+
+	next = timer_read() + delta;
+	__raw_writel(next, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0));
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static void timer_set_mode(enum clock_event_mode mode,
+			   struct clock_event_device *dev)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		/* disable the matching interrupt */
+		__raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0));
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	}
+	local_irq_restore(flags);
+}
+
+static struct clock_event_device ckevt = {
+	.name		= "clockevent",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.rating		= 200,
+	.set_next_event	= timer_set_next_event,
+	.set_mode	= timer_set_mode,
+};
+
+static cycle_t clksrc_read(void)
+{
+	return timer_read();
+}
+
+static struct clocksource cksrc = {
+	.name		= "clocksource",
+	.shift		= 20,
+	.rating		= 200,
+	.read		= clksrc_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init timer_config(void)
+{
+	uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR);
+	uint32_t cer = __raw_readl(TIMERS_VIRT_BASE + TMR_CER);
+	uint32_t cmr = __raw_readl(TIMERS_VIRT_BASE + TMR_CMR);
+
+	__raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */
+
+	ccr &= TMR_CCR_CS_0(0x3);
+	__raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
+
+	/* free-running mode */
+	__raw_writel(cmr | 0x01, TIMERS_VIRT_BASE + TMR_CMR);
+
+	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */
+	__raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0));  /* clear status */
+	__raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0));
+
+	/* enable timer counter */
+	__raw_writel(cer | 0x01, TIMERS_VIRT_BASE + TMR_CER);
+}
+
+static struct irqaction timer_irq = {
+	.name		= "timer",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= timer_interrupt,
+	.dev_id		= &ckevt,
+};
+
+void __init timer_init(int irq)
+{
+	timer_config();
+
+	set_tcr2ns_scale(CLOCK_TICK_RATE);
+
+	ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift);
+	ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt);
+	ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt);
+	ckevt.cpumask = cpumask_of(0);
+
+	cksrc.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cksrc.shift);
+
+	setup_irq(irq, &timer_irq);
+
+	clocksource_register(&cksrc);
+	clockevents_register_device(&ckevt);
+}
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
new file mode 100644
index 0000000..08cfef6
--- /dev/null
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -0,0 +1,47 @@
+/*
+ *  linux/arch/arm/mach-mmp/ttc_dkb.c
+ *
+ *  Support for the Marvell PXA910-based TTC_DKB Development Platform.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa910.h>
+#include <mach/pxa910.h>
+
+#include "common.h"
+
+#define ARRAY_AND_SIZE(x)       (x), ARRAY_SIZE(x)
+
+static unsigned long ttc_dkb_pin_config[] __initdata = {
+	/* UART2 */
+	GPIO47_UART2_RXD,
+	GPIO48_UART2_TXD,
+};
+
+static void __init ttc_dkb_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
+
+	/* on-chip devices */
+	pxa910_add_uart(1);
+}
+
+MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = pxa910_init_irq,
+	.timer          = &pxa910_timer,
+	.init_machine   = ttc_dkb_init,
+MACHINE_END
diff --git a/arch/arm/mach-msm/include/mach/system.h b/arch/arm/mach-msm/include/mach/system.h
index f05ad2e..574ccc4 100644
--- a/arch/arm/mach-msm/include/mach/system.h
+++ b/arch/arm/mach-msm/include/mach/system.h
@@ -17,7 +17,7 @@
 
 void arch_idle(void);
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	for (;;) ;  /* depends on IPC w/ other core */
 }
diff --git a/arch/arm/mach-mv78xx0/Kconfig b/arch/arm/mach-mv78xx0/Kconfig
index d83cb86..6fbe68f 100644
--- a/arch/arm/mach-mv78xx0/Kconfig
+++ b/arch/arm/mach-mv78xx0/Kconfig
@@ -8,6 +8,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell DB-78x00-BP Development Board.
 
+config MACH_RD78X00_MASA
+	bool "Marvell RD-78x00-mASA Reference Design"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell RD-78x00-mASA Reference Design.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-mv78xx0/Makefile b/arch/arm/mach-mv78xx0/Makefile
index ec16c05..da628b7 100644
--- a/arch/arm/mach-mv78xx0/Makefile
+++ b/arch/arm/mach-mv78xx0/Makefile
@@ -1,2 +1,3 @@
 obj-y				+= common.o addr-map.o irq.o pcie.o
 obj-$(CONFIG_MACH_DB78X00_BP)	+= db78x00-bp-setup.o
+obj-$(CONFIG_MACH_RD78X00_MASA)	+= rd78x00-masa-setup.o
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index b0e4e0d..a575daa 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -14,7 +14,9 @@
 #include <linux/serial_8250.h>
 #include <linux/mbus.h>
 #include <linux/mv643xx_eth.h>
+#include <linux/mv643xx_i2c.h>
 #include <linux/ata_platform.h>
+#include <linux/ethtool.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <mach/mv78xx0.h>
@@ -430,9 +432,22 @@
 
 void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
 {
+	u32 dev, rev;
+
 	eth_data->shared = &mv78xx0_ge10_shared;
 	mv78xx0_ge10.dev.platform_data = eth_data;
 
+	/*
+	 * On the Z0, ge10 and ge11 are internally connected back
+	 * to back, and not brought out.
+	 */
+	mv78xx0_pcie_id(&dev, &rev);
+	if (dev == MV78X00_Z0_DEV_ID) {
+		eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
+		eth_data->speed = SPEED_1000;
+		eth_data->duplex = DUPLEX_FULL;
+	}
+
 	platform_device_register(&mv78xx0_ge10_shared);
 	platform_device_register(&mv78xx0_ge10);
 }
@@ -484,13 +499,101 @@
 
 void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
 {
+	u32 dev, rev;
+
 	eth_data->shared = &mv78xx0_ge11_shared;
 	mv78xx0_ge11.dev.platform_data = eth_data;
 
+	/*
+	 * On the Z0, ge10 and ge11 are internally connected back
+	 * to back, and not brought out.
+	 */
+	mv78xx0_pcie_id(&dev, &rev);
+	if (dev == MV78X00_Z0_DEV_ID) {
+		eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
+		eth_data->speed = SPEED_1000;
+		eth_data->duplex = DUPLEX_FULL;
+	}
+
 	platform_device_register(&mv78xx0_ge11_shared);
 	platform_device_register(&mv78xx0_ge11);
 }
 
+/*****************************************************************************
+ * I2C bus 0
+ ****************************************************************************/
+
+static struct mv64xxx_i2c_pdata mv78xx0_i2c_0_pdata = {
+	.freq_m		= 8, /* assumes 166 MHz TCLK */
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource mv78xx0_i2c_0_resources[] = {
+	{
+		.name   = "i2c 0 base",
+		.start  = I2C_0_PHYS_BASE,
+		.end    = I2C_0_PHYS_BASE + 0x1f,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "i2c 0 irq",
+		.start  = IRQ_MV78XX0_I2C_0,
+		.end    = IRQ_MV78XX0_I2C_0,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device mv78xx0_i2c_0 = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mv78xx0_i2c_0_resources),
+	.resource	= mv78xx0_i2c_0_resources,
+	.dev		= {
+		.platform_data	= &mv78xx0_i2c_0_pdata,
+	},
+};
+
+/*****************************************************************************
+ * I2C bus 1
+ ****************************************************************************/
+
+static struct mv64xxx_i2c_pdata mv78xx0_i2c_1_pdata = {
+	.freq_m		= 8, /* assumes 166 MHz TCLK */
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource mv78xx0_i2c_1_resources[] = {
+	{
+		.name   = "i2c 1 base",
+		.start  = I2C_1_PHYS_BASE,
+		.end    = I2C_1_PHYS_BASE + 0x1f,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.name   = "i2c 1 irq",
+		.start  = IRQ_MV78XX0_I2C_1,
+		.end    = IRQ_MV78XX0_I2C_1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device mv78xx0_i2c_1 = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(mv78xx0_i2c_1_resources),
+	.resource	= mv78xx0_i2c_1_resources,
+	.dev		= {
+		.platform_data	= &mv78xx0_i2c_1_pdata,
+	},
+};
+
+void __init mv78xx0_i2c_init(void)
+{
+	platform_device_register(&mv78xx0_i2c_0);
+	platform_device_register(&mv78xx0_i2c_1);
+}
 
 /*****************************************************************************
  * SATA
@@ -719,6 +822,32 @@
 /*****************************************************************************
  * General
  ****************************************************************************/
+static char * __init mv78xx0_id(void)
+{
+	u32 dev, rev;
+
+	mv78xx0_pcie_id(&dev, &rev);
+
+	if (dev == MV78X00_Z0_DEV_ID) {
+		if (rev == MV78X00_REV_Z0)
+			return "MV78X00-Z0";
+		else
+			return "MV78X00-Rev-Unsupported";
+	} else if (dev == MV78100_DEV_ID) {
+		if (rev == MV78100_REV_A0)
+			return "MV78100-A0";
+		else
+			return "MV78100-Rev-Unsupported";
+	} else if (dev == MV78200_DEV_ID) {
+		if (rev == MV78100_REV_A0)
+			return "MV78200-A0";
+		else
+			return "MV78200-Rev-Unsupported";
+	} else {
+		return "Device-Unknown";
+	}
+}
+
 static int __init is_l2_writethrough(void)
 {
 	return !!(readl(CPU_CONTROL) & L2_WRITETHROUGH);
@@ -737,7 +866,8 @@
 	get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
 	tclk = get_tclk();
 
-	printk(KERN_INFO "MV78xx0 core #%d, ", core_index);
+	printk(KERN_INFO "%s ", mv78xx0_id());
+	printk("core #%d, ", core_index);
 	printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
 	printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
 	printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
diff --git a/arch/arm/mach-mv78xx0/common.h b/arch/arm/mach-mv78xx0/common.h
index 78af5de..befc224 100644
--- a/arch/arm/mach-mv78xx0/common.h
+++ b/arch/arm/mach-mv78xx0/common.h
@@ -29,6 +29,8 @@
 void mv78xx0_setup_pcie_mem_win(int window, u32 base, u32 size,
 				int maj, int min);
 
+void mv78xx0_pcie_id(u32 *dev, u32 *rev);
+
 void mv78xx0_ehci0_init(void);
 void mv78xx0_ehci1_init(void);
 void mv78xx0_ehci2_init(void);
@@ -42,6 +44,7 @@
 void mv78xx0_uart1_init(void);
 void mv78xx0_uart2_init(void);
 void mv78xx0_uart3_init(void);
+void mv78xx0_i2c_init(void);
 
 extern struct sys_timer mv78xx0_timer;
 
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index 2e285bb..efdabe0 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -14,6 +14,7 @@
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ethtool.h>
+#include <linux/i2c.h>
 #include <mach/mv78xx0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -28,21 +29,22 @@
 };
 
 static struct mv643xx_eth_platform_data db78x00_ge10_data = {
-	.phy_addr	= MV643XX_ETH_PHY_NONE,
-	.speed		= SPEED_1000,
-	.duplex		= DUPLEX_FULL,
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(10),
 };
 
 static struct mv643xx_eth_platform_data db78x00_ge11_data = {
-	.phy_addr	= MV643XX_ETH_PHY_NONE,
-	.speed		= SPEED_1000,
-	.duplex		= DUPLEX_FULL,
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(11),
 };
 
 static struct mv_sata_platform_data db78x00_sata_data = {
 	.n_ports	= 2,
 };
 
+static struct i2c_board_info __initdata db78x00_i2c_rtc = {
+	I2C_BOARD_INFO("ds1338", 0x68),
+};
+
+
 static void __init db78x00_init(void)
 {
 	/*
@@ -64,6 +66,8 @@
 		mv78xx0_sata_init(&db78x00_sata_data);
 		mv78xx0_uart0_init();
 		mv78xx0_uart2_init();
+		mv78xx0_i2c_init();
+		i2c_register_board_info(0, &db78x00_i2c_rtc, 1);
 	} else {
 		mv78xx0_uart1_init();
 		mv78xx0_uart3_init();
diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
index e930ea5..582cffc 100644
--- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
@@ -80,6 +80,18 @@
 #define  TIMER_VIRT_BASE	(BRIDGE_VIRT_BASE | 0x0300)
 
 /*
+ * Supported devices and revisions.
+ */
+#define MV78X00_Z0_DEV_ID	0x6381
+#define MV78X00_REV_Z0		1
+
+#define MV78100_DEV_ID		0x7810
+#define MV78100_REV_A0		1
+
+#define MV78200_DEV_ID		0x7820
+#define MV78200_REV_A0		1
+
+/*
  * Register Map
  */
 #define DDR_VIRT_BASE		(MV78XX0_REGS_VIRT_BASE | 0x00000)
@@ -90,6 +102,8 @@
 #define DEV_BUS_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x10000)
 #define  SAMPLE_AT_RESET_LOW	(DEV_BUS_VIRT_BASE | 0x0030)
 #define  SAMPLE_AT_RESET_HIGH	(DEV_BUS_VIRT_BASE | 0x0034)
+#define  I2C_0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1000)
+#define  I2C_1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1100)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
 #define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2000)
 #define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2100)
diff --git a/arch/arm/mach-mv78xx0/include/mach/system.h b/arch/arm/mach-mv78xx0/include/mach/system.h
index 7d51794..1d6350b 100644
--- a/arch/arm/mach-mv78xx0/include/mach/system.h
+++ b/arch/arm/mach-mv78xx0/include/mach/system.h
@@ -17,7 +17,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * Enable soft reset to assert RSTOUTn.
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index aad3a7a..a560439 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -33,6 +33,12 @@
 static struct resource pcie_mem_space;
 
 
+void __init mv78xx0_pcie_id(u32 *dev, u32 *rev)
+{
+	*dev = orion_pcie_dev_id((void __iomem *)PCIE00_VIRT_BASE);
+	*rev = orion_pcie_rev((void __iomem *)PCIE00_VIRT_BASE);
+}
+
 static void __init mv78xx0_pcie_preinit(void)
 {
 	int i;
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
new file mode 100644
index 0000000..e136b7a
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-mv78x00/rd78x00-masa-setup.c
+ *
+ * Marvell RD-78x00-mASA Development 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/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <mach/mv78xx0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include "common.h"
+
+static struct mv643xx_eth_platform_data rd78x00_masa_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv643xx_eth_platform_data rd78x00_masa_ge01_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(9),
+};
+
+static struct mv643xx_eth_platform_data rd78x00_masa_ge10_data = {
+};
+
+static struct mv643xx_eth_platform_data rd78x00_masa_ge11_data = {
+};
+
+static struct mv_sata_platform_data rd78x00_masa_sata_data = {
+	.n_ports	= 2,
+};
+
+static void __init rd78x00_masa_init(void)
+{
+	/*
+	 * Basic MV78x00 setup. Needs to be called early.
+	 */
+	mv78xx0_init();
+
+	/*
+	 * Partition on-chip peripherals between the two CPU cores.
+	 */
+	if (mv78xx0_core_index() == 0) {
+		mv78xx0_ehci0_init();
+		mv78xx0_ehci1_init();
+		mv78xx0_ge00_init(&rd78x00_masa_ge00_data);
+		mv78xx0_ge10_init(&rd78x00_masa_ge10_data);
+		mv78xx0_sata_init(&rd78x00_masa_sata_data);
+		mv78xx0_uart0_init();
+		mv78xx0_uart2_init();
+	} else {
+		mv78xx0_ehci2_init();
+		mv78xx0_ge01_init(&rd78x00_masa_ge01_data);
+		mv78xx0_ge11_init(&rd78x00_masa_ge11_data);
+		mv78xx0_uart1_init();
+		mv78xx0_uart3_init();
+	}
+}
+
+static int __init rd78x00_pci_init(void)
+{
+	/*
+	 * Assign all PCIe devices to CPU core #0.
+	 */
+	if (machine_is_rd78x00_masa() && mv78xx0_core_index() == 0)
+		mv78xx0_pcie_init(1, 1);
+
+	return 0;
+}
+subsys_initcall(rd78x00_pci_init);
+
+MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@marvell.com> */
+	.phys_io	= MV78XX0_REGS_PHYS_BASE,
+	.io_pg_offst	= ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= rd78x00_masa_init,
+	.map_io		= mv78xx0_map_io,
+	.init_irq	= mv78xx0_init_irq,
+	.timer		= &mv78xx0_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx1/Kconfig b/arch/arm/mach-mx1/Kconfig
index 2b59fc7..eb7660f 100644
--- a/arch/arm/mach-mx1/Kconfig
+++ b/arch/arm/mach-mx1/Kconfig
@@ -1,6 +1,6 @@
 if ARCH_MX1
 
-comment "MX1 Platforms"
+comment "MX1 platforms:"
 
 config MACH_MXLADS
 	bool
@@ -11,4 +11,9 @@
 	help
 	  Say Y here if you are using Motorola MX1ADS/MXLADS boards
 
+config MACH_SCB9328
+	bool "Synertronixx scb9328"
+	help
+	  Say Y here if you are using a Synertronixx scb9328 board
+
 endif
diff --git a/arch/arm/mach-mx1/Makefile b/arch/arm/mach-mx1/Makefile
index b969719..82f1309 100644
--- a/arch/arm/mach-mx1/Makefile
+++ b/arch/arm/mach-mx1/Makefile
@@ -8,3 +8,4 @@
 
 # Specific board support
 obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
+obj-$(CONFIG_MACH_SCB9328) += scb9328.o
\ No newline at end of file
diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c
index 4bcd1ec..0d0f306 100644
--- a/arch/arm/mach-mx1/clock.c
+++ b/arch/arm/mach-mx1/clock.c
@@ -25,6 +25,7 @@
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include "crm_regs.h"
 
 static int _clk_enable(struct clk *clk)
@@ -87,33 +88,6 @@
 	return clk->parent->set_rate(clk->parent, rate);
 }
 
-/*
- *  get the system pll clock in Hz
- *
- *                  mfi + mfn / (mfd +1)
- *  f = 2 * f_ref * --------------------
- *                        pd + 1
- */
-static unsigned long mx1_decode_pll(unsigned int pll, u32 f_ref)
-{
-	unsigned long long ll;
-	unsigned long quot;
-
-	u32 mfi = (pll >> 10) & 0xf;
-	u32 mfn = pll & 0x3ff;
-	u32 mfd = (pll >> 16) & 0x3ff;
-	u32 pd =  (pll >> 26) & 0xf;
-
-	mfi = mfi <= 5 ? 5 : mfi;
-
-	ll = 2 * (unsigned long long)f_ref *
-		((mfi << 16) + (mfn << 16) / (mfd + 1));
-	quot = (pd + 1) * (1 << 16);
-	ll += quot / 2;
-	do_div(ll, quot);
-	return (unsigned long)ll;
-}
-
 static unsigned long clk16m_get_rate(struct clk *clk)
 {
 	return 16000000;
@@ -188,7 +162,7 @@
 
 static unsigned long system_clk_get_rate(struct clk *clk)
 {
-	return mx1_decode_pll(__raw_readl(CCM_SPCTL0),
+	return mxc_decode_pll(__raw_readl(CCM_SPCTL0),
 			      clk_get_rate(clk->parent));
 }
 
@@ -200,7 +174,7 @@
 
 static unsigned long mcu_clk_get_rate(struct clk *clk)
 {
-	return mx1_decode_pll(__raw_readl(CCM_MPCTL0),
+	return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
 			      clk_get_rate(clk->parent));
 }
 
@@ -488,7 +462,7 @@
 };
 
 static struct clk dma_clk = {
-	.name = "dma_clk",
+	.name = "dma",
 	.parent = &hclk,
 	.round_rate = _clk_parent_round_rate,
 	.set_rate = _clk_parent_set_rate,
@@ -539,7 +513,7 @@
 };
 
 static struct clk uart_clk = {
-	.name = "uart_clk",
+	.name = "uart",
 	.parent = &perclk[0],
 	.round_rate = _clk_parent_round_rate,
 	.set_rate = _clk_parent_set_rate,
@@ -621,7 +595,7 @@
 	&rtc_clk,
 };
 
-int __init mxc_clocks_init(unsigned long fref)
+int __init mx1_clocks_init(unsigned long fref)
 {
 	struct clk **clkp;
 	unsigned int reg;
@@ -652,5 +626,7 @@
 	clk_enable(&hclk);
 	clk_enable(&fclk);
 
+	mxc_timer_init(&gpt_clk);
+
 	return 0;
 }
diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c
index a956441..97f42d9 100644
--- a/arch/arm/mach-mx1/devices.c
+++ b/arch/arm/mach-mx1/devices.c
@@ -23,10 +23,11 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-
 #include <mach/irqs.h>
 #include <mach/hardware.h>
 
+#include "devices.h"
+
 static struct resource imx_csi_resources[] = {
 	[0] = {
 		.start  = 0x00224000,
diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c
index 3200cf6..7ae229b 100644
--- a/arch/arm/mach-mx1/mx1ads.c
+++ b/arch/arm/mach-mx1/mx1ads.c
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,7 +27,11 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/imx-uart.h>
-#include <mach/iomux-mx1-mx2.h>
+#include <mach/irqs.h>
+#ifdef CONFIG_I2C_IMX
+#include <mach/i2c.h>
+#endif
+#include <mach/iomux.h>
 #include "devices.h"
 
 /*
@@ -105,6 +111,55 @@
 };
 
 /*
+ * I2C
+ */
+
+#ifdef CONFIG_I2C_IMX
+static int i2c_pins[] = {
+	PA15_PF_I2C_SDA,
+	PA16_PF_I2C_SCL,
+};
+
+static int i2c_init(struct device *dev)
+{
+	return mxc_gpio_setup_multiple_pins(i2c_pins,
+			ARRAY_SIZE(i2c_pins), "I2C");
+}
+
+static void i2c_exit(struct device *dev)
+{
+	mxc_gpio_release_multiple_pins(i2c_pins,
+			ARRAY_SIZE(i2c_pins));
+}
+
+static struct pcf857x_platform_data pcf857x_data[] = {
+	{
+		.gpio_base = 4 * 32,
+	}, {
+		.gpio_base = 4 * 32 + 16,
+	}
+};
+
+static struct imxi2c_platform_data mx1ads_i2c_data = {
+	.bitrate = 100000,
+	.init = i2c_init,
+	.exit = i2c_exit,
+};
+
+static struct i2c_board_info mx1ads_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf857x", 0x22),
+		.type = "pcf8575",
+		.platform_data = &pcf857x_data[0],
+	}, {
+		I2C_BOARD_INFO("pcf857x", 0x24),
+		.type = "pcf8575",
+		.platform_data = &pcf857x_data[1],
+	},
+};
+#endif
+
+/*
  * Board init
  */
 static void __init mx1ads_init(void)
@@ -115,12 +170,19 @@
 
 	/* Physmap flash */
 	mxc_register_device(&flash_device, &mx1ads_flash_data);
+
+	/* I2C */
+#ifdef CONFIG_I2C_IMX
+	i2c_register_board_info(0, mx1ads_i2c_devices,
+				ARRAY_SIZE(mx1ads_i2c_devices));
+
+	mxc_register_device(&imx_i2c_device, &mx1ads_i2c_data);
+#endif
 }
 
 static void __init mx1ads_timer_init(void)
 {
-	mxc_clocks_init(32000);
-	mxc_timer_init("gpt_clk");
+	mx1_clocks_init(32000);
 }
 
 struct sys_timer mx1ads_timer = {
diff --git a/arch/arm/mach-mx1/scb9328.c b/arch/arm/mach-mx1/scb9328.c
new file mode 100644
index 0000000..0e71f3f
--- /dev/null
+++ b/arch/arm/mach-mx1/scb9328.c
@@ -0,0 +1,160 @@
+/*
+ * linux/arch/arm/mach-mx1/scb9328.c
+ *
+ * Copyright (c) 2004 Sascha Hauer <saschahauer@web.de>
+ * Copyright (c) 2006-2008 Juergen Beisert <jbeisert@netscape.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/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/interrupt.h>
+#include <linux/dm9000.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux.h>
+
+#include "devices.h"
+
+/*
+ * This scb9328 has a 32MiB flash
+ */
+static struct resource flash_resource = {
+	.start	= IMX_CS0_PHYS,
+	.end	= IMX_CS0_PHYS + (32 * 1024 * 1024) - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data scb_flash_data = {
+	.width  = 2,
+};
+
+static struct platform_device scb_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev = {
+		.platform_data = &scb_flash_data,
+	},
+	.resource = &flash_resource,
+	.num_resources = 1,
+};
+
+/*
+ * scb9328 has a DM9000 network controller
+ * connected to CS5, with 16 bit data path
+ * and interrupt connected to GPIO 3
+ */
+
+/*
+ * internal datapath is fixed 16 bit
+ */
+static struct dm9000_plat_data dm9000_platdata = {
+	.flags	= DM9000_PLATF_16BITONLY,
+};
+
+/*
+ * the DM9000 drivers wants two defined address spaces
+ * to gain access to address latch registers and the data path.
+ */
+static struct resource dm9000x_resources[] = {
+	[0] = {
+		.name	= "address area",
+		.start	= IMX_CS5_PHYS,
+		.end	= IMX_CS5_PHYS + 1,
+		.flags	= IORESOURCE_MEM	/* address access */
+	},
+	[1] = {
+		.name	= "data area",
+		.start	= IMX_CS5_PHYS + 4,
+		.end	= IMX_CS5_PHYS + 5,
+		.flags	= IORESOURCE_MEM	/* data access */
+	},
+	[2] = {
+		.start	= IRQ_GPIOC(3),
+		.end	= IRQ_GPIOC(3),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL
+	},
+};
+
+static struct platform_device dm9000x_device = {
+	.name		= "dm9000",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm9000x_resources),
+	.resource	= dm9000x_resources,
+	.dev		= {
+		.platform_data = &dm9000_platdata,
+	}
+};
+
+static int mxc_uart1_pins[] = {
+	PC9_PF_UART1_CTS,
+	PC10_PF_UART1_RTS,
+	PC11_PF_UART1_TXD,
+	PC12_PF_UART1_RXD,
+};
+
+static int uart1_mxc_init(struct platform_device *pdev)
+{
+	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
+			ARRAY_SIZE(mxc_uart1_pins), "UART1");
+}
+
+static int uart1_mxc_exit(struct platform_device *pdev)
+{
+	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
+			ARRAY_SIZE(mxc_uart1_pins));
+	return 0;
+}
+
+static struct imxuart_platform_data uart_pdata = {
+	.init = uart1_mxc_init,
+	.exit = uart1_mxc_exit,
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&scb_flash_device,
+	&dm9000x_device,
+};
+
+/*
+ * scb9328_init - Init the CPU card itself
+ */
+static void __init scb9328_init(void)
+{
+	mxc_register_device(&imx_uart1_device, &uart_pdata);
+
+	printk(KERN_INFO"Scb9328: Adding devices\n");
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init scb9328_timer_init(void)
+{
+	mx1_clocks_init(32000);
+}
+
+static struct sys_timer scb9328_timer = {
+	.init	= scb9328_timer_init,
+};
+
+MACHINE_START(SCB9328, "Synertronixx scb9328")
+    /* Sascha Hauer */
+	.phys_io	= 0x00200000,
+	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
+	.boot_params	= 0x08000100,
+	.map_io		= mxc_map_io,
+	.init_irq	= mxc_init_irq,
+	.timer		= &scb9328_timer,
+	.init_machine	= scb9328_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig
index 1eaa97c..42a7888 100644
--- a/arch/arm/mach-mx2/Kconfig
+++ b/arch/arm/mach-mx2/Kconfig
@@ -1,14 +1,22 @@
-comment "MX2 family CPU support"
-	depends on ARCH_MX2
+if ARCH_MX2
+
+choice
+	prompt "CPUs:"
+	default MACH_MX21
+
+config MACH_MX21
+	bool "i.MX21 support"
+	help
+	  This enables support for Freescale's MX2 based i.MX21 processor.
 
 config MACH_MX27
 	bool "i.MX27 support"
-	depends on ARCH_MX2
 	help
 	  This enables support for Freescale's MX2 based i.MX27 processor.
 
-comment "MX2 Platforms"
-	depends on ARCH_MX2
+endchoice
+
+comment "MX2 platforms:"
 
 config MACH_MX27ADS
 	bool "MX27ADS platform"
@@ -37,3 +45,5 @@
 	  PCM970 evaluation board.
 
 endchoice
+
+endif
diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile
index 382d860..950649a 100644
--- a/arch/arm/mach-mx2/Makefile
+++ b/arch/arm/mach-mx2/Makefile
@@ -4,7 +4,9 @@
 
 # Object file lists.
 
-obj-y	:=  system.o generic.o devices.o serial.o
+obj-y	:=  generic.o devices.o serial.o
+
+obj-$(CONFIG_MACH_MX21) += clock_imx21.o
 
 obj-$(CONFIG_MACH_MX27) += cpu_imx27.o
 obj-$(CONFIG_MACH_MX27) += clock_imx27.o
diff --git a/arch/arm/mach-mx2/Makefile.boot b/arch/arm/mach-mx2/Makefile.boot
index 696831d..e867398 100644
--- a/arch/arm/mach-mx2/Makefile.boot
+++ b/arch/arm/mach-mx2/Makefile.boot
@@ -1,3 +1,7 @@
-   zreladdr-y	:= 0xA0008000
-params_phys-y	:= 0xA0000100
-initrd_phys-y	:= 0xA0800000
+zreladdr-$(CONFIG_MACH_MX21)	:= 0xC0008000
+params_phys-$(CONFIG_MACH_MX21)	:= 0xC0000100
+initrd_phys-$(CONFIG_MACH_MX21)	:= 0xC0800000
+
+zreladdr-$(CONFIG_MACH_MX27)	:= 0xA0008000
+params_phys-$(CONFIG_MACH_MX27)	:= 0xA0000100
+initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c
new file mode 100644
index 0000000..2dee5c8
--- /dev/null
+++ b/arch/arm/mach-mx2/clock_imx21.c
@@ -0,0 +1,984 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.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 <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
+#include "crm_regs.h"
+
+static int _clk_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 1 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(1 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_spll_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_CSCR);
+	reg |= CCM_CSCR_SPEN;
+	__raw_writel(reg, CCM_CSCR);
+
+	while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
+		;
+	return 0;
+}
+
+static void _clk_spll_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_CSCR);
+	reg &= ~CCM_CSCR_SPEN;
+	__raw_writel(reg, CCM_CSCR);
+}
+
+
+#define CSCR() (__raw_readl(CCM_CSCR))
+#define PCDR0() (__raw_readl(CCM_PCDR0))
+#define PCDR1() (__raw_readl(CCM_PCDR1))
+
+static unsigned long _clk_perclkx_round_rate(struct clk *clk,
+					     unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (parent_rate % rate)
+		div++;
+
+	if (div > 64)
+		div = 64;
+
+	return parent_rate / div;
+}
+
+static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->id < 0 || clk->id > 3)
+		return -EINVAL;
+
+	div = parent_rate / rate;
+	if (div > 64 || div < 1 || ((parent_rate / div) != rate))
+		return -EINVAL;
+	div--;
+
+	reg =
+	    __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
+				       (clk->id << 3));
+	reg |= div << (clk->id << 3);
+	__raw_writel(reg, CCM_PCDR1);
+
+	return 0;
+}
+
+static unsigned long _clk_usb_recalc(struct clk *clk)
+{
+	unsigned long usb_pdf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
+
+	return parent_rate / (usb_pdf + 1U);
+}
+
+static unsigned long _clk_ssix_recalc(struct clk *clk, unsigned long pdf)
+{
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
+
+	return 2UL * parent_rate / pdf;
+}
+
+static unsigned long _clk_ssi1_recalc(struct clk *clk)
+{
+	return _clk_ssix_recalc(clk,
+		(PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK)
+		>> CCM_PCDR0_SSI1BAUDDIV_OFFSET);
+}
+
+static unsigned long _clk_ssi2_recalc(struct clk *clk)
+{
+	return _clk_ssix_recalc(clk,
+		(PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
+		CCM_PCDR0_SSI2BAUDDIV_OFFSET);
+}
+
+static unsigned long _clk_nfc_recalc(struct clk *clk)
+{
+	unsigned long nfc_pdf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	nfc_pdf = (PCDR0() & CCM_PCDR0_NFCDIV_MASK)
+		>> CCM_PCDR0_NFCDIV_OFFSET;
+
+	return parent_rate / (nfc_pdf + 1);
+}
+
+static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->parent->round_rate(clk->parent, rate);
+}
+
+static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
+{
+	return clk->parent->set_rate(clk->parent, rate);
+}
+
+static unsigned long external_high_reference; /* in Hz */
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+	return external_high_reference;
+}
+
+/*
+ * the high frequency external clock reference
+ * Default case is 26MHz.
+ */
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static unsigned long external_low_reference; /* in Hz */
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+/*
+ * the low frequency external clock reference
+ * Default case is 32.768kHz.
+ */
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+
+static unsigned long _clk_fpm_recalc(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) * 512;
+}
+
+/* Output of frequency pre multiplier */
+static struct clk fpm_clk = {
+	.parent = &ckil_clk,
+	.get_rate = _clk_fpm_recalc,
+};
+
+static unsigned long get_mpll_clk(struct clk *clk)
+{
+	uint32_t reg;
+	unsigned long ref_clk;
+	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
+	unsigned long long temp;
+
+	ref_clk = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(CCM_MPCTL0);
+	pdf = (reg & CCM_MPCTL0_PD_MASK)  >> CCM_MPCTL0_PD_OFFSET;
+	mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
+	mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
+	mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
+
+	mfi = (mfi <= 5) ? 5 : mfi;
+	temp = 2LL * ref_clk * mfn;
+	do_div(temp, mfd + 1);
+	temp = 2LL * ref_clk * mfi + temp;
+	do_div(temp, pdf + 1);
+
+	return (unsigned long)temp;
+}
+
+static struct clk mpll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = get_mpll_clk,
+};
+
+static unsigned long _clk_fclk_get_rate(struct clk *clk)
+{
+	unsigned long parent_rate;
+	u32 div;
+
+	div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
+	parent_rate = clk_get_rate(clk->parent);
+
+	return parent_rate / (div+1);
+}
+
+static struct clk fclk_clk = {
+	.parent = &mpll_clk,
+	.get_rate = _clk_fclk_get_rate
+};
+
+static unsigned long get_spll_clk(struct clk *clk)
+{
+	uint32_t reg;
+	unsigned long ref_clk;
+	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
+	unsigned long long temp;
+
+	ref_clk = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(CCM_SPCTL0);
+	pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
+	mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
+	mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
+	mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
+
+	mfi = (mfi <= 5) ? 5 : mfi;
+	temp = 2LL * ref_clk * mfn;
+	do_div(temp, mfd + 1);
+	temp = 2LL * ref_clk * mfi + temp;
+	do_div(temp, pdf + 1);
+
+	return (unsigned long)temp;
+}
+
+static struct clk spll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = get_spll_clk,
+	.enable = _clk_spll_enable,
+	.disable = _clk_spll_disable,
+};
+
+static unsigned long get_hclk_clk(struct clk *clk)
+{
+	unsigned long rate;
+	unsigned long bclk_pdf;
+
+	bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
+		>> CCM_CSCR_BCLK_OFFSET;
+
+	rate = clk_get_rate(clk->parent);
+	return rate / (bclk_pdf + 1);
+}
+
+static struct clk hclk_clk = {
+	.parent = &fclk_clk,
+	.get_rate = get_hclk_clk,
+};
+
+static unsigned long get_ipg_clk(struct clk *clk)
+{
+	unsigned long rate;
+	unsigned long ipg_pdf;
+
+	ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
+
+	rate = clk_get_rate(clk->parent);
+	return rate / (ipg_pdf + 1);
+}
+
+static struct clk ipg_clk = {
+	.parent = &hclk_clk,
+	.get_rate = get_ipg_clk,
+};
+
+static unsigned long _clk_perclkx_recalc(struct clk *clk)
+{
+	unsigned long perclk_pdf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->id < 0 || clk->id > 3)
+		return 0;
+
+	perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
+
+	return parent_rate / (perclk_pdf + 1);
+}
+
+static struct clk per_clk[] = {
+	{
+		.id = 0,
+		.parent = &mpll_clk,
+		.get_rate = _clk_perclkx_recalc,
+	}, {
+		.id = 1,
+		.parent = &mpll_clk,
+		.get_rate = _clk_perclkx_recalc,
+	}, {
+		.id = 2,
+		.parent = &mpll_clk,
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.get_rate = _clk_perclkx_recalc,
+		/* Enable/Disable done via lcd_clkc[1] */
+	}, {
+		.id = 3,
+		.parent = &mpll_clk,
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.get_rate = _clk_perclkx_recalc,
+		/* Enable/Disable done via csi_clk[1] */
+	},
+};
+
+static struct clk uart_ipg_clk[];
+
+static struct clk uart_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[0],
+		.secondary = &uart_ipg_clk[0],
+	}, {
+		.id = 1,
+		.parent = &per_clk[0],
+		.secondary = &uart_ipg_clk[1],
+	}, {
+		.id = 2,
+		.parent = &per_clk[0],
+		.secondary = &uart_ipg_clk[2],
+	}, {
+		.id = 3,
+		.parent = &per_clk[0],
+		.secondary = &uart_ipg_clk[3],
+	},
+};
+
+static struct clk uart_ipg_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_UART1_REG,
+		.enable_shift = CCM_PCCR_UART1_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_UART2_REG,
+		.enable_shift = CCM_PCCR_UART2_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_UART3_REG,
+		.enable_shift = CCM_PCCR_UART3_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 3,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_UART4_REG,
+		.enable_shift = CCM_PCCR_UART4_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpt_ipg_clk[];
+
+static struct clk gpt_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[0],
+		.secondary = &gpt_ipg_clk[0],
+	}, {
+		.id = 1,
+		.parent = &per_clk[0],
+		.secondary = &gpt_ipg_clk[1],
+	}, {
+		.id = 2,
+		.parent = &per_clk[0],
+		.secondary = &gpt_ipg_clk[2],
+	},
+};
+
+static struct clk gpt_ipg_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_GPT1_REG,
+		.enable_shift = CCM_PCCR_GPT1_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_GPT2_REG,
+		.enable_shift = CCM_PCCR_GPT2_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_GPT3_REG,
+		.enable_shift = CCM_PCCR_GPT3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk pwm_clk[] = {
+	{
+		.parent = &per_clk[0],
+		.secondary = &pwm_clk[1],
+	}, {
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_PWM_REG,
+		.enable_shift = CCM_PCCR_PWM_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk sdhc_ipg_clk[];
+
+static struct clk sdhc_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[1],
+		.secondary = &sdhc_ipg_clk[0],
+	}, {
+		.id = 1,
+		.parent = &per_clk[1],
+		.secondary = &sdhc_ipg_clk[1],
+	},
+};
+
+static struct clk sdhc_ipg_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SDHC1_REG,
+		.enable_shift = CCM_PCCR_SDHC1_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SDHC2_REG,
+		.enable_shift = CCM_PCCR_SDHC2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk cspi_ipg_clk[];
+
+static struct clk cspi_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[1],
+		.secondary = &cspi_ipg_clk[0],
+	}, {
+		.id = 1,
+		.parent = &per_clk[1],
+		.secondary = &cspi_ipg_clk[1],
+	}, {
+		.id = 2,
+		.parent = &per_clk[1],
+		.secondary = &cspi_ipg_clk[2],
+	},
+};
+
+static struct clk cspi_ipg_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_CSPI1_REG,
+		.enable_shift = CCM_PCCR_CSPI1_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_CSPI2_REG,
+		.enable_shift = CCM_PCCR_CSPI2_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 3,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_CSPI3_REG,
+		.enable_shift = CCM_PCCR_CSPI3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk lcdc_clk[] = {
+	{
+		.parent = &per_clk[2],
+		.secondary = &lcdc_clk[1],
+		.round_rate = _clk_parent_round_rate,
+		.set_rate = _clk_parent_set_rate,
+	}, {
+		.parent = &ipg_clk,
+		.secondary = &lcdc_clk[2],
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_LCDC_REG,
+		.enable_shift = CCM_PCCR_LCDC_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_LCDC_REG,
+		.enable_shift = CCM_PCCR_HCLK_LCDC_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk csi_clk[] = {
+	{
+		.parent = &per_clk[3],
+		.secondary = &csi_clk[1],
+		.round_rate = _clk_parent_round_rate,
+		.set_rate = _clk_parent_set_rate,
+	}, {
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_CSI_REG,
+		.enable_shift = CCM_PCCR_HCLK_CSI_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk usb_clk[] = {
+	{
+		.parent = &spll_clk,
+		.get_rate = _clk_usb_recalc,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_USBOTG_REG,
+		.enable_shift = CCM_PCCR_USBOTG_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_USBOTG_REG,
+		.enable_shift = CCM_PCCR_HCLK_USBOTG_OFFSET,
+		.disable = _clk_disable,
+	}
+};
+
+static struct clk ssi_ipg_clk[];
+
+static struct clk ssi_clk[] = {
+	{
+		.id = 0,
+		.parent = &mpll_clk,
+		.secondary = &ssi_ipg_clk[0],
+		.get_rate = _clk_ssi1_recalc,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SSI1_BAUD_REG,
+		.enable_shift = CCM_PCCR_SSI1_BAUD_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &mpll_clk,
+		.secondary = &ssi_ipg_clk[1],
+		.get_rate = _clk_ssi2_recalc,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SSI2_BAUD_REG,
+		.enable_shift = CCM_PCCR_SSI2_BAUD_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk ssi_ipg_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SSI1_REG,
+		.enable_shift = CCM_PCCR_SSI1_IPG_OFFSET,
+		.disable = _clk_disable,
+	}, {
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SSI2_REG,
+		.enable_shift = CCM_PCCR_SSI2_IPG_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+
+static struct clk nfc_clk = {
+	.parent = &fclk_clk,
+	.get_rate = _clk_nfc_recalc,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_NFC_REG,
+	.enable_shift = CCM_PCCR_NFC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk dma_clk[] = {
+	{
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_DMA_REG,
+		.enable_shift = CCM_PCCR_DMA_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &dma_clk[1],
+	},  {
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_DMA_REG,
+		.enable_shift = CCM_PCCR_HCLK_DMA_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk brom_clk = {
+	.parent = &hclk_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_HCLK_BROM_REG,
+	.enable_shift = CCM_PCCR_HCLK_BROM_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk emma_clk[] = {
+	{
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_EMMA_REG,
+		.enable_shift = CCM_PCCR_EMMA_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &emma_clk[1],
+	}, {
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_EMMA_REG,
+		.enable_shift = CCM_PCCR_HCLK_EMMA_OFFSET,
+		.disable = _clk_disable,
+	}
+};
+
+static struct clk slcdc_clk[] = {
+	{
+		.parent = &hclk_clk,
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_SLCDC_REG,
+		.enable_shift = CCM_PCCR_SLCDC_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &slcdc_clk[1],
+	}, {
+		.enable = _clk_enable,
+		.enable_reg = CCM_PCCR_HCLK_SLCDC_REG,
+		.enable_shift = CCM_PCCR_HCLK_SLCDC_OFFSET,
+		.disable = _clk_disable,
+	}
+};
+
+static struct clk wdog_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_WDT_REG,
+	.enable_shift = CCM_PCCR_WDT_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk gpio_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_GPIO_REG,
+	.enable_shift = CCM_PCCR_GPIO_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk i2c_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_I2C1_REG,
+	.enable_shift = CCM_PCCR_I2C1_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk kpp_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_KPP_REG,
+	.enable_shift = CCM_PCCR_KPP_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk owire_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_OWIRE_REG,
+	.enable_shift = CCM_PCCR_OWIRE_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk rtc_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = CCM_PCCR_RTC_REG,
+	.enable_shift = CCM_PCCR_RTC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+	div = parent_rate / rate;
+	if (parent_rate % rate)
+		div++;
+
+	if (div > 8)
+		div = 8;
+
+	return parent_rate / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+
+	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+		return -EINVAL;
+	div--;
+
+	reg = __raw_readl(CCM_PCDR0);
+
+	if (clk->parent == &usb_clk[0]) {
+		reg &= ~CCM_PCDR0_48MDIV_MASK;
+		reg |= div << CCM_PCDR0_48MDIV_OFFSET;
+	}
+	__raw_writel(reg, CCM_PCDR0);
+
+	return 0;
+}
+
+static unsigned long _clk_clko_recalc(struct clk *clk)
+{
+	u32 div = 0;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->parent == &usb_clk[0]) /* 48M */
+		div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_48MDIV_MASK
+			 >> CCM_PCDR0_48MDIV_OFFSET;
+	div++;
+
+	return parent_rate / div;
+}
+
+static struct clk clko_clk;
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
+
+	if (parent == &ckil_clk)
+		reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &fpm_clk)
+		reg |= 1 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &ckih_clk)
+		reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == mpll_clk.parent)
+		reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == spll_clk.parent)
+		reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &mpll_clk)
+		reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &spll_clk)
+		reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &fclk_clk)
+		reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &hclk_clk)
+		reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &ipg_clk)
+		reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &per_clk[0])
+		reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &per_clk[1])
+		reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &per_clk[2])
+		reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &per_clk[3])
+		reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &ssi_clk[0])
+		reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &ssi_clk[1])
+		reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &nfc_clk)
+		reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &usb_clk[0])
+		reg |= 0x14 << CCM_CCSR_CLKOSEL_OFFSET;
+	else if (parent == &clko_clk)
+		reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, CCM_CCSR);
+
+	return 0;
+}
+
+static struct clk clko_clk = {
+	.get_rate = _clk_clko_recalc,
+	.set_rate = _clk_clko_set_rate,
+	.round_rate = _clk_clko_round_rate,
+	.set_parent = _clk_clko_set_parent,
+};
+
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+static struct clk_lookup lookups[] __initdata = {
+/* It's unlikely that any driver wants one of them directly:
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+	_REGISTER_CLOCK(NULL, "ckil", ckil_clk)
+	_REGISTER_CLOCK(NULL, "fpm", fpm_clk)
+	_REGISTER_CLOCK(NULL, "mpll", mpll_clk)
+	_REGISTER_CLOCK(NULL, "spll", spll_clk)
+	_REGISTER_CLOCK(NULL, "fclk", fclk_clk)
+	_REGISTER_CLOCK(NULL, "hclk", hclk_clk)
+	_REGISTER_CLOCK(NULL, "ipg", ipg_clk)
+*/
+	_REGISTER_CLOCK(NULL, "perclk1", per_clk[0])
+	_REGISTER_CLOCK(NULL, "perclk2", per_clk[1])
+	_REGISTER_CLOCK(NULL, "perclk3", per_clk[2])
+	_REGISTER_CLOCK(NULL, "perclk4", per_clk[3])
+	_REGISTER_CLOCK(NULL, "clko", clko_clk)
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart_clk[3])
+	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[0])
+	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[1])
+	_REGISTER_CLOCK(NULL, "gpt1", gpt_clk[2])
+	_REGISTER_CLOCK(NULL, "pwm", pwm_clk[0])
+	_REGISTER_CLOCK(NULL, "sdhc1", sdhc_clk[0])
+	_REGISTER_CLOCK(NULL, "sdhc2", sdhc_clk[1])
+	_REGISTER_CLOCK(NULL, "cspi1", cspi_clk[0])
+	_REGISTER_CLOCK(NULL, "cspi2", cspi_clk[1])
+	_REGISTER_CLOCK(NULL, "cspi3", cspi_clk[2])
+	_REGISTER_CLOCK(NULL, "lcdc", lcdc_clk[0])
+	_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
+	_REGISTER_CLOCK(NULL, "usb", usb_clk[0])
+	_REGISTER_CLOCK(NULL, "ssi1", ssi_clk[0])
+	_REGISTER_CLOCK(NULL, "ssi2", ssi_clk[1])
+	_REGISTER_CLOCK(NULL, "nfc", nfc_clk)
+	_REGISTER_CLOCK(NULL, "dma", dma_clk[0])
+	_REGISTER_CLOCK(NULL, "brom", brom_clk)
+	_REGISTER_CLOCK(NULL, "emma", emma_clk[0])
+	_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
+	_REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
+	_REGISTER_CLOCK(NULL, "i2c", i2c_clk)
+	_REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK(NULL, "owire", owire_clk)
+	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+};
+
+/*
+ * must be called very early to get information about the
+ * available clock rate when the timer framework starts
+ */
+int __init mx21_clocks_init(unsigned long lref, unsigned long href)
+{
+	int i;
+	u32 cscr;
+
+	external_low_reference = lref;
+	external_high_reference = href;
+
+	/* detect clock reference for both system PLL */
+	cscr = CSCR();
+	if (cscr & CCM_CSCR_MCU)
+		mpll_clk.parent = &ckih_clk;
+	else
+		mpll_clk.parent = &fpm_clk;
+
+	if (cscr & CCM_CSCR_SP)
+		spll_clk.parent = &ckih_clk;
+	else
+		spll_clk.parent = &fpm_clk;
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/* Turn off all clock gates */
+	__raw_writel(0, CCM_PCCR0);
+	__raw_writel(CCM_PCCR_GPT1_MASK, CCM_PCCR1);
+
+	/* This turns of the serial PLL as well */
+	spll_clk.disable(&spll_clk);
+
+	/* This will propagate to all children and init all the clock rates. */
+	clk_enable(&per_clk[0]);
+	clk_enable(&gpio_clk);
+
+#ifdef CONFIG_DEBUG_LL_CONSOLE
+	clk_enable(&uart_clk[0]);
+#endif
+
+	mxc_timer_init(&gpt_clk[0]);
+	return 0;
+}
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
index c69896d..3f7280c 100644
--- a/arch/arm/mach-mx2/clock_imx27.c
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -1,6 +1,7 @@
 /*
  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,23 +21,60 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
 
 #include <mach/clock.h>
 #include <mach/common.h>
-#include <asm/div64.h>
+#include <mach/hardware.h>
 
-#include "crm_regs.h"
+/* Register offsets */
+#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
+#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
+#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
+#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
+#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
+#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
+#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
+#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
+#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
+#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
+#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
+#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
+#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
+#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
 
-static struct clk ckil_clk;
-static struct clk mpll_clk;
-static struct clk mpll_main_clk[];
-static struct clk spll_clk;
+#define CCM_CSCR_UPDATE_DIS	(1 << 31)
+#define CCM_CSCR_SSI2		(1 << 23)
+#define CCM_CSCR_SSI1		(1 << 22)
+#define CCM_CSCR_VPU		(1 << 21)
+#define CCM_CSCR_MSHC           (1 << 20)
+#define CCM_CSCR_SPLLRES        (1 << 19)
+#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SP             (1 << 17)
+#define CCM_CSCR_MCU            (1 << 16)
+#define CCM_CSCR_OSC26MDIV      (1 << 4)
+#define CCM_CSCR_OSC26M         (1 << 3)
+#define CCM_CSCR_FPM            (1 << 2)
+#define CCM_CSCR_SPEN           (1 << 1)
+#define CCM_CSCR_MPEN           (1 << 0)
 
-static int _clk_enable(struct clk *clk)
+/* i.MX27 TO 2+ */
+#define CCM_CSCR_ARM_SRC        (1 << 15)
+
+#define CCM_SPCTL1_LF           (1 << 15)
+#define CCM_SPCTL1_BRMO         (1 << 6)
+
+static struct clk mpll_main1_clk, mpll_main2_clk;
+
+static int clk_pccr_enable(struct clk *clk)
 {
 	unsigned long reg;
 
+	if (!clk->enable_reg)
+		return 0;
+
 	reg = __raw_readl(clk->enable_reg);
 	reg |= 1 << clk->enable_shift;
 	__raw_writel(reg, clk->enable_reg);
@@ -44,16 +82,19 @@
 	return 0;
 }
 
-static void _clk_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk *clk)
 {
 	unsigned long reg;
 
+	if (!clk->enable_reg)
+		return;
+
 	reg = __raw_readl(clk->enable_reg);
 	reg &= ~(1 << clk->enable_shift);
 	__raw_writel(reg, clk->enable_reg);
 }
 
-static int _clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk *clk)
 {
 	unsigned long reg;
 
@@ -61,13 +102,12 @@
 	reg |= CCM_CSCR_SPEN;
 	__raw_writel(reg, CCM_CSCR);
 
-	while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
-		;
+	while (!(__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF));
 
 	return 0;
 }
 
-static void _clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk *clk)
 {
 	unsigned long reg;
 
@@ -76,192 +116,30 @@
 	__raw_writel(reg, CCM_CSCR);
 }
 
-static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
+static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 {
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR0);
-	reg |= mask0;
-	__raw_writel(reg, CCM_PCCR0);
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg |= mask1;
-	__raw_writel(reg, CCM_PCCR1);
-
-}
-
-static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR0);
-	reg &= ~mask0;
-	__raw_writel(reg, CCM_PCCR0);
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg &= ~mask1;
-	__raw_writel(reg, CCM_PCCR1);
-}
-
-static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg |= mask1;
-	__raw_writel(reg, CCM_PCCR1);
-
-	reg = __raw_readl(CCM_PCCR0);
-	reg |= mask0;
-	__raw_writel(reg, CCM_PCCR0);
-}
-
-static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg &= ~mask1;
-	__raw_writel(reg, CCM_PCCR1);
-
-	reg = __raw_readl(CCM_PCCR0);
-	reg &= ~mask0;
-	__raw_writel(reg, CCM_PCCR0);
-}
-
-static int _clk_dma_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
-
-	return 0;
-}
-
-static void _clk_dma_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
-}
-
-static int _clk_rtic_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
-
-	return 0;
-}
-
-static void _clk_rtic_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
-}
-
-static int _clk_emma_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
-
-	return 0;
-}
-
-static void _clk_emma_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
-}
-
-static int _clk_slcdc_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
-
-	return 0;
-}
-
-static void _clk_slcdc_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
-}
-
-static int _clk_fec_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
-
-	return 0;
-}
-
-static void _clk_fec_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
-}
-
-static int _clk_vpu_enable(struct clk *clk)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
-	__raw_writel(reg, CCM_PCCR1);
-
-	return 0;
-}
-
-static void _clk_vpu_disable(struct clk *clk)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(CCM_PCCR1);
-	reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
-	__raw_writel(reg, CCM_PCCR1);
-}
-
-static int _clk_sahara2_enable(struct clk *clk)
-{
-	_clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
-
-	return 0;
-}
-
-static void _clk_sahara2_disable(struct clk *clk)
-{
-	_clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
-}
-
-static int _clk_mstick1_enable(struct clk *clk)
-{
-	_clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
-
-	return 0;
-}
-
-static void _clk_mstick1_disable(struct clk *clk)
-{
-	_clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
-}
-
-#define CSCR() (__raw_readl(CCM_CSCR))
-#define PCDR0() (__raw_readl(CCM_PCDR0))
-#define PCDR1() (__raw_readl(CCM_PCDR1))
-
-static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
-{
-	int cscr = CSCR();
+	int cscr = __raw_readl(CCM_CSCR);
 
 	if (clk->parent == parent)
 		return 0;
 
 	if (mx27_revision() >= CHIP_REV_2_0) {
-		if (parent == &mpll_main_clk[0]) {
+		if (parent == &mpll_main1_clk) {
 			cscr |= CCM_CSCR_ARM_SRC;
 		} else {
-			if (parent == &mpll_main_clk[1])
+			if (parent == &mpll_main2_clk)
 				cscr &= ~CCM_CSCR_ARM_SRC;
 			else
 				return -EINVAL;
 		}
 		__raw_writel(cscr, CCM_CSCR);
-	} else
-		return -ENODEV;
-
-	clk->parent = parent;
-	return 0;
+		clk->parent = parent;
+		return 0;
+	}
+	return -ENODEV;
 }
 
-static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
 {
 	int div;
 	unsigned long parent_rate;
@@ -278,7 +156,7 @@
 	return parent_rate / div;
 }
 
-static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk *clk, unsigned long rate)
 {
 	unsigned int div;
 	uint32_t reg;
@@ -295,19 +173,18 @@
 
 	reg = __raw_readl(CCM_CSCR);
 	if (mx27_revision() >= CHIP_REV_2_0) {
-		reg &= ~CCM_CSCR_ARM_MASK;
-		reg |= div << CCM_CSCR_ARM_OFFSET;
-		reg &= ~0x06;
-		__raw_writel(reg | 0x80000000, CCM_CSCR);
+		reg &= ~(3 << 12);
+		reg |= div << 12;
+		reg &= ~(CCM_CSCR_FPM | CCM_CSCR_SPEN);
+		__raw_writel(reg | CCM_CSCR_UPDATE_DIS, CCM_CSCR);
 	} else {
-		printk(KERN_ERR "Cant set CPU frequency!\n");
+		printk(KERN_ERR "Can't set CPU frequency!\n");
 	}
 
 	return 0;
 }
 
-static unsigned long _clk_perclkx_round_rate(struct clk *clk,
-					     unsigned long rate)
+static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
 {
 	u32 div;
 	unsigned long parent_rate;
@@ -324,7 +201,7 @@
 	return parent_rate / div;
 }
 
-static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk *clk, unsigned long rate)
 {
 	u32 reg;
 	u32 div;
@@ -340,84 +217,65 @@
 		return -EINVAL;
 	div--;
 
-	reg =
-	    __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
-				       (clk->id << 3));
+	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
 	reg |= div << (clk->id << 3);
 	__raw_writel(reg, CCM_PCDR1);
 
 	return 0;
 }
 
-static unsigned long _clk_usb_recalc(struct clk *clk)
+static unsigned long get_rate_usb(struct clk *clk)
 {
 	unsigned long usb_pdf;
 	unsigned long parent_rate;
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
+	usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
 
 	return parent_rate / (usb_pdf + 1U);
 }
 
-static unsigned long _clk_ssi1_recalc(struct clk *clk)
+static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
 {
-	unsigned long ssi1_pdf;
 	unsigned long parent_rate;
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
-					CCM_PCDR0_SSI1BAUDDIV_OFFSET;
-
 	if (mx27_revision() >= CHIP_REV_2_0)
-		ssi1_pdf += 4;
+		pdf += 4;  /* MX27 TO2+ */
 	else
-		ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
+		pdf = (pdf < 2) ? 124UL : pdf;  /* MX21 & MX27 TO1 */
 
-	return 2UL * parent_rate / ssi1_pdf;
+	return 2UL * parent_rate / pdf;
 }
 
-static unsigned long _clk_ssi2_recalc(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk *clk)
 {
-	unsigned long ssi2_pdf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
-	    CCM_PCDR0_SSI2BAUDDIV_OFFSET;
-
-	if (mx27_revision() >= CHIP_REV_2_0)
-		ssi2_pdf += 4;
-	else
-		ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
-
-	return 2UL * parent_rate / ssi2_pdf;
+	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
 }
 
-static unsigned long _clk_nfc_recalc(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk *clk)
+{
+	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+}
+
+static unsigned long get_rate_nfc(struct clk *clk)
 {
 	unsigned long nfc_pdf;
 	unsigned long parent_rate;
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (mx27_revision() >= CHIP_REV_2_0) {
-		nfc_pdf =
-		    (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
-		    CCM_PCDR0_NFCDIV2_OFFSET;
-	} else {
-		nfc_pdf =
-		    (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
-		    CCM_PCDR0_NFCDIV_OFFSET;
-	}
+	if (mx27_revision() >= CHIP_REV_2_0)
+		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
+	else
+		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 12) & 0xf;
 
 	return parent_rate / (nfc_pdf + 1);
 }
 
-static unsigned long _clk_vpu_recalc(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk *clk)
 {
 	unsigned long vpu_pdf;
 	unsigned long parent_rate;
@@ -425,25 +283,27 @@
 	parent_rate = clk_get_rate(clk->parent);
 
 	if (mx27_revision() >= CHIP_REV_2_0) {
-		vpu_pdf =
-		    (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
-		    CCM_PCDR0_VPUDIV2_OFFSET;
+		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
 		vpu_pdf += 4;
 	} else {
-		vpu_pdf =
-		    (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
-		    CCM_PCDR0_VPUDIV_OFFSET;
+		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 8) & 0xf;
 		vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
 	}
+
 	return 2UL * parent_rate / vpu_pdf;
 }
 
-static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
 {
 	return clk->parent->round_rate(clk->parent, rate);
 }
 
-static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
+static unsigned long get_rate_parent(struct clk *clk)
+{
+	return clk_get_rate(clk->parent);
+}
+
+static int set_rate_parent(struct clk *clk, unsigned long rate)
 {
 	return clk->parent->set_rate(clk->parent, rate);
 }
@@ -451,1112 +311,380 @@
 /* in Hz */
 static unsigned long external_high_reference = 26000000;
 
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk *clk)
 {
 	return external_high_reference;
 }
 
+/* in Hz */
+static unsigned long external_low_reference = 32768;
+
+static unsigned long get_rate_low_reference(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+static unsigned long get_rate_fpm(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) * 1024;
+}
+
+static unsigned long get_rate_mpll(struct clk *clk)
+{
+	return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
+			clk_get_rate(clk->parent));
+}
+
+static unsigned long get_rate_mpll_main(struct clk *clk)
+{
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	/* i.MX27 TO2:
+	 * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
+	 * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
+	 */
+	if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
+		return 2UL * parent_rate / 3UL;
+
+	return parent_rate;
+}
+
+static unsigned long get_rate_spll(struct clk *clk)
+{
+	uint32_t reg;
+	unsigned long rate;
+
+	rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(CCM_SPCTL0);
+
+	/* On TO2 we have to write the value back. Otherwise we
+	 * read 0 from this register the next time.
+	 */
+	if (mx27_revision() >= CHIP_REV_2_0)
+		__raw_writel(reg, CCM_SPCTL0);
+
+	return mxc_decode_pll(reg, rate);
+}
+
+static unsigned long get_rate_cpu(struct clk *clk)
+{
+	u32 div;
+	unsigned long rate;
+
+	if (mx27_revision() >= CHIP_REV_2_0)
+		div = (__raw_readl(CCM_CSCR) >> 12) & 0x3;
+	else
+		div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
+
+	rate = clk_get_rate(clk->parent);
+	return rate / (div + 1);
+}
+
+static unsigned long get_rate_ahb(struct clk *clk)
+{
+	unsigned long rate, bclk_pdf;
+
+	if (mx27_revision() >= CHIP_REV_2_0)
+		bclk_pdf = (__raw_readl(CCM_CSCR) >> 8) & 0x3;
+	else
+		bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
+
+	rate = clk_get_rate(clk->parent);
+	return rate / (bclk_pdf + 1);
+}
+
+static unsigned long get_rate_ipg(struct clk *clk)
+{
+	unsigned long rate, ipg_pdf;
+
+	if (mx27_revision() >= CHIP_REV_2_0)
+		return clk_get_rate(clk->parent);
+	else
+		ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
+
+	rate = clk_get_rate(clk->parent);
+	return rate / (ipg_pdf + 1);
+}
+
+static unsigned long get_rate_per(struct clk *clk)
+{
+	unsigned long perclk_pdf, parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->id < 0 || clk->id > 3)
+		return 0;
+
+	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
+
+	return parent_rate / (perclk_pdf + 1);
+}
+
 /*
  * the high frequency external clock reference
  * Default case is 26MHz. Could be changed at runtime
  * with a call to change_external_high_reference()
  */
 static struct clk ckih_clk = {
-	.name = "ckih",
-	.get_rate = get_high_reference_clock_rate,
+	.get_rate	= get_rate_high_reference,
 };
 
-/* in Hz */
-static unsigned long external_low_reference = 32768;
+static struct clk mpll_clk = {
+	.parent		= &ckih_clk,
+	.get_rate	= get_rate_mpll,
+};
 
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
-	return external_low_reference;
-}
+/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
+ * It provides the clock source whose rate is same as MPLL
+ */
+static struct clk mpll_main1_clk = {
+	.id		= 0,
+	.parent		= &mpll_clk,
+	.get_rate	= get_rate_mpll_main,
+};
+
+/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
+ * It provides the clock source whose rate is same MPLL * 2 / 3
+ */
+static struct clk mpll_main2_clk = {
+	.id		= 1,
+	.parent		= &mpll_clk,
+	.get_rate	= get_rate_mpll_main,
+};
+
+static struct clk ahb_clk = {
+	.parent		= &mpll_main2_clk,
+	.get_rate	= get_rate_ahb,
+};
+
+static struct clk ipg_clk = {
+	.parent		= &ahb_clk,
+	.get_rate	= get_rate_ipg,
+};
+
+static struct clk cpu_clk = {
+	.parent = &mpll_main2_clk,
+	.set_parent = clk_cpu_set_parent,
+	.round_rate = round_rate_cpu,
+	.get_rate = get_rate_cpu,
+	.set_rate = set_rate_cpu,
+};
+
+static struct clk spll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = get_rate_spll,
+	.enable = clk_spll_enable,
+	.disable = clk_spll_disable,
+};
 
 /*
  * the low frequency external clock reference
- * Default case is 32.768kHz Could be changed at runtime
- * with a call to change_external_low_reference()
+ * Default case is 32.768kHz.
  */
 static struct clk ckil_clk = {
-	.name = "ckil",
-	.get_rate = get_low_reference_clock_rate,
+	.get_rate = get_rate_low_reference,
 };
 
-static unsigned long get_mpll_clk(struct clk *clk)
-{
-	uint32_t reg;
-	unsigned long ref_clk;
-	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
-	unsigned long long temp;
-
-	ref_clk = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(CCM_MPCTL0);
-	pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
-	mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
-	mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
-	mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
-
-	mfi = (mfi <= 5) ? 5 : mfi;
-	temp = 2LL * ref_clk * mfn;
-	do_div(temp, mfd + 1);
-	temp = 2LL * ref_clk * mfi + temp;
-	do_div(temp, pdf + 1);
-
-	return (unsigned long)temp;
-}
-
-static struct clk mpll_clk = {
-	.name = "mpll",
-	.parent = &ckih_clk,
-	.get_rate = get_mpll_clk,
+/* Output of frequency pre multiplier */
+static struct clk fpm_clk = {
+	.parent = &ckil_clk,
+	.get_rate = get_rate_fpm,
 };
 
-static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
-{
-	unsigned long parent_rate;
+#define PCCR0 CCM_PCCR0
+#define PCCR1 CCM_PCCR1
 
-	parent_rate = clk_get_rate(clk->parent);
-
-	/* i.MX27 TO2:
-	 * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
-	 * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
-	 */
-
-	if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
-		return 2UL * parent_rate / 3UL;
-
-	return parent_rate;
-}
-
-static struct clk mpll_main_clk[] = {
-	{
-		/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
-		 * It provide the clock source whose rate is same as MPLL
-		 */
-		.name = "mpll_main",
-		.id = 0,
-		.parent = &mpll_clk,
-		.get_rate = _clk_mpll_main_get_rate
-	}, {
-		/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
-		 * It provide the clock source whose rate is same MPLL * 2/3
-		 */
-		.name = "mpll_main",
-		.id = 1,
-		.parent = &mpll_clk,
-		.get_rate = _clk_mpll_main_get_rate
+#define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.enable		= clk_pccr_enable,	\
+		.disable	= clk_pccr_disable,	\
+		.secondary	= s,			\
+		.parent		= p,			\
 	}
-};
 
-static unsigned long get_spll_clk(struct clk *clk)
-{
-	uint32_t reg;
-	unsigned long ref_clk;
-	unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
-	unsigned long long temp;
-
-	ref_clk = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(CCM_SPCTL0);
-	/*TODO: This is TO2 Bug */
-	if (mx27_revision() >= CHIP_REV_2_0)
-		__raw_writel(reg, CCM_SPCTL0);
-
-	pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
-	mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
-	mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
-	mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
-
-	mfi = (mfi <= 5) ? 5 : mfi;
-	temp = 2LL * ref_clk * mfn;
-	do_div(temp, mfd + 1);
-	temp = 2LL * ref_clk * mfi + temp;
-	do_div(temp, pdf + 1);
-
-	return (unsigned long)temp;
-}
-
-static struct clk spll_clk = {
-	.name = "spll",
-	.parent = &ckih_clk,
-	.get_rate = get_spll_clk,
-	.enable = _clk_spll_enable,
-	.disable = _clk_spll_disable,
-};
-
-static unsigned long get_cpu_clk(struct clk *clk)
-{
-	u32 div;
-	unsigned long rate;
-
-	if (mx27_revision() >= CHIP_REV_2_0)
-		div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
-	else
-		div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
-
-	rate = clk_get_rate(clk->parent);
-	return rate / (div + 1);
-}
-
-static struct clk cpu_clk = {
-	.name = "cpu_clk",
-	.parent = &mpll_main_clk[1],
-	.set_parent = _clk_cpu_set_parent,
-	.round_rate = _clk_cpu_round_rate,
-	.get_rate = get_cpu_clk,
-	.set_rate = _clk_cpu_set_rate,
-};
-
-static unsigned long get_ahb_clk(struct clk *clk)
-{
-	unsigned long rate;
-	unsigned long bclk_pdf;
-
-	if (mx27_revision() >= CHIP_REV_2_0)
-		bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
-					>> CCM_CSCR_AHB_OFFSET;
-	else
-		bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
-					>> CCM_CSCR_BCLK_OFFSET;
-
-	rate = clk_get_rate(clk->parent);
-	return rate / (bclk_pdf + 1);
-}
-
-static struct clk ahb_clk = {
-	.name = "ahb_clk",
-	.parent = &mpll_main_clk[1],
-	.get_rate = get_ahb_clk,
-};
-
-static unsigned long get_ipg_clk(struct clk *clk)
-{
-	unsigned long rate;
-	unsigned long ipg_pdf;
-
-	if (mx27_revision() >= CHIP_REV_2_0)
-		return clk_get_rate(clk->parent);
-	else
-		ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
-
-	rate = clk_get_rate(clk->parent);
-	return rate / (ipg_pdf + 1);
-}
-
-static struct clk ipg_clk = {
-	.name = "ipg_clk",
-	.parent = &ahb_clk,
-	.get_rate = get_ipg_clk,
-};
-
-static unsigned long _clk_perclkx_recalc(struct clk *clk)
-{
-	unsigned long perclk_pdf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	if (clk->id < 0 || clk->id > 3)
-		return 0;
-
-	perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
-
-	return parent_rate / (perclk_pdf + 1);
-}
-
-static struct clk per_clk[] = {
-	{
-		.name = "per_clk",
-		.id = 0,
-		.parent = &mpll_main_clk[1],
-		.get_rate = _clk_perclkx_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "per_clk",
-		.id = 1,
-		.parent = &mpll_main_clk[1],
-		.get_rate = _clk_perclkx_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "per_clk",
-		.id = 2,
-		.parent = &mpll_main_clk[1],
-		.round_rate = _clk_perclkx_round_rate,
-		.set_rate = _clk_perclkx_set_rate,
-		.get_rate = _clk_perclkx_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "per_clk",
-		.id = 3,
-		.parent = &mpll_main_clk[1],
-		.round_rate = _clk_perclkx_round_rate,
-		.set_rate = _clk_perclkx_set_rate,
-		.get_rate = _clk_perclkx_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart1_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 0,
-		.parent = &per_clk[0],
-		.secondary = &uart1_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART1_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart2_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 1,
-		.parent = &per_clk[0],
-		.secondary = &uart2_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART2_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart3_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 2,
-		.parent = &per_clk[0],
-		.secondary = &uart3_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 2,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART3_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart4_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 3,
-		.parent = &per_clk[0],
-		.secondary = &uart4_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 3,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART4_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart5_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 4,
-		.parent = &per_clk[0],
-		.secondary = &uart5_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 4,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART5_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-struct clk uart6_clk[] = {
-	{
-		.name = "uart_clk",
-		.id = 5,
-		.parent = &per_clk[0],
-		.secondary = &uart6_clk[1],
-	}, {
-		.name = "uart_ipg_clk",
-		.id = 5,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_UART6_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt1_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 0,
-		.parent = &per_clk[0],
-		.secondary = &gpt1_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT1_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt2_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 1,
-		.parent = &per_clk[0],
-		.secondary = &gpt2_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT2_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt3_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 2,
-		.parent = &per_clk[0],
-		.secondary = &gpt3_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 2,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT3_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt4_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 3,
-		.parent = &per_clk[0],
-		.secondary = &gpt4_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 3,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT4_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt5_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 4,
-		.parent = &per_clk[0],
-		.secondary = &gpt5_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 4,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT5_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk gpt6_clk[] = {
-	{
-		.name = "gpt_clk",
-		.id = 5,
-		.parent = &per_clk[0],
-		.secondary = &gpt6_clk[1],
-	}, {
-		.name = "gpt_ipg_clk",
-		.id = 5,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_GPT6_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk pwm_clk[] = {
-	{
-		.name = "pwm_clk",
-		.parent = &per_clk[0],
-		.secondary = &pwm_clk[1],
-	}, {
-		.name = "pwm_clk",
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_PWM_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk sdhc1_clk[] = {
-	{
-		.name = "sdhc_clk",
-		.id = 0,
-		.parent = &per_clk[1],
-		.secondary = &sdhc1_clk[1],
-	}, {
-		.name = "sdhc_ipg_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_SDHC1_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk sdhc2_clk[] = {
-	{
-		.name = "sdhc_clk",
-		.id = 1,
-		.parent = &per_clk[1],
-		.secondary = &sdhc2_clk[1],
-	}, {
-		.name = "sdhc_ipg_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_SDHC2_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk sdhc3_clk[] = {
-	{
-		.name = "sdhc_clk",
-		.id = 2,
-		.parent = &per_clk[1],
-		.secondary = &sdhc3_clk[1],
-	}, {
-		.name = "sdhc_ipg_clk",
-		.id = 2,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_SDHC3_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk cspi1_clk[] = {
-	{
-		.name = "cspi_clk",
-		.id = 0,
-		.parent = &per_clk[1],
-		.secondary = &cspi1_clk[1],
-	}, {
-		.name = "cspi_ipg_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_CSPI1_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk cspi2_clk[] = {
-	{
-		.name = "cspi_clk",
-		.id = 1,
-		.parent = &per_clk[1],
-		.secondary = &cspi2_clk[1],
-	}, {
-		.name = "cspi_ipg_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_CSPI2_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk cspi3_clk[] = {
-	{
-		.name = "cspi_clk",
-		.id = 2,
-		.parent = &per_clk[1],
-		.secondary = &cspi3_clk[1],
-	}, {
-		.name = "cspi_ipg_clk",
-		.id = 2,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_CSPI3_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk lcdc_clk[] = {
-	{
-		.name = "lcdc_clk",
-		.parent = &per_clk[2],
-		.secondary = &lcdc_clk[1],
-		.round_rate = _clk_parent_round_rate,
-		.set_rate = _clk_parent_set_rate,
-	}, {
-		.name = "lcdc_ipg_clk",
-		.parent = &ipg_clk,
-		.secondary = &lcdc_clk[2],
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_LCDC_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "lcdc_ahb_clk",
-		.parent = &ahb_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk csi_clk[] = {
-	{
-		.name = "csi_perclk",
-		.parent = &per_clk[3],
-		.secondary = &csi_clk[1],
-		.round_rate = _clk_parent_round_rate,
-		.set_rate = _clk_parent_set_rate,
-	}, {
-		.name = "csi_ahb_clk",
-		.parent = &ahb_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk usb_clk[] = {
-	{
-		.name = "usb_clk",
-		.parent = &spll_clk,
-		.get_rate = _clk_usb_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_USBOTG_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "usb_ahb_clk",
-		.parent = &ahb_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
-		.disable = _clk_disable,
+#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
+	static struct clk name = {				\
+		.id		= i,				\
+		.enable_reg	= er,				\
+		.enable_shift	= es,				\
+		.get_rate	= get_rate_##getsetround,	\
+		.set_rate	= set_rate_##getsetround,	\
+		.round_rate	= round_rate_##getsetround,	\
+		.enable		= clk_pccr_enable,		\
+		.disable	= clk_pccr_disable,		\
+		.secondary	= s,				\
+		.parent		= p,				\
 	}
-};
 
-static struct clk ssi1_clk[] = {
-	{
-		.name = "ssi_clk",
-		.id = 0,
-		.parent = &mpll_main_clk[1],
-		.secondary = &ssi1_clk[1],
-		.get_rate = _clk_ssi1_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "ssi_ipg_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
-		.disable = _clk_disable,
+/* Forward declaration to keep the following list in order */
+static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+		  dma_clk1, lcdc_clk2, vpu_clk1;
+
+/* All clocks we can gate through PCCRx in the order of PCCRx bits */
+DEFINE_CLOCK(ssi2_clk1,    1, PCCR0,  0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ssi1_clk1,    0, PCCR0,  1, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(slcdc_clk,    0, PCCR0,  2, NULL, &slcdc_clk1, &ahb_clk);
+DEFINE_CLOCK(sdhc3_clk1,   0, PCCR0,  3, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdhc2_clk1,   0, PCCR0,  4, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdhc1_clk1,   0, PCCR0,  5, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(scc_clk,      0, PCCR0,  6, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sahara2_clk,  0, PCCR0,  7, NULL, &sahara2_clk1, &ahb_clk);
+DEFINE_CLOCK(rtic_clk,     0, PCCR0,  8, NULL, &rtic_clk1, &ahb_clk);
+DEFINE_CLOCK(rtc_clk,      0, PCCR0,  9, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pwm_clk1,     0, PCCR0, 11, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(owire_clk,    0, PCCR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(mstick_clk1,  0, PCCR0, 13, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(lcdc_clk1,    0, PCCR0, 14, NULL, &lcdc_clk2, &ipg_clk);
+DEFINE_CLOCK(kpp_clk,      0, PCCR0, 15, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(iim_clk,      0, PCCR0, 16, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(i2c2_clk,     1, PCCR0, 17, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(i2c1_clk,     0, PCCR0, 18, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt6_clk1,    0, PCCR0, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt5_clk1,    0, PCCR0, 20, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt4_clk1,    0, PCCR0, 21, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt3_clk1,    0, PCCR0, 22, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt2_clk1,    0, PCCR0, 23, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpt1_clk1,    0, PCCR0, 24, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(gpio_clk,     0, PCCR0, 25, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(fec_clk,      0, PCCR0, 26, NULL, &fec_clk1, &ahb_clk);
+DEFINE_CLOCK(emma_clk,     0, PCCR0, 27, NULL, &emma_clk1, &ahb_clk);
+DEFINE_CLOCK(dma_clk,      0, PCCR0, 28, NULL, &dma_clk1, &ahb_clk);
+DEFINE_CLOCK(cspi13_clk1,  0, PCCR0, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi2_clk1,   0, PCCR0, 30, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi1_clk1,   0, PCCR0, 31, NULL, NULL, &ipg_clk);
+
+DEFINE_CLOCK(mstick_clk,   0, PCCR1,  2, NULL, &mstick_clk1, &ipg_clk);
+DEFINE_CLOCK(nfc_clk,      0, PCCR1,  3, get_rate_nfc, NULL, &cpu_clk);
+DEFINE_CLOCK(ssi2_clk,     1, PCCR1,  4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk);
+DEFINE_CLOCK(ssi1_clk,     0, PCCR1,  5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk);
+DEFINE_CLOCK(vpu_clk,      0, PCCR1,  6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk);
+DEFINE_CLOCK1(per4_clk,    3, PCCR1,  7, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per3_clk,    2, PCCR1,  8, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per2_clk,    1, PCCR1,  9, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK1(per1_clk,    0, PCCR1, 10, per, NULL, &mpll_main2_clk);
+DEFINE_CLOCK(usb_clk1,     0, PCCR1, 11, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(slcdc_clk1,   0, PCCR1, 12, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(sahara2_clk1, 0, PCCR1, 13, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(rtic_clk1,    0, PCCR1, 14, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(lcdc_clk2,    0, PCCR1, 15, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(vpu_clk1,     0, PCCR1, 16, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(fec_clk1,     0, PCCR1, 17, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(emma_clk1,    0, PCCR1, 18, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(emi_clk,      0, PCCR1, 19, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(dma_clk1,     0, PCCR1, 20, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(csi_clk1,     0, PCCR1, 21, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(brom_clk,     0, PCCR1, 22, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(ata_clk,      0, PCCR1, 23, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(wdog_clk,     0, PCCR1, 24, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(usb_clk,      0, PCCR1, 25, get_rate_usb, &usb_clk1, &spll_clk);
+DEFINE_CLOCK(uart6_clk1,   0, PCCR1, 26, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart5_clk1,   0, PCCR1, 27, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart4_clk1,   0, PCCR1, 28, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart3_clk1,   0, PCCR1, 29, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart2_clk1,   0, PCCR1, 30, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart1_clk1,   0, PCCR1, 31, NULL, NULL, &ipg_clk);
+
+/* Clocks we cannot directly gate, but drivers need their rates */
+DEFINE_CLOCK(cspi1_clk,    0, 0,      0, NULL, &cspi1_clk1, &per2_clk);
+DEFINE_CLOCK(cspi2_clk,    1, 0,      0, NULL, &cspi2_clk1, &per2_clk);
+DEFINE_CLOCK(cspi3_clk,    2, 0,      0, NULL, &cspi13_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc1_clk,    0, 0,      0, NULL, &sdhc1_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc2_clk,    1, 0,      0, NULL, &sdhc2_clk1, &per2_clk);
+DEFINE_CLOCK(sdhc3_clk,    2, 0,      0, NULL, &sdhc3_clk1, &per2_clk);
+DEFINE_CLOCK(pwm_clk,      0, 0,      0, NULL, &pwm_clk1, &per1_clk);
+DEFINE_CLOCK(gpt1_clk,     0, 0,      0, NULL, &gpt1_clk1, &per1_clk);
+DEFINE_CLOCK(gpt2_clk,     1, 0,      0, NULL, &gpt2_clk1, &per1_clk);
+DEFINE_CLOCK(gpt3_clk,     2, 0,      0, NULL, &gpt3_clk1, &per1_clk);
+DEFINE_CLOCK(gpt4_clk,     3, 0,      0, NULL, &gpt4_clk1, &per1_clk);
+DEFINE_CLOCK(gpt5_clk,     4, 0,      0, NULL, &gpt5_clk1, &per1_clk);
+DEFINE_CLOCK(gpt6_clk,     5, 0,      0, NULL, &gpt6_clk1, &per1_clk);
+DEFINE_CLOCK(uart1_clk,    0, 0,      0, NULL, &uart1_clk1, &per1_clk);
+DEFINE_CLOCK(uart2_clk,    1, 0,      0, NULL, &uart2_clk1, &per1_clk);
+DEFINE_CLOCK(uart3_clk,    2, 0,      0, NULL, &uart3_clk1, &per1_clk);
+DEFINE_CLOCK(uart4_clk,    3, 0,      0, NULL, &uart4_clk1, &per1_clk);
+DEFINE_CLOCK(uart5_clk,    4, 0,      0, NULL, &uart5_clk1, &per1_clk);
+DEFINE_CLOCK(uart6_clk,    5, 0,      0, NULL, &uart6_clk1, &per1_clk);
+DEFINE_CLOCK1(lcdc_clk,    0, 0,      0, parent, &lcdc_clk1, &per3_clk);
+DEFINE_CLOCK1(csi_clk,     0, 0,      0, parent, &csi_clk1, &per4_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
 	},
+
+static struct clk_lookup lookups[] __initdata = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK("imx-uart.5", NULL, uart6_clk)
+	_REGISTER_CLOCK(NULL, "gpt1", gpt1_clk)
+	_REGISTER_CLOCK(NULL, "gpt2", gpt2_clk)
+	_REGISTER_CLOCK(NULL, "gpt3", gpt3_clk)
+	_REGISTER_CLOCK(NULL, "gpt4", gpt4_clk)
+	_REGISTER_CLOCK(NULL, "gpt5", gpt5_clk)
+	_REGISTER_CLOCK(NULL, "gpt6", gpt6_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
+	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
+	_REGISTER_CLOCK("mxc-mmc.2", NULL, sdhc3_clk)
+	_REGISTER_CLOCK(NULL, "cspi1", cspi1_clk)
+	_REGISTER_CLOCK(NULL, "cspi2", cspi2_clk)
+	_REGISTER_CLOCK(NULL, "cspi3", cspi3_clk)
+	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
+	_REGISTER_CLOCK(NULL, "csi", csi_clk)
+	_REGISTER_CLOCK(NULL, "usb", usb_clk)
+	_REGISTER_CLOCK(NULL, "ssi1", ssi1_clk)
+	_REGISTER_CLOCK(NULL, "ssi2", ssi2_clk)
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK(NULL, "vpu", vpu_clk)
+	_REGISTER_CLOCK(NULL, "dma", dma_clk)
+	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+	_REGISTER_CLOCK(NULL, "brom", brom_clk)
+	_REGISTER_CLOCK(NULL, "emma", emma_clk)
+	_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK(NULL, "emi", emi_clk)
+	_REGISTER_CLOCK(NULL, "sahara2", sahara2_clk)
+	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK(NULL, "mstick", mstick_clk)
+	_REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+	_REGISTER_CLOCK(NULL, "gpio", gpio_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
+	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+	_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+	_REGISTER_CLOCK(NULL, "scc", scc_clk)
 };
 
-static struct clk ssi2_clk[] = {
-	{
-		.name = "ssi_clk",
-		.id = 1,
-		.parent = &mpll_main_clk[1],
-		.secondary = &ssi2_clk[1],
-		.get_rate = _clk_ssi2_recalc,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR1,
-		.enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "ssi_ipg_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.parent = &cpu_clk,
-	.get_rate = _clk_nfc_recalc,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk vpu_clk = {
-	.name = "vpu_clk",
-	.parent = &mpll_main_clk[1],
-	.get_rate = _clk_vpu_recalc,
-	.enable = _clk_vpu_enable,
-	.disable = _clk_vpu_disable,
-};
-
-static struct clk dma_clk = {
-	.name = "dma_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_dma_enable,
-	.disable = _clk_dma_disable,
-};
-
-static struct clk rtic_clk = {
-	.name = "rtic_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_rtic_enable,
-	.disable = _clk_rtic_disable,
-};
-
-static struct clk brom_clk = {
-	.name = "brom_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk emma_clk = {
-	.name = "emma_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_emma_enable,
-	.disable = _clk_emma_disable,
-};
-
-static struct clk slcdc_clk = {
-	.name = "slcdc_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_slcdc_enable,
-	.disable = _clk_slcdc_disable,
-};
-
-static struct clk fec_clk = {
-	.name = "fec_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_fec_enable,
-	.disable = _clk_fec_disable,
-};
-
-static struct clk emi_clk = {
-	.name = "emi_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk sahara2_clk = {
-	.name = "sahara_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_sahara2_enable,
-	.disable = _clk_sahara2_disable,
-};
-
-static struct clk ata_clk = {
-	.name = "ata_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk mstick1_clk = {
-	.name = "mstick1_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_mstick1_enable,
-	.disable = _clk_mstick1_disable,
-};
-
-static struct clk wdog_clk = {
-	.name = "wdog_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR1_WDT_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk gpio_clk = {
-	.name = "gpio_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR1,
-	.enable_shift = CCM_PCCR0_GPIO_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk i2c_clk[] = {
-	{
-		.name = "i2c_clk",
-		.id = 0,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_I2C1_OFFSET,
-		.disable = _clk_disable,
-	}, {
-		.name = "i2c_clk",
-		.id = 1,
-		.parent = &ipg_clk,
-		.enable = _clk_enable,
-		.enable_reg = CCM_PCCR0,
-		.enable_shift = CCM_PCCR0_I2C2_OFFSET,
-		.disable = _clk_disable,
-	},
-};
-
-static struct clk iim_clk = {
-	.name = "iim_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR0,
-	.enable_shift = CCM_PCCR0_IIM_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk kpp_clk = {
-	.name = "kpp_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR0,
-	.enable_shift = CCM_PCCR0_KPP_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk owire_clk = {
-	.name = "owire_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR0,
-	.enable_shift = CCM_PCCR0_OWIRE_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk rtc_clk = {
-	.name = "rtc_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR0,
-	.enable_shift = CCM_PCCR0_RTC_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk scc_clk = {
-	.name = "scc_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = CCM_PCCR0,
-	.enable_shift = CCM_PCCR0_SCC_OFFSET,
-	.disable = _clk_disable,
-};
-
-static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
+/* Adjust the clock path for TO2 and later */
+static void __init to2_adjust_clocks(void)
 {
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	div = parent_rate / rate;
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 8)
-		div = 8;
-
-	return parent_rate / div;
-}
-
-static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg;
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-
-	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-		return -EINVAL;
-	div--;
-
-	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
-	reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
-	__raw_writel(reg, CCM_PCDR0);
-
-	return 0;
-}
-
-static unsigned long _clk_clko_recalc(struct clk *clk)
-{
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
-		CCM_PCDR0_CLKODIV_OFFSET;
-	div++;
-
-	return parent_rate / div;
-}
-
-static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
-
-	if (parent == &ckil_clk)
-		reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &ckih_clk)
-		reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == mpll_clk.parent)
-		reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == spll_clk.parent)
-		reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &mpll_clk)
-		reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &spll_clk)
-		reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &cpu_clk)
-		reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &ahb_clk)
-		reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &ipg_clk)
-		reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &per_clk[0])
-		reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &per_clk[1])
-		reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &per_clk[2])
-		reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &per_clk[3])
-		reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &ssi1_clk[0])
-		reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &ssi2_clk[0])
-		reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &nfc_clk)
-		reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &mstick1_clk)
-		reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &vpu_clk)
-		reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
-	else if (parent == &usb_clk[0])
-		reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, CCM_CCSR);
-
-	return 0;
-}
-
-static int _clk_clko_enable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
-	__raw_writel(reg, CCM_PCDR0);
-
-	return 0;
-}
-
-static void _clk_clko_disable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
-	__raw_writel(reg, CCM_PCDR0);
-}
-
-static struct clk clko_clk = {
-	.name = "clko_clk",
-	.get_rate = _clk_clko_recalc,
-	.set_rate = _clk_clko_set_rate,
-	.round_rate = _clk_clko_round_rate,
-	.set_parent = _clk_clko_set_parent,
-	.enable = _clk_clko_enable,
-	.disable = _clk_clko_disable,
-};
-
-static struct clk *mxc_clks[] = {
-	&ckih_clk,
-	&ckil_clk,
-	&mpll_clk,
-	&mpll_main_clk[0],
-	&mpll_main_clk[1],
-	&spll_clk,
-	&cpu_clk,
-	&ahb_clk,
-	&ipg_clk,
-	&per_clk[0],
-	&per_clk[1],
-	&per_clk[2],
-	&per_clk[3],
-	&clko_clk,
-	&uart1_clk[0],
-	&uart1_clk[1],
-	&uart2_clk[0],
-	&uart2_clk[1],
-	&uart3_clk[0],
-	&uart3_clk[1],
-	&uart4_clk[0],
-	&uart4_clk[1],
-	&uart5_clk[0],
-	&uart5_clk[1],
-	&uart6_clk[0],
-	&uart6_clk[1],
-	&gpt1_clk[0],
-	&gpt1_clk[1],
-	&gpt2_clk[0],
-	&gpt2_clk[1],
-	&gpt3_clk[0],
-	&gpt3_clk[1],
-	&gpt4_clk[0],
-	&gpt4_clk[1],
-	&gpt5_clk[0],
-	&gpt5_clk[1],
-	&gpt6_clk[0],
-	&gpt6_clk[1],
-	&pwm_clk[0],
-	&pwm_clk[1],
-	&sdhc1_clk[0],
-	&sdhc1_clk[1],
-	&sdhc2_clk[0],
-	&sdhc2_clk[1],
-	&sdhc3_clk[0],
-	&sdhc3_clk[1],
-	&cspi1_clk[0],
-	&cspi1_clk[1],
-	&cspi2_clk[0],
-	&cspi2_clk[1],
-	&cspi3_clk[0],
-	&cspi3_clk[1],
-	&lcdc_clk[0],
-	&lcdc_clk[1],
-	&lcdc_clk[2],
-	&csi_clk[0],
-	&csi_clk[1],
-	&usb_clk[0],
-	&usb_clk[1],
-	&ssi1_clk[0],
-	&ssi1_clk[1],
-	&ssi2_clk[0],
-	&ssi2_clk[1],
-	&nfc_clk,
-	&vpu_clk,
-	&dma_clk,
-	&rtic_clk,
-	&brom_clk,
-	&emma_clk,
-	&slcdc_clk,
-	&fec_clk,
-	&emi_clk,
-	&sahara2_clk,
-	&ata_clk,
-	&mstick1_clk,
-	&wdog_clk,
-	&gpio_clk,
-	&i2c_clk[0],
-	&i2c_clk[1],
-	&iim_clk,
-	&kpp_clk,
-	&owire_clk,
-	&rtc_clk,
-	&scc_clk,
-};
-
-void __init change_external_low_reference(unsigned long new_ref)
-{
-	external_low_reference = new_ref;
-}
-
-unsigned long __init clk_early_get_timer_rate(void)
-{
-	return clk_get_rate(&per_clk[0]);
-}
-
-static void __init probe_mxc_clocks(void)
-{
-	int i;
+	unsigned long cscr = __raw_readl(CCM_CSCR);
 
 	if (mx27_revision() >= CHIP_REV_2_0) {
-		if (CSCR() & 0x8000)
-			cpu_clk.parent = &mpll_main_clk[0];
+		if (cscr & CCM_CSCR_ARM_SRC)
+			cpu_clk.parent = &mpll_main1_clk;
 
-		if (!(CSCR() & 0x00800000))
-			ssi2_clk[0].parent = &spll_clk;
+		if (!(cscr & CCM_CSCR_SSI2))
+			ssi1_clk.parent = &spll_clk;
 
-		if (!(CSCR() & 0x00400000))
-			ssi1_clk[0].parent = &spll_clk;
+		if (!(cscr & CCM_CSCR_SSI1))
+			ssi1_clk.parent = &spll_clk;
 
-		if (!(CSCR() & 0x00200000))
+		if (!(cscr & CCM_CSCR_VPU))
 			vpu_clk.parent = &spll_clk;
 	} else {
 		cpu_clk.parent = &mpll_clk;
@@ -1565,11 +693,13 @@
 		cpu_clk.set_rate = NULL;
 		ahb_clk.parent = &mpll_clk;
 
-		for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
-			per_clk[i].parent = &mpll_clk;
+		per1_clk.parent = &mpll_clk;
+		per2_clk.parent = &mpll_clk;
+		per3_clk.parent = &mpll_clk;
+		per4_clk.parent = &mpll_clk;
 
-		ssi1_clk[0].parent = &mpll_clk;
-		ssi2_clk[0].parent = &mpll_clk;
+		ssi1_clk.parent = &mpll_clk;
+		ssi2_clk.parent = &mpll_clk;
 
 		vpu_clk.parent = &mpll_clk;
 	}
@@ -1579,47 +709,47 @@
  * must be called very early to get information about the
  * available clock rate when the timer framework starts
  */
-int __init mxc_clocks_init(unsigned long fref)
+int __init mx27_clocks_init(unsigned long fref)
 {
-	u32 cscr;
-	struct clk **clkp;
+	u32 cscr = __raw_readl(CCM_CSCR);
+	int i;
 
 	external_high_reference = fref;
 
-	/* detect clock reference for both system PLL */
-	cscr = CSCR();
+	/* detect clock reference for both system PLLs */
 	if (cscr & CCM_CSCR_MCU)
 		mpll_clk.parent = &ckih_clk;
 	else
-		mpll_clk.parent = &ckil_clk;
+		mpll_clk.parent = &fpm_clk;
 
 	if (cscr & CCM_CSCR_SP)
 		spll_clk.parent = &ckih_clk;
 	else
-		spll_clk.parent = &ckil_clk;
+		spll_clk.parent = &fpm_clk;
 
-	probe_mxc_clocks();
+	to2_adjust_clocks();
 
-	per_clk[0].enable(&per_clk[0]);
-	gpt1_clk[1].enable(&gpt1_clk[1]);
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
 
-	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
-		clk_register(*clkp);
+	/* Turn off all clocks we do not need */
+	__raw_writel(0, CCM_PCCR0);
+	__raw_writel((1 << 10) | (1 << 19), CCM_PCCR1);
 
-	/* Turn off all possible clocks */
-	__raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
-	__raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
-		     CCM_PCCR1);
 	spll_clk.disable(&spll_clk);
 
-	/* This will propagate to all children and init all the clock rates */
-
-	clk_enable(&emi_clk);
+	/* enable basic clocks */
+	clk_enable(&per1_clk);
 	clk_enable(&gpio_clk);
+	clk_enable(&emi_clk);
 	clk_enable(&iim_clk);
-	clk_enable(&gpt1_clk[0]);
+
 #ifdef CONFIG_DEBUG_LL_CONSOLE
-	clk_enable(&uart1_clk[0]);
+	clk_enable(&uart1_clk);
 #endif
+
+	mxc_timer_init(&gpt1_clk);
+
 	return 0;
 }
+
diff --git a/arch/arm/mach-mx2/cpu_imx27.c b/arch/arm/mach-mx2/cpu_imx27.c
index 239308f..d9e3bf9 100644
--- a/arch/arm/mach-mx2/cpu_imx27.c
+++ b/arch/arm/mach-mx2/cpu_imx27.c
@@ -26,11 +26,11 @@
 
 #include <mach/hardware.h>
 
-#include "crm_regs.h"
-
 static int cpu_silicon_rev = -1;
 static int cpu_partnumber;
 
+#define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
+
 static void query_silicon_parameter(void)
 {
 	u32 val;
diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h
index 94644cd..749de76 100644
--- a/arch/arm/mach-mx2/crm_regs.h
+++ b/arch/arm/mach-mx2/crm_regs.h
@@ -38,42 +38,36 @@
 #define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
 #define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
 
-#define CCM_CSCR_USB_OFFSET     28
-#define CCM_CSCR_USB_MASK       (0x7 << 28)
+#define CCM_CSCR_PRESC_OFFSET   29
+#define CCM_CSCR_PRESC_MASK     (0x7 << CCM_CSCR_PRESC_OFFSET)
+
+#define CCM_CSCR_USB_OFFSET     26
+#define CCM_CSCR_USB_MASK       (0x7 << CCM_CSCR_USB_OFFSET)
 #define CCM_CSCR_SD_OFFSET      24
-#define CCM_CSCR_SD_MASK        (0x3 << 24)
-#define CCM_CSCR_SSI2           (1 << 23)
-#define CCM_CSCR_SSI2_OFFSET    23
-#define CCM_CSCR_SSI1           (1 << 22)
-#define CCM_CSCR_SSI1_OFFSET    22
-#define CCM_CSCR_VPU           (1 << 21)
-#define CCM_CSCR_VPU_OFFSET    21
-#define CCM_CSCR_MSHC           (1 << 20)
-#define CCM_CSCR_SPLLRES        (1 << 19)
-#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SD_MASK        (0x3 << CCM_CSCR_SD_OFFSET)
+#define CCM_CSCR_SPLLRES        (1 << 22)
+#define CCM_CSCR_MPLLRES        (1 << 21)
+#define CCM_CSCR_SSI2_OFFSET    20
+#define CCM_CSCR_SSI2           (1 << CCM_CSCR_SSI2_OFFSET)
+#define CCM_CSCR_SSI1_OFFSET    19
+#define CCM_CSCR_SSI1           (1 << CCM_CSCR_SSI1_OFFSET)
+#define CCM_CSCR_FIR_OFFSET    	18
+#define CCM_CSCR_FIR		(1 << CCM_CSCR_FIR_OFFSET)
 #define CCM_CSCR_SP             (1 << 17)
 #define CCM_CSCR_MCU            (1 << 16)
-/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_ARM_SRC        (1 << 15)
-#define CCM_CSCR_ARM_OFFSET     12
-#define CCM_CSCR_ARM_MASK       (0x3 << 12)
-/* CCM_CSCR_ARM_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_PRESC_OFFSET   13
-#define CCM_CSCR_PRESC_MASK     (0x7 << 13)
-#define CCM_CSCR_BCLK_OFFSET    9
-#define CCM_CSCR_BCLK_MASK      (0xf << 9)
-#define CCM_CSCR_IPDIV_OFFSET   8
-#define CCM_CSCR_IPDIV          (1 << 8)
-/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
-#define CCM_CSCR_AHB_OFFSET     8
-#define CCM_CSCR_AHB_MASK       (0x3 << 8)
-/* CCM_CSCR_AHB_xxx just be avaliable on i.MX27 TO2*/
+#define CCM_CSCR_BCLK_OFFSET	10
+#define CCM_CSCR_BCLK_MASK      (0xf << CCM_CSCR_BCLK_OFFSET)
+#define CCM_CSCR_IPDIV_OFFSET   9
+#define CCM_CSCR_IPDIV          (1 << CCM_CSCR_IPDIV_OFFSET)
+
 #define CCM_CSCR_OSC26MDIV      (1 << 4)
 #define CCM_CSCR_OSC26M         (1 << 3)
 #define CCM_CSCR_FPM            (1 << 2)
 #define CCM_CSCR_SPEN           (1 << 1)
 #define CCM_CSCR_MPEN           1
 
+
+
 #define CCM_MPCTL0_CPLM         (1 << 31)
 #define CCM_MPCTL0_PD_OFFSET    26
 #define CCM_MPCTL0_PD_MASK      (0xf << 26)
@@ -109,25 +103,14 @@
 
 #define CCM_PCDR0_SSI2BAUDDIV_OFFSET    26
 #define CCM_PCDR0_SSI2BAUDDIV_MASK      (0x3f << 26)
-#define CCM_PCDR0_CLKO_EN               25
-#define CCM_PCDR0_CLKODIV_OFFSET        22
-#define CCM_PCDR0_CLKODIV_MASK          (0x7 << 22)
 #define CCM_PCDR0_SSI1BAUDDIV_OFFSET    16
 #define CCM_PCDR0_SSI1BAUDDIV_MASK      (0x3f << 16)
-/*The difinition for i.MX27 TO2*/
-#define CCM_PCDR0_VPUDIV2_OFFSET        10
-#define CCM_PCDR0_VPUDIV2_MASK          (0x3f << 10)
-#define CCM_PCDR0_NFCDIV2_OFFSET         6
-#define CCM_PCDR0_NFCDIV2_MASK           (0xf << 6)
-#define CCM_PCDR0_MSHCDIV2_MASK          0x3f
-/*The difinition for i.MX27 TO2*/
 #define CCM_PCDR0_NFCDIV_OFFSET         12
 #define CCM_PCDR0_NFCDIV_MASK           (0xf << 12)
-#define CCM_PCDR0_VPUDIV_OFFSET        8
-#define CCM_PCDR0_VPUDIV_MASK          (0xf << 8)
-#define CCM_PCDR0_MSHCDIV_OFFSET        0
-#define CCM_PCDR0_MSHCDIV_MASK          0x1f
-
+#define CCM_PCDR0_48MDIV_OFFSET		5
+#define CCM_PCDR0_48MDIV_MASK		(0x7 << CCM_PCDR0_48MDIV_OFFSET)
+#define CCM_PCDR0_FIRIDIV_OFFSET	0
+#define CCM_PCDR0_FIRIDIV_MASK		0x1f
 #define CCM_PCDR1_PERDIV4_OFFSET        24
 #define CCM_PCDR1_PERDIV4_MASK          (0x3f << 24)
 #define CCM_PCDR1_PERDIV3_OFFSET        16
@@ -137,133 +120,135 @@
 #define CCM_PCDR1_PERDIV1_OFFSET        0
 #define CCM_PCDR1_PERDIV1_MASK          0x3f
 
-#define CCM_PCCR0_CSPI1_OFFSET          31
-#define CCM_PCCR0_CSPI1_MASK            (1 << 31)
-#define CCM_PCCR0_CSPI2_OFFSET          30
-#define CCM_PCCR0_CSPI2_MASK            (1 << 30)
-#define CCM_PCCR0_CSPI3_OFFSET          29
-#define CCM_PCCR0_CSPI3_MASK            (1 << 29)
-#define CCM_PCCR0_DMA_OFFSET            28
-#define CCM_PCCR0_DMA_MASK              (1 << 28)
-#define CCM_PCCR0_EMMA_OFFSET           27
-#define CCM_PCCR0_EMMA_MASK             (1 << 27)
-#define CCM_PCCR0_FEC_OFFSET            26
-#define CCM_PCCR0_FEC_MASK              (1 << 26)
-#define CCM_PCCR0_GPIO_OFFSET           25
-#define CCM_PCCR0_GPIO_MASK             (1 << 25)
-#define CCM_PCCR0_GPT1_OFFSET           24
-#define CCM_PCCR0_GPT1_MASK             (1 << 24)
-#define CCM_PCCR0_GPT2_OFFSET           23
-#define CCM_PCCR0_GPT2_MASK             (1 << 23)
-#define CCM_PCCR0_GPT3_OFFSET           22
-#define CCM_PCCR0_GPT3_MASK             (1 << 22)
-#define CCM_PCCR0_GPT4_OFFSET           21
-#define CCM_PCCR0_GPT4_MASK             (1 << 21)
-#define CCM_PCCR0_GPT5_OFFSET           20
-#define CCM_PCCR0_GPT5_MASK             (1 << 20)
-#define CCM_PCCR0_GPT6_OFFSET           19
-#define CCM_PCCR0_GPT6_MASK             (1 << 19)
-#define CCM_PCCR0_I2C1_OFFSET           18
-#define CCM_PCCR0_I2C1_MASK             (1 << 18)
-#define CCM_PCCR0_I2C2_OFFSET           17
-#define CCM_PCCR0_I2C2_MASK             (1 << 17)
-#define CCM_PCCR0_IIM_OFFSET            16
-#define CCM_PCCR0_IIM_MASK              (1 << 16)
-#define CCM_PCCR0_KPP_OFFSET            15
-#define CCM_PCCR0_KPP_MASK              (1 << 15)
-#define CCM_PCCR0_LCDC_OFFSET           14
-#define CCM_PCCR0_LCDC_MASK             (1 << 14)
-#define CCM_PCCR0_MSHC_OFFSET           13
-#define CCM_PCCR0_MSHC_MASK             (1 << 13)
-#define CCM_PCCR0_OWIRE_OFFSET          12
-#define CCM_PCCR0_OWIRE_MASK            (1 << 12)
-#define CCM_PCCR0_PWM_OFFSET            11
-#define CCM_PCCR0_PWM_MASK              (1 << 11)
-#define CCM_PCCR0_RTC_OFFSET            9
-#define CCM_PCCR0_RTC_MASK              (1 << 9)
-#define CCM_PCCR0_RTIC_OFFSET           8
-#define CCM_PCCR0_RTIC_MASK             (1 << 8)
-#define CCM_PCCR0_SAHARA_OFFSET         7
-#define CCM_PCCR0_SAHARA_MASK           (1 << 7)
-#define CCM_PCCR0_SCC_OFFSET            6
-#define CCM_PCCR0_SCC_MASK              (1 << 6)
-#define CCM_PCCR0_SDHC1_OFFSET          5
-#define CCM_PCCR0_SDHC1_MASK            (1 << 5)
-#define CCM_PCCR0_SDHC2_OFFSET          4
-#define CCM_PCCR0_SDHC2_MASK            (1 << 4)
-#define CCM_PCCR0_SDHC3_OFFSET          3
-#define CCM_PCCR0_SDHC3_MASK            (1 << 3)
-#define CCM_PCCR0_SLCDC_OFFSET          2
-#define CCM_PCCR0_SLCDC_MASK            (1 << 2)
-#define CCM_PCCR0_SSI1_IPG_OFFSET       1
-#define CCM_PCCR0_SSI1_IPG_MASK         (1 << 1)
-#define CCM_PCCR0_SSI2_IPG_OFFSET       0
-#define CCM_PCCR0_SSI2_IPG_MASK         (1 << 0)
+#define CCM_PCCR_HCLK_CSI_OFFSET       	31
+#define CCM_PCCR_HCLK_CSI_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_DMA_OFFSET       	30
+#define CCM_PCCR_HCLK_DMA_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_BROM_OFFSET      	28
+#define CCM_PCCR_HCLK_BROM_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_EMMA_OFFSET      	27
+#define CCM_PCCR_HCLK_EMMA_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_LCDC_OFFSET      	26
+#define CCM_PCCR_HCLK_LCDC_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_SLCDC_OFFSET     	25
+#define CCM_PCCR_HCLK_SLCDC_REG	        CCM_PCCR0
+#define CCM_PCCR_HCLK_USBOTG_OFFSET    	24
+#define CCM_PCCR_HCLK_USBOTG_REG	CCM_PCCR0
+#define CCM_PCCR_HCLK_BMI_OFFSET    	23
+#define CCM_PCCR_BMI_MASK          	(1 << CCM_PCCR_BMI_MASK)
+#define CCM_PCCR_HCLK_BMI_REG	    	CCM_PCCR0
+#define CCM_PCCR_PERCLK4_OFFSET        	22
+#define CCM_PCCR_PERCLK4_REG	    	CCM_PCCR0
+#define CCM_PCCR_SLCDC_OFFSET          	21
+#define CCM_PCCR_SLCDC_REG		CCM_PCCR0
+#define CCM_PCCR_FIRI_BAUD_OFFSET       20
+#define CCM_PCCR_FIRI_BAUD_MASK         (1 << CCM_PCCR_FIRI_BAUD_MASK)
+#define CCM_PCCR_FIRI_BAUD_REG	        CCM_PCCR0
+#define CCM_PCCR_NFC_OFFSET		19
+#define CCM_PCCR_NFC_REG		CCM_PCCR0
+#define CCM_PCCR_LCDC_OFFSET           	18
+#define CCM_PCCR_LCDC_REG		CCM_PCCR0
+#define CCM_PCCR_SSI1_BAUD_OFFSET      	17
+#define CCM_PCCR_SSI1_BAUD_REG	    	CCM_PCCR0
+#define CCM_PCCR_SSI2_BAUD_OFFSET      	16
+#define CCM_PCCR_SSI2_BAUD_REG	    	CCM_PCCR0
+#define CCM_PCCR_EMMA_OFFSET           	15
+#define CCM_PCCR_EMMA_REG		CCM_PCCR0
+#define CCM_PCCR_USBOTG_OFFSET         	14
+#define CCM_PCCR_USBOTG_REG		CCM_PCCR0
+#define CCM_PCCR_DMA_OFFSET            	13
+#define CCM_PCCR_DMA_REG            	CCM_PCCR0
+#define CCM_PCCR_I2C1_OFFSET           	12
+#define CCM_PCCR_I2C1_REG		CCM_PCCR0
+#define CCM_PCCR_GPIO_OFFSET           	11
+#define CCM_PCCR_GPIO_REG		CCM_PCCR0
+#define CCM_PCCR_SDHC2_OFFSET          	10
+#define CCM_PCCR_SDHC2_REG		CCM_PCCR0
+#define CCM_PCCR_SDHC1_OFFSET          	9
+#define CCM_PCCR_SDHC1_REG		CCM_PCCR0
+#define CCM_PCCR_FIRI_OFFSET		8
+#define CCM_PCCR_FIRI_MASK		(1 << CCM_PCCR_BAUD_MASK)
+#define CCM_PCCR_FIRI_REG		CCM_PCCR0
+#define CCM_PCCR_SSI2_IPG_OFFSET       	7
+#define CCM_PCCR_SSI2_REG		CCM_PCCR0
+#define CCM_PCCR_SSI1_IPG_OFFSET       	6
+#define CCM_PCCR_SSI1_REG		CCM_PCCR0
+#define CCM_PCCR_CSPI2_OFFSET		5
+#define	CCM_PCCR_CSPI2_REG		CCM_PCCR0
+#define CCM_PCCR_CSPI1_OFFSET		4
+#define	CCM_PCCR_CSPI1_REG		CCM_PCCR0
+#define CCM_PCCR_UART4_OFFSET          	3
+#define CCM_PCCR_UART4_REG		CCM_PCCR0
+#define CCM_PCCR_UART3_OFFSET          	2
+#define CCM_PCCR_UART3_REG		CCM_PCCR0
+#define CCM_PCCR_UART2_OFFSET          	1
+#define CCM_PCCR_UART2_REG		CCM_PCCR0
+#define CCM_PCCR_UART1_OFFSET          	0
+#define CCM_PCCR_UART1_REG		CCM_PCCR0
 
-#define CCM_PCCR1_UART1_OFFSET          31
-#define CCM_PCCR1_UART1_MASK            (1 << 31)
-#define CCM_PCCR1_UART2_OFFSET          30
-#define CCM_PCCR1_UART2_MASK            (1 << 30)
-#define CCM_PCCR1_UART3_OFFSET          29
-#define CCM_PCCR1_UART3_MASK            (1 << 29)
-#define CCM_PCCR1_UART4_OFFSET          28
-#define CCM_PCCR1_UART4_MASK            (1 << 28)
-#define CCM_PCCR1_UART5_OFFSET          27
-#define CCM_PCCR1_UART5_MASK            (1 << 27)
-#define CCM_PCCR1_UART6_OFFSET          26
-#define CCM_PCCR1_UART6_MASK            (1 << 26)
-#define CCM_PCCR1_USBOTG_OFFSET         25
-#define CCM_PCCR1_USBOTG_MASK           (1 << 25)
-#define CCM_PCCR1_WDT_OFFSET            24
-#define CCM_PCCR1_WDT_MASK              (1 << 24)
-#define CCM_PCCR1_HCLK_ATA_OFFSET       23
-#define CCM_PCCR1_HCLK_ATA_MASK         (1 << 23)
-#define CCM_PCCR1_HCLK_BROM_OFFSET      22
-#define CCM_PCCR1_HCLK_BROM_MASK        (1 << 22)
-#define CCM_PCCR1_HCLK_CSI_OFFSET       21
-#define CCM_PCCR1_HCLK_CSI_MASK         (1 << 21)
-#define CCM_PCCR1_HCLK_DMA_OFFSET       20
-#define CCM_PCCR1_HCLK_DMA_MASK         (1 << 20)
-#define CCM_PCCR1_HCLK_EMI_OFFSET       19
-#define CCM_PCCR1_HCLK_EMI_MASK         (1 << 19)
-#define CCM_PCCR1_HCLK_EMMA_OFFSET      18
-#define CCM_PCCR1_HCLK_EMMA_MASK        (1 << 18)
-#define CCM_PCCR1_HCLK_FEC_OFFSET       17
-#define CCM_PCCR1_HCLK_FEC_MASK         (1 << 17)
-#define CCM_PCCR1_HCLK_VPU_OFFSET       16
-#define CCM_PCCR1_HCLK_VPU_MASK         (1 << 16)
-#define CCM_PCCR1_HCLK_LCDC_OFFSET      15
-#define CCM_PCCR1_HCLK_LCDC_MASK        (1 << 15)
-#define CCM_PCCR1_HCLK_RTIC_OFFSET      14
-#define CCM_PCCR1_HCLK_RTIC_MASK        (1 << 14)
-#define CCM_PCCR1_HCLK_SAHARA_OFFSET    13
-#define CCM_PCCR1_HCLK_SAHARA_MASK      (1 << 13)
-#define CCM_PCCR1_HCLK_SLCDC_OFFSET     12
-#define CCM_PCCR1_HCLK_SLCDC_MASK       (1 << 12)
-#define CCM_PCCR1_HCLK_USBOTG_OFFSET    11
-#define CCM_PCCR1_HCLK_USBOTG_MASK      (1 << 11)
-#define CCM_PCCR1_PERCLK1_OFFSET        10
-#define CCM_PCCR1_PERCLK1_MASK          (1 << 10)
-#define CCM_PCCR1_PERCLK2_OFFSET        9
-#define CCM_PCCR1_PERCLK2_MASK          (1 << 9)
-#define CCM_PCCR1_PERCLK3_OFFSET        8
-#define CCM_PCCR1_PERCLK3_MASK          (1 << 8)
-#define CCM_PCCR1_PERCLK4_OFFSET        7
-#define CCM_PCCR1_PERCLK4_MASK          (1 << 7)
-#define CCM_PCCR1_VPU_BAUD_OFFSET       6
-#define CCM_PCCR1_VPU_BAUD_MASK         (1 << 6)
-#define CCM_PCCR1_SSI1_BAUD_OFFSET      5
-#define CCM_PCCR1_SSI1_BAUD_MASK        (1 << 5)
-#define CCM_PCCR1_SSI2_BAUD_OFFSET      4
-#define CCM_PCCR1_SSI2_BAUD_MASK        (1 << 4)
-#define CCM_PCCR1_NFC_BAUD_OFFSET       3
-#define CCM_PCCR1_NFC_BAUD_MASK         (1 << 3)
-#define CCM_PCCR1_MSHC_BAUD_OFFSET      2
-#define CCM_PCCR1_MSHC_BAUD_MASK        (1 << 2)
+#define CCM_PCCR_OWIRE_OFFSET          	31
+#define CCM_PCCR_OWIRE_REG		CCM_PCCR1
+#define CCM_PCCR_KPP_OFFSET            	30
+#define CCM_PCCR_KPP_REG		CCM_PCCR1
+#define CCM_PCCR_RTC_OFFSET            	29
+#define CCM_PCCR_RTC_REG		CCM_PCCR1
+#define CCM_PCCR_PWM_OFFSET            	28
+#define CCM_PCCR_PWM_REG		CCM_PCCR1
+#define CCM_PCCR_GPT3_OFFSET           	27
+#define CCM_PCCR_GPT3_REG		CCM_PCCR1
+#define CCM_PCCR_GPT2_OFFSET           	26
+#define CCM_PCCR_GPT2_REG		CCM_PCCR1
+#define CCM_PCCR_GPT1_OFFSET           	25
+#define CCM_PCCR_GPT1_REG		CCM_PCCR1
+#define CCM_PCCR_WDT_OFFSET            	24
+#define CCM_PCCR_WDT_REG		CCM_PCCR1
+#define CCM_PCCR_CSPI3_OFFSET		23
+#define	CCM_PCCR_CSPI3_REG		CCM_PCCR1
+
+#define CCM_PCCR_CSPI1_MASK            	(1 << CCM_PCCR_CSPI1_OFFSET)
+#define CCM_PCCR_CSPI2_MASK            	(1 << CCM_PCCR_CSPI2_OFFSET)
+#define CCM_PCCR_CSPI3_MASK            	(1 << CCM_PCCR_CSPI3_OFFSET)
+#define CCM_PCCR_DMA_MASK              	(1 << CCM_PCCR_DMA_OFFSET)
+#define CCM_PCCR_EMMA_MASK             	(1 << CCM_PCCR_EMMA_OFFSET)
+#define CCM_PCCR_GPIO_MASK             	(1 << CCM_PCCR_GPIO_OFFSET)
+#define CCM_PCCR_GPT1_MASK             	(1 << CCM_PCCR_GPT1_OFFSET)
+#define CCM_PCCR_GPT2_MASK             	(1 << CCM_PCCR_GPT2_OFFSET)
+#define CCM_PCCR_GPT3_MASK             	(1 << CCM_PCCR_GPT3_OFFSET)
+#define CCM_PCCR_HCLK_BROM_MASK		(1 << CCM_PCCR_HCLK_BROM_OFFSET)
+#define CCM_PCCR_HCLK_CSI_MASK         	(1 << CCM_PCCR_HCLK_CSI_OFFSET)
+#define CCM_PCCR_HCLK_DMA_MASK         	(1 << CCM_PCCR_HCLK_DMA_OFFSET)
+#define CCM_PCCR_HCLK_EMMA_MASK        	(1 << CCM_PCCR_HCLK_EMMA_OFFSET)
+#define CCM_PCCR_HCLK_LCDC_MASK        	(1 << CCM_PCCR_HCLK_LCDC_OFFSET)
+#define CCM_PCCR_HCLK_SLCDC_MASK       	(1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
+#define CCM_PCCR_HCLK_USBOTG_MASK      	(1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
+#define CCM_PCCR_I2C1_MASK             	(1 << CCM_PCCR_I2C1_OFFSET)
+#define CCM_PCCR_KPP_MASK              	(1 << CCM_PCCR_KPP_OFFSET)
+#define CCM_PCCR_LCDC_MASK             	(1 << CCM_PCCR_LCDC_OFFSET)
+#define CCM_PCCR_NFC_MASK		(1 << CCM_PCCR_NFC_OFFSET)
+#define CCM_PCCR_OWIRE_MASK            	(1 << CCM_PCCR_OWIRE_OFFSET)
+#define CCM_PCCR_PERCLK4_MASK          	(1 << CCM_PCCR_PERCLK4_OFFSET)
+#define CCM_PCCR_PWM_MASK              	(1 << CCM_PCCR_PWM_OFFSET)
+#define CCM_PCCR_RTC_MASK              	(1 << CCM_PCCR_RTC_OFFSET)
+#define CCM_PCCR_SDHC1_MASK            	(1 << CCM_PCCR_SDHC1_OFFSET)
+#define CCM_PCCR_SDHC2_MASK            	(1 << CCM_PCCR_SDHC2_OFFSET)
+#define CCM_PCCR_SLCDC_MASK            	(1 << CCM_PCCR_SLCDC_OFFSET)
+#define CCM_PCCR_SSI1_BAUD_MASK        	(1 << CCM_PCCR_SSI1_BAUD_OFFSET)
+#define CCM_PCCR_SSI1_IPG_MASK         	(1 << CCM_PCCR_SSI1_IPG_OFFSET)
+#define CCM_PCCR_SSI2_BAUD_MASK        	(1 << CCM_PCCR_SSI2_BAUD_OFFSET)
+#define CCM_PCCR_SSI2_IPG_MASK         	(1 << CCM_PCCR_SSI2_IPG_OFFSET)
+#define CCM_PCCR_UART1_MASK            	(1 << CCM_PCCR_UART1_OFFSET)
+#define CCM_PCCR_UART2_MASK            	(1 << CCM_PCCR_UART2_OFFSET)
+#define CCM_PCCR_UART3_MASK            	(1 << CCM_PCCR_UART3_OFFSET)
+#define CCM_PCCR_UART4_MASK            	(1 << CCM_PCCR_UART4_OFFSET)
+#define CCM_PCCR_USBOTG_MASK           	(1 << CCM_PCCR_USBOTG_OFFSET)
+#define CCM_PCCR_WDT_MASK              	(1 << CCM_PCCR_WDT_OFFSET)
+
 
 #define CCM_CCSR_32KSR          (1 << 15)
+
 #define CCM_CCSR_CLKMODE1       (1 << 9)
 #define CCM_CCSR_CLKMODE0       (1 << 8)
+
 #define CCM_CCSR_CLKOSEL_OFFSET 0
 #define CCM_CCSR_CLKOSEL_MASK   0x1f
 
diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c
index 2f9240b..a0f1b36 100644
--- a/arch/arm/mach-mx2/devices.c
+++ b/arch/arm/mach-mx2/devices.c
@@ -34,6 +34,10 @@
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/mmc.h>
+
+#include "devices.h"
 
 /*
  * Resource definition for the MXC IrDA
@@ -225,37 +229,215 @@
 	.resource = mxc_nand_resources,
 };
 
+/*
+ * lcdc:
+ * - i.MX1: the basic controller
+ * - i.MX21: to be checked
+ * - i.MX27: like i.MX1, with slightly variations
+ */
+static struct resource mxc_fb[] = {
+	{
+		.start = LCDC_BASE_ADDR,
+		.end   = LCDC_BASE_ADDR + 0xFFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_LCDC,
+		.end   = MXC_INT_LCDC,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+/* mxc lcd driver */
+struct platform_device mxc_fb_device = {
+	.name = "imx-fb",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_fb),
+	.resource = mxc_fb,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+	},
+};
+
+#ifdef CONFIG_MACH_MX27
+static struct resource mxc_fec_resources[] = {
+	{
+		.start	= FEC_BASE_ADDR,
+		.end	= FEC_BASE_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= MXC_INT_FEC,
+		.end	= MXC_INT_FEC,
+		.flags	= IORESOURCE_IRQ
+	},
+};
+
+struct platform_device mxc_fec_device = {
+	.name = "fec",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_fec_resources),
+	.resource = mxc_fec_resources,
+};
+#endif
+
+static struct resource mxc_i2c_1_resources[] = {
+	[0] = {
+		.start	= I2C_BASE_ADDR,
+		.end	= I2C_BASE_ADDR + 0x0fff,
+		.flags	= IORESOURCE_MEM
+	},
+	[1] = {
+		.start	= MXC_INT_I2C,
+		.end	= MXC_INT_I2C,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+struct platform_device mxc_i2c_device0 = {
+	.name = "imx-i2c",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_i2c_1_resources),
+	.resource = mxc_i2c_1_resources
+};
+
+#ifdef CONFIG_MACH_MX27
+static struct resource mxc_i2c_2_resources[] = {
+	[0] = {
+		.start	= I2C2_BASE_ADDR,
+		.end	= I2C2_BASE_ADDR + 0x0fff,
+		.flags	= IORESOURCE_MEM
+	},
+	[1] = {
+		.start	= MXC_INT_I2C2,
+		.end	= MXC_INT_I2C2,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+struct platform_device mxc_i2c_device1 = {
+	.name = "imx-i2c",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxc_i2c_2_resources),
+	.resource = mxc_i2c_2_resources
+};
+#endif
+
+static struct resource mxc_pwm_resources[] = {
+	[0] = {
+		.start	= PWM_BASE_ADDR,
+		.end	= PWM_BASE_ADDR + 0x0fff,
+		.flags	= IORESOURCE_MEM
+	},
+	[1] = {
+		.start   = MXC_INT_PWM,
+		.end     = MXC_INT_PWM,
+		.flags   = IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device mxc_pwm_device = {
+	.name = "mxc_pwm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_pwm_resources),
+	.resource = mxc_pwm_resources
+};
+
+/*
+ * Resource definition for the MXC SDHC
+ */
+static struct resource mxc_sdhc1_resources[] = {
+	[0] = {
+			.start = SDHC1_BASE_ADDR,
+			.end   = SDHC1_BASE_ADDR + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+			},
+	[1] = {
+			.start = MXC_INT_SDHC1,
+			.end   = MXC_INT_SDHC1,
+			.flags = IORESOURCE_IRQ,
+			},
+	[2] = {
+			.start  = DMA_REQ_SDHC1,
+			.end    = DMA_REQ_SDHC1,
+			.flags  = IORESOURCE_DMA
+		},
+};
+
+static u64 mxc_sdhc1_dmamask = 0xffffffffUL;
+
+struct platform_device mxc_sdhc_device0 = {
+       .name           = "mxc-mmc",
+       .id             = 0,
+       .dev            = {
+               .dma_mask = &mxc_sdhc1_dmamask,
+               .coherent_dma_mask = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(mxc_sdhc1_resources),
+       .resource       = mxc_sdhc1_resources,
+};
+
+static struct resource mxc_sdhc2_resources[] = {
+	[0] = {
+			.start = SDHC2_BASE_ADDR,
+			.end   = SDHC2_BASE_ADDR + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+			},
+	[1] = {
+			.start = MXC_INT_SDHC2,
+			.end   = MXC_INT_SDHC2,
+			.flags = IORESOURCE_IRQ,
+			},
+	[2] = {
+			.start  = DMA_REQ_SDHC2,
+			.end    = DMA_REQ_SDHC2,
+			.flags  = IORESOURCE_DMA
+		},
+};
+
+static u64 mxc_sdhc2_dmamask = 0xffffffffUL;
+
+struct platform_device mxc_sdhc_device1 = {
+       .name           = "mxc-mmc",
+       .id             = 1,
+       .dev            = {
+               .dma_mask = &mxc_sdhc2_dmamask,
+               .coherent_dma_mask = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(mxc_sdhc2_resources),
+       .resource       = mxc_sdhc2_resources,
+};
+
 /* GPIO port description */
 static struct mxc_gpio_port imx_gpio_ports[] = {
 	[0] = {
 		.chip.label = "gpio-0",
 		.irq = MXC_INT_GPIO,
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 0),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR),
 		.virtual_irq_start = MXC_GPIO_IRQ_START,
 	},
 	[1] = {
 		.chip.label = "gpio-1",
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 1),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x100),
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
 	},
 	[2] = {
 		.chip.label = "gpio-2",
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 2),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x200),
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
 	},
 	[3] = {
 		.chip.label = "gpio-3",
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 3),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x300),
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 96,
 	},
 	[4] = {
 		.chip.label = "gpio-4",
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 4),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x400),
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 128,
 	},
 	[5] = {
 		.chip.label = "gpio-5",
-		.base = (void*)(AIPI_BASE_ADDR_VIRT + 0x15000 + 0x100 * 5),
+		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x500),
 		.virtual_irq_start = MXC_GPIO_IRQ_START + 160,
 	}
 };
diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h
index 1e8cb57..049005b 100644
--- a/arch/arm/mach-mx2/devices.h
+++ b/arch/arm/mach-mx2/devices.h
@@ -1,4 +1,3 @@
-
 extern struct platform_device mxc_gpt1;
 extern struct platform_device mxc_gpt2;
 extern struct platform_device mxc_gpt3;
@@ -14,3 +13,10 @@
 extern struct platform_device mxc_uart_device5;
 extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mxc_nand_device;
+extern struct platform_device mxc_fb_device;
+extern struct platform_device mxc_fec_device;
+extern struct platform_device mxc_pwm_device;
+extern struct platform_device mxc_i2c_device0;
+extern struct platform_device mxc_i2c_device1;
+extern struct platform_device mxc_sdhc_device0;
+extern struct platform_device mxc_sdhc_device1;
diff --git a/arch/arm/mach-mx2/generic.c b/arch/arm/mach-mx2/generic.c
index dea6521..bd51dd0 100644
--- a/arch/arm/mach-mx2/generic.c
+++ b/arch/arm/mach-mx2/generic.c
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c
index 2b5c67f..4a3b097 100644
--- a/arch/arm/mach-mx2/mx27ads.c
+++ b/arch/arm/mach-mx2/mx27ads.c
@@ -31,7 +31,7 @@
 #include <asm/mach/map.h>
 #include <mach/gpio.h>
 #include <mach/imx-uart.h>
-#include <mach/iomux-mx1-mx2.h>
+#include <mach/iomux.h>
 #include <mach/board-mx27ads.h>
 
 #include "devices.h"
@@ -135,6 +135,7 @@
 {
 	mxc_gpio_release_multiple_pins(mxc_uart3_pins,
 			ARRAY_SIZE(mxc_uart3_pins));
+	return 0;
 }
 
 static int mxc_uart4_pins[] = {
@@ -179,6 +180,7 @@
 
 static struct platform_device *platform_devices[] __initdata = {
 	&mx27ads_nor_mtd_device,
+	&mxc_fec_device,
 };
 
 static int mxc_fec_pins[] = {
@@ -196,7 +198,7 @@
 	PD11_AOUT_FEC_TX_CLK,
 	PD12_AOUT_FEC_RXD0,
 	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_CLR,
+	PD14_AOUT_FEC_RX_CLK,
 	PD15_AOUT_FEC_COL,
 	PD16_AIN_FEC_TX_ER,
 	PF23_AIN_FEC_TX_EN
@@ -208,12 +210,6 @@
 			ARRAY_SIZE(mxc_fec_pins), "FEC");
 }
 
-static void gpio_fec_inactive(void)
-{
-	mxc_gpio_release_multiple_pins(mxc_fec_pins,
-			ARRAY_SIZE(mxc_fec_pins));
-}
-
 static struct imxuart_platform_data uart_pdata[] = {
 	{
 		.init = uart_mxc_port0_init,
@@ -263,11 +259,10 @@
 	if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0)
 		fref = 27000000;
 
-	mxc_clocks_init(fref);
-	mxc_timer_init("gpt_clk.0");
+	mx27_clocks_init(fref);
 }
 
-struct sys_timer mx27ads_timer = {
+static struct sys_timer mx27ads_timer = {
 	.init	= mx27ads_timer_init,
 };
 
@@ -280,7 +275,7 @@
 	},
 };
 
-void __init mx27ads_map_io(void)
+static void __init mx27ads_map_io(void)
 {
 	mxc_map_io();
 	iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc));
diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c
index dfd4156..aa4eaa6 100644
--- a/arch/arm/mach-mx2/pcm038.c
+++ b/arch/arm/mach-mx2/pcm038.c
@@ -20,11 +20,18 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/plat-ram.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/iomux-mx1-mx2.h>
+#include <mach/iomux.h>
+#ifdef CONFIG_I2C_IMX
+#include <mach/i2c.h>
+#endif
 #include <asm/mach/time.h>
 #include <mach/imx-uart.h>
 #include <mach/board-pcm038.h>
@@ -121,10 +128,10 @@
 	return 0;
 }
 
-static int mxc_uart2_pins[] = { PE10_PF_UART3_CTS,
+static int mxc_uart2_pins[] = { PE8_PF_UART3_TXD,
 				PE9_PF_UART3_RXD,
 				PE10_PF_UART3_CTS,
-				PE9_PF_UART3_RXD };
+				PE11_PF_UART3_RTS };
 
 static int uart_mxc_port2_init(struct platform_device *pdev)
 {
@@ -170,7 +177,7 @@
 	PD11_AOUT_FEC_TX_CLK,
 	PD12_AOUT_FEC_RXD0,
 	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_CLR,
+	PD14_AOUT_FEC_RX_CLK,
 	PD15_AOUT_FEC_COL,
 	PD16_AIN_FEC_TX_ER,
 	PF23_AIN_FEC_TX_EN
@@ -182,12 +189,6 @@
 			ARRAY_SIZE(mxc_fec_pins), "FEC");
 }
 
-static void gpio_fec_inactive(void)
-{
-	mxc_gpio_release_multiple_pins(mxc_fec_pins,
-			ARRAY_SIZE(mxc_fec_pins));
-}
-
 static struct mxc_nand_platform_data pcm038_nand_board_info = {
 	.width = 1,
 	.hw_ecc = 1,
@@ -196,6 +197,7 @@
 static struct platform_device *platform_devices[] __initdata = {
 	&pcm038_nor_mtd_device,
 	&mxc_w1_master_device,
+	&mxc_fec_device,
 	&pcm038_sram_mtd_device,
 };
 
@@ -208,6 +210,51 @@
 	__raw_writel(0x22220a00, CSCR_A(1));
 }
 
+#ifdef CONFIG_I2C_IMX
+static int mxc_i2c1_pins[] = {
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL
+};
+
+static int pcm038_i2c_1_init(struct device *dev)
+{
+	return mxc_gpio_setup_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins),
+			"I2C1");
+}
+
+static void pcm038_i2c_1_exit(struct device *dev)
+{
+	mxc_gpio_release_multiple_pins(mxc_i2c1_pins, ARRAY_SIZE(mxc_i2c1_pins));
+}
+
+static struct imxi2c_platform_data pcm038_i2c_1_data = {
+	.bitrate = 100000,
+	.init = pcm038_i2c_1_init,
+	.exit = pcm038_i2c_1_exit,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm038_i2c_devices[] = {
+	[0] = {
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	},
+	[1] = {
+		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		.type = "pcf8563"
+	},
+	[2] = {
+		I2C_BOARD_INFO("lm75", 0x4a),
+		.type = "lm75"
+	}
+};
+#endif
+
 static void __init pcm038_init(void)
 {
 	gpio_fec_active();
@@ -217,9 +264,17 @@
 	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
 	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
 
-	mxc_gpio_mode(PE16_AF_RTCK); /* OWIRE */
+	mxc_gpio_mode(PE16_AF_OWIRE);
 	mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info);
 
+#ifdef CONFIG_I2C_IMX
+	/* only the i2c master 1 is used on this CPU card */
+	i2c_register_board_info(1, pcm038_i2c_devices,
+				ARRAY_SIZE(pcm038_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data);
+#endif
+
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
@@ -229,11 +284,10 @@
 
 static void __init pcm038_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("gpt_clk.0");
+	mx27_clocks_init(26000000);
 }
 
-struct sys_timer pcm038_timer = {
+static struct sys_timer pcm038_timer = {
 	.init = pcm038_timer_init,
 };
 
diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c
index a560cd6..bf4e520 100644
--- a/arch/arm/mach-mx2/pcm970-baseboard.c
+++ b/arch/arm/mach-mx2/pcm970-baseboard.c
@@ -17,9 +17,138 @@
  */
 
 #include <linux/platform_device.h>
-#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
 #include <asm/mach/arch.h>
 
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/mmc.h>
+#include <mach/imxfb.h>
+#include <mach/iomux.h>
+
+#include "devices.h"
+
+static int pcm970_sdhc2_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_PORTC + 28);
+}
+
+static int pcm970_sdhc2_pins[] = {
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+};
+
+static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void *data)
+{
+	int ret;
+
+	ret = mxc_gpio_setup_multiple_pins(pcm970_sdhc2_pins,
+		ARRAY_SIZE(pcm970_sdhc2_pins), "sdhc2");
+	if(ret)
+		return ret;
+
+	ret = request_irq(IRQ_GPIOC(29), detect_irq, 0,
+				"imx-mmc-detect", data);
+	if (ret)
+		goto out_release_gpio;
+
+	set_irq_type(IRQ_GPIOC(29), IRQF_TRIGGER_FALLING);
+
+	ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro");
+	if (ret)
+		goto out_release_gpio;
+
+	mxc_gpio_mode((GPIO_PORTC | 28) | GPIO_GPIO | GPIO_IN);
+	gpio_direction_input(GPIO_PORTC + 28);
+
+	return 0;
+
+out_release_gpio:
+	mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins,
+			ARRAY_SIZE(pcm970_sdhc2_pins));
+	return ret;
+}
+
+static void pcm970_sdhc2_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOC(29), data);
+	gpio_free(GPIO_PORTC + 28);
+	mxc_gpio_release_multiple_pins(pcm970_sdhc2_pins,
+			ARRAY_SIZE(pcm970_sdhc2_pins));
+}
+
+static struct imxmmc_platform_data sdhc_pdata = {
+	.get_ro = pcm970_sdhc2_get_ro,
+	.init = pcm970_sdhc2_init,
+	.exit = pcm970_sdhc2_exit,
+};
+
+static int mxc_fb_pins[] = {
+	PA5_PF_LSCLK,	PA6_PF_LD0,	PA7_PF_LD1,	PA8_PF_LD2,
+	PA9_PF_LD3,	PA10_PF_LD4,	PA11_PF_LD5,	PA12_PF_LD6,
+	PA13_PF_LD7,	PA14_PF_LD8,	PA15_PF_LD9,	PA16_PF_LD10,
+	PA17_PF_LD11,	PA18_PF_LD12,	PA19_PF_LD13,	PA20_PF_LD14,
+	PA21_PF_LD15,	PA22_PF_LD16,	PA23_PF_LD17,	PA24_PF_REV,
+	PA25_PF_CLS,	PA26_PF_PS,	PA27_PF_SPL_SPR, PA28_PF_HSYNC,
+	PA29_PF_VSYNC,	PA30_PF_CONTRAST, PA31_PF_OE_ACD
+};
+
+static int pcm038_fb_init(struct platform_device *pdev)
+{
+	return mxc_gpio_setup_multiple_pins(mxc_fb_pins,
+			ARRAY_SIZE(mxc_fb_pins), "FB");
+}
+
+static int pcm038_fb_exit(struct platform_device *pdev)
+{
+	mxc_gpio_release_multiple_pins(mxc_fb_pins, ARRAY_SIZE(mxc_fb_pins));
+
+	return 0;
+}
+
+/*
+ * Connected is a portrait Sharp-QVGA display
+ * of type: LQ035Q7DH06
+ */
+static struct imx_fb_platform_data pcm038_fb_data = {
+	.pixclock	= 188679, /* in ps (5.3MHz) */
+	.xres		= 240,
+	.yres		= 320,
+
+	.bpp		= 16,
+	.hsync_len	= 7,
+	.left_margin	= 5,
+	.right_margin	= 16,
+
+	.vsync_len	= 1,
+	.upper_margin	= 7,
+	.lower_margin	= 9,
+	.fixed_screen_cpu = 0,
+
+	/*
+	 * - HSYNC active high
+	 * - VSYNC active high
+	 * - clk notenabled while idle
+	 * - clock not inverted
+	 * - data not inverted
+	 * - data enable low active
+	 * - enable sharp mode
+	 */
+	.pcr		= 0xFA0080C0,
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
+
+	.init = pcm038_fb_init,
+	.exit = pcm038_fb_exit,
+};
+
 /*
  * system init for baseboard usage. Will be called by pcm038 init.
  *
@@ -28,4 +157,6 @@
  */
 void __init pcm970_baseboard_init(void)
 {
+	mxc_register_device(&mxc_fb_device, &pcm038_fb_data);
+	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
 }
diff --git a/arch/arm/mach-mx2/serial.c b/arch/arm/mach-mx2/serial.c
index 16debc2..40a485c 100644
--- a/arch/arm/mach-mx2/serial.c
+++ b/arch/arm/mach-mx2/serial.c
@@ -22,6 +22,7 @@
 #include <linux/serial.h>
 #include <mach/hardware.h>
 #include <mach/imx-uart.h>
+#include "devices.h"
 
 static struct resource uart0[] = {
 	{
@@ -99,6 +100,7 @@
 	.num_resources = ARRAY_SIZE(uart3),
 };
 
+#ifdef CONFIG_MACH_MX27
 static struct resource uart4[] = {
 	{
 		.start = UART5_BASE_ADDR,
@@ -136,3 +138,4 @@
 	.resource = uart5,
 	.num_resources = ARRAY_SIZE(uart5),
 };
+#endif
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index e79659e..d623558 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -1,21 +1,40 @@
-menu "MX3 Options"
-	depends on ARCH_MX3
+if ARCH_MX3
+
+config ARCH_MX31
+	bool
+
+config ARCH_MX35
+	bool
+
+comment "MX3 platforms:"
 
 config MACH_MX31ADS
 	bool "Support MX31ADS platforms"
+	select ARCH_MX31
 	default y
 	help
 	  Include support for MX31ADS platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX31ADS_WM1133_EV1
+	bool "Support Wolfson Microelectronics 1133-EV1 module"
+	depends on MACH_MX31ADS
+	select MFD_WM8350_CONFIG_MODE_0
+	select MFD_WM8352_CONFIG_MODE_0
+	help
+	  Include support for the Wolfson Microelectronics 1133-EV1 PMU
+	  and audio module for the MX31ADS platform.
+
 config MACH_PCM037
-	bool "Support Phytec pcm037 platforms"
+	bool "Support Phytec pcm037 (i.MX31) platforms"
+	select ARCH_MX31
 	help
 	  Include support for Phytec pcm037 platform. This includes
 	  specific configurations for the board and its peripherals.
 
 config MACH_MX31LITE
 	bool "Support MX31 LITEKIT (LogicPD)"
+	select ARCH_MX31
 	default n
 	help
 	  Include support for MX31 LITEKIT platform. This includes specific
@@ -23,6 +42,7 @@
 
 config MACH_MX31_3DS
 	bool "Support MX31PDK (3DS)"
+	select ARCH_MX31
 	default n
 	help
 	  Include support for MX31PDK (3DS) platform. This includes specific
@@ -30,10 +50,18 @@
 
 config MACH_MX31MOBOARD
 	bool "Support mx31moboard platforms (EPFL Mobots group)"
+	select ARCH_MX31
 	default n
 	help
 	  Include support for mx31moboard platform. This includes specific
 	  configurations for the board and its peripherals.
 
-endmenu
+config MACH_QONG
+	bool "Support Dave/DENX QongEVB-LITE platform"
+	select ARCH_MX31
+	default n
+	help
+	  Include support for Dave/DENX QongEVB-LITE platform. This includes
+	  specific configurations for the board and its peripherals.
 
+endif
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 5a15154..272c8a9 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -4,9 +4,13 @@
 
 # Object file lists.
 
-obj-y			:= mm.o clock.o devices.o iomux.o
+obj-y				:= mm.o devices.o
+obj-$(CONFIG_ARCH_MX31)		+= clock.o iomux.o
+obj-$(CONFIG_ARCH_MX35)		+= clock-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mx31ads.o
 obj-$(CONFIG_MACH_MX31LITE)	+= mx31lite.o
 obj-$(CONFIG_MACH_PCM037)	+= pcm037.o
 obj-$(CONFIG_MACH_MX31_3DS)	+= mx31pdk.o
-obj-$(CONFIG_MACH_MX31MOBOARD)	+= mx31moboard.o
+obj-$(CONFIG_MACH_MX31MOBOARD)	+= mx31moboard.o mx31moboard-devboard.o \
+				   mx31moboard-marxbot.o
+obj-$(CONFIG_MACH_QONG)		+= qong.o
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
new file mode 100644
index 0000000..53a112d
--- /dev/null
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2009 by Sascha 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+
+#define CCM_BASE	IO_ADDRESS(CCM_BASE_ADDR)
+
+#define CCM_CCMR        0x00
+#define CCM_PDR0        0x04
+#define CCM_PDR1        0x08
+#define CCM_PDR2        0x0C
+#define CCM_PDR3        0x10
+#define CCM_PDR4        0x14
+#define CCM_RCSR        0x18
+#define CCM_MPCTL       0x1C
+#define CCM_PPCTL       0x20
+#define CCM_ACMR        0x24
+#define CCM_COSR        0x28
+#define CCM_CGR0        0x2C
+#define CCM_CGR1        0x30
+#define CCM_CGR2        0x34
+#define CCM_CGR3        0x38
+
+#ifdef HAVE_SET_RATE_SUPPORT
+static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost)
+{
+	u32 min_pre, temp_pre, old_err, err;
+
+	min_pre = (div - 1) / maxpost + 1;
+	old_err = 8;
+
+	for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+		if (div > (temp_pre * maxpost))
+			break;
+
+		if (div < (temp_pre * temp_pre))
+			continue;
+
+		err = div % temp_pre;
+
+		if (err == 0) {
+			*pre = temp_pre;
+			break;
+		}
+
+		err = temp_pre - err;
+
+		if (err < old_err) {
+			old_err = err;
+			*pre = temp_pre;
+		}
+	}
+
+	*post = (div + *pre - 1) / *pre;
+}
+
+/* get the best values for a 3-bit divider combined with a 6-bit divider */
+static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post)
+{
+	if (div >= 512) {
+		*pre = 8;
+		*post = 64;
+	} else if (div >= 64) {
+		calc_dividers(div, pre, post, 64);
+	} else if (div <= 8) {
+		*pre = div;
+		*post = 1;
+	} else {
+		*pre = 1;
+		*post = div;
+	}
+}
+
+/* get the best values for two cascaded 3-bit dividers */
+static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post)
+{
+	if (div >= 64) {
+		*pre = *post = 8;
+	} else if (div > 8) {
+		calc_dividers(div, pre, post, 8);
+	} else {
+		*pre = 1;
+		*post = div;
+	}
+}
+#endif
+
+static unsigned long get_rate_mpll(void)
+{
+	ulong mpctl = __raw_readl(CCM_BASE + CCM_MPCTL);
+
+	return mxc_decode_pll(mpctl, 24000000);
+}
+
+static unsigned long get_rate_ppll(void)
+{
+	ulong ppctl = __raw_readl(CCM_BASE + CCM_PPCTL);
+
+	return mxc_decode_pll(ppctl, 24000000);
+}
+
+struct arm_ahb_div {
+	unsigned char arm, ahb, sel;
+};
+
+static struct arm_ahb_div clk_consumer[] = {
+	{ .arm = 1, .ahb = 4, .sel = 0},
+	{ .arm = 1, .ahb = 3, .sel = 1},
+	{ .arm = 2, .ahb = 2, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 4, .ahb = 1, .sel = 0},
+	{ .arm = 1, .ahb = 5, .sel = 0},
+	{ .arm = 1, .ahb = 8, .sel = 0},
+	{ .arm = 1, .ahb = 6, .sel = 1},
+	{ .arm = 2, .ahb = 4, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 4, .ahb = 2, .sel = 0},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+};
+
+static struct arm_ahb_div clk_automotive[] = {
+	{ .arm = 1, .ahb = 3, .sel = 0},
+	{ .arm = 1, .ahb = 2, .sel = 1},
+	{ .arm = 2, .ahb = 1, .sel = 1},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+	{ .arm = 1, .ahb = 6, .sel = 0},
+	{ .arm = 1, .ahb = 4, .sel = 1},
+	{ .arm = 2, .ahb = 2, .sel = 1},
+	{ .arm = 0, .ahb = 0, .sel = 0},
+};
+
+static unsigned long get_rate_arm(void)
+{
+	unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+	struct arm_ahb_div *aad;
+	unsigned long fref = get_rate_mpll();
+
+	if (pdr0 & 1) {
+		/* consumer path */
+		aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+		if (aad->sel)
+			fref = fref * 2 / 3;
+	} else {
+		/* auto path */
+		aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+		if (aad->sel)
+			fref = fref * 3 / 4;
+	}
+	return fref / aad->arm;
+}
+
+static unsigned long get_rate_ahb(struct clk *clk)
+{
+	unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+	struct arm_ahb_div *aad;
+	unsigned long fref = get_rate_mpll();
+
+	if (pdr0 & 1)
+		/* consumer path */
+		aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+	else
+		/* auto path */
+		aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+
+	return fref / aad->ahb;
+}
+
+static unsigned long get_rate_ipg(struct clk *clk)
+{
+	return get_rate_ahb(NULL) >> 1;
+}
+
+static unsigned long get_3_3_div(unsigned long in)
+{
+	return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1);
+}
+
+static unsigned long get_rate_uart(struct clk *clk)
+{
+	unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3);
+	unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
+	unsigned long div = get_3_3_div(pdr4 >> 10);
+
+	if (pdr3 & (1 << 14))
+		return get_rate_arm() / div;
+	else
+		return get_rate_ppll() / div;
+}
+
+static unsigned long get_rate_sdhc(struct clk *clk)
+{
+	unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3);
+	unsigned long div, rate;
+
+	if (pdr3 & (1 << 6))
+		rate = get_rate_arm();
+	else
+		rate = get_rate_ppll();
+
+	switch (clk->id) {
+	default:
+	case 0:
+		div = pdr3 & 0x3f;
+		break;
+	case 1:
+		div = (pdr3 >> 8) & 0x3f;
+		break;
+	case 2:
+		div = (pdr3 >> 16) & 0x3f;
+		break;
+	}
+
+	return rate / get_3_3_div(div);
+}
+
+static unsigned long get_rate_mshc(struct clk *clk)
+{
+	unsigned long pdr1 = __raw_readl(CCM_BASE + CCM_PDR1);
+	unsigned long div1, div2, rate;
+
+	if (pdr1 & (1 << 7))
+		rate = get_rate_arm();
+	else
+		rate = get_rate_ppll();
+
+	div1 = (pdr1 >> 29) & 0x7;
+	div2 = (pdr1 >> 22) & 0x3f;
+
+	return rate / ((div1 + 1) * (div2 + 1));
+}
+
+static unsigned long get_rate_ssi(struct clk *clk)
+{
+	unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2);
+	unsigned long div1, div2, rate;
+
+	if (pdr2 & (1 << 6))
+		rate = get_rate_arm();
+	else
+		rate = get_rate_ppll();
+
+	switch (clk->id) {
+	default:
+	case 0:
+		div1 = pdr2 & 0x3f;
+		div2 = (pdr2 >> 24) & 0x7;
+		break;
+	case 1:
+		div1 = (pdr2 >> 8) & 0x3f;
+		div2 = (pdr2 >> 27) & 0x7;
+		break;
+	}
+
+	return rate / ((div1 + 1) * (div2 + 1));
+}
+
+static unsigned long get_rate_csi(struct clk *clk)
+{
+	unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2);
+	unsigned long rate;
+
+	if (pdr2 & (1 << 7))
+		rate = get_rate_arm();
+	else
+		rate = get_rate_ppll();
+
+	return rate / get_3_3_div((pdr2 >> 16) & 0x3f);
+}
+
+static unsigned long get_rate_ipg_per(struct clk *clk)
+{
+	unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+	unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
+	unsigned long div1, div2;
+
+	if (pdr0 & (1 << 26)) {
+		div1 = (pdr4 >> 19) & 0x7;
+		div2 = (pdr4 >> 16) & 0x7;
+		return get_rate_arm() / ((div1 + 1) * (div2 + 1));
+	} else {
+		div1 = (pdr0 >> 12) & 0x7;
+		return get_rate_ahb(NULL) / div1;
+	}
+}
+
+static int clk_cgr_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 3 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void clk_cgr_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(3 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr)		\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= CCM_BASE + er,	\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.set_rate	= sr,			\
+		.enable		= clk_cgr_enable,	\
+		.disable	= clk_cgr_disable,	\
+	}
+
+DEFINE_CLOCK(asrc_clk,   0, CCM_CGR0,  0, NULL, NULL);
+DEFINE_CLOCK(ata_clk,    0, CCM_CGR0,  2, get_rate_ipg, NULL);
+DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0,  4, NULL, NULL);
+DEFINE_CLOCK(can1_clk,   0, CCM_CGR0,  6, get_rate_ipg, NULL);
+DEFINE_CLOCK(can2_clk,   1, CCM_CGR0,  8, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi1_clk,  0, CCM_CGR0, 10, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi2_clk,  1, CCM_CGR0, 12, get_rate_ipg, NULL);
+DEFINE_CLOCK(ect_clk,    0, CCM_CGR0, 14, get_rate_ipg, NULL);
+DEFINE_CLOCK(edio_clk,   0, CCM_CGR0, 16, NULL, NULL);
+DEFINE_CLOCK(emi_clk,    0, CCM_CGR0, 18, get_rate_ipg, NULL);
+DEFINE_CLOCK(epit1_clk,  0, CCM_CGR0, 20, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(epit2_clk,  1, CCM_CGR0, 22, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(esai_clk,   0, CCM_CGR0, 24, NULL, NULL);
+DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL);
+DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL);
+DEFINE_CLOCK(esdhc3_clk, 2, CCM_CGR0, 30, get_rate_sdhc, NULL);
+
+DEFINE_CLOCK(fec_clk,    0, CCM_CGR1,  0, get_rate_ipg, NULL);
+DEFINE_CLOCK(gpio1_clk,  0, CCM_CGR1,  2, NULL, NULL);
+DEFINE_CLOCK(gpio2_clk,  1, CCM_CGR1,  4, NULL, NULL);
+DEFINE_CLOCK(gpio3_clk,  2, CCM_CGR1,  6, NULL, NULL);
+DEFINE_CLOCK(gpt_clk,    0, CCM_CGR1,  8, get_rate_ipg, NULL);
+DEFINE_CLOCK(i2c1_clk,   0, CCM_CGR1, 10, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(i2c2_clk,   1, CCM_CGR1, 12, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(i2c3_clk,   2, CCM_CGR1, 14, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL);
+DEFINE_CLOCK(ipu_clk,    0, CCM_CGR1, 18, NULL, NULL);
+DEFINE_CLOCK(kpp_clk,    0, CCM_CGR1, 20, get_rate_ipg, NULL);
+DEFINE_CLOCK(mlb_clk,    0, CCM_CGR1, 22, get_rate_ahb, NULL);
+DEFINE_CLOCK(mshc_clk,   0, CCM_CGR1, 24, get_rate_mshc, NULL);
+DEFINE_CLOCK(owire_clk,  0, CCM_CGR1, 26, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(pwm_clk,    0, CCM_CGR1, 28, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(rngc_clk,   0, CCM_CGR1, 30, get_rate_ipg, NULL);
+
+DEFINE_CLOCK(rtc_clk,    0, CCM_CGR2,  0, get_rate_ipg, NULL);
+DEFINE_CLOCK(rtic_clk,   0, CCM_CGR2,  2, get_rate_ahb, NULL);
+DEFINE_CLOCK(scc_clk,    0, CCM_CGR2,  4, get_rate_ipg, NULL);
+DEFINE_CLOCK(sdma_clk,   0, CCM_CGR2,  6, NULL, NULL);
+DEFINE_CLOCK(spba_clk,   0, CCM_CGR2,  8, get_rate_ipg, NULL);
+DEFINE_CLOCK(spdif_clk,  0, CCM_CGR2, 10, NULL, NULL);
+DEFINE_CLOCK(ssi1_clk,   0, CCM_CGR2, 12, get_rate_ssi, NULL);
+DEFINE_CLOCK(ssi2_clk,   1, CCM_CGR2, 14, get_rate_ssi, NULL);
+DEFINE_CLOCK(uart1_clk,  0, CCM_CGR2, 16, get_rate_uart, NULL);
+DEFINE_CLOCK(uart2_clk,  1, CCM_CGR2, 18, get_rate_uart, NULL);
+DEFINE_CLOCK(uart3_clk,  2, CCM_CGR2, 20, get_rate_uart, NULL);
+DEFINE_CLOCK(usbotg_clk, 0, CCM_CGR2, 22, NULL, NULL);
+DEFINE_CLOCK(wdog_clk,   0, CCM_CGR2, 24, NULL, NULL);
+DEFINE_CLOCK(max_clk,    0, CCM_CGR2, 26, NULL, NULL);
+DEFINE_CLOCK(admux_clk,  0, CCM_CGR2, 30, NULL, NULL);
+
+DEFINE_CLOCK(csi_clk,    0, CCM_CGR3,  0, get_rate_csi, NULL);
+DEFINE_CLOCK(iim_clk,    0, CCM_CGR3,  2, NULL, NULL);
+DEFINE_CLOCK(gpu2d_clk,  0, CCM_CGR3,  4, NULL, NULL);
+
+#define _REGISTER_CLOCK(d, n, c)	\
+	{				\
+		.dev_id = d,		\
+		.con_id = n,		\
+		.clk = &c,		\
+	},
+
+static struct clk_lookup lookups[] __initdata = {
+	_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
+	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
+	_REGISTER_CLOCK(NULL, "can", can1_clk)
+	_REGISTER_CLOCK(NULL, "can", can2_clk)
+	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK(NULL, "ect", ect_clk)
+	_REGISTER_CLOCK(NULL, "edio", edio_clk)
+	_REGISTER_CLOCK(NULL, "emi", emi_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
+	_REGISTER_CLOCK(NULL, "esai", esai_clk)
+	_REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk)
+	_REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk)
+	_REGISTER_CLOCK(NULL, "sdhc", esdhc3_clk)
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
+	_REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
+	_REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
+	_REGISTER_CLOCK("gpt.0", NULL, gpt_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
+	_REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk)
+	_REGISTER_CLOCK(NULL, "ipu", ipu_clk)
+	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+	_REGISTER_CLOCK(NULL, "mlb", mlb_clk)
+	_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
+	_REGISTER_CLOCK("mxc_w1", NULL, owire_clk)
+	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK(NULL, "rngc", rngc_clk)
+	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+	_REGISTER_CLOCK(NULL, "scc", scc_clk)
+	_REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+	_REGISTER_CLOCK(NULL, "spba", spba_clk)
+	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
+	_REGISTER_CLOCK(NULL, "ssi", ssi1_clk)
+	_REGISTER_CLOCK(NULL, "ssi", ssi2_clk)
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK(NULL, "usbotg", usbotg_clk)
+	_REGISTER_CLOCK("mxc_wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK(NULL, "max", max_clk)
+	_REGISTER_CLOCK(NULL, "admux", admux_clk)
+	_REGISTER_CLOCK(NULL, "csi", csi_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
+	_REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk)
+};
+
+int __init mx35_clocks_init()
+{
+	int i;
+	unsigned int ll = 0;
+
+	mxc_set_cpu_type(MXC_CPU_MX35);
+
+#ifdef CONFIG_DEBUG_LL_CONSOLE
+	ll = (3 << 16);
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/* Turn off all clocks except the ones we need to survive, namely:
+	 * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart
+	 */
+	__raw_writel((3 << 18), CCM_BASE + CCM_CGR0);
+	__raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
+			CCM_BASE + CCM_CGR1);
+	__raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2);
+	__raw_writel(0, CCM_BASE + CCM_CGR3);
+
+	mxc_timer_init(&gpt_clk);
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
index b1746aa..ca46f48 100644
--- a/arch/arm/mach-mx3/clock.c
+++ b/arch/arm/mach-mx3/clock.c
@@ -23,9 +23,13 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
 #include <mach/clock.h>
 #include <mach/hardware.h>
-#include <asm/div64.h>
+#include <mach/common.h>
 
 #include "crm_regs.h"
 
@@ -64,17 +68,17 @@
 }
 
 static struct clk mcu_pll_clk;
-static struct clk mcu_main_clk;
-static struct clk usb_pll_clk;
 static struct clk serial_pll_clk;
 static struct clk ipg_clk;
 static struct clk ckih_clk;
-static struct clk ahb_clk;
 
-static int _clk_enable(struct clk *clk)
+static int cgr_enable(struct clk *clk)
 {
 	u32 reg;
 
+	if (!clk->enable_reg)
+		return 0;
+
 	reg = __raw_readl(clk->enable_reg);
 	reg |= 3 << clk->enable_shift;
 	__raw_writel(reg, clk->enable_reg);
@@ -82,133 +86,69 @@
 	return 0;
 }
 
-static void _clk_disable(struct clk *clk)
+static void cgr_disable(struct clk *clk)
 {
 	u32 reg;
 
+	if (!clk->enable_reg)
+		return;
+
 	reg = __raw_readl(clk->enable_reg);
 	reg &= ~(3 << clk->enable_shift);
+
+	/* special case for EMI clock */
+	if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8)
+		reg |= (1 << clk->enable_shift);
+
 	__raw_writel(reg, clk->enable_reg);
 }
 
-static void _clk_emi_disable(struct clk *clk)
+static unsigned long pll_ref_get_rate(void)
 {
-	u32 reg;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(3 << clk->enable_shift);
-	reg |= (1 << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg;
-	signed long pd = 1;	/* Pre-divider */
-	signed long mfi;	/* Multiplication Factor (Integer part) */
-	signed long mfn;	/* Multiplication Factor (Integer part) */
-	signed long mfd;	/* Multiplication Factor (Denominator Part) */
-	signed long tmp;
-	u32 ref_freq = clk_get_rate(clk->parent);
-
-	while (((ref_freq / pd) * 10) > rate)
-		pd++;
-
-	if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
-		return -EINVAL;
-
-	/* the ref_freq/2 in the following is to round up */
-	mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
-	if (mfi < 5 || mfi > 15)
-		return -EINVAL;
-
-	/* pick a mfd value that will work
-	 * then solve for mfn */
-	mfd = ref_freq / 50000;
-
-	/*
-	 *          pll_freq * pd * mfd
-	 *   mfn = --------------------  -  (mfi * mfd)
-	 *           2 * ref_freq
-	 */
-	/* the tmp/2 is for rounding */
-	tmp = ref_freq / 10000;
-	mfn =
-	    ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
-	    (mfi * mfd);
-
-	mfn = mfn & 0x3ff;
-	pd--;
-	mfd--;
-
-	/* Change the Pll value */
-	reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
-	    (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
-	    (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
-
-	if (clk == &mcu_pll_clk)
-		__raw_writel(reg, MXC_CCM_MPCTL);
-	else if (clk == &usb_pll_clk)
-		__raw_writel(reg, MXC_CCM_UPCTL);
-	else if (clk == &serial_pll_clk)
-		__raw_writel(reg, MXC_CCM_SRPCTL);
-
-	return 0;
-}
-
-static unsigned long _clk_pll_get_rate(struct clk *clk)
-{
-	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
-	unsigned long reg, ccmr;
-	s64 temp;
+	unsigned long ccmr;
 	unsigned int prcs;
 
 	ccmr = __raw_readl(MXC_CCM_CCMR);
 	prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
 	if (prcs == 0x1)
-		ref_clk = CKIL_CLK_FREQ * 1024;
+		return CKIL_CLK_FREQ * 1024;
 	else
-		ref_clk = clk_get_rate(&ckih_clk);
-
-	if (clk == &mcu_pll_clk) {
-		if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
-			return ref_clk;
-		if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
-			return ref_clk;
-		reg = __raw_readl(MXC_CCM_MPCTL);
-	} else if (clk == &usb_pll_clk)
-		reg = __raw_readl(MXC_CCM_UPCTL);
-	else if (clk == &serial_pll_clk)
-		reg = __raw_readl(MXC_CCM_SRPCTL);
-	else {
-		BUG();
-		return 0;
-	}
-
-	pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
-	mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
-	mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
-	mfi = (mfi <= 5) ? 5 : mfi;
-	mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
-
-	if (mfn >= 0x200) {
-		mfn |= 0xFFFFFE00;
-		mfn_abs = -mfn;
-	}
-
-	ref_clk *= 2;
-	ref_clk /= pdf + 1;
-
-	temp = (u64) ref_clk * mfn_abs;
-	do_div(temp, mfd + 1);
-	if (mfn < 0)
-		temp = -temp;
-	temp = (ref_clk * mfi) + temp;
-
-	return temp;
+		return clk_get_rate(&ckih_clk);
 }
 
-static int _clk_usb_pll_enable(struct clk *clk)
+static unsigned long usb_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_UPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static unsigned long serial_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_SRPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static unsigned long mcu_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg, ccmr;
+
+	ccmr = __raw_readl(MXC_CCM_CCMR);
+
+	if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS))
+		return clk_get_rate(&ckih_clk);
+
+	reg = __raw_readl(MXC_CCM_MPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static int usb_pll_enable(struct clk *clk)
 {
 	u32 reg;
 
@@ -222,7 +162,7 @@
 	return 0;
 }
 
-static void _clk_usb_pll_disable(struct clk *clk)
+static void usb_pll_disable(struct clk *clk)
 {
 	u32 reg;
 
@@ -231,7 +171,7 @@
 	__raw_writel(reg, MXC_CCM_CCMR);
 }
 
-static int _clk_serial_pll_enable(struct clk *clk)
+static int serial_pll_enable(struct clk *clk)
 {
 	u32 reg;
 
@@ -245,7 +185,7 @@
 	return 0;
 }
 
-static void _clk_serial_pll_disable(struct clk *clk)
+static void serial_pll_disable(struct clk *clk)
 {
 	u32 reg;
 
@@ -258,7 +198,7 @@
 #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
 #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
 
-static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
+static unsigned long mcu_main_get_rate(struct clk *clk)
 {
 	u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
 
@@ -268,7 +208,7 @@
 		return clk_get_rate(&mcu_pll_clk);
 }
 
-static unsigned long _clk_hclk_get_rate(struct clk *clk)
+static unsigned long ahb_get_rate(struct clk *clk)
 {
 	unsigned long max_pdf;
 
@@ -277,7 +217,7 @@
 	return clk_get_rate(clk->parent) / (max_pdf + 1);
 }
 
-static unsigned long _clk_ipg_get_rate(struct clk *clk)
+static unsigned long ipg_get_rate(struct clk *clk)
 {
 	unsigned long ipg_pdf;
 
@@ -286,7 +226,7 @@
 	return clk_get_rate(clk->parent) / (ipg_pdf + 1);
 }
 
-static unsigned long _clk_nfc_get_rate(struct clk *clk)
+static unsigned long nfc_get_rate(struct clk *clk)
 {
 	unsigned long nfc_pdf;
 
@@ -295,7 +235,7 @@
 	return clk_get_rate(clk->parent) / (nfc_pdf + 1);
 }
 
-static unsigned long _clk_hsp_get_rate(struct clk *clk)
+static unsigned long hsp_get_rate(struct clk *clk)
 {
 	unsigned long hsp_pdf;
 
@@ -304,7 +244,7 @@
 	return clk_get_rate(clk->parent) / (hsp_pdf + 1);
 }
 
-static unsigned long _clk_usb_get_rate(struct clk *clk)
+static unsigned long usb_get_rate(struct clk *clk)
 {
 	unsigned long usb_pdf, usb_prepdf;
 
@@ -315,7 +255,7 @@
 	return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
 }
 
-static unsigned long _clk_csi_get_rate(struct clk *clk)
+static unsigned long csi_get_rate(struct clk *clk)
 {
 	u32 reg, pre, post;
 
@@ -329,7 +269,7 @@
 	return clk_get_rate(clk->parent) / (pre * post);
 }
 
-static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long csi_round_rate(struct clk *clk, unsigned long rate)
 {
 	u32 pre, post, parent = clk_get_rate(clk->parent);
 	u32 div = parent / rate;
@@ -342,7 +282,7 @@
 	return parent / (pre * post);
 }
 
-static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
+static int csi_set_rate(struct clk *clk, unsigned long rate)
 {
 	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
 
@@ -363,16 +303,7 @@
 	return 0;
 }
 
-static unsigned long _clk_per_get_rate(struct clk *clk)
-{
-	unsigned long per_pdf;
-
-	per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
-		       MXC_CCM_PDR0_PER_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (per_pdf + 1);
-}
-
-static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+static unsigned long ssi1_get_rate(struct clk *clk)
 {
 	unsigned long ssi1_pdf, ssi1_prepdf;
 
@@ -383,7 +314,7 @@
 	return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
 }
 
-static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+static unsigned long ssi2_get_rate(struct clk *clk)
 {
 	unsigned long ssi2_pdf, ssi2_prepdf;
 
@@ -394,7 +325,7 @@
 	return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
 }
 
-static unsigned long _clk_firi_get_rate(struct clk *clk)
+static unsigned long firi_get_rate(struct clk *clk)
 {
 	unsigned long firi_pdf, firi_prepdf;
 
@@ -405,7 +336,7 @@
 	return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
 }
 
-static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long firi_round_rate(struct clk *clk, unsigned long rate)
 {
 	u32 pre, post;
 	u32 parent = clk_get_rate(clk->parent);
@@ -420,7 +351,7 @@
 
 }
 
-static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
+static int firi_set_rate(struct clk *clk, unsigned long rate)
 {
 	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
 
@@ -441,12 +372,12 @@
 	return 0;
 }
 
-static unsigned long _clk_mbx_get_rate(struct clk *clk)
+static unsigned long mbx_get_rate(struct clk *clk)
 {
 	return clk_get_rate(clk->parent) / 2;
 }
 
-static unsigned long _clk_mstick1_get_rate(struct clk *clk)
+static unsigned long mstick1_get_rate(struct clk *clk)
 {
 	unsigned long msti_pdf;
 
@@ -455,7 +386,7 @@
 	return clk_get_rate(clk->parent) / (msti_pdf + 1);
 }
 
-static unsigned long _clk_mstick2_get_rate(struct clk *clk)
+static unsigned long mstick2_get_rate(struct clk *clk)
 {
 	unsigned long msti_pdf;
 
@@ -472,661 +403,185 @@
 }
 
 static struct clk ckih_clk = {
-	.name = "ckih",
 	.get_rate = clk_ckih_get_rate,
 };
 
-static unsigned long clk_ckil_get_rate(struct clk *clk)
-{
-	return CKIL_CLK_FREQ;
-}
-
-static struct clk ckil_clk = {
-	.name = "ckil",
-	.get_rate = clk_ckil_get_rate,
-};
-
 static struct clk mcu_pll_clk = {
-	.name = "mcu_pll",
 	.parent = &ckih_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = _clk_pll_get_rate,
+	.get_rate = mcu_pll_get_rate,
 };
 
 static struct clk mcu_main_clk = {
-	.name = "mcu_main_clk",
 	.parent = &mcu_pll_clk,
-	.get_rate = _clk_mcu_main_get_rate,
+	.get_rate = mcu_main_get_rate,
 };
 
 static struct clk serial_pll_clk = {
-	.name = "serial_pll",
 	.parent = &ckih_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = _clk_pll_get_rate,
-	.enable = _clk_serial_pll_enable,
-	.disable = _clk_serial_pll_disable,
+	.get_rate = serial_pll_get_rate,
+	.enable = serial_pll_enable,
+	.disable = serial_pll_disable,
 };
 
 static struct clk usb_pll_clk = {
-	.name = "usb_pll",
 	.parent = &ckih_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = _clk_pll_get_rate,
-	.enable = _clk_usb_pll_enable,
-	.disable = _clk_usb_pll_disable,
+	.get_rate = usb_pll_get_rate,
+	.enable = usb_pll_enable,
+	.disable = usb_pll_disable,
 };
 
 static struct clk ahb_clk = {
-	.name = "ahb_clk",
 	.parent = &mcu_main_clk,
-	.get_rate = _clk_hclk_get_rate,
+	.get_rate = ahb_get_rate,
 };
 
-static struct clk per_clk = {
-	.name = "per_clk",
-	.parent = &usb_pll_clk,
-	.get_rate = _clk_per_get_rate,
+#define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.enable		= cgr_enable,		\
+		.disable	= cgr_disable,		\
+		.secondary	= s,			\
+		.parent		= p,			\
+	}
+
+#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
+	static struct clk name = {				\
+		.id		= i,				\
+		.enable_reg	= er,				\
+		.enable_shift	= es,				\
+		.get_rate	= getsetround##_get_rate,	\
+		.set_rate	= getsetround##_set_rate,	\
+		.round_rate	= getsetround##_round_rate,	\
+		.enable		= cgr_enable,			\
+		.disable	= cgr_disable,			\
+		.secondary	= s,				\
+		.parent		= p,				\
+	}
+
+DEFINE_CLOCK(perclk_clk,  0, NULL,          0, NULL, NULL, &ipg_clk);
+
+DEFINE_CLOCK(sdhc1_clk,   0, MXC_CCM_CGR0,  0, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(sdhc2_clk,   1, MXC_CCM_CGR0,  2, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(gpt_clk,     0, MXC_CCM_CGR0,  4, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart2_clk,   1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(ssi1_clk,    0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(i2c1_clk,    0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c2_clk,    1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c3_clk,    2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(mpeg4_clk,   0, MXC_CCM_CGR1,  0, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1,  2, mstick1_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1,  4, mstick2_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK1(csi_clk,    0, MXC_CCM_CGR1,  6, csi, NULL, &ahb_clk);
+DEFINE_CLOCK(rtc_clk,     0, MXC_CCM_CGR1,  8, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(wdog_clk,    0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pwm_clk,     0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(usb_clk2,    0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(kpp_clk,     0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipu_clk,     0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk);
+DEFINE_CLOCK(uart3_clk,   2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart4_clk,   3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart5_clk,   4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(owire_clk,   0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(ssi2_clk,    1, MXC_CCM_CGR2,  0, ssi2_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(cspi1_clk,   0, MXC_CCM_CGR2,  2, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi2_clk,   1, MXC_CCM_CGR2,  4, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(mbx_clk,     0, MXC_CCM_CGR2,  6, mbx_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(emi_clk,     0, MXC_CCM_CGR2,  8, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(rtic_clk,    0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK1(firi_clk,   0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk);
+
+DEFINE_CLOCK(sdma_clk2,   0, NULL,          0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(usb_clk1,    0, NULL,          0, usb_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(nfc_clk,     0, NULL,          0, nfc_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(scc_clk,     0, NULL,          0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipg_clk,     0, NULL,          0, ipg_get_rate, NULL, &ahb_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] __initdata = {
+	_REGISTER_CLOCK(NULL, "emi", emi_clk)
+	_REGISTER_CLOCK(NULL, "cspi", cspi1_clk)
+	_REGISTER_CLOCK(NULL, "cspi", cspi2_clk)
+	_REGISTER_CLOCK(NULL, "cspi", cspi3_clk)
+	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+	_REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
+	_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
+	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
+	_REGISTER_CLOCK("mx3-camera.0", "csi", csi_clk)
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
+	_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
+	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
+	_REGISTER_CLOCK(NULL, "ssi", ssi1_clk)
+	_REGISTER_CLOCK(NULL, "ssi", ssi2_clk)
+	_REGISTER_CLOCK(NULL, "firi", firi_clk)
+	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+	_REGISTER_CLOCK(NULL, "rng", rng_clk)
+	_REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
+	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
+	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
+	_REGISTER_CLOCK(NULL, "scc", scc_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
+	_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
+	_REGISTER_CLOCK(NULL, "mbx", mbx_clk)
 };
 
-static struct clk perclk_clk = {
-	.name = "perclk_clk",
-	.parent = &ipg_clk,
-};
-
-static struct clk cspi_clk[] = {
-	{
-	 .name = "cspi_clk",
-	 .id = 0,
-	 .parent = &ipg_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR2,
-	 .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "cspi_clk",
-	 .id = 1,
-	 .parent = &ipg_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR2,
-	 .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "cspi_clk",
-	 .id = 2,
-	 .parent = &ipg_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk ipg_clk = {
-	.name = "ipg_clk",
-	.parent = &ahb_clk,
-	.get_rate = _clk_ipg_get_rate,
-};
-
-static struct clk emi_clk = {
-	.name = "emi_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR2,
-	.enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
-	.disable = _clk_emi_disable,
-};
-
-static struct clk gpt_clk = {
-	.name = "gpt_clk",
-	.parent = &perclk_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR0,
-	.enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk pwm_clk = {
-	.name = "pwm_clk",
-	.parent = &perclk_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR0,
-	.enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk epit_clk[] = {
-	{
-	 .name = "epit_clk",
-	 .id = 0,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "epit_clk",
-	 .id = 1,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk nfc_clk = {
-	.name = "nfc_clk",
-	.parent = &ahb_clk,
-	.get_rate = _clk_nfc_get_rate,
-};
-
-static struct clk scc_clk = {
-	.name = "scc_clk",
-	.parent = &ipg_clk,
-};
-
-static struct clk ipu_clk = {
-	.name = "ipu_clk",
-	.parent = &mcu_main_clk,
-	.get_rate = _clk_hsp_get_rate,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk kpp_clk = {
-	.name = "kpp_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk wdog_clk = {
-	.name = "wdog_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
-	.disable = _clk_disable,
-};
-static struct clk rtc_clk = {
-	.name = "rtc_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk usb_clk[] = {
-	{
-	 .name = "usb_clk",
-	 .parent = &usb_pll_clk,
-	 .get_rate = _clk_usb_get_rate,},
-	{
-	 .name = "usb_ahb_clk",
-	 .parent = &ahb_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk csi_clk = {
-	.name = "csi_clk",
-	.parent = &serial_pll_clk,
-	.get_rate = _clk_csi_get_rate,
-	.round_rate = _clk_csi_round_rate,
-	.set_rate = _clk_csi_set_rate,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk uart_clk[] = {
-	{
-	 .name = "uart_clk",
-	 .id = 0,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "uart_clk",
-	 .id = 1,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "uart_clk",
-	 .id = 2,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "uart_clk",
-	 .id = 3,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "uart_clk",
-	 .id = 4,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk i2c_clk[] = {
-	{
-	 .name = "i2c_clk",
-	 .id = 0,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "i2c_clk",
-	 .id = 1,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "i2c_clk",
-	 .id = 2,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk owire_clk = {
-	.name = "owire_clk",
-	.parent = &perclk_clk,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
-	.enable = _clk_enable,
-	.disable = _clk_disable,
-};
-
-static struct clk sdhc_clk[] = {
-	{
-	 .name = "sdhc_clk",
-	 .id = 0,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "sdhc_clk",
-	 .id = 1,
-	 .parent = &perclk_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk ssi_clk[] = {
-	{
-	 .name = "ssi_clk",
-	 .parent = &serial_pll_clk,
-	 .get_rate = _clk_ssi1_get_rate,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "ssi_clk",
-	 .id = 1,
-	 .parent = &serial_pll_clk,
-	 .get_rate = _clk_ssi2_get_rate,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR2,
-	 .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk firi_clk = {
-	.name = "firi_clk",
-	.parent = &usb_pll_clk,
-	.round_rate = _clk_firi_round_rate,
-	.set_rate = _clk_firi_set_rate,
-	.get_rate = _clk_firi_get_rate,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR2,
-	.enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk ata_clk = {
-	.name = "ata_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR0,
-	.enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk mbx_clk = {
-	.name = "mbx_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR2,
-	.enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
-	.get_rate = _clk_mbx_get_rate,
-};
-
-static struct clk vpu_clk = {
-	.name = "vpu_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR2,
-	.enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
-	.get_rate = _clk_mbx_get_rate,
-};
-
-static struct clk rtic_clk = {
-	.name = "rtic_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR2,
-	.enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk rng_clk = {
-	.name = "rng_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR0,
-	.enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk sdma_clk[] = {
-	{
-	 .name = "sdma_ahb_clk",
-	 .parent = &ahb_clk,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR0,
-	 .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "sdma_ipg_clk",
-	 .parent = &ipg_clk,}
-};
-
-static struct clk mpeg4_clk = {
-	.name = "mpeg4_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk vl2cc_clk = {
-	.name = "vl2cc_clk",
-	.parent = &ahb_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR1,
-	.enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
-	.disable = _clk_disable,
-};
-
-static struct clk mstick_clk[] = {
-	{
-	 .name = "mstick_clk",
-	 .id = 0,
-	 .parent = &usb_pll_clk,
-	 .get_rate = _clk_mstick1_get_rate,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
-	 .disable = _clk_disable,},
-	{
-	 .name = "mstick_clk",
-	 .id = 1,
-	 .parent = &usb_pll_clk,
-	 .get_rate = _clk_mstick2_get_rate,
-	 .enable = _clk_enable,
-	 .enable_reg = MXC_CCM_CGR1,
-	 .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
-	 .disable = _clk_disable,},
-};
-
-static struct clk iim_clk = {
-	.name = "iim_clk",
-	.parent = &ipg_clk,
-	.enable = _clk_enable,
-	.enable_reg = MXC_CCM_CGR0,
-	.enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
-	.disable = _clk_disable,
-};
-
-static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
-{
-	u32 div, parent = clk_get_rate(clk->parent);
-
-	div = parent / rate;
-	if (parent % rate)
-		div++;
-
-	if (div > 8)
-		div = 16;
-	else if (div > 4)
-		div = 8;
-	else if (div > 2)
-		div = 4;
-
-	return parent / div;
-}
-
-static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div, parent = clk_get_rate(clk->parent);
-
-	div = parent / rate;
-
-	if (div == 16)
-		div = 4;
-	else if (div == 8)
-		div = 3;
-	else if (div == 4)
-		div = 2;
-	else if (div == 2)
-		div = 1;
-	else if (div == 1)
-		div = 0;
-	else
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
-	reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
-	__raw_writel(reg, MXC_CCM_COSR);
-
-	return 0;
-}
-
-static unsigned long _clk_cko1_get_rate(struct clk *clk)
-{
-	u32 div;
-
-	div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
-	    MXC_CCM_COSR_CLKOUTDIV_OFFSET;
-
-	return clk_get_rate(clk->parent) / (1 << div);
-}
-
-static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
+int __init mx31_clocks_init(unsigned long fref)
 {
 	u32 reg;
+	int i;
 
-	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
-
-	if (parent == &mcu_main_clk)
-		reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &ipg_clk)
-		reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &usb_pll_clk)
-		reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == mcu_main_clk.parent)
-		reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &ahb_clk)
-		reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &serial_pll_clk)
-		reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &ckih_clk)
-		reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &emi_clk)
-		reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &ipu_clk)
-		reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &nfc_clk)
-		reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else if (parent == &uart_clk[0])
-		reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_COSR);
-
-	return 0;
-}
-
-static int _clk_cko1_enable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
-	__raw_writel(reg, MXC_CCM_COSR);
-
-	return 0;
-}
-
-static void _clk_cko1_disable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
-	__raw_writel(reg, MXC_CCM_COSR);
-}
-
-static struct clk cko1_clk = {
-	.name = "cko1_clk",
-	.get_rate = _clk_cko1_get_rate,
-	.set_rate = _clk_cko1_set_rate,
-	.round_rate = _clk_cko1_round_rate,
-	.set_parent = _clk_cko1_set_parent,
-	.enable = _clk_cko1_enable,
-	.disable = _clk_cko1_disable,
-};
-
-static struct clk *mxc_clks[] = {
-	&ckih_clk,
-	&ckil_clk,
-	&mcu_pll_clk,
-	&usb_pll_clk,
-	&serial_pll_clk,
-	&mcu_main_clk,
-	&ahb_clk,
-	&per_clk,
-	&perclk_clk,
-	&cko1_clk,
-	&emi_clk,
-	&cspi_clk[0],
-	&cspi_clk[1],
-	&cspi_clk[2],
-	&ipg_clk,
-	&gpt_clk,
-	&pwm_clk,
-	&wdog_clk,
-	&rtc_clk,
-	&epit_clk[0],
-	&epit_clk[1],
-	&nfc_clk,
-	&ipu_clk,
-	&kpp_clk,
-	&usb_clk[0],
-	&usb_clk[1],
-	&csi_clk,
-	&uart_clk[0],
-	&uart_clk[1],
-	&uart_clk[2],
-	&uart_clk[3],
-	&uart_clk[4],
-	&i2c_clk[0],
-	&i2c_clk[1],
-	&i2c_clk[2],
-	&owire_clk,
-	&sdhc_clk[0],
-	&sdhc_clk[1],
-	&ssi_clk[0],
-	&ssi_clk[1],
-	&firi_clk,
-	&ata_clk,
-	&rtic_clk,
-	&rng_clk,
-	&sdma_clk[0],
-	&sdma_clk[1],
-	&mstick_clk[0],
-	&mstick_clk[1],
-	&scc_clk,
-	&iim_clk,
-};
-
-int __init mxc_clocks_init(unsigned long fref)
-{
-	u32 reg;
-	struct clk **clkp;
+	mxc_set_cpu_type(MXC_CPU_MX31);
 
 	ckih_rate = fref;
 
-	for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
-		clk_register(*clkp);
-
-	if (cpu_is_mx31()) {
-		clk_register(&mpeg4_clk);
-		clk_register(&mbx_clk);
-	} else {
-		clk_register(&vpu_clk);
-		clk_register(&vl2cc_clk);
-	}
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
 
 	/* Turn off all possible clocks */
-	__raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
+	__raw_writel((3 << 4), MXC_CCM_CGR0);
 	__raw_writel(0, MXC_CCM_CGR1);
-
-	__raw_writel(MXC_CCM_CGR2_EMI_MASK |
-		     MXC_CCM_CGR2_IPMUX1_MASK |
-		     MXC_CCM_CGR2_IPMUX2_MASK |
-		     MXC_CCM_CGR2_MXCCLKENSEL_MASK |	/* for MX32 */
-		     MXC_CCM_CGR2_CHIKCAMPEN_MASK |	/* for MX32 */
-		     MXC_CCM_CGR2_OVRVPUBUSY_MASK |	/* for MX32 */
+	__raw_writel((3 << 8) | (3 << 14) | (3 << 16)|
 		     1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
 					   MX32, but still required to be set */
 		     MXC_CCM_CGR2);
 
-	clk_disable(&cko1_clk);
-	clk_disable(&usb_pll_clk);
+	usb_pll_disable(&usb_pll_clk);
 
 	pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
 
@@ -1143,6 +598,8 @@
 		__raw_writel(reg, MXC_CCM_PMCR1);
 	}
 
+	mxc_timer_init(&ipg_clk);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h
index 4a0e0ed..adfa362 100644
--- a/arch/arm/mach-mx3/crm_regs.h
+++ b/arch/arm/mach-mx3/crm_regs.h
@@ -91,47 +91,6 @@
 #define MXC_CCM_PDR0_MCU_PODF_OFFSET            0
 #define MXC_CCM_PDR0_MCU_PODF_MASK              0x7
 
-#define MXC_CCM_PDR0_HSP_DIV_1                  (0x0 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_2                  (0x1 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_3                  (0x2 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_4                  (0x3 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_5                  (0x4 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_6                  (0x5 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_7                  (0x6 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_8                  (0x7 << 11)
-
-#define MXC_CCM_PDR0_IPG_DIV_1                  (0x0 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_2                  (0x1 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_3                  (0x2 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_4                  (0x3 << 6)
-
-#define MXC_CCM_PDR0_MAX_DIV_1                  (0x0 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_2                  (0x1 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_3                  (0x2 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_4                  (0x3 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_5                  (0x4 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_6                  (0x5 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_7                  (0x6 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_8                  (0x7 << 3)
-
-#define MXC_CCM_PDR0_NFC_DIV_1                  (0x0 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_2                  (0x1 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_3                  (0x2 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_4                  (0x3 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_5                  (0x4 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_6                  (0x5 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_7                  (0x6 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_8                  (0x7 << 8)
-
-#define MXC_CCM_PDR0_MCU_DIV_1                  0x0
-#define MXC_CCM_PDR0_MCU_DIV_2                  0x1
-#define MXC_CCM_PDR0_MCU_DIV_3                  0x2
-#define MXC_CCM_PDR0_MCU_DIV_4                  0x3
-#define MXC_CCM_PDR0_MCU_DIV_5                  0x4
-#define MXC_CCM_PDR0_MCU_DIV_6                  0x5
-#define MXC_CCM_PDR0_MCU_DIV_7                  0x6
-#define MXC_CCM_PDR0_MCU_DIV_8                  0x7
-
 #define MXC_CCM_PDR1_USB_PRDF_OFFSET            30
 #define MXC_CCM_PDR1_USB_PRDF_MASK              (0x3 << 30)
 #define MXC_CCM_PDR1_USB_PODF_OFFSET            27
@@ -152,118 +111,6 @@
 /* Bit definitions for RCSR */
 #define MXC_CCM_RCSR_NF16B			0x80000000
 
-/* Bit definitions for both MCU, USB and SR PLL control registers */
-#define MXC_CCM_PCTL_BRM                        0x80000000
-#define MXC_CCM_PCTL_PD_OFFSET                  26
-#define MXC_CCM_PCTL_PD_MASK                    (0xF << 26)
-#define MXC_CCM_PCTL_MFD_OFFSET                 16
-#define MXC_CCM_PCTL_MFD_MASK                   (0x3FF << 16)
-#define MXC_CCM_PCTL_MFI_OFFSET                 10
-#define MXC_CCM_PCTL_MFI_MASK                   (0xF << 10)
-#define MXC_CCM_PCTL_MFN_OFFSET                 0
-#define MXC_CCM_PCTL_MFN_MASK                   0x3FF
-
-#define MXC_CCM_CGR0_SD_MMC1_OFFSET             0
-#define MXC_CCM_CGR0_SD_MMC1_MASK               (0x3 << 0)
-#define MXC_CCM_CGR0_SD_MMC2_OFFSET             2
-#define MXC_CCM_CGR0_SD_MMC2_MASK               (0x3 << 2)
-#define MXC_CCM_CGR0_GPT_OFFSET                 4
-#define MXC_CCM_CGR0_GPT_MASK                   (0x3 << 4)
-#define MXC_CCM_CGR0_EPIT1_OFFSET               6
-#define MXC_CCM_CGR0_EPIT1_MASK                 (0x3 << 6)
-#define MXC_CCM_CGR0_EPIT2_OFFSET               8
-#define MXC_CCM_CGR0_EPIT2_MASK                 (0x3 << 8)
-#define MXC_CCM_CGR0_IIM_OFFSET                 10
-#define MXC_CCM_CGR0_IIM_MASK                   (0x3 << 10)
-#define MXC_CCM_CGR0_ATA_OFFSET                 12
-#define MXC_CCM_CGR0_ATA_MASK                   (0x3 << 12)
-#define MXC_CCM_CGR0_SDMA_OFFSET                14
-#define MXC_CCM_CGR0_SDMA_MASK                  (0x3 << 14)
-#define MXC_CCM_CGR0_CSPI3_OFFSET               16
-#define MXC_CCM_CGR0_CSPI3_MASK                 (0x3 << 16)
-#define MXC_CCM_CGR0_RNG_OFFSET                 18
-#define MXC_CCM_CGR0_RNG_MASK                   (0x3 << 18)
-#define MXC_CCM_CGR0_UART1_OFFSET               20
-#define MXC_CCM_CGR0_UART1_MASK                 (0x3 << 20)
-#define MXC_CCM_CGR0_UART2_OFFSET               22
-#define MXC_CCM_CGR0_UART2_MASK                 (0x3 << 22)
-#define MXC_CCM_CGR0_SSI1_OFFSET                24
-#define MXC_CCM_CGR0_SSI1_MASK                  (0x3 << 24)
-#define MXC_CCM_CGR0_I2C1_OFFSET                26
-#define MXC_CCM_CGR0_I2C1_MASK                  (0x3 << 26)
-#define MXC_CCM_CGR0_I2C2_OFFSET                28
-#define MXC_CCM_CGR0_I2C2_MASK                  (0x3 << 28)
-#define MXC_CCM_CGR0_I2C3_OFFSET                30
-#define MXC_CCM_CGR0_I2C3_MASK                  (0x3 << 30)
-
-#define MXC_CCM_CGR1_HANTRO_OFFSET              0
-#define MXC_CCM_CGR1_HANTRO_MASK                (0x3 << 0)
-#define MXC_CCM_CGR1_MEMSTICK1_OFFSET           2
-#define MXC_CCM_CGR1_MEMSTICK1_MASK             (0x3 << 2)
-#define MXC_CCM_CGR1_MEMSTICK2_OFFSET           4
-#define MXC_CCM_CGR1_MEMSTICK2_MASK             (0x3 << 4)
-#define MXC_CCM_CGR1_CSI_OFFSET                 6
-#define MXC_CCM_CGR1_CSI_MASK                   (0x3 << 6)
-#define MXC_CCM_CGR1_RTC_OFFSET                 8
-#define MXC_CCM_CGR1_RTC_MASK                   (0x3 << 8)
-#define MXC_CCM_CGR1_WDOG_OFFSET                10
-#define MXC_CCM_CGR1_WDOG_MASK                  (0x3 << 10)
-#define MXC_CCM_CGR1_PWM_OFFSET                 12
-#define MXC_CCM_CGR1_PWM_MASK                   (0x3 << 12)
-#define MXC_CCM_CGR1_SIM_OFFSET                 14
-#define MXC_CCM_CGR1_SIM_MASK                   (0x3 << 14)
-#define MXC_CCM_CGR1_ECT_OFFSET                 16
-#define MXC_CCM_CGR1_ECT_MASK                   (0x3 << 16)
-#define MXC_CCM_CGR1_USBOTG_OFFSET              18
-#define MXC_CCM_CGR1_USBOTG_MASK                (0x3 << 18)
-#define MXC_CCM_CGR1_KPP_OFFSET                 20
-#define MXC_CCM_CGR1_KPP_MASK                   (0x3 << 20)
-#define MXC_CCM_CGR1_IPU_OFFSET                 22
-#define MXC_CCM_CGR1_IPU_MASK                   (0x3 << 22)
-#define MXC_CCM_CGR1_UART3_OFFSET               24
-#define MXC_CCM_CGR1_UART3_MASK                 (0x3 << 24)
-#define MXC_CCM_CGR1_UART4_OFFSET               26
-#define MXC_CCM_CGR1_UART4_MASK                 (0x3 << 26)
-#define MXC_CCM_CGR1_UART5_OFFSET               28
-#define MXC_CCM_CGR1_UART5_MASK                 (0x3 << 28)
-#define MXC_CCM_CGR1_OWIRE_OFFSET               30
-#define MXC_CCM_CGR1_OWIRE_MASK                 (0x3 << 30)
-
-#define MXC_CCM_CGR2_SSI2_OFFSET                0
-#define MXC_CCM_CGR2_SSI2_MASK                  (0x3 << 0)
-#define MXC_CCM_CGR2_CSPI1_OFFSET               2
-#define MXC_CCM_CGR2_CSPI1_MASK                 (0x3 << 2)
-#define MXC_CCM_CGR2_CSPI2_OFFSET               4
-#define MXC_CCM_CGR2_CSPI2_MASK                 (0x3 << 4)
-#define MXC_CCM_CGR2_GACC_OFFSET                6
-#define MXC_CCM_CGR2_GACC_MASK                  (0x3 << 6)
-#define MXC_CCM_CGR2_EMI_OFFSET                 8
-#define MXC_CCM_CGR2_EMI_MASK                   (0x3 << 8)
-#define MXC_CCM_CGR2_RTIC_OFFSET                10
-#define MXC_CCM_CGR2_RTIC_MASK                  (0x3 << 10)
-#define MXC_CCM_CGR2_FIRI_OFFSET                12
-#define MXC_CCM_CGR2_FIRI_MASK                  (0x3 << 12)
-#define MXC_CCM_CGR2_IPMUX1_OFFSET              14
-#define MXC_CCM_CGR2_IPMUX1_MASK                (0x3 << 14)
-#define MXC_CCM_CGR2_IPMUX2_OFFSET              16
-#define MXC_CCM_CGR2_IPMUX2_MASK                (0x3 << 16)
-
-/* These new CGR2 bits are added in MX32 */
-#define MXC_CCM_CGR2_APMSYSCLKSEL_OFFSET	18
-#define MXC_CCM_CGR2_APMSYSCLKSEL_MASK		(0x3 << 18)
-#define MXC_CCM_CGR2_APMSSICLKSEL_OFFSET	20
-#define MXC_CCM_CGR2_APMSSICLKSEL_MASK		(0x3 << 20)
-#define MXC_CCM_CGR2_APMPERCLKSEL_OFFSET	22
-#define MXC_CCM_CGR2_APMPERCLKSEL_MASK		(0x3 << 22)
-#define MXC_CCM_CGR2_MXCCLKENSEL_OFFSET		24
-#define MXC_CCM_CGR2_MXCCLKENSEL_MASK		(0x1 << 24)
-#define MXC_CCM_CGR2_CHIKCAMPEN_OFFSET		25
-#define MXC_CCM_CGR2_CHIKCAMPEN_MASK		(0x1 << 25)
-#define MXC_CCM_CGR2_OVRVPUBUSY_OFFSET		26
-#define MXC_CCM_CGR2_OVRVPUBUSY_MASK		(0x1 << 26)
-#define MXC_CCM_CGR2_APMENA_OFFSET		30
-#define MXC_CCM_CGR2_AOMENA_MASK		(0x1 << 30)
-
 /*
  * LTR0 register offsets
  */
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index f842880..380be0c 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -25,6 +25,8 @@
 #include <mach/irqs.h>
 #include <mach/imx-uart.h>
 
+#include "devices.h"
+
 static struct resource uart0[] = {
 	{
 		.start = UART1_BASE_ADDR,
@@ -82,6 +84,7 @@
 	.num_resources = ARRAY_SIZE(uart2),
 };
 
+#ifdef CONFIG_ARCH_MX31
 static struct resource uart3[] = {
 	{
 		.start = UART4_BASE_ADDR,
@@ -119,6 +122,7 @@
 	.resource = uart4,
 	.num_resources = ARRAY_SIZE(uart4),
 };
+#endif /* CONFIG_ARCH_MX31 */
 
 /* GPIO port description */
 static struct mxc_gpio_port imx_gpio_ports[] = {
@@ -164,8 +168,8 @@
 
 static struct resource mxc_nand_resources[] = {
 	{
-		.start	= NFC_BASE_ADDR,
-		.end	= NFC_BASE_ADDR + 0xfff,
+		.start	= 0, /* runtime dependent */
+		.end	= 0,
 		.flags	= IORESOURCE_MEM
 	}, {
 		.start	= MXC_INT_NANDFC,
@@ -180,3 +184,188 @@
 	.num_resources = ARRAY_SIZE(mxc_nand_resources),
 	.resource = mxc_nand_resources,
 };
+
+static struct resource mxc_i2c0_resources[] = {
+	{
+		.start = I2C_BASE_ADDR,
+		.end = I2C_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C,
+		.end = MXC_INT_I2C,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_i2c_device0 = {
+	.name = "imx-i2c",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_i2c0_resources),
+	.resource = mxc_i2c0_resources,
+};
+
+static struct resource mxc_i2c1_resources[] = {
+	{
+		.start = I2C2_BASE_ADDR,
+		.end = I2C2_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C2,
+		.end = MXC_INT_I2C2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_i2c_device1 = {
+	.name = "imx-i2c",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxc_i2c1_resources),
+	.resource = mxc_i2c1_resources,
+};
+
+static struct resource mxc_i2c2_resources[] = {
+	{
+		.start = I2C3_BASE_ADDR,
+		.end = I2C3_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C3,
+		.end = MXC_INT_I2C3,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_i2c_device2 = {
+	.name = "imx-i2c",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(mxc_i2c2_resources),
+	.resource = mxc_i2c2_resources,
+};
+
+#ifdef CONFIG_ARCH_MX31
+static struct resource mxcsdhc0_resources[] = {
+	{
+		.start = MMC_SDHC1_BASE_ADDR,
+		.end = MMC_SDHC1_BASE_ADDR + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_MMC_SDHC1,
+		.end = MXC_INT_MMC_SDHC1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource mxcsdhc1_resources[] = {
+	{
+		.start = MMC_SDHC2_BASE_ADDR,
+		.end = MMC_SDHC2_BASE_ADDR + SZ_16K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_MMC_SDHC2,
+		.end = MXC_INT_MMC_SDHC2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxcsdhc_device0 = {
+	.name = "mxc-mmc",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxcsdhc0_resources),
+	.resource = mxcsdhc0_resources,
+};
+
+struct platform_device mxcsdhc_device1 = {
+	.name = "mxc-mmc",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mxcsdhc1_resources),
+	.resource = mxcsdhc1_resources,
+};
+#endif /* CONFIG_ARCH_MX31 */
+
+/* i.MX31 Image Processing Unit */
+
+/* The resource order is important! */
+static struct resource mx3_ipu_rsrc[] = {
+	{
+		.start = IPU_CTRL_BASE_ADDR,
+		.end = IPU_CTRL_BASE_ADDR + 0x5F,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IPU_CTRL_BASE_ADDR + 0x88,
+		.end = IPU_CTRL_BASE_ADDR + 0xB3,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_IPU_SYN,
+		.end = MXC_INT_IPU_SYN,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = MXC_INT_IPU_ERR,
+		.end = MXC_INT_IPU_ERR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mx3_ipu = {
+	.name = "ipu-core",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(mx3_ipu_rsrc),
+	.resource = mx3_ipu_rsrc,
+};
+
+static struct resource fb_resources[] = {
+	{
+		.start	= IPU_CTRL_BASE_ADDR + 0xB4,
+		.end	= IPU_CTRL_BASE_ADDR + 0x1BF,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device mx3_fb = {
+	.name		= "mx3_sdc_fb",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(fb_resources),
+	.resource	= fb_resources,
+	.dev		= {
+		.coherent_dma_mask = 0xffffffff,
+       },
+};
+
+#ifdef CONFIG_ARCH_MX35
+static struct resource mxc_fec_resources[] = {
+	{
+		.start	= MXC_FEC_BASE_ADDR,
+		.end	= MXC_FEC_BASE_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= MXC_INT_FEC,
+		.end	= MXC_INT_FEC,
+		.flags	= IORESOURCE_IRQ
+	},
+};
+
+struct platform_device mxc_fec_device = {
+	.name = "fec",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_fec_resources),
+	.resource = mxc_fec_resources,
+};
+#endif
+
+static int mx3_devices_init(void)
+{
+	if (cpu_is_mx31()) {
+		mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR;
+		mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff;
+	}
+	if (cpu_is_mx35()) {
+		mxc_nand_resources[0].start = MX35_NFC_BASE_ADDR;
+		mxc_nand_resources[0].end = MX35_NFC_BASE_ADDR + 0xfff;
+	}
+
+	return 0;
+}
+
+subsys_initcall(mx3_devices_init);
diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h
index 9949ef4..88c04b2 100644
--- a/arch/arm/mach-mx3/devices.h
+++ b/arch/arm/mach-mx3/devices.h
@@ -6,3 +6,11 @@
 extern struct platform_device mxc_uart_device4;
 extern struct platform_device mxc_w1_master_device;
 extern struct platform_device mxc_nand_device;
+extern struct platform_device mxc_i2c_device0;
+extern struct platform_device mxc_i2c_device1;
+extern struct platform_device mxc_i2c_device2;
+extern struct platform_device mx3_ipu;
+extern struct platform_device mx3_fb;
+extern struct platform_device mxc_fec_device;
+extern struct platform_device mxcsdhc_device0;
+extern struct platform_device mxcsdhc_device1;
diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c
index 7a5088b..40ffc5a 100644
--- a/arch/arm/mach-mx3/iomux.c
+++ b/arch/arm/mach-mx3/iomux.c
@@ -1,6 +1,7 @@
 /*
  * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -21,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/kernel.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 #include <mach/iomux-mx3.h>
@@ -38,6 +40,8 @@
 static DEFINE_SPINLOCK(gpio_mux_lock);
 
 #define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
+
+unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
 /*
  * set the mode for a IOMUX pin.
  */
@@ -50,9 +54,6 @@
 	field = pin_mode & 0x3;
 	mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
 
-	pr_debug("%s: reg offset = 0x%x field = %d mode = 0x%02x\n",
-			__func__, (pin_mode & IOMUX_REG_MASK), field, mode);
-
 	spin_lock(&gpio_mux_lock);
 
 	l = __raw_readl(reg);
@@ -93,6 +94,86 @@
 EXPORT_SYMBOL(mxc_iomux_set_pad);
 
 /*
+ * setups a single pin:
+ * 	- reserves the pin so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
+ */
+int mxc_iomux_setup_pin(const unsigned int pin, const char *label)
+{
+	unsigned pad = pin & IOMUX_PADNUM_MASK;
+	unsigned gpio;
+
+	if (pad >= (PIN_MAX + 1)) {
+		printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
+			pad, label ? label : "?");
+		return -EINVAL;
+	}
+
+	if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
+		printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
+			pad, label ? label : "?");
+		return -EINVAL;
+	}
+	mxc_iomux_mode(pin);
+
+	/* if we have a gpio, we can allocate it */
+	gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
+	if (gpio < (GPIO_PORT_MAX + 1) * 32)
+		if (gpio_request(gpio, label))
+			return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_setup_pin);
+
+int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+		const char *label)
+{
+	unsigned int *p = pin_list;
+	int i;
+	int ret = -EINVAL;
+
+	for (i = 0; i < count; i++) {
+		if (mxc_iomux_setup_pin(*p, label))
+			goto setup_error;
+		p++;
+	}
+	return 0;
+
+setup_error:
+	mxc_iomux_release_multiple_pins(pin_list, i);
+	return ret;
+}
+EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
+
+void mxc_iomux_release_pin(const unsigned int pin)
+{
+	unsigned pad = pin & IOMUX_PADNUM_MASK;
+	unsigned gpio;
+
+	if (pad < (PIN_MAX + 1))
+		clear_bit(pad, mxc_pin_alloc_map);
+
+	gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
+	if (gpio < (GPIO_PORT_MAX + 1) * 32)
+		gpio_free(gpio);
+}
+EXPORT_SYMBOL(mxc_iomux_release_pin);
+
+void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+{
+	unsigned int *p = pin_list;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		mxc_iomux_release_pin(*p);
+		p++;
+	}
+}
+EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
+
+/*
  * This function enables/disables the general purpose function for a particular
  * signal.
  */
@@ -111,4 +192,3 @@
 	spin_unlock(&gpio_mux_lock);
 }
 EXPORT_SYMBOL(mxc_iomux_set_gpr);
-
diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index 0589b5c..9e1459c 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -22,10 +22,14 @@
 
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <mach/hardware.h>
+#include <linux/err.h>
+
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <asm/hardware/cache-l2x0.h>
+
 #include <mach/common.h>
+#include <mach/hardware.h>
 
 /*!
  * @file mm.c
@@ -50,6 +54,16 @@
 		.pfn		= __phys_to_pfn(AVIC_BASE_ADDR),
 		.length		= AVIC_SIZE,
 		.type		= MT_DEVICE_NONSHARED
+	}, {
+		.virtual	= AIPS1_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
+		.length		= AIPS1_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	}, {
+		.virtual	= AIPS2_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
+		.length		= AIPS2_SIZE,
+		.type		= MT_DEVICE_NONSHARED
 	},
 };
 
@@ -62,3 +76,24 @@
 {
 	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
+
+#ifdef CONFIG_CACHE_L2X0
+static int mxc_init_l2x0(void)
+{
+	void __iomem *l2x0_base;
+
+	l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
+	if (IS_ERR(l2x0_base)) {
+		printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+				PTR_ERR(l2x0_base));
+		return 0;
+	}
+
+	l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+
+	return 0;
+}
+
+arch_initcall(mxc_init_l2x0);
+#endif
+
diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c
index f902a7c..83e5e8e 100644
--- a/arch/arm/mach-mx3/mx31ads.c
+++ b/arch/arm/mach-mx3/mx31ads.c
@@ -22,6 +22,8 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
 #include <linux/irq.h>
 
 #include <mach/hardware.h>
@@ -35,6 +37,12 @@
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
 
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
+
 #include "devices.h"
 
 /*!
@@ -94,13 +102,16 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
+static int uart_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
+};
+
 static inline void mxc_init_imx_uart(void)
 {
-	mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
-	mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
-	mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
-	mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
 }
 #else /* !SERIAL_IMX */
@@ -176,7 +187,7 @@
 	/*
 	 * Configure INT line as GPIO input
 	 */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO));
+	mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
 
 	/* disable the interrupt and clear the status */
 	__raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
@@ -191,26 +202,301 @@
 	set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
 }
 
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+/* This section defines setup for the Wolfson Microelectronics
+ * 1133-EV1 PMU/audio board.  When other PMU boards are supported the
+ * regulator definitions may be shared with them, but for now they can
+ * only be used with this board so would generate warnings about
+ * unused statics and some of the configuration is specific to this
+ * module.
+ */
+
+/* CPU */
+static struct regulator_consumer_supply sw1a_consumers[] = {
+	{
+		.supply = "cpu_vcc",
+	}
+};
+
+static struct regulator_init_data sw1a_data = {
+	.constraints = {
+		.name = "SW1A",
+		.min_uV = 1275000,
+		.max_uV = 1600000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_FAST,
+		.state_mem = {
+			 .uV = 1400000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sw1a_consumers),
+	.consumer_supplies = sw1a_consumers,
+};
+
+/* System IO - High */
+static struct regulator_init_data viohi_data = {
+	.constraints = {
+		.name = "VIOHO",
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.state_mem = {
+			 .uV = 2800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* System IO - Low */
+static struct regulator_init_data violo_data = {
+	.constraints = {
+		.name = "VIOLO",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* DDR RAM */
+static struct regulator_init_data sw2a_data = {
+	.constraints = {
+		.name = "SW2A",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.state_disk = {
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 0,
+		 },
+		.always_on = 1,
+		.boot_on = 1,
+		.initial_state = PM_SUSPEND_MEM,
+	},
+};
+
+static struct regulator_init_data ldo1_data = {
+	.constraints = {
+		.name = "VCAM/VMMC1/VMMC2",
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+	},
+};
+
+static struct regulator_consumer_supply ldo2_consumers[] = {
+	{
+		.supply = "AVDD",
+	},
+	{
+		.supply = "HPVDD",
+	},
+};
+
+/* CODEC and SIM */
+static struct regulator_init_data ldo2_data = {
+	.constraints = {
+		.name = "VESIM/VSIM/AVDD",
+		.min_uV = 3300000,
+		.max_uV = 3300000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
+	.consumer_supplies = ldo2_consumers,
+};
+
+/* General */
+static struct regulator_init_data vdig_data = {
+	.constraints = {
+		.name = "VDIG",
+		.min_uV = 1500000,
+		.max_uV = 1500000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* Tranceivers */
+static struct regulator_init_data ldo4_data = {
+	.constraints = {
+		.name = "VRF1/CVDD_2.775",
+		.min_uV = 2500000,
+		.max_uV = 2500000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+static struct wm8350_led_platform_data wm8350_led_data = {
+	.name            = "wm8350:white",
+	.default_trigger = "heartbeat",
+	.max_uA          = 27899,
+};
+
+static struct wm8350_audio_platform_data imx32ads_wm8350_setup = {
+	.vmid_discharge_msecs = 1000,
+	.drain_msecs = 30,
+	.cap_discharge_msecs = 700,
+	.vmid_charge_msecs = 700,
+	.vmid_s_curve = WM8350_S_CURVE_SLOW,
+	.dis_out4 = WM8350_DISCHARGE_SLOW,
+	.dis_out3 = WM8350_DISCHARGE_SLOW,
+	.dis_out2 = WM8350_DISCHARGE_SLOW,
+	.dis_out1 = WM8350_DISCHARGE_SLOW,
+	.vroi_out4 = WM8350_TIE_OFF_500R,
+	.vroi_out3 = WM8350_TIE_OFF_500R,
+	.vroi_out2 = WM8350_TIE_OFF_500R,
+	.vroi_out1 = WM8350_TIE_OFF_500R,
+	.vroi_enable = 0,
+	.codec_current_on = WM8350_CODEC_ISEL_1_0,
+	.codec_current_standby = WM8350_CODEC_ISEL_0_5,
+	.codec_current_charge = WM8350_CODEC_ISEL_1_5,
+};
+
+static int mx31_wm8350_init(struct wm8350 *wm8350)
+{
+	int i;
+
+	wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_ON);
+
+	wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_ON);
+
+	wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	/* Fix up for our own supplies. */
+	for (i = 0; i < ARRAY_SIZE(ldo2_consumers); i++)
+		ldo2_consumers[i].dev = wm8350->dev;
+
+	wm8350_register_regulator(wm8350, WM8350_DCDC_1, &sw1a_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_3, &viohi_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_4, &violo_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_6, &sw2a_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_1, &ldo1_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_2, &ldo2_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_3, &vdig_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_4, &ldo4_data);
+
+	/* LEDs */
+	wm8350_dcdc_set_slot(wm8350, WM8350_DCDC_5, 1, 1,
+			     WM8350_DC5_ERRACT_SHUTDOWN_CONV);
+	wm8350_isink_set_flash(wm8350, WM8350_ISINK_A,
+			       WM8350_ISINK_FLASH_DISABLE,
+			       WM8350_ISINK_FLASH_TRIG_BIT,
+			       WM8350_ISINK_FLASH_DUR_32MS,
+			       WM8350_ISINK_FLASH_ON_INSTANT,
+			       WM8350_ISINK_FLASH_OFF_INSTANT,
+			       WM8350_ISINK_FLASH_MODE_EN);
+	wm8350_dcdc25_set_mode(wm8350, WM8350_DCDC_5,
+			       WM8350_ISINK_MODE_BOOST,
+			       WM8350_ISINK_ILIM_NORMAL,
+			       WM8350_DC5_RMP_20V,
+			       WM8350_DC5_FBSRC_ISINKA);
+	wm8350_register_led(wm8350, 0, WM8350_DCDC_5, WM8350_ISINK_A,
+			    &wm8350_led_data);
+
+	wm8350->codec.platform_data = &imx32ads_wm8350_setup;
+
+	return 0;
+}
+
+static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
+	.init = mx31_wm8350_init,
+};
+#endif
+
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+	{
+		I2C_BOARD_INFO("wm8350", 0x1a),
+		.platform_data = &mx31_wm8350_pdata,
+		.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+	},
+#endif
+};
+
+static void mxc_init_i2c(void)
+{
+	i2c_register_board_info(1, mx31ads_i2c1_devices,
+				ARRAY_SIZE(mx31ads_i2c1_devices));
+
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1));
+
+	mxc_register_device(&mxc_i2c_device1, NULL);
+}
+#else
+static void mxc_init_i2c(void)
+{
+}
+#endif
+
 /*!
  * This structure defines static mappings for the i.MX31ADS board.
  */
 static struct map_desc mx31ads_io_desc[] __initdata = {
 	{
-		.virtual	= AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length		= AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
 		.virtual	= SPBA0_BASE_ADDR_VIRT,
 		.pfn		= __phys_to_pfn(SPBA0_BASE_ADDR),
 		.length		= SPBA0_SIZE,
 		.type		= MT_DEVICE_NONSHARED
 	}, {
-		.virtual	= AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length		= AIPS2_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
 		.virtual	= CS4_BASE_ADDR_VIRT,
 		.pfn		= __phys_to_pfn(CS4_BASE_ADDR),
 		.length		= CS4_SIZE / 2,
@@ -221,13 +507,13 @@
 /*!
  * Set up static virtual mappings.
  */
-void __init mx31ads_map_io(void)
+static void __init mx31ads_map_io(void)
 {
 	mxc_map_io();
 	iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
 }
 
-void __init mx31ads_init_irq(void)
+static void __init mx31ads_init_irq(void)
 {
 	mxc_init_irq();
 	mx31ads_init_expio();
@@ -240,15 +526,15 @@
 {
 	mxc_init_extuart();
 	mxc_init_imx_uart();
+	mxc_init_i2c();
 }
 
 static void __init mx31ads_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("ipg_clk.0");
+	mx31_clocks_init(26000000);
 }
 
-struct sys_timer mx31ads_timer = {
+static struct sys_timer mx31ads_timer = {
 	.init	= mx31ads_timer_init,
 };
 
diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c
index c434400..894d98c 100644
--- a/arch/arm/mach-mx3/mx31lite.c
+++ b/arch/arm/mach-mx3/mx31lite.c
@@ -42,21 +42,11 @@
  */
 static struct map_desc mx31lite_io_desc[] __initdata = {
 	{
-		.virtual = AIPS1_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length = AIPS1_SIZE,
-		.type = MT_DEVICE_NONSHARED
-	}, {
 		.virtual = SPBA0_BASE_ADDR_VIRT,
 		.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
 		.length = SPBA0_SIZE,
 		.type = MT_DEVICE_NONSHARED
 	}, {
-		.virtual = AIPS2_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length = AIPS2_SIZE,
-		.type = MT_DEVICE_NONSHARED
-	}, {
 		.virtual = CS4_BASE_ADDR_VIRT,
 		.pfn = __phys_to_pfn(CS4_BASE_ADDR),
 		.length = CS4_SIZE,
@@ -82,8 +72,7 @@
 
 static void __init mx31lite_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("ipg_clk.0");
+	mx31_clocks_init(26000000);
 }
 
 struct sys_timer mx31lite_timer = {
diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c
new file mode 100644
index 0000000..d080b4a
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31moboard-devboard.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#include "devices.h"
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mxc_uart1_pins[] = {
+	MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2,
+};
+
+/*
+ * system init for baseboard usage. Will be called by mx31moboard init.
+ */
+void __init mx31moboard_devboard_init(void)
+{
+	printk(KERN_INFO "Initializing mx31devboard peripherals\n");
+	mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1");
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+}
diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c
new file mode 100644
index 0000000..9ef9566
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#include "devices.h"
+
+/*
+ * system init for baseboard usage. Will be called by mx31moboard init.
+ */
+void __init mx31moboard_marxbot_init(void)
+{
+	printk(KERN_INFO "Initializing mx31marxbot peripherals\n");
+}
diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c
index c29098a..34c2a1b 100644
--- a/arch/arm/mach-mx3/mx31moboard.c
+++ b/arch/arm/mach-mx3/mx31moboard.c
@@ -32,6 +32,7 @@
 #include <mach/common.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
+#include <mach/board-mx31moboard.h>
 
 #include "devices.h"
 
@@ -63,6 +64,18 @@
 	&mx31moboard_flash,
 };
 
+static int mxc_uart0_pins[] = {
+	MX31_PIN_CTS1__CTS1, MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
+};
+static int mxc_uart4_pins[] = {
+	MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
+	MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
+};
+
+static int mx31moboard_baseboard;
+core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
+
 /*
  * Board specific initialization.
  */
@@ -70,58 +83,29 @@
 {
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
-	mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
-	mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
-	mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+	mxc_iomux_setup_multiple_pins(mxc_uart0_pins, ARRAY_SIZE(mxc_uart0_pins), "uart0");
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
 
-	mxc_iomux_mode(MX31_PIN_CTS2__CTS2);
-	mxc_iomux_mode(MX31_PIN_RTS2__RTS2);
-	mxc_iomux_mode(MX31_PIN_TXD2__TXD2);
-	mxc_iomux_mode(MX31_PIN_RXD2__RXD2);
-
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-
-	mxc_iomux_mode(MX31_PIN_PC_RST__CTS5);
-	mxc_iomux_mode(MX31_PIN_PC_VS2__RTS5);
-	mxc_iomux_mode(MX31_PIN_PC_BVD2__TXD5);
-	mxc_iomux_mode(MX31_PIN_PC_BVD1__RXD5);
-
+	mxc_iomux_setup_multiple_pins(mxc_uart4_pins, ARRAY_SIZE(mxc_uart4_pins), "uart4");
 	mxc_register_device(&mxc_uart_device4, &uart_pdata);
-}
 
-/*
- * This structure defines static mappings for the mx31moboard.
- */
-static struct map_desc mx31moboard_io_desc[] __initdata = {
-	{
-		.virtual	= AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length		= AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length		= AIPS2_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	},
-};
-
-/*
- * Set up static virtual mappings.
- */
-void __init mx31moboard_map_io(void)
-{
-	mxc_map_io();
-	iotable_init(mx31moboard_io_desc, ARRAY_SIZE(mx31moboard_io_desc));
+	switch (mx31moboard_baseboard) {
+	case MX31NOBOARD:
+		break;
+	case MX31DEVBOARD:
+		mx31moboard_devboard_init();
+		break;
+	case MX31MARXBOT:
+		mx31moboard_marxbot_init();
+		break;
+	default:
+		printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n", mx31moboard_baseboard);
+	}
 }
 
 static void __init mx31moboard_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("ipg_clk.0");
+	mx31_clocks_init(26000000);
 }
 
 struct sys_timer mx31moboard_timer = {
@@ -133,7 +117,7 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31moboard_map_io,
+	.map_io         = mxc_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &mx31moboard_timer,
diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c
index d464d06..bc63f17 100644
--- a/arch/arm/mach-mx3/mx31pdk.c
+++ b/arch/arm/mach-mx3/mx31pdk.c
@@ -45,40 +45,17 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static inline void mxc_init_imx_uart(void)
-{
-	mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
-	mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
-	mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
-	mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-}
-
-/*!
- * This structure defines static mappings for the i.MX31PDK board.
- */
-static struct map_desc mx31pdk_io_desc[] __initdata = {
-	{
-		.virtual	= AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length		= AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length		= AIPS2_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	},
+static int uart_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
 };
 
-/*!
- * Set up static virtual mappings.
- */
-static void __init mx31pdk_map_io(void)
+static inline void mxc_init_imx_uart(void)
 {
-	mxc_map_io();
-	iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
+	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
 }
 
 /*!
@@ -91,8 +68,7 @@
 
 static void __init mx31pdk_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("ipg_clk.0");
+	mx31_clocks_init(26000000);
 }
 
 static struct sys_timer mx31pdk_timer = {
@@ -108,7 +84,7 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31pdk_map_io,
+	.map_io         = mxc_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &mx31pdk_timer,
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index 8cea825..5fce022 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -26,6 +26,8 @@
 #include <linux/gpio.h>
 #include <linux/smc911x.h>
 #include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -37,6 +39,10 @@
 #include <mach/iomux-mx3.h>
 #include <mach/board-pcm037.h>
 #include <mach/mxc_nand.h>
+#include <mach/mmc.h>
+#ifdef CONFIG_I2C_IMX
+#include <mach/i2c.h>
+#endif
 
 #include "devices.h"
 
@@ -117,12 +123,90 @@
 	.hw_ecc = 1,
 };
 
+#ifdef CONFIG_I2C_IMX
+static int i2c_1_pins[] = {
+	MX31_PIN_CSPI2_MOSI__SCL,
+	MX31_PIN_CSPI2_MISO__SDA,
+};
+
+static int pcm037_i2c_1_init(struct device *dev)
+{
+	return mxc_iomux_setup_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins),
+			"i2c-1");
+}
+
+static void pcm037_i2c_1_exit(struct device *dev)
+{
+	mxc_iomux_release_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins));
+}
+
+static struct imxi2c_platform_data pcm037_i2c_1_data = {
+	.bitrate = 100000,
+	.init = pcm037_i2c_1_init,
+	.exit = pcm037_i2c_1_exit,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm037_i2c_devices[] = {
+       {
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		.type = "pcf8563",
+	}
+};
+#endif
+
+static int sdhc1_pins[] = {
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+};
+
+static int pcm970_sdhc1_init(struct device *dev, irq_handler_t h, void *data)
+{
+	return mxc_iomux_setup_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins),
+				"sdhc-1");
+}
+
+static void pcm970_sdhc1_exit(struct device *dev, void *data)
+{
+	mxc_iomux_release_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins));
+}
+
+/* No card and rw detection at the moment */
+static struct imxmmc_platform_data sdhc_pdata = {
+	.init = pcm970_sdhc1_init,
+	.exit = pcm970_sdhc1_exit,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&pcm037_flash,
 	&pcm037_eth,
 	&pcm037_sram_device,
 };
 
+static int uart0_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
+};
+
+static int uart2_pins[] = {
+	MX31_PIN_CSPI3_MOSI__RXD3,
+	MX31_PIN_CSPI3_MISO__TXD3
+};
+
 /*
  * Board specific initialization.
  */
@@ -130,59 +214,33 @@
 {
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 
-	mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
-	mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
-	mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
-	mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+	mxc_iomux_setup_multiple_pins(uart0_pins, ARRAY_SIZE(uart0_pins), "uart-0");
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
 
-	mxc_iomux_mode(MX31_PIN_CSPI3_MOSI__RXD3);
-	mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3);
-
+	mxc_iomux_setup_multiple_pins(uart2_pins, ARRAY_SIZE(uart2_pins), "uart-2");
 	mxc_register_device(&mxc_uart_device2, &uart_pdata);
 
-	mxc_iomux_mode(MX31_PIN_BATT_LINE__OWIRE);
+	mxc_iomux_setup_pin(MX31_PIN_BATT_LINE__OWIRE, "batt-0wire");
 	mxc_register_device(&mxc_w1_master_device, NULL);
 
 	/* SMSC9215 IRQ pin */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO));
-	if (!gpio_request(MX31_PIN_GPIO3_1, "pcm037-eth"))
+	if (!mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
+				"pcm037-eth"))
 		gpio_direction_input(MX31_PIN_GPIO3_1);
 
+#ifdef CONFIG_I2C_IMX
+	i2c_register_board_info(1, pcm037_i2c_devices,
+			ARRAY_SIZE(pcm037_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
+#endif
 	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
-}
-
-/*
- * This structure defines static mappings for the pcm037 board.
- */
-static struct map_desc pcm037_io_desc[] __initdata = {
-	{
-		.virtual	= AIPS1_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
-		.length		= AIPS1_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	}, {
-		.virtual	= AIPS2_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
-		.length		= AIPS2_SIZE,
-		.type		= MT_DEVICE_NONSHARED
-	},
-};
-
-/*
- * Set up static virtual mappings.
- */
-void __init pcm037_map_io(void)
-{
-	mxc_map_io();
-	iotable_init(pcm037_io_desc, ARRAY_SIZE(pcm037_io_desc));
+	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
 }
 
 static void __init pcm037_timer_init(void)
 {
-	mxc_clocks_init(26000000);
-	mxc_timer_init("ipg_clk.0");
+	mx31_clocks_init(26000000);
 }
 
 struct sys_timer pcm037_timer = {
@@ -194,7 +252,7 @@
 	.phys_io	= AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
 	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = pcm037_map_io,
+	.map_io         = mxc_map_io,
 	.init_irq       = mxc_init_irq,
 	.init_machine   = mxc_board_init,
 	.timer          = &pcm037_timer,
diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c
new file mode 100644
index 0000000..6c4283c
--- /dev/null
+++ b/arch/arm/mach-mx3/qong.c
@@ -0,0 +1,312 @@
+/*
+ *  Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/nand.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <mach/board-qong.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include "devices.h"
+
+/* FPGA defines */
+#define QONG_FPGA_VERSION(major, minor, rev)	\
+	(((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF))
+
+#define QONG_FPGA_BASEADDR 		CS1_BASE_ADDR
+#define QONG_FPGA_PERIPH_SIZE 		(1 << 24)
+
+#define QONG_FPGA_CTRL_BASEADDR		QONG_FPGA_BASEADDR
+#define QONG_FPGA_CTRL_SIZE 		0x10
+/* FPGA control registers */
+#define QONG_FPGA_CTRL_VERSION		0x00
+
+#define QONG_DNET_ID		1
+#define QONG_DNET_BASEADDR	\
+	(QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
+#define QONG_DNET_SIZE 		0x00001000
+
+#define QONG_FPGA_IRQ		IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
+
+/*
+ * This file contains the board-specific initialization routines.
+ */
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int uart_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins),
+			"uart-0");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+}
+
+static struct resource dnet_resources[] = {
+	[0] = {
+		.name	= "dnet-memory",
+		.start	= QONG_DNET_BASEADDR,
+		.end	= QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= QONG_FPGA_IRQ,
+		.end	= QONG_FPGA_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dnet_device = {
+	.name			= "dnet",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(dnet_resources),
+	.resource		= dnet_resources,
+};
+
+static int __init qong_init_dnet(void)
+{
+	int ret;
+
+	ret = platform_device_register(&dnet_device);
+	return ret;
+}
+
+/* MTD NOR flash */
+
+static struct physmap_flash_data qong_flash_data = {
+	.width = 2,
+};
+
+static struct resource qong_flash_resource = {
+	.start = CS0_BASE_ADDR,
+	.end = CS0_BASE_ADDR + QONG_NOR_SIZE - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &qong_flash_data,
+		},
+	.resource = &qong_flash_resource,
+	.num_resources = 1,
+};
+
+static void qong_init_nor_mtd(void)
+{
+	(void)platform_device_register(&qong_nor_mtd_device);
+}
+
+/*
+ * Hardware specific access to control-lines
+ */
+static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24));
+	else
+		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23));
+}
+
+/*
+ * Read the Device Ready pin.
+ */
+static int qong_nand_device_ready(struct mtd_info *mtd)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+}
+
+static void qong_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	if (chip >= 0)
+		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+	else
+		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
+}
+
+static struct platform_nand_data qong_nand_data = {
+	.chip = {
+		.chip_delay		= 20,
+		.options		= 0,
+	},
+	.ctrl = {
+		.cmd_ctrl 		= qong_nand_cmd_ctrl,
+		.dev_ready		= qong_nand_device_ready,
+		.select_chip		= qong_nand_select_chip,
+	}
+};
+
+static struct resource qong_nand_resource = {
+	.start  	= CS3_BASE_ADDR,
+	.end    	= CS3_BASE_ADDR + SZ_32M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nand_device = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &qong_nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &qong_nand_resource,
+};
+
+static void __init qong_init_nand_mtd(void)
+{
+	/* init CS */
+	__raw_writel(0x00004f00, CSCR_U(3));
+	__raw_writel(0x20013b31, CSCR_L(3));
+	__raw_writel(0x00020800, CSCR_A(3));
+	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
+
+	/* enable pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable"))
+		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+
+	/* ready/busy pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy"))
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+
+	/* write protect pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp"))
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B));
+
+	platform_device_register(&qong_nand_device);
+}
+
+static void __init qong_init_fpga(void)
+{
+	void __iomem *regs;
+	u32 fpga_ver;
+
+	regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE);
+	if (!regs) {
+		printk(KERN_ERR "%s: failed to map registers, aborting.\n",
+				__func__);
+		return;
+	}
+
+	fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION);
+	iounmap(regs);
+	printk(KERN_INFO "Qong FPGA version %d.%d.%d\n",
+			(fpga_ver & 0xF000) >> 12,
+			(fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF);
+	if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) {
+		printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based "
+				"devices won't be registered!\n");
+		return;
+	}
+
+	/* register FPGA-based devices */
+	qong_init_nand_mtd();
+	qong_init_dnet();
+}
+
+/*
+ * This structure defines the MX31 memory map.
+ */
+static struct map_desc qong_io_desc[] __initdata = {
+	{
+		.virtual = AIPS1_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
+		.length = AIPS1_SIZE,
+		.type = MT_DEVICE_NONSHARED
+	}, {
+		.virtual = AIPS2_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
+		.length = AIPS2_SIZE,
+		.type = MT_DEVICE_NONSHARED
+	}
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+static void __init qong_map_io(void)
+{
+	mxc_map_io();
+	iotable_init(qong_io_desc, ARRAY_SIZE(qong_io_desc));
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_init_imx_uart();
+	qong_init_nor_mtd();
+	qong_init_fpga();
+}
+
+static void __init qong_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer qong_timer = {
+	.init	= qong_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros defined in arch.h in order to
+ * initialize __mach_desc_QONG data structure.
+ */
+
+MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
+	/* Maintainer: DENX Software Engineering GmbH */
+	.phys_io        = AIPS1_BASE_ADDR,
+	.io_pg_offst    = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = PHYS_OFFSET + 0x100,
+	.map_io         = qong_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &qong_timer,
+MACHINE_END
diff --git a/arch/arm/mach-netx/include/mach/system.h b/arch/arm/mach-netx/include/mach/system.h
index 6c1023b..dc7b4bc 100644
--- a/arch/arm/mach-netx/include/mach/system.h
+++ b/arch/arm/mach-netx/include/mach/system.h
@@ -28,7 +28,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES,
 	       NETX_SYSTEM_RES_CR);
diff --git a/arch/arm/mach-ns9xxx/include/mach/system.h b/arch/arm/mach-ns9xxx/include/mach/system.h
index e2068c5..1561588 100644
--- a/arch/arm/mach-ns9xxx/include/mach/system.h
+++ b/arch/arm/mach-ns9xxx/include/mach/system.h
@@ -20,7 +20,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 #ifdef CONFIG_PROCESSOR_NS9360
 	if (processor_is_ns9360())
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 10a301e..3f325d3 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -7,6 +7,11 @@
 	select CPU_ARM926T
 	select ARCH_OMAP_OTG
 
+config ARCH_OMAP850
+	depends on ARCH_OMAP1
+	bool "OMAP850 Based System"
+	select CPU_ARM926T
+
 config ARCH_OMAP15XX
 	depends on ARCH_OMAP1
 	default y
@@ -46,6 +51,12 @@
 	  TI OMAP 1710 H3 board support. Say Y here if you have such
 	  a board.
 
+config MACH_OMAP_HTCWIZARD
+	bool "HTC Wizard"
+	depends on ARCH_OMAP850
+	help
+	  HTC Wizard smartphone support (AKA QTEK 9100, ...)
+
 config MACH_OMAP_OSK
 	bool "TI OSK Support"
 	depends on ARCH_OMAP1 && ARCH_OMAP16XX
@@ -163,7 +174,7 @@
 
 config OMAP_ARM_195MHZ
 	bool "OMAP ARM 195 MHz CPU"
-	depends on ARCH_OMAP1 && ARCH_OMAP730
+	depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850)
 	help
           Enable 195MHz clock for OMAP CPU. If unsure, say N.
 
@@ -175,13 +186,13 @@
 
 config OMAP_ARM_182MHZ
 	bool "OMAP ARM 182 MHz CPU"
-	depends on ARCH_OMAP1 && ARCH_OMAP730
+	depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850)
 	help
           Enable 182MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_168MHZ
 	bool "OMAP ARM 168 MHz CPU"
-	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
+	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
 	help
           Enable 168MHz clock for OMAP CPU. If unsure, say N.
 
@@ -193,20 +204,20 @@
 
 config OMAP_ARM_120MHZ
 	bool "OMAP ARM 120 MHz CPU"
-	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
+	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
 	help
           Enable 120MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_60MHZ
 	bool "OMAP ARM 60 MHz CPU"
-	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
+	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
         default y
 	help
           Enable 60MHz clock for OMAP CPU. If unsure, say Y.
 
 config OMAP_ARM_30MHZ
 	bool "OMAP ARM 30 MHz CPU"
-	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730)
+	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
 	help
           Enable 30MHz clock for OMAP CPU. If unsure, say N.
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 2e61839..8b40aac 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -175,7 +175,6 @@
 static struct omap_board_config_kernel ams_delta_config[] = {
 	{ OMAP_TAG_LCD,		&ams_delta_lcd_config },
 	{ OMAP_TAG_UART,	&ams_delta_uart_config },
-	{ OMAP_TAG_USB,		&ams_delta_usb_config },
 };
 
 static struct resource ams_delta_kp_resources[] = {
@@ -232,6 +231,7 @@
 	/* Clear latch2 (NAND, LCD, modem enable) */
 	ams_delta_latch2_write(~0, 0);
 
+	omap_usb_init(&ams_delta_usb_config);
 	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 }
 
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 3030829..19e0e923 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -34,7 +34,39 @@
 #include <mach/keypad.h>
 #include <mach/common.h>
 #include <mach/board.h>
-#include <mach/board-fsample.h>
+
+/* fsample is pretty close to p2-sample */
+
+#define fsample_cpld_read(reg) __raw_readb(reg)
+#define fsample_cpld_write(val, reg) __raw_writeb(val, reg)
+
+#define FSAMPLE_CPLD_BASE    0xE8100000
+#define FSAMPLE_CPLD_SIZE    SZ_4K
+#define FSAMPLE_CPLD_START   0x05080000
+
+#define FSAMPLE_CPLD_REG_A   (FSAMPLE_CPLD_BASE + 0x00)
+#define FSAMPLE_CPLD_SWITCH  (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_UART    (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_REG_B   (FSAMPLE_CPLD_BASE + 0x04)
+#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06)
+#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06)
+
+#define FSAMPLE_CPLD_BIT_BT_RESET         0
+#define FSAMPLE_CPLD_BIT_LCD_RESET        1
+#define FSAMPLE_CPLD_BIT_CAM_PWDN         2
+#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE   3
+#define FSAMPLE_CPLD_BIT_SD_MMC_EN        4
+#define FSAMPLE_CPLD_BIT_aGPS_PWREN       5
+#define FSAMPLE_CPLD_BIT_BACKLIGHT        6
+#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET    7
+#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N    8
+#define FSAMPLE_CPLD_BIT_OTG_RESET        9
+
+#define fsample_cpld_set(bit) \
+    fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR)
+
+#define fsample_cpld_clear(bit) \
+    fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)
 
 static int fsample_keymap[] = {
 	KEY(0,0,KEY_UP),
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 7d26702..e724940 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -62,7 +62,6 @@
 };
 
 static struct omap_board_config_kernel generic_config[] __initdata = {
-	{ OMAP_TAG_USB,		NULL },
 	{ OMAP_TAG_UART,	&generic_uart_config },
 };
 
@@ -70,12 +69,12 @@
 {
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap15xx()) {
-		generic_config[0].data = &generic1510_usb_config;
+		omap_usb_init(&generic1510_usb_config);
 	}
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
 	if (!cpu_is_omap1510()) {
-		generic_config[0].data = &generic1610_usb_config;
+		omap_usb_init(&generic1610_usb_config);
 	}
 #endif
 
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
index 409fa56..44d4a96 100644
--- a/arch/arm/mach-omap1/board-h2-mmc.c
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -19,6 +19,8 @@
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
+#include "board-h2.h"
+
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
 static int mmc_set_power(struct device *dev, int slot, int power_on,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 0d784a7..f695aa0 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -46,6 +46,11 @@
 #include <mach/keypad.h>
 #include <mach/common.h>
 
+#include "board-h2.h"
+
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define OMAP1610_ETHR_START		0x04000300
+
 static int h2_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -364,7 +369,6 @@
 };
 
 static struct omap_board_config_kernel h2_config[] __initdata = {
-	{ OMAP_TAG_USB,		&h2_usb_config },
 	{ OMAP_TAG_UART,	&h2_uart_config },
 	{ OMAP_TAG_LCD,		&h2_lcd_config },
 };
@@ -413,6 +417,7 @@
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, h2_i2c_board_info,
 			      ARRAY_SIZE(h2_i2c_board_info));
+	omap_usb_init(&h2_usb_config);
 	h2_mmc_init();
 }
 
diff --git a/arch/arm/plat-omap/include/mach/board-h2.h b/arch/arm/mach-omap1/board-h2.h
similarity index 90%
rename from arch/arm/plat-omap/include/mach/board-h2.h
rename to arch/arm/mach-omap1/board-h2.h
index 15531c8..315e266 100644
--- a/arch/arm/plat-omap/include/mach/board-h2.h
+++ b/arch/arm/mach-omap1/board-h2.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/board-h2.h
+ * arch/arm/mach-omap1/board-h2.h
  *
  * Hardware definitions for TI OMAP1610 H2 board.
  *
@@ -29,9 +29,6 @@
 #ifndef __ASM_ARCH_OMAP_H2_H
 #define __ASM_ARCH_OMAP_H2_H
 
-/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
-#define OMAP1610_ETHR_START		0x04000300
-
 #define H2_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
 #	define H2_TPS_GPIO_MMC_PWR_EN	(H2_TPS_GPIO_BASE + 3)
 
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
index fdfe793..0d8a3c1 100644
--- a/arch/arm/mach-omap1/board-h3-mmc.c
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -19,6 +19,8 @@
 #include <mach/mmc.h>
 #include <mach/gpio.h>
 
+#include "board-h3.h"
+
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
 static int mmc_set_power(struct device *dev, int slot, int power_on,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index bf08b6ad..4695965 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -50,6 +50,11 @@
 #include <mach/dma.h>
 #include <mach/common.h>
 
+#include "board-h3.h"
+
+/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
+#define OMAP1710_ETHR_START		0x04000300
+
 #define H3_TS_GPIO	48
 
 static int h3_keymap[] = {
@@ -418,7 +423,6 @@
 };
 
 static struct omap_board_config_kernel h3_config[] __initdata = {
-	{ OMAP_TAG_USB,		&h3_usb_config },
 	{ OMAP_TAG_UART,	&h3_uart_config },
 	{ OMAP_TAG_LCD,		&h3_lcd_config },
 };
@@ -472,6 +476,7 @@
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, h3_i2c_board_info,
 			      ARRAY_SIZE(h3_i2c_board_info));
+	omap_usb_init(&h3_usb_config);
 	h3_mmc_init();
 }
 
diff --git a/arch/arm/plat-omap/include/mach/board-h3.h b/arch/arm/mach-omap1/board-h3.h
similarity index 90%
rename from arch/arm/plat-omap/include/mach/board-h3.h
rename to arch/arm/mach-omap1/board-h3.h
index 1888326..78de535 100644
--- a/arch/arm/plat-omap/include/mach/board-h3.h
+++ b/arch/arm/mach-omap1/board-h3.h
@@ -1,5 +1,5 @@
 /*
- * arch/arm/plat-omap/include/mach/board-h3.h
+ * arch/arm/mach-omap1/board-h3.h
  *
  * Copyright (C) 2001 RidgeRun, Inc.
  * Copyright (C) 2004 Texas Instruments, Inc.
@@ -27,9 +27,6 @@
 #ifndef __ASM_ARCH_OMAP_H3_H
 #define __ASM_ARCH_OMAP_H3_H
 
-/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
-#define OMAP1710_ETHR_START		0x04000300
-
 #define H3_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
 #	define H3_TPS_GPIO_MMC_PWR_EN	(H3_TPS_GPIO_BASE + 4)
 
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 071cd02..2fd98260 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -39,6 +39,9 @@
 #include <mach/common.h>
 #include <mach/mmc.h>
 
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define INNOVATOR1610_ETHR_START	0x04000300
+
 static int innovator_keymap[] = {
 	KEY(0, 0, KEY_F1),
 	KEY(0, 3, KEY_DOWN),
@@ -370,7 +373,6 @@
 };
 
 static struct omap_board_config_kernel innovator_config[] = {
-	{ OMAP_TAG_USB,         NULL },
 	{ OMAP_TAG_LCD,		NULL },
 	{ OMAP_TAG_UART,	&innovator_uart_config },
 };
@@ -392,13 +394,13 @@
 
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
-		innovator_config[0].data = &innovator1510_usb_config;
+		omap_usb_init(&innovator1510_usb_config);
 		innovator_config[1].data = &innovator1510_lcd_config;
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP16XX
 	if (cpu_is_omap1610()) {
-		innovator_config[0].data = &h2_usb_config;
+		omap_usb_init(&h2_usb_config);
 		innovator_config[1].data = &innovator1610_lcd_config;
 	}
 #endif
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index af51e0b..7bc7a3c 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -233,10 +233,6 @@
 }
 #endif
 
-static struct omap_board_config_kernel nokia770_config[] __initdata = {
-	{ OMAP_TAG_USB,		NULL },
-};
-
 #if	defined(CONFIG_OMAP_DSP)
 /*
  * audio power control
@@ -371,19 +367,16 @@
 
 static void __init omap_nokia770_init(void)
 {
-	nokia770_config[0].data = &nokia770_usb_config;
-
 	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
 	spi_register_board_info(nokia770_spi_board_info,
 				ARRAY_SIZE(nokia770_spi_board_info));
-	omap_board_config = nokia770_config;
-	omap_board_config_size = ARRAY_SIZE(nokia770_config);
 	omap_gpio_init();
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 	omap_dsp_init();
 	ads7846_dev_init();
 	mipid_dev_init();
+	omap_usb_init(&nokia770_usb_config);
 	nokia770_mmc_init();
 }
 
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 1a16ecb..cf3247b 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -52,6 +52,20 @@
 #include <mach/tc.h>
 #include <mach/common.h>
 
+/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
+#define OMAP_OSK_ETHR_START		0x04800300
+
+/* TPS65010 has four GPIOs.  nPG and LED2 can be treated like GPIOs with
+ * alternate pin configurations for hardware-controlled blinking.
+ */
+#define OSK_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+#	define OSK_TPS_GPIO_USB_PWR_EN	(OSK_TPS_GPIO_BASE + 0)
+#	define OSK_TPS_GPIO_LED_D3	(OSK_TPS_GPIO_BASE + 1)
+#	define OSK_TPS_GPIO_LAN_RESET	(OSK_TPS_GPIO_BASE + 2)
+#	define OSK_TPS_GPIO_DSP_PWR_EN	(OSK_TPS_GPIO_BASE + 3)
+#	define OSK_TPS_GPIO_LED_D9	(OSK_TPS_GPIO_BASE + 4)
+#	define OSK_TPS_GPIO_LED_D2	(OSK_TPS_GPIO_BASE + 5)
+
 static struct mtd_partition osk_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -290,7 +304,6 @@
 #endif
 
 static struct omap_board_config_kernel osk_config[] __initdata = {
-	{ OMAP_TAG_USB,           &osk_usb_config },
 	{ OMAP_TAG_UART,		&osk_uart_config },
 #ifdef	CONFIG_OMAP_OSK_MISTRAL
 	{ OMAP_TAG_LCD,			&osk_lcd_config },
@@ -541,6 +554,8 @@
 	l |= (3 << 1);
 	omap_writel(l, USB_TRANSCEIVER_CTRL);
 
+	omap_usb_init(&osk_usb_config);
+
 	/* irq for tps65010 chip */
 	/* bootloader effectively does:  omap_cfg_reg(U19_1610_MPUIO1); */
 	if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0)
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 99f2b43..886b4c0 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -43,6 +43,21 @@
 #include <mach/keypad.h>
 #include <mach/common.h>
 
+#define PALMTE_USBDETECT_GPIO	0
+#define PALMTE_USB_OR_DC_GPIO	1
+#define PALMTE_TSC_GPIO		4
+#define PALMTE_PINTDAV_GPIO	6
+#define PALMTE_MMC_WP_GPIO	8
+#define PALMTE_MMC_POWER_GPIO	9
+#define PALMTE_HDQ_GPIO		11
+#define PALMTE_HEADPHONES_GPIO	14
+#define PALMTE_SPEAKER_GPIO	15
+#define PALMTE_DC_GPIO		OMAP_MPUIO(2)
+#define PALMTE_MMC_SWITCH_GPIO	OMAP_MPUIO(4)
+#define PALMTE_MMC1_GPIO	OMAP_MPUIO(6)
+#define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
+#define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
+
 static void __init omap_palmte_init_irq(void)
 {
 	omap1_init_common_hw();
@@ -286,7 +301,6 @@
 #endif
 
 static struct omap_board_config_kernel palmte_config[] __initdata = {
-	{ OMAP_TAG_USB,		&palmte_usb_config },
 	{ OMAP_TAG_LCD,		&palmte_lcd_config },
 	{ OMAP_TAG_UART,	&palmte_uart_config },
 };
@@ -341,6 +355,7 @@
 	spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
 	palmte_misc_gpio_setup();
 	omap_serial_init();
+	omap_usb_init(&palmte_usb_config);
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 1cbc127..4f1b448 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -43,6 +43,13 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
+#define PALMTT_USBDETECT_GPIO	0
+#define PALMTT_CABLE_GPIO	1
+#define PALMTT_LED_GPIO		3
+#define PALMTT_PENIRQ_GPIO	6
+#define PALMTT_MMC_WP_GPIO	8
+#define PALMTT_HDQ_GPIO		11
+
 static int palmtt_keymap[] = {
 	KEY(0, 0, KEY_ESC),
 	KEY(0, 1, KEY_SPACE),
@@ -272,7 +279,6 @@
 };
 
 static struct omap_board_config_kernel palmtt_config[] __initdata = {
-	{ OMAP_TAG_USB,		&palmtt_usb_config	},
 	{ OMAP_TAG_LCD,		&palmtt_lcd_config	},
 	{ OMAP_TAG_UART,	&palmtt_uart_config	},
 };
@@ -297,6 +303,7 @@
 
 	spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo));
 	omap_serial_init();
+	omap_usb_init(&palmtt_usb_config);
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
 
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index baf5efb..9a55c3c 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -46,6 +46,16 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
+#define PALMZ71_USBDETECT_GPIO	0
+#define PALMZ71_PENIRQ_GPIO	6
+#define PALMZ71_MMC_WP_GPIO	8
+#define PALMZ71_HDQ_GPIO 	11
+
+#define PALMZ71_HOTSYNC_GPIO	OMAP_MPUIO(1)
+#define PALMZ71_CABLE_GPIO	OMAP_MPUIO(2)
+#define PALMZ71_SLIDER_GPIO	OMAP_MPUIO(3)
+#define PALMZ71_MMC_IN_GPIO	OMAP_MPUIO(4)
+
 static void __init
 omap_palmz71_init_irq(void)
 {
@@ -239,7 +249,6 @@
 };
 
 static struct omap_board_config_kernel palmz71_config[] __initdata = {
-	{OMAP_TAG_USB,	&palmz71_usb_config},
 	{OMAP_TAG_LCD,	&palmz71_lcd_config},
 	{OMAP_TAG_UART,	&palmz71_uart_config},
 };
@@ -313,6 +322,7 @@
 
 	spi_register_board_info(palmz71_boardinfo,
 				ARRAY_SIZE(palmz71_boardinfo));
+	omap_usb_init(&palmz71_usb_config);
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 	palmz71_gpio_setup(0);
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
index 66a4d7d..58a46e4 100644
--- a/arch/arm/mach-omap1/board-sx1-mmc.c
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -17,6 +17,7 @@
 #include <mach/hardware.h>
 #include <mach/mmc.h>
 #include <mach/gpio.h>
+#include <mach/board-sx1.h>
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 28c76a1..c096577 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -41,6 +41,7 @@
 #include <mach/board.h>
 #include <mach/common.h>
 #include <mach/keypad.h>
+#include <mach/board-sx1.h>
 
 /* Write to I2C device */
 int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
@@ -373,7 +374,6 @@
 };
 
 static struct omap_board_config_kernel sx1_config[] __initdata = {
-	{ OMAP_TAG_USB,	&sx1_usb_config },
 	{ OMAP_TAG_LCD,	&sx1_lcd_config },
 	{ OMAP_TAG_UART,	&sx1_uart_config },
 };
@@ -388,6 +388,7 @@
 	omap_board_config_size = ARRAY_SIZE(sx1_config);
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
+	omap_usb_init(&sx1_usb_config);
 	sx1_mmc_init();
 
 	/* turn on USB power */
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index a765354..98275e0 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -145,7 +145,6 @@
 };
 
 static struct omap_board_config_kernel voiceblue_config[] = {
-	{ OMAP_TAG_USB,  &voiceblue_usb_config },
 	{ OMAP_TAG_UART, &voiceblue_uart_config },
 };
 
@@ -185,6 +184,7 @@
 	omap_board_config = voiceblue_config;
 	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
 	omap_serial_init();
+	omap_usb_init(&voiceblue_usb_config);
 	omap_register_i2c_bus(1, 100, NULL, 0);
 
 	/* There is a good chance board is going up, so enable power LED
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 5fba207..dafe4f7 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -20,41 +20,161 @@
 #include <linux/io.h>
 
 #include <asm/mach-types.h>
+#include <asm/clkdev.h>
 
 #include <mach/cpu.h>
 #include <mach/usb.h>
 #include <mach/clock.h>
 #include <mach/sram.h>
 
+static const struct clkops clkops_generic;
+static const struct clkops clkops_uart;
+static const struct clkops clkops_dspck;
+
 #include "clock.h"
 
+static int clk_omap1_dummy_enable(struct clk *clk)
+{
+	return 0;
+}
+
+static void clk_omap1_dummy_disable(struct clk *clk)
+{
+}
+
+static const struct clkops clkops_dummy = {
+	.enable = clk_omap1_dummy_enable,
+	.disable = clk_omap1_dummy_disable,
+};
+
+static struct clk dummy_ck = {
+	.name	= "dummy",
+	.ops	= &clkops_dummy,
+	.flags	= RATE_FIXED,
+};
+
+struct omap_clk {
+	u32		cpu;
+	struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck, cp) 		\
+	{				\
+		 .cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
+#define CK_310	(1 << 0)
+#define CK_730	(1 << 1)
+#define CK_1510	(1 << 2)
+#define CK_16XX	(1 << 3)
+
+static struct omap_clk omap_clks[] = {
+	/* non-ULPD clocks */
+	CLK(NULL,	"ck_ref",	&ck_ref,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"ck_dpll1",	&ck_dpll1,	CK_16XX | CK_1510 | CK_310),
+	/* CK_GEN1 clocks */
+	CLK(NULL,	"ck_dpll1out",	&ck_dpll1out.clk, CK_16XX),
+	CLK(NULL,	"ck_sossi",	&sossi_ck,	CK_16XX),
+	CLK(NULL,	"arm_ck",	&arm_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"armper_ck",	&armper_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"arm_gpio_ck",	&arm_gpio_ck,	CK_1510 | CK_310),
+	CLK(NULL,	"armxor_ck",	&armxor_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"armtim_ck",	&armtim_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK("omap_wdt",	"fck",		&armwdt_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK("omap_wdt",	"ick",		&armper_ck.clk,	CK_16XX),
+	CLK("omap_wdt", "ick",		&dummy_ck,	CK_1510 | CK_310),
+	CLK(NULL,	"arminth_ck",	&arminth_ck1510, CK_1510 | CK_310),
+	CLK(NULL,	"arminth_ck",	&arminth_ck16xx, CK_16XX),
+	/* CK_GEN2 clocks */
+	CLK(NULL,	"dsp_ck",	&dsp_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"dspmmu_ck",	&dspmmu_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"dspper_ck",	&dspper_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"dspxor_ck",	&dspxor_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"dsptim_ck",	&dsptim_ck,	CK_16XX | CK_1510 | CK_310),
+	/* CK_GEN3 clocks */
+	CLK(NULL,	"tc_ck",	&tc_ck.clk,	CK_16XX | CK_1510 | CK_310 | CK_730),
+	CLK(NULL,	"tipb_ck",	&tipb_ck,	CK_1510 | CK_310),
+	CLK(NULL,	"l3_ocpi_ck",	&l3_ocpi_ck,	CK_16XX),
+	CLK(NULL,	"tc1_ck",	&tc1_ck,	CK_16XX),
+	CLK(NULL,	"tc2_ck",	&tc2_ck,	CK_16XX),
+	CLK(NULL,	"dma_ck",	&dma_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX),
+	CLK(NULL,	"api_ck",	&api_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"lb_ck",	&lb_ck.clk,	CK_1510 | CK_310),
+	CLK(NULL,	"rhea1_ck",	&rhea1_ck,	CK_16XX),
+	CLK(NULL,	"rhea2_ck",	&rhea2_ck,	CK_16XX),
+	CLK(NULL,	"lcd_ck",	&lcd_ck_16xx,	CK_16XX | CK_730),
+	CLK(NULL,	"lcd_ck",	&lcd_ck_1510.clk, CK_1510 | CK_310),
+	/* ULPD clocks */
+	CLK(NULL,	"uart1_ck",	&uart1_1510,	CK_1510 | CK_310),
+	CLK(NULL,	"uart1_ck",	&uart1_16xx.clk, CK_16XX),
+	CLK(NULL,	"uart2_ck",	&uart2_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"uart3_ck",	&uart3_1510,	CK_1510 | CK_310),
+	CLK(NULL,	"uart3_ck",	&uart3_16xx.clk, CK_16XX),
+	CLK(NULL,	"usb_clko",	&usb_clko,	CK_16XX | CK_1510 | CK_310),
+	CLK(NULL,	"usb_hhc_ck",	&usb_hhc_ck1510, CK_1510 | CK_310),
+	CLK(NULL,	"usb_hhc_ck",	&usb_hhc_ck16xx, CK_16XX),
+	CLK(NULL,	"usb_dc_ck",	&usb_dc_ck,	CK_16XX),
+	CLK(NULL,	"mclk",		&mclk_1510,	CK_1510 | CK_310),
+	CLK(NULL,	"mclk",		&mclk_16xx,	CK_16XX),
+	CLK(NULL,	"bclk",		&bclk_1510,	CK_1510 | CK_310),
+	CLK(NULL,	"bclk",		&bclk_16xx,	CK_16XX),
+	CLK("mmci-omap.0", "fck",	&mmc1_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK("mmci-omap.0", "ick",	&armper_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK("mmci-omap.1", "fck",	&mmc2_ck,	CK_16XX),
+	CLK("mmci-omap.1", "ick",	&armper_ck.clk,	CK_16XX),
+	/* Virtual clocks */
+	CLK(NULL,	"mpu",		&virtual_ck_mpu, CK_16XX | CK_1510 | CK_310),
+	CLK("i2c_omap.1", "fck",	&i2c_fck,	CK_16XX | CK_1510 | CK_310),
+	CLK("i2c_omap.1", "ick",	&i2c_ick,	CK_16XX),
+	CLK("i2c_omap.1", "ick",	&dummy_ck,	CK_1510 | CK_310),
+	CLK("omap_uwire", "fck",	&armxor_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK("omap-mcbsp.1", "ick",	&dspper_ck,	CK_16XX),
+	CLK("omap-mcbsp.1", "ick",	&dummy_ck,	CK_1510 | CK_310),
+	CLK("omap-mcbsp.2", "ick",	&armper_ck.clk,	CK_16XX),
+	CLK("omap-mcbsp.2", "ick",	&dummy_ck,	CK_1510 | CK_310),
+	CLK("omap-mcbsp.3", "ick",	&dspper_ck,	CK_16XX),
+	CLK("omap-mcbsp.3", "ick",	&dummy_ck,	CK_1510 | CK_310),
+	CLK("omap-mcbsp.1", "fck",	&dspxor_ck,	CK_16XX | CK_1510 | CK_310),
+	CLK("omap-mcbsp.2", "fck",	&armper_ck.clk,	CK_16XX | CK_1510 | CK_310),
+	CLK("omap-mcbsp.3", "fck",	&dspxor_ck,	CK_16XX | CK_1510 | CK_310),
+};
+
+static int omap1_clk_enable_generic(struct clk * clk);
+static int omap1_clk_enable(struct clk *clk);
+static void omap1_clk_disable_generic(struct clk * clk);
+static void omap1_clk_disable(struct clk *clk);
+
 __u32 arm_idlect1_mask;
 
 /*-------------------------------------------------------------------------
  * Omap1 specific clock functions
  *-------------------------------------------------------------------------*/
 
-static void omap1_watchdog_recalc(struct clk * clk)
+static unsigned long omap1_watchdog_recalc(struct clk *clk)
 {
-	clk->rate = clk->parent->rate / 14;
+	return clk->parent->rate / 14;
 }
 
-static void omap1_uart_recalc(struct clk * clk)
+static unsigned long omap1_uart_recalc(struct clk *clk)
 {
-	unsigned int val = omap_readl(clk->enable_reg);
-	if (val & clk->enable_bit)
-		clk->rate = 48000000;
-	else
-		clk->rate = 12000000;
+	unsigned int val = __raw_readl(clk->enable_reg);
+	return val & clk->enable_bit ? 48000000 : 12000000;
 }
 
-static void omap1_sossi_recalc(struct clk *clk)
+static unsigned long omap1_sossi_recalc(struct clk *clk)
 {
 	u32 div = omap_readl(MOD_CONF_CTRL_1);
 
 	div = (div >> 17) & 0x7;
 	div++;
-	clk->rate = clk->parent->rate / div;
+
+	return clk->parent->rate / div;
 }
 
 static int omap1_clk_enable_dsp_domain(struct clk *clk)
@@ -78,6 +198,11 @@
 	}
 }
 
+static const struct clkops clkops_dspck = {
+	.enable		= &omap1_clk_enable_dsp_domain,
+	.disable	= &omap1_clk_disable_dsp_domain,
+};
+
 static int omap1_clk_enable_uart_functional(struct clk *clk)
 {
 	int ret;
@@ -105,6 +230,11 @@
 	omap1_clk_disable_generic(clk);
 }
 
+static const struct clkops clkops_uart = {
+	.enable		= &omap1_clk_enable_uart_functional,
+	.disable	= &omap1_clk_disable_uart_functional,
+};
+
 static void omap1_clk_allow_idle(struct clk *clk)
 {
 	struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
@@ -197,9 +327,6 @@
 	struct clk * parent;
 	unsigned  dsor_exp;
 
-	if (unlikely(!(clk->flags & RATE_CKCTL)))
-		return -EINVAL;
-
 	parent = clk->parent;
 	if (unlikely(parent == NULL))
 		return -EIO;
@@ -215,22 +342,15 @@
 	return dsor_exp;
 }
 
-static void omap1_ckctl_recalc(struct clk * clk)
+static unsigned long omap1_ckctl_recalc(struct clk *clk)
 {
-	int dsor;
-
 	/* Calculate divisor encoded as 2-bit exponent */
-	dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
+	int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
 
-	if (unlikely(clk->rate == clk->parent->rate / dsor))
-		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
-
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+	return clk->parent->rate / dsor;
 }
 
-static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
+static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk)
 {
 	int dsor;
 
@@ -245,12 +365,7 @@
 	dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
 	omap1_clk_disable(&api_ck.clk);
 
-	if (unlikely(clk->rate == clk->parent->rate / dsor))
-		return; /* No change, quick exit */
-	clk->rate = clk->parent->rate / dsor;
-
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+	return clk->parent->rate / dsor;
 }
 
 /* MPU virtual clock functions */
@@ -289,35 +404,57 @@
 		omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
 
 	ck_dpll1.rate = ptr->pll_rate;
-	propagate_rate(&ck_dpll1);
 	return 0;
 }
 
 static int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
 {
-	int  ret = -EINVAL;
-	int  dsor_exp;
-	__u16  regval;
+	int dsor_exp;
+	u16 regval;
 
-	if (clk->flags & RATE_CKCTL) {
-		dsor_exp = calc_dsor_exp(clk, rate);
-		if (dsor_exp > 3)
-			dsor_exp = -EINVAL;
-		if (dsor_exp < 0)
-			return dsor_exp;
+	dsor_exp = calc_dsor_exp(clk, rate);
+	if (dsor_exp > 3)
+		dsor_exp = -EINVAL;
+	if (dsor_exp < 0)
+		return dsor_exp;
 
-		regval = __raw_readw(DSP_CKCTL);
-		regval &= ~(3 << clk->rate_offset);
-		regval |= dsor_exp << clk->rate_offset;
-		__raw_writew(regval, DSP_CKCTL);
-		clk->rate = clk->parent->rate / (1 << dsor_exp);
-		ret = 0;
-	}
+	regval = __raw_readw(DSP_CKCTL);
+	regval &= ~(3 << clk->rate_offset);
+	regval |= dsor_exp << clk->rate_offset;
+	__raw_writew(regval, DSP_CKCTL);
+	clk->rate = clk->parent->rate / (1 << dsor_exp);
 
-	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-		propagate_rate(clk);
+	return 0;
+}
 
-	return ret;
+static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+{
+	int dsor_exp = calc_dsor_exp(clk, rate);
+	if (dsor_exp < 0)
+		return dsor_exp;
+	if (dsor_exp > 3)
+		dsor_exp = 3;
+	return clk->parent->rate / (1 << dsor_exp);
+}
+
+static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+{
+	int dsor_exp;
+	u16 regval;
+
+	dsor_exp = calc_dsor_exp(clk, rate);
+	if (dsor_exp > 3)
+		dsor_exp = -EINVAL;
+	if (dsor_exp < 0)
+		return dsor_exp;
+
+	regval = omap_readw(ARM_CKCTL);
+	regval &= ~(3 << clk->rate_offset);
+	regval |= dsor_exp << clk->rate_offset;
+	regval = verify_ckctl_value(regval);
+	omap_writew(regval, ARM_CKCTL);
+	clk->rate = clk->parent->rate / (1 << dsor_exp);
+	return 0;
 }
 
 static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate)
@@ -372,14 +509,14 @@
 {
 	unsigned int val;
 
-	val = omap_readl(clk->enable_reg);
+	val = __raw_readl(clk->enable_reg);
 	if (rate == 12000000)
 		val &= ~(1 << clk->enable_bit);
 	else if (rate == 48000000)
 		val |= (1 << clk->enable_bit);
 	else
 		return -EINVAL;
-	omap_writel(val, clk->enable_reg);
+	__raw_writel(val, clk->enable_reg);
 	clk->rate = rate;
 
 	return 0;
@@ -398,8 +535,8 @@
 	else
 		ratio_bits = (dsor - 2) << 2;
 
-	ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd;
-	omap_writew(ratio_bits, clk->enable_reg);
+	ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
+	__raw_writew(ratio_bits, clk->enable_reg);
 
 	return 0;
 }
@@ -423,8 +560,6 @@
 	omap_writel(l, MOD_CONF_CTRL_1);
 
 	clk->rate = p_rate / (div + 1);
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
 
 	return 0;
 }
@@ -440,8 +575,8 @@
 	__u16 ratio_bits;
 
 	/* Determine current rate and ensure clock is based on 96MHz APLL */
-	ratio_bits = omap_readw(clk->enable_reg) & ~1;
-	omap_writew(ratio_bits, clk->enable_reg);
+	ratio_bits = __raw_readw(clk->enable_reg) & ~1;
+	__raw_writew(ratio_bits, clk->enable_reg);
 
 	ratio_bits = (ratio_bits & 0xfc) >> 2;
 	if (ratio_bits > 6)
@@ -468,7 +603,7 @@
 				omap1_clk_deny_idle(clk->parent);
 		}
 
-		ret = clk->enable(clk);
+		ret = clk->ops->enable(clk);
 
 		if (unlikely(ret != 0) && clk->parent) {
 			omap1_clk_disable(clk->parent);
@@ -482,7 +617,7 @@
 static void omap1_clk_disable(struct clk *clk)
 {
 	if (clk->usecount > 0 && !(--clk->usecount)) {
-		clk->disable(clk);
+		clk->ops->disable(clk);
 		if (likely(clk->parent)) {
 			omap1_clk_disable(clk->parent);
 			if (clk->flags & CLOCK_NO_IDLE_PARENT)
@@ -496,9 +631,6 @@
 	__u16 regval16;
 	__u32 regval32;
 
-	if (clk->flags & ALWAYS_ENABLED)
-		return 0;
-
 	if (unlikely(clk->enable_reg == NULL)) {
 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
 		       clk->name);
@@ -506,25 +638,13 @@
 	}
 
 	if (clk->flags & ENABLE_REG_32BIT) {
-		if (clk->flags & VIRTUAL_IO_ADDRESS) {
-			regval32 = __raw_readl(clk->enable_reg);
-			regval32 |= (1 << clk->enable_bit);
-			__raw_writel(regval32, clk->enable_reg);
-		} else {
-			regval32 = omap_readl(clk->enable_reg);
-			regval32 |= (1 << clk->enable_bit);
-			omap_writel(regval32, clk->enable_reg);
-		}
+		regval32 = __raw_readl(clk->enable_reg);
+		regval32 |= (1 << clk->enable_bit);
+		__raw_writel(regval32, clk->enable_reg);
 	} else {
-		if (clk->flags & VIRTUAL_IO_ADDRESS) {
-			regval16 = __raw_readw(clk->enable_reg);
-			regval16 |= (1 << clk->enable_bit);
-			__raw_writew(regval16, clk->enable_reg);
-		} else {
-			regval16 = omap_readw(clk->enable_reg);
-			regval16 |= (1 << clk->enable_bit);
-			omap_writew(regval16, clk->enable_reg);
-		}
+		regval16 = __raw_readw(clk->enable_reg);
+		regval16 |= (1 << clk->enable_bit);
+		__raw_writew(regval16, clk->enable_reg);
 	}
 
 	return 0;
@@ -539,44 +659,26 @@
 		return;
 
 	if (clk->flags & ENABLE_REG_32BIT) {
-		if (clk->flags & VIRTUAL_IO_ADDRESS) {
-			regval32 = __raw_readl(clk->enable_reg);
-			regval32 &= ~(1 << clk->enable_bit);
-			__raw_writel(regval32, clk->enable_reg);
-		} else {
-			regval32 = omap_readl(clk->enable_reg);
-			regval32 &= ~(1 << clk->enable_bit);
-			omap_writel(regval32, clk->enable_reg);
-		}
+		regval32 = __raw_readl(clk->enable_reg);
+		regval32 &= ~(1 << clk->enable_bit);
+		__raw_writel(regval32, clk->enable_reg);
 	} else {
-		if (clk->flags & VIRTUAL_IO_ADDRESS) {
-			regval16 = __raw_readw(clk->enable_reg);
-			regval16 &= ~(1 << clk->enable_bit);
-			__raw_writew(regval16, clk->enable_reg);
-		} else {
-			regval16 = omap_readw(clk->enable_reg);
-			regval16 &= ~(1 << clk->enable_bit);
-			omap_writew(regval16, clk->enable_reg);
-		}
+		regval16 = __raw_readw(clk->enable_reg);
+		regval16 &= ~(1 << clk->enable_bit);
+		__raw_writew(regval16, clk->enable_reg);
 	}
 }
 
+static const struct clkops clkops_generic = {
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
+};
+
 static long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	int dsor_exp;
-
 	if (clk->flags & RATE_FIXED)
 		return clk->rate;
 
-	if (clk->flags & RATE_CKCTL) {
-		dsor_exp = calc_dsor_exp(clk, rate);
-		if (dsor_exp < 0)
-			return dsor_exp;
-		if (dsor_exp > 3)
-			dsor_exp = 3;
-		return clk->parent->rate / (1 << dsor_exp);
-	}
-
 	if (clk->round_rate != NULL)
 		return clk->round_rate(clk, rate);
 
@@ -586,30 +688,9 @@
 static int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	int  ret = -EINVAL;
-	int  dsor_exp;
-	__u16  regval;
 
 	if (clk->set_rate)
 		ret = clk->set_rate(clk, rate);
-	else if (clk->flags & RATE_CKCTL) {
-		dsor_exp = calc_dsor_exp(clk, rate);
-		if (dsor_exp > 3)
-			dsor_exp = -EINVAL;
-		if (dsor_exp < 0)
-			return dsor_exp;
-
-		regval = omap_readw(ARM_CKCTL);
-		regval &= ~(3 << clk->rate_offset);
-		regval |= dsor_exp << clk->rate_offset;
-		regval = verify_ckctl_value(regval);
-		omap_writew(regval, ARM_CKCTL);
-		clk->rate = clk->parent->rate / (1 << dsor_exp);
-		ret = 0;
-	}
-
-	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-		propagate_rate(clk);
-
 	return ret;
 }
 
@@ -632,17 +713,10 @@
 	}
 
 	/* Is the clock already disabled? */
-	if (clk->flags & ENABLE_REG_32BIT) {
-		if (clk->flags & VIRTUAL_IO_ADDRESS)
-			regval32 = __raw_readl(clk->enable_reg);
-			else
-				regval32 = omap_readl(clk->enable_reg);
-	} else {
-		if (clk->flags & VIRTUAL_IO_ADDRESS)
-			regval32 = __raw_readw(clk->enable_reg);
-		else
-			regval32 = omap_readw(clk->enable_reg);
-	}
+	if (clk->flags & ENABLE_REG_32BIT)
+		regval32 = __raw_readl(clk->enable_reg);
+	else
+		regval32 = __raw_readw(clk->enable_reg);
 
 	if ((regval32 & (1 << clk->enable_bit)) == 0)
 		return;
@@ -659,7 +733,7 @@
 	}
 
 	printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
-	clk->disable(clk);
+	clk->ops->disable(clk);
 	printk(" done\n");
 }
 
@@ -677,10 +751,10 @@
 
 int __init omap1_clk_init(void)
 {
-	struct clk ** clkp;
+	struct omap_clk *c;
 	const struct omap_clock_config *info;
 	int crystal_type = 0; /* Default 12 MHz */
-	u32 reg;
+	u32 reg, cpu_mask;
 
 #ifdef CONFIG_DEBUG_LL
 	/* Resets some clocks that may be left on from bootloader,
@@ -700,28 +774,25 @@
 	/* By default all idlect1 clocks are allowed to idle */
 	arm_idlect1_mask = ~0;
 
-	for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
-		if (((*clkp)->flags &CLOCK_IN_OMAP1510) && cpu_is_omap1510()) {
-			clk_register(*clkp);
-			continue;
-		}
+	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
+		clk_init_one(c->lk.clk);
 
-		if (((*clkp)->flags &CLOCK_IN_OMAP16XX) && cpu_is_omap16xx()) {
-			clk_register(*clkp);
-			continue;
-		}
+	cpu_mask = 0;
+	if (cpu_is_omap16xx())
+		cpu_mask |= CK_16XX;
+	if (cpu_is_omap1510())
+		cpu_mask |= CK_1510;
+	if (cpu_is_omap730())
+		cpu_mask |= CK_730;
+	if (cpu_is_omap310())
+		cpu_mask |= CK_310;
 
-		if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) {
-			clk_register(*clkp);
-			continue;
+	for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
+		if (c->cpu & cpu_mask) {
+			clkdev_add(&c->lk);
+			clk_register(c->lk.clk);
 		}
 
-		if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
-			clk_register(*clkp);
-			continue;
-		}
-	}
-
 	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
 	if (info != NULL) {
 		if (!cpu_is_omap15xx())
@@ -769,7 +840,6 @@
 			}
 		}
 	}
-	propagate_rate(&ck_dpll1);
 #else
 	/* Find the highest supported frequency and enable it */
 	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
@@ -778,9 +848,9 @@
 		omap_writew(0x2290, DPLL_CTL);
 		omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL);
 		ck_dpll1.rate = 60000000;
-		propagate_rate(&ck_dpll1);
 	}
 #endif
+	propagate_rate(&ck_dpll1);
 	/* Cache rates for clocks connected to ck_ref (not dpll1) */
 	propagate_rate(&ck_ref);
 	printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
@@ -832,4 +902,3 @@
 
 	return 0;
 }
-
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index c1dcdf1..17f8742 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -13,27 +13,22 @@
 #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
 #define __ARCH_ARM_MACH_OMAP1_CLOCK_H
 
-static int omap1_clk_enable_generic(struct clk * clk);
-static void omap1_clk_disable_generic(struct clk * clk);
-static void omap1_ckctl_recalc(struct clk * clk);
-static void omap1_watchdog_recalc(struct clk * clk);
+static unsigned long omap1_ckctl_recalc(struct clk *clk);
+static unsigned long omap1_watchdog_recalc(struct clk *clk);
 static int omap1_set_sossi_rate(struct clk *clk, unsigned long rate);
-static void omap1_sossi_recalc(struct clk *clk);
-static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
-static int omap1_clk_enable_dsp_domain(struct clk * clk);
+static unsigned long omap1_sossi_recalc(struct clk *clk);
+static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk);
 static int omap1_clk_set_rate_dsp_domain(struct clk * clk, unsigned long rate);
-static void omap1_clk_disable_dsp_domain(struct clk * clk);
 static int omap1_set_uart_rate(struct clk * clk, unsigned long rate);
-static void omap1_uart_recalc(struct clk * clk);
-static int omap1_clk_enable_uart_functional(struct clk * clk);
-static void omap1_clk_disable_uart_functional(struct clk * clk);
+static unsigned long omap1_uart_recalc(struct clk *clk);
 static int omap1_set_ext_clk_rate(struct clk * clk, unsigned long rate);
 static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate);
 static void omap1_init_ext_clk(struct clk * clk);
 static int omap1_select_table_rate(struct clk * clk, unsigned long rate);
 static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate);
-static int omap1_clk_enable(struct clk *clk);
-static void omap1_clk_disable(struct clk *clk);
+
+static int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate);
+static long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate);
 
 struct mpu_rate {
 	unsigned long		rate;
@@ -152,101 +147,84 @@
 
 static struct clk ck_ref = {
 	.name		= "ck_ref",
+	.ops		= &clkops_null,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk ck_dpll1 = {
 	.name		= "ck_dpll1",
+	.ops		= &clkops_null,
 	.parent		= &ck_ref,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk ck_dpll1out = {
 	.clk = {
 		.name		= "ck_dpll1out",
+		.ops		= &clkops_generic,
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP16XX | CLOCK_IDLE_CONTROL |
-				  ENABLE_REG_32BIT | RATE_PROPAGATES,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_CKOUT_ARM,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 12,
 };
 
 static struct clk sossi_ck = {
 	.name		= "ck_sossi",
+	.ops		= &clkops_generic,
 	.parent		= &ck_dpll1out.clk,
-	.flags		= CLOCK_IN_OMAP16XX | CLOCK_NO_IDLE_PARENT |
-			  ENABLE_REG_32BIT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_1,
+	.flags		= CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1),
 	.enable_bit	= 16,
 	.recalc		= &omap1_sossi_recalc,
 	.set_rate	= &omap1_set_sossi_rate,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk arm_ck = {
 	.name		= "arm_ck",
+	.ops		= &clkops_null,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
-			  ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_ARMDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.round_rate	= omap1_clk_round_rate_ckctl_arm,
+	.set_rate	= omap1_clk_set_rate_ckctl_arm,
 };
 
 static struct arm_idlect1_clk armper_ck = {
 	.clk = {
 		.name		= "armper_ck",
+		.ops		= &clkops_generic,
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP310 | RATE_CKCTL |
-				  CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_PERCK,
 		.rate_offset	= CKCTL_PERDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
+		.round_rate	= omap1_clk_round_rate_ckctl_arm,
+		.set_rate	= omap1_clk_set_rate_ckctl_arm,
 	},
 	.idlect_shift	= 2,
 };
 
 static struct clk arm_gpio_ck = {
 	.name		= "arm_gpio_ck",
+	.ops		= &clkops_generic,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
-	.enable_reg	= (void __iomem *)ARM_IDLECT2,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 	.enable_bit	= EN_GPIOCK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk armxor_ck = {
 	.clk = {
 		.name		= "armxor_ck",
+		.ops		= &clkops_generic,
 		.parent		= &ck_ref,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_XORPCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 1,
 };
@@ -254,14 +232,12 @@
 static struct arm_idlect1_clk armtim_ck = {
 	.clk = {
 		.name		= "armtim_ck",
+		.ops		= &clkops_generic,
 		.parent		= &ck_ref,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_TIMCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 9,
 };
@@ -269,201 +245,166 @@
 static struct arm_idlect1_clk armwdt_ck = {
 	.clk = {
 		.name		= "armwdt_ck",
+		.ops		= &clkops_generic,
 		.parent		= &ck_ref,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_WDTCK,
 		.recalc		= &omap1_watchdog_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 0,
 };
 
 static struct clk arminth_ck16xx = {
 	.name		= "arminth_ck",
+	.ops		= &clkops_null,
 	.parent		= &arm_ck,
-	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	/* Note: On 16xx the frequency can be divided by 2 by programming
 	 * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
 	 *
 	 * 1510 version is in TC clocks.
 	 */
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dsp_ck = {
 	.name		= "dsp_ck",
+	.ops		= &clkops_generic,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_CKCTL,
-	.enable_reg	= (void __iomem *)ARM_CKCTL,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_CKCTL),
 	.enable_bit	= EN_DSPCK,
 	.rate_offset	= CKCTL_DSPDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.round_rate	= omap1_clk_round_rate_ckctl_arm,
+	.set_rate	= omap1_clk_set_rate_ckctl_arm,
 };
 
 static struct clk dspmmu_ck = {
 	.name		= "dspmmu_ck",
+	.ops		= &clkops_null,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_CKCTL | ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_DSPMMUDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.round_rate	= omap1_clk_round_rate_ckctl_arm,
+	.set_rate	= omap1_clk_set_rate_ckctl_arm,
 };
 
 static struct clk dspper_ck = {
 	.name		= "dspper_ck",
+	.ops		= &clkops_dspck,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_CKCTL | VIRTUAL_IO_ADDRESS,
 	.enable_reg	= DSP_IDLECT2,
 	.enable_bit	= EN_PERCK,
 	.rate_offset	= CKCTL_PERDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc_dsp_domain,
+	.round_rate	= omap1_clk_round_rate_ckctl_arm,
 	.set_rate	= &omap1_clk_set_rate_dsp_domain,
-	.enable		= &omap1_clk_enable_dsp_domain,
-	.disable	= &omap1_clk_disable_dsp_domain,
 };
 
 static struct clk dspxor_ck = {
 	.name		= "dspxor_ck",
+	.ops		= &clkops_dspck,
 	.parent		= &ck_ref,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_IO_ADDRESS,
 	.enable_reg	= DSP_IDLECT2,
 	.enable_bit	= EN_XORPCK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_dsp_domain,
-	.disable	= &omap1_clk_disable_dsp_domain,
 };
 
 static struct clk dsptim_ck = {
 	.name		= "dsptim_ck",
+	.ops		= &clkops_dspck,
 	.parent		= &ck_ref,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_IO_ADDRESS,
 	.enable_reg	= DSP_IDLECT2,
 	.enable_bit	= EN_DSPTIMCK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_dsp_domain,
-	.disable	= &omap1_clk_disable_dsp_domain,
 };
 
 /* Tie ARM_IDLECT1:IDLIF_ARM to this logical clock structure */
 static struct arm_idlect1_clk tc_ck = {
 	.clk = {
 		.name		= "tc_ck",
+		.ops		= &clkops_null,
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
-				  RATE_CKCTL | RATE_PROPAGATES |
-				  ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
+		.flags		= CLOCK_IDLE_CONTROL,
 		.rate_offset	= CKCTL_TCDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
+		.round_rate	= omap1_clk_round_rate_ckctl_arm,
+		.set_rate	= omap1_clk_set_rate_ckctl_arm,
 	},
 	.idlect_shift	= 6,
 };
 
 static struct clk arminth_ck1510 = {
 	.name		= "arminth_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	/* Note: On 1510 the frequency follows TC_CK
 	 *
 	 * 16xx version is in MPU clocks.
 	 */
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tipb_ck = {
 	/* No-idle controlled by "tc_ck" */
 	.name		= "tipb_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk l3_ocpi_ck = {
 	/* No-idle controlled by "tc_ck" */
 	.name		= "l3_ocpi_ck",
+	.ops		= &clkops_generic,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX,
-	.enable_reg	= (void __iomem *)ARM_IDLECT3,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT3),
 	.enable_bit	= EN_OCPI_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tc1_ck = {
 	.name		= "tc1_ck",
+	.ops		= &clkops_generic,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX,
-	.enable_reg	= (void __iomem *)ARM_IDLECT3,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT3),
 	.enable_bit	= EN_TC1_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk tc2_ck = {
 	.name		= "tc2_ck",
+	.ops		= &clkops_generic,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX,
-	.enable_reg	= (void __iomem *)ARM_IDLECT3,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT3),
 	.enable_bit	= EN_TC2_CK,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dma_ck = {
 	/* No-idle controlled by "tc_ck" */
 	.name		= "dma_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk dma_lcdfree_ck = {
 	.name		= "dma_lcdfree_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct arm_idlect1_clk api_ck = {
 	.clk = {
 		.name		= "api_ck",
+		.ops		= &clkops_generic,
 		.parent		= &tc_ck.clk,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_APICK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 8,
 };
@@ -471,276 +412,238 @@
 static struct arm_idlect1_clk lb_ck = {
 	.clk = {
 		.name		= "lb_ck",
+		.ops		= &clkops_generic,
 		.parent		= &tc_ck.clk,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-				  CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_LBCK,
 		.recalc		= &followparent_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
 	},
 	.idlect_shift	= 4,
 };
 
 static struct clk rhea1_ck = {
 	.name		= "rhea1_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk rhea2_ck = {
 	.name		= "rhea2_ck",
+	.ops		= &clkops_null,
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk lcd_ck_16xx = {
 	.name		= "lcd_ck",
+	.ops		= &clkops_generic,
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 | RATE_CKCTL,
-	.enable_reg	= (void __iomem *)ARM_IDLECT2,
+	.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 	.enable_bit	= EN_LCDCK,
 	.rate_offset	= CKCTL_LCDDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.round_rate	= omap1_clk_round_rate_ckctl_arm,
+	.set_rate	= omap1_clk_set_rate_ckctl_arm,
 };
 
 static struct arm_idlect1_clk lcd_ck_1510 = {
 	.clk = {
 		.name		= "lcd_ck",
+		.ops		= &clkops_generic,
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-				  RATE_CKCTL | CLOCK_IDLE_CONTROL,
-		.enable_reg	= (void __iomem *)ARM_IDLECT2,
+		.flags		= CLOCK_IDLE_CONTROL,
+		.enable_reg	= OMAP1_IO_ADDRESS(ARM_IDLECT2),
 		.enable_bit	= EN_LCDCK,
 		.rate_offset	= CKCTL_LCDDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
-		.enable		= &omap1_clk_enable_generic,
-		.disable	= &omap1_clk_disable_generic,
+		.round_rate	= omap1_clk_round_rate_ckctl_arm,
+		.set_rate	= omap1_clk_set_rate_ckctl_arm,
 	},
 	.idlect_shift	= 3,
 };
 
 static struct clk uart1_1510 = {
 	.name		= "uart1_ck",
+	.ops		= &clkops_null,
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
-			  CLOCK_NO_IDLE_PARENT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 29,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct uart_clk uart1_16xx = {
 	.clk	= {
 		.name		= "uart1_ck",
+		.ops		= &clkops_uart,
 		/* Direct from ULPD, no real parent */
 		.parent		= &armper_ck.clk,
 		.rate		= 48000000,
-		.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED |
-				  ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
-		.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+		.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+				  CLOCK_NO_IDLE_PARENT,
+		.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 		.enable_bit	= 29,
-		.enable		= &omap1_clk_enable_uart_functional,
-		.disable	= &omap1_clk_disable_uart_functional,
 	},
 	.sysc_addr	= 0xfffb0054,
 };
 
 static struct clk uart2_ck = {
 	.name		= "uart2_ck",
+	.ops		= &clkops_null,
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
-			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 30,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk uart3_1510 = {
 	.name		= "uart3_ck",
+	.ops		= &clkops_null,
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
-			  CLOCK_NO_IDLE_PARENT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 31,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
 	.recalc		= &omap1_uart_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct uart_clk uart3_16xx = {
 	.clk	= {
 		.name		= "uart3_ck",
+		.ops		= &clkops_uart,
 		/* Direct from ULPD, no real parent */
 		.parent		= &armper_ck.clk,
 		.rate		= 48000000,
-		.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED |
-				  ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
-		.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+		.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+				  CLOCK_NO_IDLE_PARENT,
+		.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 		.enable_bit	= 31,
-		.enable		= &omap1_clk_enable_uart_functional,
-		.disable	= &omap1_clk_disable_uart_functional,
 	},
 	.sysc_addr	= 0xfffb9854,
 };
 
 static struct clk usb_clko = {	/* 6 MHz output on W4_USB_CLKO */
 	.name		= "usb_clko",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent */
 	.rate		= 6000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
-	.enable_reg	= (void __iomem *)ULPD_CLOCK_CTRL,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL),
 	.enable_bit	= USB_MCLK_EN_BIT,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_hhc_ck1510 = {
 	.name		= "usb_hhc_ck",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
-			  RATE_FIXED | ENABLE_REG_32BIT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= USB_HOST_HHC_UHOST_EN,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_hhc_ck16xx = {
 	.name		= "usb_hhc_ck",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000,
 	/* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
-	.flags		= CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT,
-	.enable_reg	= (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */
 	.enable_bit	= 8 /* UHOST_EN */,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk usb_dc_ck = {
 	.name		= "usb_dc_ck",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000,
-	.flags		= CLOCK_IN_OMAP16XX | RATE_FIXED,
-	.enable_reg	= (void __iomem *)SOFT_REQ_REG,
+	.flags		= RATE_FIXED,
+	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
 	.enable_bit	= 4,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mclk_1510 = {
 	.name		= "mclk",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
- 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
- 	.enable_reg	= (void __iomem *)SOFT_REQ_REG,
- 	.enable_bit	= 6,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.flags		= RATE_FIXED,
+	.enable_reg	= OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+	.enable_bit	= 6,
 };
 
 static struct clk mclk_16xx = {
 	.name		= "mclk",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
-	.flags		= CLOCK_IN_OMAP16XX,
-	.enable_reg	= (void __iomem *)COM_CLK_DIV_CTRL_SEL,
+	.enable_reg	= OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL),
 	.enable_bit	= COM_ULPD_PLL_CLK_REQ,
 	.set_rate	= &omap1_set_ext_clk_rate,
 	.round_rate	= &omap1_round_ext_clk_rate,
 	.init		= &omap1_init_ext_clk,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk bclk_1510 = {
 	.name		= "bclk",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk bclk_16xx = {
 	.name		= "bclk",
+	.ops		= &clkops_generic,
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
-	.flags		= CLOCK_IN_OMAP16XX,
-	.enable_reg	= (void __iomem *)SWD_CLK_DIV_CTRL_SEL,
+	.enable_reg	= OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL),
 	.enable_bit	= SWD_ULPD_PLL_CLK_REQ,
 	.set_rate	= &omap1_set_ext_clk_rate,
 	.round_rate	= &omap1_round_ext_clk_rate,
 	.init		= &omap1_init_ext_clk,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mmc1_ck = {
 	.name		= "mmc_ck",
+	.ops		= &clkops_generic,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
-			  CLOCK_NO_IDLE_PARENT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 23,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk mmc2_ck = {
 	.name		= "mmc_ck",
 	.id		= 1,
+	.ops		= &clkops_generic,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
-	.flags		= CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
-	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+	.enable_reg	= OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
 	.enable_bit	= 20,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk virtual_ck_mpu = {
 	.name		= "mpu",
-	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
+	.ops		= &clkops_null,
 	.parent		= &arm_ck, /* Is smarter alias for */
 	.recalc		= &followparent_recalc,
 	.set_rate	= &omap1_select_table_rate,
 	.round_rate	= &omap1_round_to_table_rate,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 /* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
@@ -748,78 +651,19 @@
 static struct clk i2c_fck = {
 	.name		= "i2c_fck",
 	.id		= 1,
-	.flags		= CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
-			  ALWAYS_ENABLED,
+	.ops		= &clkops_null,
+	.flags		= CLOCK_NO_IDLE_PARENT,
 	.parent		= &armxor_ck.clk,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
 };
 
 static struct clk i2c_ick = {
 	.name		= "i2c_ick",
 	.id		= 1,
-	.flags		= CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
-			  ALWAYS_ENABLED,
+	.ops		= &clkops_null,
+	.flags		= CLOCK_NO_IDLE_PARENT,
 	.parent		= &armper_ck.clk,
 	.recalc		= &followparent_recalc,
-	.enable		= &omap1_clk_enable_generic,
-	.disable	= &omap1_clk_disable_generic,
-};
-
-static struct clk * onchip_clks[] = {
-	/* non-ULPD clocks */
-	&ck_ref,
-	&ck_dpll1,
-	/* CK_GEN1 clocks */
-	&ck_dpll1out.clk,
-	&sossi_ck,
-	&arm_ck,
-	&armper_ck.clk,
-	&arm_gpio_ck,
-	&armxor_ck.clk,
-	&armtim_ck.clk,
-	&armwdt_ck.clk,
-	&arminth_ck1510,  &arminth_ck16xx,
-	/* CK_GEN2 clocks */
-	&dsp_ck,
-	&dspmmu_ck,
-	&dspper_ck,
-	&dspxor_ck,
-	&dsptim_ck,
-	/* CK_GEN3 clocks */
-	&tc_ck.clk,
-	&tipb_ck,
-	&l3_ocpi_ck,
-	&tc1_ck,
-	&tc2_ck,
-	&dma_ck,
-	&dma_lcdfree_ck,
-	&api_ck.clk,
-	&lb_ck.clk,
-	&rhea1_ck,
-	&rhea2_ck,
-	&lcd_ck_16xx,
-	&lcd_ck_1510.clk,
-	/* ULPD clocks */
-	&uart1_1510,
-	&uart1_16xx.clk,
-	&uart2_ck,
-	&uart3_1510,
-	&uart3_16xx.clk,
-	&usb_clko,
-	&usb_hhc_ck1510, &usb_hhc_ck16xx,
-	&usb_dc_ck,
-	&mclk_1510,  &mclk_16xx,
-	&bclk_1510,  &bclk_16xx,
-	&mmc1_ck,
-	&mmc2_ck,
-	/* Virtual clocks */
-	&virtual_ck_mpu,
-	&i2c_fck,
-	&i2c_ick,
 };
 
 #endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ba5d7c0..bbbaeb0 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -86,7 +86,7 @@
 };
 
 static struct platform_device mbox_device = {
-	.name		= "mailbox",
+	.name		= "omap1-mailbox",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(mbox_resources),
 	.resource	= mbox_resources,
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c
index 89bb875..4ef26fa 100644
--- a/arch/arm/mach-omap1/id.c
+++ b/arch/arm/mach-omap1/id.c
@@ -38,6 +38,7 @@
 	{ .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
 	{ .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
 	{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
+	{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320500, .type = 0x08500000},
 	{ .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
 	{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
 	{ .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
@@ -77,7 +78,7 @@
 	prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
 	omap_id = omap_readl(OMAP32_ID_1);
 
-	/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
+	/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */
 	if (((prod_id >> 20) == 0) || (prod_id == omap_id))
 		prod_id = 0;
 	else
@@ -178,6 +179,7 @@
 
 	switch (cpu_type) {
 	case 0x07:
+	case 0x08:
 		omap_revision |= 0x07;
 		break;
 	case 0x03:
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 4c3e582..3afe540 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -52,6 +52,22 @@
 };
 #endif
 
+#ifdef CONFIG_ARCH_OMAP850
+static struct map_desc omap850_io_desc[] __initdata = {
+	{
+		.virtual	= OMAP850_DSP_BASE,
+		.pfn		= __phys_to_pfn(OMAP850_DSP_START),
+		.length		= OMAP850_DSP_SIZE,
+		.type		= MT_DEVICE
+	}, {
+		.virtual	= OMAP850_DSPREG_BASE,
+		.pfn		= __phys_to_pfn(OMAP850_DSPREG_START),
+		.length		= OMAP850_DSPREG_SIZE,
+		.type		= MT_DEVICE
+	}
+};
+#endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct map_desc omap1510_io_desc[] __initdata = {
 	{
@@ -109,6 +125,13 @@
 		iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
 	}
 #endif
+
+#ifdef CONFIG_ARCH_OMAP850
+	if (cpu_is_omap850()) {
+		iotable_init(omap850_io_desc, ARRAY_SIZE(omap850_io_desc));
+	}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap15xx()) {
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 9ad5197..de03c84 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -145,6 +145,14 @@
 };
 #endif
 
+#ifdef CONFIG_ARCH_OMAP850
+static struct omap_irq_bank omap850_irq_banks[] = {
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3f8e22f },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xfdb9c1f2 },
+	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0x800040f3 },
+};
+#endif
+
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_irq_bank omap1510_irq_banks[] = {
 	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3febfff },
@@ -184,6 +192,12 @@
 		irq_bank_count = ARRAY_SIZE(omap730_irq_banks);
 	}
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	if (cpu_is_omap850()) {
+		irq_banks = omap850_irq_banks;
+		irq_bank_count = ARRAY_SIZE(omap850_irq_banks);
+	}
+#endif
 #ifdef CONFIG_ARCH_OMAP15XX
 	if (cpu_is_omap1510()) {
 		irq_banks = omap1510_irq_banks;
@@ -214,9 +228,8 @@
 	irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
 
 	/* Enable interrupts in global mask */
-	if (cpu_is_omap730()) {
+	if (cpu_is_omap7xx())
 		irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
-	}
 
 	/* Install the interrupt handlers for each bank */
 	for (i = 0; i < irq_bank_count; i++) {
@@ -236,6 +249,8 @@
 
 	if (cpu_is_omap730())
 		omap_unmask_irq(INT_730_IH2_IRQ);
+	else if (cpu_is_omap850())
+		omap_unmask_irq(INT_850_IH2_IRQ);
 	else if (cpu_is_omap15xx())
 		omap_unmask_irq(INT_1510_IH2_IRQ);
 	else if (cpu_is_omap16xx())
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
index 59abbf3..0af4d6c 100644
--- a/arch/arm/mach-omap1/mailbox.c
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -1,7 +1,7 @@
 /*
  * Mailbox reservation modules for DSP
  *
- * Copyright (C) 2006 Nokia Corporation
+ * Copyright (C) 2006-2009 Nokia Corporation
  * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -27,7 +27,7 @@
 #define MAILBOX_DSP2ARM1_Flag		0x1c
 #define MAILBOX_DSP2ARM2_Flag		0x20
 
-unsigned long mbox_base;
+static void __iomem *mbox_base;
 
 struct omap_mbox1_fifo {
 	unsigned long cmd;
@@ -40,14 +40,14 @@
 	struct omap_mbox1_fifo rx_fifo;
 };
 
-static inline int mbox_read_reg(unsigned int reg)
+static inline int mbox_read_reg(size_t ofs)
 {
-	return __raw_readw(mbox_base + reg);
+	return __raw_readw(mbox_base + ofs);
 }
 
-static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+static inline void mbox_write_reg(u32 val, size_t ofs)
 {
-	__raw_writew(val, mbox_base + reg);
+	__raw_writew(val, mbox_base + ofs);
 }
 
 /* msg */
@@ -143,7 +143,7 @@
 };
 EXPORT_SYMBOL(mbox_dsp_info);
 
-static int __init omap1_mbox_probe(struct platform_device *pdev)
+static int __devinit omap1_mbox_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int ret = 0;
@@ -170,12 +170,10 @@
 	}
 	mbox_dsp_info.irq = res->start;
 
-	ret = omap_mbox_register(&mbox_dsp_info);
-
-	return ret;
+	return omap_mbox_register(&pdev->dev, &mbox_dsp_info);
 }
 
-static int omap1_mbox_remove(struct platform_device *pdev)
+static int __devexit omap1_mbox_remove(struct platform_device *pdev)
 {
 	omap_mbox_unregister(&mbox_dsp_info);
 
@@ -184,9 +182,9 @@
 
 static struct platform_driver omap1_mbox_driver = {
 	.probe	= omap1_mbox_probe,
-	.remove	= omap1_mbox_remove,
+	.remove	= __devexit_p(omap1_mbox_remove),
 	.driver	= {
-		.name	= "mailbox",
+		.name	= "omap1-mailbox",
 	},
 };
 
@@ -203,4 +201,7 @@
 module_init(omap1_mbox_init);
 module_exit(omap1_mbox_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
+MODULE_AUTHOR("Hiroshi DOYU" <Hiroshi.DOYU@nokia.com>);
+MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 575ba31..d040c3f 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -28,9 +28,9 @@
 #define DPS_RSTCT2_PER_EN	(1 << 0)
 #define DSP_RSTCT2_WD_PER_EN	(1 << 1)
 
-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
-const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
-#endif
+static int dsp_use;
+static struct clk *api_clk;
+static struct clk *dsp_clk;
 
 static void omap1_mcbsp_request(unsigned int id)
 {
@@ -39,20 +39,40 @@
 	 * are DSP public peripherals.
 	 */
 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
-		omap_dsp_request_mem();
-		/*
-		 * DSP external peripheral reset
-		 * FIXME: This should be moved to dsp code
-		 */
-		__raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
-				DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
+		if (dsp_use++ == 0) {
+			api_clk = clk_get(NULL, "api_clk");
+			dsp_clk = clk_get(NULL, "dsp_clk");
+			if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
+				clk_enable(api_clk);
+				clk_enable(dsp_clk);
+
+				omap_dsp_request_mem();
+				/*
+				 * DSP external peripheral reset
+				 * FIXME: This should be moved to dsp code
+				 */
+				__raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
+						DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
+			}
+		}
 	}
 }
 
 static void omap1_mcbsp_free(unsigned int id)
 {
-	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
-		omap_dsp_release_mem();
+	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+		if (--dsp_use == 0) {
+			omap_dsp_release_mem();
+			if (!IS_ERR(api_clk)) {
+				clk_disable(api_clk);
+				clk_put(api_clk);
+			}
+			if (!IS_ERR(dsp_clk)) {
+				clk_disable(dsp_clk);
+				clk_put(dsp_clk);
+			}
+		}
+	}
 }
 
 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
@@ -94,8 +114,6 @@
 		.rx_irq		= INT_McBSP1RX,
 		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 3,
 	},
 	{
 		.phys_base	= OMAP1510_MCBSP2_BASE,
@@ -112,8 +130,6 @@
 		.rx_irq		= INT_McBSP3RX,
 		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 3,
 	},
 };
 #define OMAP15XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap15xx_mcbsp_pdata)
@@ -131,8 +147,6 @@
 		.rx_irq		= INT_McBSP1RX,
 		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 3,
 	},
 	{
 		.phys_base	= OMAP1610_MCBSP2_BASE,
@@ -149,8 +163,6 @@
 		.rx_irq		= INT_McBSP3RX,
 		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 3,
 	},
 };
 #define OMAP16XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap16xx_mcbsp_pdata)
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index 062c905..721e0d9 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -58,6 +58,25 @@
 #define OMAP730_PINS_SZ		0
 #endif	/* CONFIG_ARCH_OMAP730 */
 
+#ifdef CONFIG_ARCH_OMAP850
+struct pin_config __initdata_or_module omap850_pins[] = {
+MUX_CFG_850("E2_850_KBR0",        12,   21,    0,   20,   1, 0)
+MUX_CFG_850("J7_850_KBR1",        12,   25,    0,   24,   1, 0)
+MUX_CFG_850("E1_850_KBR2",        12,   29,    0,   28,   1, 0)
+MUX_CFG_850("F3_850_KBR3",        13,    1,    0,    0,   1, 0)
+MUX_CFG_850("D2_850_KBR4",        13,    5,    0,    4,   1, 0)
+MUX_CFG_850("C2_850_KBC0",        13,    9,    0,    8,   1, 0)
+MUX_CFG_850("D3_850_KBC1",        13,   13,    0,   12,   1, 0)
+MUX_CFG_850("E4_850_KBC2",        13,   17,    0,   16,   1, 0)
+MUX_CFG_850("F4_850_KBC3",        13,   21,    0,   20,   1, 0)
+MUX_CFG_850("E3_850_KBC4",        13,   25,    0,   24,   1, 0)
+
+MUX_CFG_850("AA17_850_USB_DM",     2,   21,    0,   20,   0, 0)
+MUX_CFG_850("W16_850_USB_PU_EN",   2,   25,    0,   24,   0, 0)
+MUX_CFG_850("W17_850_USB_VBUSI",   2,   29,    0,   28,   0, 0)
+};
+#endif
+
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
 static struct pin_config __initdata_or_module omap1xxx_pins[] = {
 /*
@@ -419,6 +438,11 @@
 			printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
 			       cfg->pull_name, cfg->pull_reg, pull_orig, pull);
 	}
+
+#ifdef CONFIG_ARCH_OMAP850
+	omap_mux_register(omap850_pins, ARRAY_SIZE(omap850_pins));
+#endif
+
 #endif
 
 #ifdef CONFIG_OMAP_MUX_ERRORS
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 0002084..842090b 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -121,6 +121,13 @@
 		serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
 	}
 
+	if (cpu_is_omap850()) {
+		serial_platform_data[0].regshift = 0;
+		serial_platform_data[1].regshift = 0;
+		serial_platform_data[0].irq = INT_850_UART_MODEM_1;
+		serial_platform_data[1].irq = INT_850_UART_MODEM_IRDA_2;
+	}
+
 	if (cpu_is_omap15xx()) {
 		serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
 		serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 3754b79..64ab386 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -58,4 +58,12 @@
 
 config MACH_OMAP3_PANDORA
 	bool "OMAP3 Pandora"
-	depends on ARCH_OMAP3 && ARCH_OMAP34XX
\ No newline at end of file
+	depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OMAP_3430SDP
+	bool "OMAP 3430 SDP board"
+	depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_NOKIA_RX51
+	bool "Nokia RX-51 board"
+	depends on ARCH_OMAP3 && ARCH_OMAP34XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index bbd12bc..a2c3fcc 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \
+obj-y := irq.o id.o io.o sdrc.o control.o prcm.o clock.o mux.o \
 		devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
 		clockdomain.o
 
@@ -14,6 +14,10 @@
 obj-$(CONFIG_ARCH_OMAP2430)		+= sram243x.o
 obj-$(CONFIG_ARCH_OMAP3)		+= sram34xx.o
 
+# SMS/SDRC
+obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
+# obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
+
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-y					+= pm.o
@@ -38,4 +42,12 @@
 					   mmc-twl4030.o
 obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o \
 					   mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o \
+					   mmc-twl4030.o
 
+obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o \
+					   board-rx51-peripherals.o \
+# Platform specific device init code
+ifeq ($(CONFIG_USB_MUSB_SOC),y)
+obj-y					+= usb-musb.o
+endif
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 83fa372..2214365 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -35,12 +35,16 @@
 #include <mach/board.h>
 #include <mach/common.h>
 #include <mach/gpmc.h>
+#include <mach/usb.h>
 
 #include "mmc-twl4030.h"
 
+#define SDP2430_CS0_BASE	0x04000000
 #define	SDP2430_FLASH_CS	0
 #define	SDP2430_SMC91X_CS	5
 
+#define SDP2430_ETHR_GPIO_IRQ		149
+
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -102,8 +106,8 @@
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
-		.end	= OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
+		.start	= OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
+		.end	= OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 	},
 };
@@ -170,13 +174,13 @@
 	sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f;
 	udelay(100);
 
-	if (gpio_request(OMAP24XX_ETHR_GPIO_IRQ, "SMC91x irq") < 0) {
+	if (gpio_request(SDP2430_ETHR_GPIO_IRQ, "SMC91x irq") < 0) {
 		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			OMAP24XX_ETHR_GPIO_IRQ);
+			SDP2430_ETHR_GPIO_IRQ);
 		gpmc_cs_free(eth_cs);
 		goto out;
 	}
-	gpio_direction_input(OMAP24XX_ETHR_GPIO_IRQ);
+	gpio_direction_input(SDP2430_ETHR_GPIO_IRQ);
 
 out:
 	clk_disable(gpmc_fck);
@@ -185,7 +189,7 @@
 
 static void __init omap_2430sdp_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	sdp2430_init_smc91x();
@@ -251,6 +255,7 @@
 	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
+	usb_musb_init();
 }
 
 static void __init omap_2430sdp_map_io(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
new file mode 100644
index 0000000..ed92749
--- /dev/null
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -0,0 +1,542 @@
+/*
+ * linux/arch/arm/mach-omap2/board-3430sdp.c
+ *
+ * Copyright (C) 2007 Texas Instruments
+ *
+ * Modified from mach-omap2/board-generic.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/regulator/machine.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/mcspi.h>
+#include <mach/mux.h>
+#include <mach/board.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/gpmc.h>
+
+#include <mach/control.h>
+#include <mach/keypad.h>
+
+#include "mmc-twl4030.h"
+
+#define CONFIG_DISABLE_HFCLK 1
+
+#define SDP3430_ETHR_GPIO_IRQ_SDPV1	29
+#define SDP3430_ETHR_GPIO_IRQ_SDPV2	6
+#define SDP3430_SMC91X_CS		3
+
+#define SDP3430_TS_GPIO_IRQ_SDPV1	3
+#define SDP3430_TS_GPIO_IRQ_SDPV2	2
+
+#define ENABLE_VAUX3_DEDICATED	0x03
+#define ENABLE_VAUX3_DEV_GRP	0x20
+
+#define TWL4030_MSECURE_GPIO 22
+
+static struct resource sdp3430_smc91x_resources[] = {
+	[0] = {
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 0,
+		.end	= 0,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct platform_device sdp3430_smc91x_device = {
+	.name		= "smc91x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(sdp3430_smc91x_resources),
+	.resource	= sdp3430_smc91x_resources,
+};
+
+static int sdp3430_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(0, 4, KEY_C),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(1, 4, KEY_G),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(2, 4, KEY_3),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P),
+	KEY(3, 4, KEY_Q),
+	KEY(4, 0, KEY_R),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_T),
+	KEY(4, 3, KEY_U),
+	KEY(4, 4, KEY_D),
+	KEY(5, 0, KEY_V),
+	KEY(5, 1, KEY_W),
+	KEY(5, 2, KEY_L),
+	KEY(5, 3, KEY_S),
+	KEY(5, 4, KEY_H),
+	0
+};
+
+static struct twl4030_keypad_data sdp3430_kp_data = {
+	.rows		= 5,
+	.cols		= 6,
+	.keymap		= sdp3430_keymap,
+	.keymapsize	= ARRAY_SIZE(sdp3430_keymap),
+	.rep		= 1,
+};
+
+static int ts_gpio;	/* Needed for ads7846_get_pendown_state */
+
+/**
+ * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq
+ *
+ * @return - void. If request gpio fails then Flag KERN_ERR.
+ */
+static void ads7846_dev_init(void)
+{
+	if (gpio_request(ts_gpio, "ADS7846 pendown") < 0) {
+		printk(KERN_ERR "can't get ads746 pen down GPIO\n");
+		return;
+	}
+
+	gpio_direction_input(ts_gpio);
+
+	omap_set_gpio_debounce(ts_gpio, 1);
+	omap_set_gpio_debounce_time(ts_gpio, 0xa);
+}
+
+static int ads7846_get_pendown_state(void)
+{
+	return !gpio_get_value(ts_gpio);
+}
+
+static struct ads7846_platform_data tsc2046_config __initdata = {
+	.get_pendown_state	= ads7846_get_pendown_state,
+	.keep_vref_on		= 1,
+};
+
+
+static struct omap2_mcspi_device_config tsc2046_mcspi_config = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+static struct spi_board_info sdp3430_spi_board_info[] __initdata = {
+	[0] = {
+		/*
+		 * TSC2046 operates at a max freqency of 2MHz, so
+		 * operate slightly below at 1.5MHz
+		 */
+		.modalias		= "ads7846",
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.max_speed_hz		= 1500000,
+		.controller_data	= &tsc2046_mcspi_config,
+		.irq			= 0,
+		.platform_data		= &tsc2046_config,
+	},
+};
+
+static struct platform_device sdp3430_lcd_device = {
+	.name		= "sdp2430_lcd",
+	.id		= -1,
+};
+
+static struct regulator_consumer_supply sdp3430_vdac_supply = {
+	.supply		= "vdac",
+	.dev		= &sdp3430_lcd_device.dev,
+};
+
+static struct regulator_consumer_supply sdp3430_vdvi_supply = {
+	.supply		= "vdvi",
+	.dev		= &sdp3430_lcd_device.dev,
+};
+
+static struct platform_device *sdp3430_devices[] __initdata = {
+	&sdp3430_smc91x_device,
+	&sdp3430_lcd_device,
+};
+
+static inline void __init sdp3430_init_smc91x(void)
+{
+	int eth_cs;
+	unsigned long cs_mem_base;
+	int eth_gpio = 0;
+
+	eth_cs = SDP3430_SMC91X_CS;
+
+	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+		return;
+	}
+
+	sdp3430_smc91x_resources[0].start = cs_mem_base + 0x300;
+	sdp3430_smc91x_resources[0].end = cs_mem_base + 0x30f;
+	udelay(100);
+
+	if (omap_rev() > OMAP3430_REV_ES1_0)
+		eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV2;
+	else
+		eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV1;
+
+	sdp3430_smc91x_resources[1].start = gpio_to_irq(eth_gpio);
+
+	if (gpio_request(eth_gpio, "SMC91x irq") < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+			eth_gpio);
+		return;
+	}
+	gpio_direction_input(eth_gpio);
+}
+
+static void __init omap_3430sdp_init_irq(void)
+{
+	omap2_init_common_hw(NULL);
+	omap_init_irq();
+	omap_gpio_init();
+	sdp3430_init_smc91x();
+}
+
+static struct omap_uart_config sdp3430_uart_config __initdata = {
+	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_lcd_config sdp3430_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_board_config_kernel sdp3430_config[] __initdata = {
+	{ OMAP_TAG_UART,	&sdp3430_uart_config },
+	{ OMAP_TAG_LCD,		&sdp3430_lcd_config },
+};
+
+static int sdp3430_batt_table[] = {
+/* 0 C*/
+30800, 29500, 28300, 27100,
+26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
+17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
+11600, 11200, 10800, 10400, 10000, 9630,   9280,   8950,   8620,   8310,
+8020,   7730,   7460,   7200,   6950,   6710,   6470,   6250,   6040,   5830,
+5640,   5450,   5260,   5090,   4920,   4760,   4600,   4450,   4310,   4170,
+4040,   3910,   3790,   3670,   3550
+};
+
+static struct twl4030_bci_platform_data sdp3430_bci_data = {
+	.battery_tmp_tbl	= sdp3430_batt_table,
+	.tblsize		= ARRAY_SIZE(sdp3430_batt_table),
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+	{
+		.mmc		= 1,
+		/* 8 bits (default) requires S6.3 == ON,
+		 * so the SIM card isn't used; else 4 bits.
+		 */
+		.wires		= 8,
+		.gpio_wp	= 4,
+	},
+	{
+		.mmc		= 2,
+		.wires		= 8,
+		.gpio_wp	= 7,
+	},
+	{}	/* Terminator */
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply sdp3430_vsim_supply = {
+	.supply			= "vmmc_aux",
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc2_supply = {
+	.supply			= "vmmc",
+};
+
+static int sdp3430_twl_gpio_setup(struct device *dev,
+		unsigned gpio, unsigned ngpio)
+{
+	/* gpio + 0 is "mmc0_cd" (input/IRQ),
+	 * gpio + 1 is "mmc1_cd" (input/IRQ)
+	 */
+	mmc[0].gpio_cd = gpio + 0;
+	mmc[1].gpio_cd = gpio + 1;
+	twl4030_mmc_init(mmc);
+
+	/* link regulators to MMC adapters ... we "know" the
+	 * regulators will be set up only *after* we return.
+	 */
+	sdp3430_vmmc1_supply.dev = mmc[0].dev;
+	sdp3430_vsim_supply.dev = mmc[0].dev;
+	sdp3430_vmmc2_supply.dev = mmc[1].dev;
+
+	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
+	gpio_request(gpio + 7, "sub_lcd_en_bkl");
+	gpio_direction_output(gpio + 7, 0);
+
+	/* gpio + 15 is "sub_lcd_nRST" (output) */
+	gpio_request(gpio + 15, "sub_lcd_nRST");
+	gpio_direction_output(gpio + 15, 0);
+
+	return 0;
+}
+
+static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
+	.gpio_base	= OMAP_MAX_GPIO_LINES,
+	.irq_base	= TWL4030_GPIO_IRQ_BASE,
+	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.pulldowns	= BIT(2) | BIT(6) | BIT(8) | BIT(13)
+				| BIT(16) | BIT(17),
+	.setup		= sdp3430_twl_gpio_setup,
+};
+
+static struct twl4030_usb_data sdp3430_usb_data = {
+	.usb_mode	= T2_USB_MODE_ULPI,
+};
+
+static struct twl4030_madc_platform_data sdp3430_madc_data = {
+	.irq_line	= 1,
+};
+
+/*
+ * Apply all the fixed voltages since most versions of U-Boot
+ * don't bother with that initialization.
+ */
+
+/* VAUX1 for mainboard (irda and sub-lcd) */
+static struct regulator_init_data sdp3430_vaux1 = {
+	.constraints = {
+		.min_uV			= 2800000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VAUX2 for camera module */
+static struct regulator_init_data sdp3430_vaux2 = {
+	.constraints = {
+		.min_uV			= 2800000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VAUX3 for LCD board */
+static struct regulator_init_data sdp3430_vaux3 = {
+	.constraints = {
+		.min_uV			= 2800000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VAUX4 for OMAP VDD_CSI2 (camera) */
+static struct regulator_init_data sdp3430_vaux4 = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data sdp3430_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &sdp3430_vmmc1_supply,
+};
+
+/* VMMC2 for MMC2 card */
+static struct regulator_init_data sdp3430_vmmc2 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 1850000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &sdp3430_vmmc2_supply,
+};
+
+/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
+static struct regulator_init_data sdp3430_vsim = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 3000000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &sdp3430_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video */
+static struct regulator_init_data sdp3430_vdac = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &sdp3430_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data sdp3430_vpll2 = {
+	.constraints = {
+		.name			= "VDVI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &sdp3430_vdvi_supply,
+};
+
+static struct twl4030_platform_data sdp3430_twldata = {
+	.irq_base	= TWL4030_IRQ_BASE,
+	.irq_end	= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.bci		= &sdp3430_bci_data,
+	.gpio		= &sdp3430_gpio_data,
+	.madc		= &sdp3430_madc_data,
+	.keypad		= &sdp3430_kp_data,
+	.usb		= &sdp3430_usb_data,
+
+	.vaux1		= &sdp3430_vaux1,
+	.vaux2		= &sdp3430_vaux2,
+	.vaux3		= &sdp3430_vaux3,
+	.vaux4		= &sdp3430_vaux4,
+	.vmmc1		= &sdp3430_vmmc1,
+	.vmmc2		= &sdp3430_vmmc2,
+	.vsim		= &sdp3430_vsim,
+	.vdac		= &sdp3430_vdac,
+	.vpll2		= &sdp3430_vpll2,
+};
+
+static struct i2c_board_info __initdata sdp3430_i2c_boardinfo[] = {
+	{
+		I2C_BOARD_INFO("twl4030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &sdp3430_twldata,
+	},
+};
+
+static int __init omap3430_i2c_init(void)
+{
+	/* i2c1 for PMIC only */
+	omap_register_i2c_bus(1, 2600, sdp3430_i2c_boardinfo,
+			ARRAY_SIZE(sdp3430_i2c_boardinfo));
+	/* i2c2 on camera connector (for sensor control) and optional isp1301 */
+	omap_register_i2c_bus(2, 400, NULL, 0);
+	/* i2c3 on display connector (for DVI, tfp410) */
+	omap_register_i2c_bus(3, 400, NULL, 0);
+	return 0;
+}
+
+static void __init omap_3430sdp_init(void)
+{
+	omap3430_i2c_init();
+	platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices));
+	omap_board_config = sdp3430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	if (omap_rev() > OMAP3430_REV_ES1_0)
+		ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2;
+	else
+		ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV1;
+	sdp3430_spi_board_info[0].irq = gpio_to_irq(ts_gpio);
+	spi_register_board_info(sdp3430_spi_board_info,
+				ARRAY_SIZE(sdp3430_spi_board_info));
+	ads7846_dev_init();
+	omap_serial_init();
+	usb_musb_init();
+}
+
+static void __init omap_3430sdp_map_io(void)
+{
+	omap2_set_globals_343x();
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
+	/* Maintainer: Syed Khasim - Texas Instruments Inc */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap_3430sdp_map_io,
+	.init_irq	= omap_3430sdp_init_irq,
+	.init_machine	= omap_3430sdp_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 0a7b24ba..06dfba8 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -51,6 +51,7 @@
 
 #define APOLLON_FLASH_CS	0
 #define APOLLON_ETH_CS		1
+#define APOLLON_ETHR_GPIO_IRQ	74
 
 static struct mtd_partition apollon_partitions[] = {
 	{
@@ -249,7 +250,7 @@
 
 static void __init omap_apollon_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	apollon_init_smc91x();
@@ -272,7 +273,6 @@
 
 static struct omap_board_config_kernel apollon_config[] = {
 	{ OMAP_TAG_UART,	&apollon_uart_config },
-	{ OMAP_TAG_USB,		&apollon_usb_config },
 	{ OMAP_TAG_LCD,		&apollon_lcd_config },
 };
 
@@ -299,6 +299,7 @@
 	omap_cfg_reg(P21_242X_GPIO12);
 	gpio_request(12, "USB suspend");
 	gpio_direction_output(12, 0);
+	omap_usb_init(&apollon_usb_config);
 }
 
 static void __init omap_apollon_init(void)
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 3b34c20..3492162 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -33,7 +33,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 }
 
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 5e9b146..a0267a9 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -47,6 +47,8 @@
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
 
+#define H4_ETHR_GPIO_IRQ		92
+
 static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
 static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
 
@@ -341,7 +343,7 @@
 	udelay(100);
 
 	omap_cfg_reg(M15_24XX_GPIO92);
-	if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0)
+	if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0)
 		gpmc_cs_free(eth_cs);
 
 out:
@@ -363,7 +365,7 @@
 
 static void __init omap_h4_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	h4_init_flash();
@@ -377,6 +379,39 @@
 	.ctrl_name	= "internal",
 };
 
+static struct omap_usb_config h4_usb_config __initdata = {
+#ifdef	CONFIG_MACH_OMAP2_H4_USB1
+	/* NOTE:  usb1 could also be used with 3 wire signaling */
+	.pins[1]	= 4,
+#endif
+
+#ifdef	CONFIG_MACH_OMAP_H4_OTG
+	/* S1.10 ON -- USB OTG port
+	 * usb0 switched to Mini-AB port and isp1301 transceiver;
+	 * S2.POS3 = OFF, S2.POS4 = ON ... to allow battery charging
+	 */
+	.otg		= 1,
+	.pins[0]	= 4,
+#ifdef	CONFIG_USB_GADGET_OMAP
+	/* use OTG cable, or standard A-to-MiniB */
+	.hmc_mode	= 0x14,	/* 0:dev/otg 1:host 2:disable */
+#elif	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	/* use OTG cable, or NONSTANDARD (B-to-MiniB) */
+	.hmc_mode	= 0x11,	/* 0:host 1:host 2:disable */
+#endif	/* XX */
+
+#else
+	/* S1.10 OFF -- usb "download port"
+	 * usb0 switched to Mini-B port and isp1105 transceiver;
+	 * S2.POS3 = ON, S2.POS4 = OFF ... to enable battery charging
+	 */
+	.register_dev	= 1,
+	.pins[0]	= 3,
+/*	.hmc_mode	= 0x14,*/	/* 0:dev 1:host 2:disable */
+	.hmc_mode	= 0x00,		/* 0:dev|otg 1:disable 2:disable */
+#endif
+};
+
 static struct omap_board_config_kernel h4_config[] = {
 	{ OMAP_TAG_UART,	&h4_uart_config },
 	{ OMAP_TAG_LCD,		&h4_lcd_config },
@@ -428,6 +463,7 @@
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap_board_config = h4_config;
 	omap_board_config_size = ARRAY_SIZE(h4_config);
+	omap_usb_init(&h4_usb_config);
 	omap_serial_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 6031e17..e096f77 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -22,31 +22,34 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/board-ldp.h>
 #include <mach/mcspi.h>
 #include <mach/gpio.h>
 #include <mach/board.h>
 #include <mach/common.h>
 #include <mach/gpmc.h>
 
-#include <asm/io.h>
 #include <asm/delay.h>
 #include <mach/control.h>
+#include <mach/usb.h>
 
 #include "mmc-twl4030.h"
 
-#define SDP3430_SMC91X_CS	3
+#define LDP_SMC911X_CS		1
+#define LDP_SMC911X_GPIO	152
+#define DEBUG_BASE		0x08000000
+#define LDP_ETHR_START		DEBUG_BASE
 
 static struct resource ldp_smc911x_resources[] = {
 	[0] = {
-		.start	= OMAP34XX_ETHR_START,
-		.end	= OMAP34XX_ETHR_START + SZ_4K,
+		.start	= LDP_ETHR_START,
+		.end	= LDP_ETHR_START + SZ_4K,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -98,7 +101,7 @@
 
 static void __init omap_ldp_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 	ldp_init_smc911x();
@@ -162,6 +165,7 @@
 	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
+	usb_musb_init();
 }
 
 static void __init omap_ldp_map_io(void)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index e39cd2c..744740a 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -41,6 +41,7 @@
 #include <mach/gpmc.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
+#include <mach/usb.h>
 
 #include "mmc-twl4030.h"
 
@@ -175,9 +176,6 @@
 {
 	omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
 			ARRAY_SIZE(beagle_i2c_boardinfo));
-#ifdef CONFIG_I2C2_OMAP_BEAGLE
-	omap_register_i2c_bus(2, 400, NULL, 0);
-#endif
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
 	omap_register_i2c_bus(3, 100, NULL, 0);
@@ -186,7 +184,7 @@
 
 static void __init omap3_beagle_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -316,6 +314,7 @@
 	/* REVISIT leave DVI powered down until it's needed ... */
 	gpio_direction_output(170, true);
 
+	usb_musb_init();
 	omap3beagle_flash_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index b319610..402f09c 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -34,6 +34,7 @@
 #include <mach/gpio.h>
 #include <mach/hardware.h>
 #include <mach/mcspi.h>
+#include <mach/usb.h>
 
 #include "mmc-twl4030.h"
 
@@ -53,6 +54,13 @@
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 127,
 		.ext_clock	= 1,
+		.transceiver	= true,
+	},
+	{
+		.mmc		= 3,
+		.wires		= 4,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
 	},
 	{}	/* Terminator */
 };
@@ -110,7 +118,7 @@
 
 static void __init omap3pandora_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -193,6 +201,7 @@
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap3pandora_ads7846_init();
+	usb_musb_init();
 }
 
 static void __init omap3pandora_map_io(void)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 82b3dc5..b3f6e9d8 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -37,20 +37,85 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 
-#include <mach/board-overo.h>
 #include <mach/board.h>
 #include <mach/common.h>
 #include <mach/gpio.h>
 #include <mach/gpmc.h>
 #include <mach/hardware.h>
 #include <mach/nand.h>
+#include <mach/usb.h>
 
 #include "mmc-twl4030.h"
 
+#define OVERO_GPIO_BT_XGATE	15
+#define OVERO_GPIO_W2W_NRESET	16
+#define OVERO_GPIO_BT_NRESET	164
+#define OVERO_GPIO_USBH_CPEN	168
+#define OVERO_GPIO_USBH_NRESET	183
+
 #define NAND_BLOCK_SIZE SZ_128K
 #define GPMC_CS0_BASE  0x60
 #define GPMC_CS_SIZE   0x30
 
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
+	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+
+#include <mach/mcspi.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+	.turbo_mode	= 0,
+	.single_channel	= 1,	/* 0: slave, 1: master */
+};
+
+static int ads7846_get_pendown_state(void)
+{
+	return !gpio_get_value(OVERO_GPIO_PENDOWN);
+}
+
+static struct ads7846_platform_data ads7846_config = {
+	.x_max			= 0x0fff,
+	.y_max			= 0x0fff,
+	.x_plate_ohms		= 180,
+	.pressure_max		= 255,
+	.debounce_max		= 10,
+	.debounce_tol		= 3,
+	.debounce_rep		= 1,
+	.get_pendown_state	= ads7846_get_pendown_state,
+	.keep_vref_on		= 1,
+};
+
+static struct spi_board_info overo_spi_board_info[] __initdata = {
+	{
+		.modalias		= "ads7846",
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.max_speed_hz		= 1500000,
+		.controller_data	= &ads7846_mcspi_config,
+		.irq			= OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
+		.platform_data		= &ads7846_config,
+	}
+};
+
+static void __init overo_ads7846_init(void)
+{
+	if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) &&
+	    (gpio_direction_input(OVERO_GPIO_PENDOWN) == 0)) {
+		gpio_export(OVERO_GPIO_PENDOWN, 0);
+	} else {
+		printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n");
+		return;
+	}
+
+	spi_register_board_info(overo_spi_board_info,
+			ARRAY_SIZE(overo_spi_board_info));
+}
+
+#else
+static inline void __init overo_ads7846_init(void) { return; }
+#endif
+
 static struct mtd_partition overo_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -174,7 +239,7 @@
 
 static void __init overo_init_irq(void)
 {
-	omap2_init_common_hw();
+	omap2_init_common_hw(NULL);
 	omap_init_irq();
 	omap_gpio_init();
 }
@@ -209,6 +274,7 @@
 		.wires		= 4,
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= -EINVAL,
+		.transceiver	= true,
 	},
 	{}	/* Terminator */
 };
@@ -222,6 +288,8 @@
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
 	overo_flash_init();
+	usb_musb_init();
+	overo_ads7846_init();
 
 	if ((gpio_request(OVERO_GPIO_W2W_NRESET,
 			  "OVERO_GPIO_W2W_NRESET") == 0) &&
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
new file mode 100644
index 0000000..a738172
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -0,0 +1,419 @@
+/*
+ * linux/arch/arm/mach-omap2/board-rx51-flash.c
+ *
+ * Copyright (C) 2008-2009 Nokia
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+
+#include <mach/mcspi.h>
+#include <mach/mux.h>
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/gpmc.h>
+#include <mach/keypad.h>
+
+#include "mmc-twl4030.h"
+
+
+#define SMC91X_CS			1
+#define SMC91X_GPIO_IRQ			54
+#define SMC91X_GPIO_RESET		164
+#define SMC91X_GPIO_PWRDWN		86
+
+static struct resource rx51_smc91x_resources[] = {
+	[0] = {
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct platform_device rx51_smc91x_device = {
+	.name		= "smc91x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(rx51_smc91x_resources),
+	.resource	= rx51_smc91x_resources,
+};
+
+static int rx51_keymap[] = {
+	KEY(0, 0, KEY_Q),
+	KEY(0, 1, KEY_W),
+	KEY(0, 2, KEY_E),
+	KEY(0, 3, KEY_R),
+	KEY(0, 4, KEY_T),
+	KEY(0, 5, KEY_Y),
+	KEY(0, 6, KEY_U),
+	KEY(0, 7, KEY_I),
+	KEY(1, 0, KEY_O),
+	KEY(1, 1, KEY_D),
+	KEY(1, 2, KEY_DOT),
+	KEY(1, 3, KEY_V),
+	KEY(1, 4, KEY_DOWN),
+	KEY(2, 0, KEY_P),
+	KEY(2, 1, KEY_F),
+	KEY(2, 2, KEY_UP),
+	KEY(2, 3, KEY_B),
+	KEY(2, 4, KEY_RIGHT),
+	KEY(3, 0, KEY_COMMA),
+	KEY(3, 1, KEY_G),
+	KEY(3, 2, KEY_ENTER),
+	KEY(3, 3, KEY_N),
+	KEY(4, 0, KEY_BACKSPACE),
+	KEY(4, 1, KEY_H),
+	KEY(4, 3, KEY_M),
+	KEY(4, 4, KEY_LEFTCTRL),
+	KEY(5, 1, KEY_J),
+	KEY(5, 2, KEY_Z),
+	KEY(5, 3, KEY_SPACE),
+	KEY(5, 4, KEY_LEFTSHIFT),
+	KEY(6, 0, KEY_A),
+	KEY(6, 1, KEY_K),
+	KEY(6, 2, KEY_X),
+	KEY(6, 3, KEY_SPACE),
+	KEY(6, 4, KEY_FN),
+	KEY(7, 0, KEY_S),
+	KEY(7, 1, KEY_L),
+	KEY(7, 2, KEY_C),
+	KEY(7, 3, KEY_LEFT),
+	KEY(0xff, 0, KEY_F6),
+	KEY(0xff, 1, KEY_F7),
+	KEY(0xff, 2, KEY_F8),
+	KEY(0xff, 4, KEY_F9),
+	KEY(0xff, 5, KEY_F10),
+};
+
+static struct twl4030_keypad_data rx51_kp_data = {
+	.rows		= 8,
+	.cols		= 8,
+	.keymap		= rx51_keymap,
+	.keymapsize	= ARRAY_SIZE(rx51_keymap),
+	.rep		= 1,
+};
+
+static struct platform_device *rx51_peripherals_devices[] = {
+	&rx51_smc91x_device,
+};
+
+/*
+ * Timings are taken from smsc-lan91c96-ms.pdf
+ */
+static int smc91x_init_gpmc(int cs)
+{
+	struct gpmc_timings t;
+	const int t2_r = 45;		/* t2 in Figure 12.10 */
+	const int t2_w = 30;		/* t2 in Figure 12.11 */
+	const int t3 = 15;		/* t3 in Figure 12.10 */
+	const int t5_r = 0;		/* t5 in Figure 12.10 */
+	const int t6_r = 45;		/* t6 in Figure 12.10 */
+	const int t6_w = 0;		/* t6 in Figure 12.11 */
+	const int t7_w = 15;		/* t7 in Figure 12.11 */
+	const int t15 = 12;		/* t15 in Figure 12.2 */
+	const int t20 = 185;		/* t20 in Figure 12.2 */
+
+	memset(&t, 0, sizeof(t));
+
+	t.cs_on = t15;
+	t.cs_rd_off = t3 + t2_r + t5_r;	/* Figure 12.10 */
+	t.cs_wr_off = t3 + t2_w + t6_w;	/* Figure 12.11 */
+	t.adv_on = t3;			/* Figure 12.10 */
+	t.adv_rd_off = t3 + t2_r;	/* Figure 12.10 */
+	t.adv_wr_off = t3 + t2_w;	/* Figure 12.11 */
+	t.oe_off = t3 + t2_r + t5_r;	/* Figure 12.10 */
+	t.oe_on = t.oe_off - t6_r;	/* Figure 12.10 */
+	t.we_off = t3 + t2_w + t6_w;	/* Figure 12.11 */
+	t.we_on = t.we_off - t7_w;	/* Figure 12.11 */
+	t.rd_cycle = t20;		/* Figure 12.2 */
+	t.wr_cycle = t20;		/* Figure 12.4 */
+	t.access = t3 + t2_r + t5_r;	/* Figure 12.10 */
+	t.wr_access = t3 + t2_w + t6_w;	/* Figure 12.11 */
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16);
+
+	return gpmc_cs_set_timings(cs, &t);
+}
+
+static void __init rx51_init_smc91x(void)
+{
+	unsigned long cs_mem_base;
+	int ret;
+
+	omap_cfg_reg(U8_34XX_GPIO54_DOWN);
+	omap_cfg_reg(G25_34XX_GPIO86_OUT);
+	omap_cfg_reg(H19_34XX_GPIO164_OUT);
+
+	if (gpmc_cs_request(SMC91X_CS, SZ_16M, &cs_mem_base) < 0) {
+		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+		return;
+	}
+
+	rx51_smc91x_resources[0].start = cs_mem_base + 0x300;
+	rx51_smc91x_resources[0].end = cs_mem_base + 0x30f;
+
+	smc91x_init_gpmc(SMC91X_CS);
+
+	if (gpio_request(SMC91X_GPIO_IRQ, "SMC91X irq") < 0)
+		goto free1;
+
+	gpio_direction_input(SMC91X_GPIO_IRQ);
+	rx51_smc91x_resources[1].start = gpio_to_irq(SMC91X_GPIO_IRQ);
+
+	ret = gpio_request(SMC91X_GPIO_PWRDWN, "SMC91X powerdown");
+	if (ret)
+		goto free2;
+	gpio_direction_output(SMC91X_GPIO_PWRDWN, 0);
+
+	ret = gpio_request(SMC91X_GPIO_RESET, "SMC91X reset");
+	if (ret)
+		goto free3;
+	gpio_direction_output(SMC91X_GPIO_RESET, 0);
+	gpio_set_value(SMC91X_GPIO_RESET, 1);
+	msleep(100);
+	gpio_set_value(SMC91X_GPIO_RESET, 0);
+
+	return;
+
+free3:
+	gpio_free(SMC91X_GPIO_PWRDWN);
+free2:
+	gpio_free(SMC91X_GPIO_IRQ);
+free1:
+	gpmc_cs_free(SMC91X_CS);
+
+	printk(KERN_ERR "Could not initialize smc91x\n");
+}
+
+static struct twl4030_madc_platform_data rx51_madc_data = {
+	.irq_line		= 1,
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+	{
+		.name		= "external",
+		.mmc		= 1,
+		.wires		= 4,
+		.cover_only	= true,
+		.gpio_cd	= 160,
+		.gpio_wp	= -EINVAL,
+	},
+	{
+		.name		= "internal",
+		.mmc		= 2,
+		.wires		= 8,
+		.gpio_cd	= -EINVAL,
+		.gpio_wp	= -EINVAL,
+	},
+	{}	/* Terminator */
+};
+
+static struct regulator_consumer_supply rx51_vmmc1_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply rx51_vmmc2_supply = {
+	.supply			= "vmmc",
+};
+
+static struct regulator_consumer_supply rx51_vsim_supply = {
+	.supply			= "vmmc_aux",
+};
+
+static struct regulator_init_data rx51_vaux1 = {
+	.constraints = {
+		.name			= "V28",
+		.min_uV			= 2800000,
+		.max_uV			= 2800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data rx51_vaux2 = {
+	.constraints = {
+		.name			= "VCSI",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+/* VAUX3 - adds more power to VIO_18 rail */
+static struct regulator_init_data rx51_vaux3 = {
+	.constraints = {
+		.name			= "VCAM_DIG_18",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data rx51_vaux4 = {
+	.constraints = {
+		.name			= "VCAM_ANA_28",
+		.min_uV			= 2800000,
+		.max_uV			= 2800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct regulator_init_data rx51_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &rx51_vmmc1_supply,
+};
+
+static struct regulator_init_data rx51_vmmc2 = {
+	.constraints = {
+		.name			= "VMMC2_30",
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &rx51_vmmc2_supply,
+};
+
+static struct regulator_init_data rx51_vsim = {
+	.constraints = {
+		.name			= "VMMC2_IO_18",
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &rx51_vsim_supply,
+};
+
+static struct regulator_init_data rx51_vdac = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
+{
+	/* FIXME this gpio setup is just a placeholder for now */
+	gpio_request(gpio + 6, "backlight_pwm");
+	gpio_direction_output(gpio + 6, 0);
+	gpio_request(gpio + 7, "speaker_en");
+	gpio_direction_output(gpio + 7, 1);
+
+	/* set up MMC adapters, linking their regulators to them */
+	twl4030_mmc_init(mmc);
+	rx51_vmmc1_supply.dev = mmc[0].dev;
+	rx51_vmmc2_supply.dev = mmc[1].dev;
+	rx51_vsim_supply.dev = mmc[1].dev;
+
+	return 0;
+}
+
+static struct twl4030_gpio_platform_data rx51_gpio_data = {
+	.gpio_base		= OMAP_MAX_GPIO_LINES,
+	.irq_base		= TWL4030_GPIO_IRQ_BASE,
+	.irq_end		= TWL4030_GPIO_IRQ_END,
+	.pulldowns		= BIT(0) | BIT(1) | BIT(2) | BIT(3)
+				| BIT(4) | BIT(5)
+				| BIT(8) | BIT(9) | BIT(10) | BIT(11)
+				| BIT(12) | BIT(13) | BIT(14) | BIT(15)
+				| BIT(16) | BIT(17) ,
+	.setup			= rx51_twlgpio_setup,
+};
+
+static struct twl4030_platform_data rx51_twldata = {
+	.irq_base		= TWL4030_IRQ_BASE,
+	.irq_end		= TWL4030_IRQ_END,
+
+	/* platform_data for children goes here */
+	.gpio			= &rx51_gpio_data,
+	.keypad			= &rx51_kp_data,
+	.madc			= &rx51_madc_data,
+
+	.vaux1			= &rx51_vaux1,
+	.vaux2			= &rx51_vaux2,
+	.vaux3			= &rx51_vaux3,
+	.vaux4			= &rx51_vaux4,
+	.vmmc1			= &rx51_vmmc1,
+	.vmmc2			= &rx51_vmmc2,
+	.vsim			= &rx51_vsim,
+	.vdac			= &rx51_vdac,
+};
+
+static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = {
+	{
+		I2C_BOARD_INFO("twl5030", 0x48),
+		.flags = I2C_CLIENT_WAKE,
+		.irq = INT_34XX_SYS_NIRQ,
+		.platform_data = &rx51_twldata,
+	},
+};
+
+static int __init rx51_i2c_init(void)
+{
+	omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1,
+			ARRAY_SIZE(rx51_peripherals_i2c_board_info_1));
+	omap_register_i2c_bus(2, 100, NULL, 0);
+	omap_register_i2c_bus(3, 400, NULL, 0);
+	return 0;
+}
+
+
+void __init rx51_peripherals_init(void)
+{
+	platform_add_devices(rx51_peripherals_devices,
+				ARRAY_SIZE(rx51_peripherals_devices));
+	rx51_i2c_init();
+	rx51_init_smc91x();
+}
+
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
new file mode 100644
index 0000000..3a0daac
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -0,0 +1,96 @@
+/*
+ * linux/arch/arm/mach-omap2/board-rx51.c
+ *
+ * Copyright (C) 2007, 2008 Nokia
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/mcspi.h>
+#include <mach/mux.h>
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/keypad.h>
+#include <mach/dma.h>
+#include <mach/gpmc.h>
+#include <mach/usb.h>
+
+static struct omap_uart_config rx51_uart_config = {
+	.enabled_uarts	= ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_lcd_config rx51_lcd_config = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_fbmem_config rx51_fbmem0_config = {
+	.size = 752 * 1024,
+};
+
+static struct omap_fbmem_config rx51_fbmem1_config = {
+	.size = 752 * 1024,
+};
+
+static struct omap_fbmem_config rx51_fbmem2_config = {
+	.size = 752 * 1024,
+};
+
+static struct omap_board_config_kernel rx51_config[] = {
+	{ OMAP_TAG_UART,	&rx51_uart_config },
+	{ OMAP_TAG_FBMEM,	&rx51_fbmem0_config },
+	{ OMAP_TAG_FBMEM,	&rx51_fbmem1_config },
+	{ OMAP_TAG_FBMEM,	&rx51_fbmem2_config },
+	{ OMAP_TAG_LCD,		&rx51_lcd_config },
+};
+
+static void __init rx51_init_irq(void)
+{
+	omap2_init_common_hw(NULL);
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+extern void __init rx51_peripherals_init(void);
+
+static void __init rx51_init(void)
+{
+	omap_board_config = rx51_config;
+	omap_board_config_size = ARRAY_SIZE(rx51_config);
+	omap_serial_init();
+	usb_musb_init();
+	rx51_peripherals_init();
+}
+
+static void __init rx51_map_io(void)
+{
+	omap2_set_globals_343x();
+	omap2_map_common_io();
+}
+
+MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
+	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= rx51_map_io,
+	.init_irq	= rx51_init_irq,
+	.init_machine	= rx51_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index ce4d46a..4247a15 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -26,11 +26,10 @@
 
 #include <mach/clock.h>
 #include <mach/clockdomain.h>
-#include <mach/sram.h>
 #include <mach/cpu.h>
 #include <asm/div64.h>
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "sdrc.h"
 #include "clock.h"
 #include "prm.h"
@@ -46,7 +45,7 @@
 #define DPLL_MIN_DIVIDER		1
 
 /* Possible error results from _dpll_test_mult */
-#define DPLL_MULT_UNDERFLOW		(1 << 0)
+#define DPLL_MULT_UNDERFLOW		-1
 
 /*
  * Scale factor to mitigate roundoff errors in DPLL rate rounding.
@@ -59,6 +58,16 @@
 #define DPLL_ROUNDING_VAL		((DPLL_SCALE_BASE / 2) * \
 					 (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
 
+/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
+#define DPLL_FINT_BAND1_MIN		750000
+#define DPLL_FINT_BAND1_MAX		2100000
+#define DPLL_FINT_BAND2_MIN		7500000
+#define DPLL_FINT_BAND2_MAX		21000000
+
+/* _dpll_test_fint() return codes */
+#define DPLL_FINT_UNDERFLOW		-1
+#define DPLL_FINT_INVALID		-2
+
 u8 cpu_mask;
 
 /*-------------------------------------------------------------------------
@@ -66,6 +75,74 @@
  *-------------------------------------------------------------------------*/
 
 /**
+ * _omap2xxx_clk_commit - commit clock parent/rate changes in hardware
+ * @clk: struct clk *
+ *
+ * If @clk has the DELAYED_APP flag set, meaning that parent/rate changes
+ * don't take effect until the VALID_CONFIG bit is written, write the
+ * VALID_CONFIG bit and wait for the write to complete.  No return value.
+ */
+static void _omap2xxx_clk_commit(struct clk *clk)
+{
+	if (!cpu_is_omap24xx())
+		return;
+
+	if (!(clk->flags & DELAYED_APP))
+		return;
+
+	prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD,
+		OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+	/* OCP barrier */
+	prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
+}
+
+/*
+ * _dpll_test_fint - test whether an Fint value is valid for the DPLL
+ * @clk: DPLL struct clk to test
+ * @n: divider value (N) to test
+ *
+ * Tests whether a particular divider @n will result in a valid DPLL
+ * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
+ * Correction".  Returns 0 if OK, -1 if the enclosing loop can terminate
+ * (assuming that it is counting N upwards), or -2 if the enclosing loop
+ * should skip to the next iteration (again assuming N is increasing).
+ */
+static int _dpll_test_fint(struct clk *clk, u8 n)
+{
+	struct dpll_data *dd;
+	long fint;
+	int ret = 0;
+
+	dd = clk->dpll_data;
+
+	/* DPLL divider must result in a valid jitter correction val */
+	fint = clk->parent->rate / (n + 1);
+	if (fint < DPLL_FINT_BAND1_MIN) {
+
+		pr_debug("rejecting n=%d due to Fint failure, "
+			 "lowering max_divider\n", n);
+		dd->max_divider = n;
+		ret = DPLL_FINT_UNDERFLOW;
+
+	} else if (fint > DPLL_FINT_BAND1_MAX &&
+		   fint < DPLL_FINT_BAND2_MIN) {
+
+		pr_debug("rejecting n=%d due to Fint failure\n", n);
+		ret = DPLL_FINT_INVALID;
+
+	} else if (fint > DPLL_FINT_BAND2_MAX) {
+
+		pr_debug("rejecting n=%d due to Fint failure, "
+			 "boosting min_divider\n", n);
+		dd->min_divider = n;
+		ret = DPLL_FINT_INVALID;
+
+	}
+
+	return ret;
+}
+
+/**
  * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
  * @clk: OMAP clock struct ptr to use
  *
@@ -120,7 +197,7 @@
 						 clk->name, clks->parent->name,
 						 ((clk->parent) ?
 						  clk->parent->name : "NULL"));
-					clk->parent = clks->parent;
+					clk_reparent(clk, clks->parent);
 				};
 				found = 1;
 			}
@@ -134,25 +211,52 @@
 	return;
 }
 
-/* Returns the DPLL rate */
+/**
+ * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
+ * @clk: struct clk * of a DPLL
+ *
+ * DPLLs can be locked or bypassed - basically, enabled or disabled.
+ * When locked, the DPLL output depends on the M and N values.  When
+ * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
+ * or sys_clk.  Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
+ * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
+ * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
+ * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
+ * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
+ * if the clock @clk is not a DPLL.
+ */
 u32 omap2_get_dpll_rate(struct clk *clk)
 {
 	long long dpll_clk;
-	u32 dpll_mult, dpll_div, dpll;
+	u32 dpll_mult, dpll_div, v;
 	struct dpll_data *dd;
 
 	dd = clk->dpll_data;
-	/* REVISIT: What do we return on error? */
 	if (!dd)
 		return 0;
 
-	dpll = __raw_readl(dd->mult_div1_reg);
-	dpll_mult = dpll & dd->mult_mask;
+	/* Return bypass rate if DPLL is bypassed */
+	v = __raw_readl(dd->control_reg);
+	v &= dd->enable_mask;
+	v >>= __ffs(dd->enable_mask);
+
+	if (cpu_is_omap24xx()) {
+		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
+		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
+			return dd->clk_bypass->rate;
+	} else if (cpu_is_omap34xx()) {
+		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
+		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
+			return dd->clk_bypass->rate;
+	}
+
+	v = __raw_readl(dd->mult_div1_reg);
+	dpll_mult = v & dd->mult_mask;
 	dpll_mult >>= __ffs(dd->mult_mask);
-	dpll_div = dpll & dd->div1_mask;
+	dpll_div = v & dd->div1_mask;
 	dpll_div >>= __ffs(dd->div1_mask);
 
-	dpll_clk = (long long)clk->parent->rate * dpll_mult;
+	dpll_clk = (long long)dd->clk_ref->rate * dpll_mult;
 	do_div(dpll_clk, dpll_div + 1);
 
 	return dpll_clk;
@@ -162,14 +266,11 @@
  * Used for clocks that have the same value as the parent clock,
  * divided by some factor
  */
-void omap2_fixed_divisor_recalc(struct clk *clk)
+unsigned long omap2_fixed_divisor_recalc(struct clk *clk)
 {
 	WARN_ON(!clk->fixed_div);
 
-	clk->rate = clk->parent->rate / clk->fixed_div;
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
+	return clk->parent->rate / clk->fixed_div;
 }
 
 /**
@@ -190,11 +291,10 @@
 	 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
 	 * 34xx reverses this, just to keep us on our toes
 	 */
-	if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) {
+	if (cpu_mask & (RATE_IN_242X | RATE_IN_243X))
 		ena = mask;
-	} else if (cpu_mask & RATE_IN_343X) {
+	else if (cpu_mask & RATE_IN_343X)
 		ena = 0;
-	}
 
 	/* Wait for lock */
 	while (((__raw_readl(reg) & mask) != ena) &&
@@ -228,31 +328,12 @@
 	 * it and pull it into struct clk itself somehow.
 	 */
 	reg = clk->enable_reg;
-	if ((((u32)reg & 0xff) >= CM_FCLKEN1) &&
-	    (((u32)reg & 0xff) <= OMAP24XX_CM_FCLKEN2))
-		other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x10); /* CM_ICLKEN* */
-	else if ((((u32)reg & 0xff) >= CM_ICLKEN1) &&
-		 (((u32)reg & 0xff) <= OMAP24XX_CM_ICLKEN4))
-		other_reg = (void __iomem *)(((u32)reg & ~0xf0) | 0x00); /* CM_FCLKEN* */
-	else
-		return;
 
-	/* REVISIT: What are the appropriate exclusions for 34XX? */
-	/* No check for DSS or cam clocks */
-	if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
-		if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
-		    clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
-		    clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
-			return;
-	}
-
-	/* REVISIT: What are the appropriate exclusions for 34XX? */
-	/* OMAP3: ignore DSS-mod clocks */
-	if (cpu_is_omap34xx() &&
-	    (((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(OMAP3430_DSS_MOD, 0) ||
-	     ((((u32)reg & ~0xff) == (u32)OMAP_CM_REGADDR(CORE_MOD, 0)) &&
-	     clk->enable_bit == OMAP3430_EN_SSI_SHIFT)))
-		return;
+	/*
+	 * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
+	 * it's just a matter of XORing the bits.
+	 */
+	other_reg = (void __iomem *)((u32)reg ^ (CM_FCLKEN ^ CM_ICLKEN));
 
 	/* Check if both functional and interface clocks
 	 * are running. */
@@ -264,18 +345,9 @@
 	omap2_wait_clock_ready(st_reg, bit, clk->name);
 }
 
-/* Enables clock without considering parent dependencies or use count
- * REVISIT: Maybe change this to use clk->enable like on omap1?
- */
-int _omap2_clk_enable(struct clk *clk)
+static int omap2_dflt_clk_enable(struct clk *clk)
 {
-	u32 regval32;
-
-	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
-		return 0;
-
-	if (clk->enable)
-		return clk->enable(clk);
+	u32 v;
 
 	if (unlikely(clk->enable_reg == NULL)) {
 		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
@@ -283,33 +355,38 @@
 		return 0; /* REVISIT: -EINVAL */
 	}
 
-	regval32 = __raw_readl(clk->enable_reg);
+	v = __raw_readl(clk->enable_reg);
 	if (clk->flags & INVERT_ENABLE)
-		regval32 &= ~(1 << clk->enable_bit);
+		v &= ~(1 << clk->enable_bit);
 	else
-		regval32 |= (1 << clk->enable_bit);
-	__raw_writel(regval32, clk->enable_reg);
-	wmb();
-
-	omap2_clk_wait_ready(clk);
+		v |= (1 << clk->enable_bit);
+	__raw_writel(v, clk->enable_reg);
+	v = __raw_readl(clk->enable_reg); /* OCP barrier */
 
 	return 0;
 }
 
-/* Disables clock without considering parent dependencies or use count */
-void _omap2_clk_disable(struct clk *clk)
+static int omap2_dflt_clk_enable_wait(struct clk *clk)
 {
-	u32 regval32;
+	int ret;
 
-	if (clk->flags & (ALWAYS_ENABLED | PARENT_CONTROLS_CLOCK))
-		return;
-
-	if (clk->disable) {
-		clk->disable(clk);
-		return;
+	if (!clk->enable_reg) {
+		printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+		       clk->name);
+		return 0; /* REVISIT: -EINVAL */
 	}
 
-	if (clk->enable_reg == NULL) {
+	ret = omap2_dflt_clk_enable(clk);
+	if (ret == 0)
+		omap2_clk_wait_ready(clk);
+	return ret;
+}
+
+static void omap2_dflt_clk_disable(struct clk *clk)
+{
+	u32 v;
+
+	if (!clk->enable_reg) {
 		/*
 		 * 'Independent' here refers to a clock which is not
 		 * controlled by its parent.
@@ -319,20 +396,44 @@
 		return;
 	}
 
-	regval32 = __raw_readl(clk->enable_reg);
+	v = __raw_readl(clk->enable_reg);
 	if (clk->flags & INVERT_ENABLE)
-		regval32 |= (1 << clk->enable_bit);
+		v |= (1 << clk->enable_bit);
 	else
-		regval32 &= ~(1 << clk->enable_bit);
-	__raw_writel(regval32, clk->enable_reg);
-	wmb();
+		v &= ~(1 << clk->enable_bit);
+	__raw_writel(v, clk->enable_reg);
+	/* No OCP barrier needed here since it is a disable operation */
+}
+
+const struct clkops clkops_omap2_dflt_wait = {
+	.enable		= omap2_dflt_clk_enable_wait,
+	.disable	= omap2_dflt_clk_disable,
+};
+
+const struct clkops clkops_omap2_dflt = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+};
+
+/* Enables clock without considering parent dependencies or use count
+ * REVISIT: Maybe change this to use clk->enable like on omap1?
+ */
+static int _omap2_clk_enable(struct clk *clk)
+{
+	return clk->ops->enable(clk);
+}
+
+/* Disables clock without considering parent dependencies or use count */
+static void _omap2_clk_disable(struct clk *clk)
+{
+	clk->ops->disable(clk);
 }
 
 void omap2_clk_disable(struct clk *clk)
 {
 	if (clk->usecount > 0 && !(--clk->usecount)) {
 		_omap2_clk_disable(clk);
-		if (likely((u32)clk->parent))
+		if (clk->parent)
 			omap2_clk_disable(clk->parent);
 		if (clk->clkdm)
 			omap2_clkdm_clk_disable(clk->clkdm, clk);
@@ -345,30 +446,29 @@
 	int ret = 0;
 
 	if (clk->usecount++ == 0) {
-		if (likely((u32)clk->parent))
-			ret = omap2_clk_enable(clk->parent);
-
-		if (unlikely(ret != 0)) {
-			clk->usecount--;
-			return ret;
-		}
-
 		if (clk->clkdm)
 			omap2_clkdm_clk_enable(clk->clkdm, clk);
 
+		if (clk->parent) {
+			ret = omap2_clk_enable(clk->parent);
+			if (ret)
+				goto err;
+		}
+
 		ret = _omap2_clk_enable(clk);
-
-		if (unlikely(ret != 0)) {
-			if (clk->clkdm)
-				omap2_clkdm_clk_disable(clk->clkdm, clk);
-
-			if (clk->parent) {
+		if (ret) {
+			if (clk->parent)
 				omap2_clk_disable(clk->parent);
-				clk->usecount--;
-			}
+
+			goto err;
 		}
 	}
+	return ret;
 
+err:
+	if (clk->clkdm)
+		omap2_clkdm_clk_disable(clk->clkdm, clk);
+	clk->usecount--;
 	return ret;
 }
 
@@ -376,24 +476,22 @@
  * Used for clocks that are part of CLKSEL_xyz governed clocks.
  * REVISIT: Maybe change to use clk->enable() functions like on omap1?
  */
-void omap2_clksel_recalc(struct clk *clk)
+unsigned long omap2_clksel_recalc(struct clk *clk)
 {
+	unsigned long rate;
 	u32 div = 0;
 
 	pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
 
 	div = omap2_clksel_get_divisor(clk);
 	if (div == 0)
-		return;
+		return clk->rate;
 
-	if (unlikely(clk->rate == clk->parent->rate / div))
-		return;
-	clk->rate = clk->parent->rate / div;
+	rate = clk->parent->rate / div;
 
-	pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+	pr_debug("clock: new clock rate is %ld (div %d)\n", rate, div);
 
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+	return rate;
 }
 
 /**
@@ -405,8 +503,8 @@
  * the element associated with the supplied parent clock address.
  * Returns a pointer to the struct clksel on success or NULL on error.
  */
-const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
-						struct clk *src_clk)
+static const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
+						       struct clk *src_clk)
 {
 	const struct clksel *clks;
 
@@ -455,7 +553,7 @@
 	*new_div = 1;
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
-	if (clks == NULL)
+	if (!clks)
 		return ~0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
@@ -514,7 +612,7 @@
 /* Given a clock and a rate apply a clock specific rounding function */
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	if (clk->round_rate != NULL)
+	if (clk->round_rate)
 		return clk->round_rate(clk, rate);
 
 	if (clk->flags & RATE_FIXED)
@@ -540,7 +638,7 @@
 	const struct clksel_rate *clkr;
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
-	if (clks == NULL)
+	if (!clks)
 		return 0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
@@ -576,7 +674,7 @@
 	WARN_ON(div == 0);
 
 	clks = omap2_get_clksel_by_parent(clk, clk->parent);
-	if (clks == NULL)
+	if (!clks)
 		return ~0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
@@ -595,23 +693,6 @@
 }
 
 /**
- * omap2_get_clksel - find clksel register addr & field mask for a clk
- * @clk: struct clk to use
- * @field_mask: ptr to u32 to store the register field mask
- *
- * Returns the address of the clksel register upon success or NULL on error.
- */
-void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
-{
-	if (unlikely((clk->clksel_reg == NULL) || (clk->clksel_mask == NULL)))
-		return NULL;
-
-	*field_mask = clk->clksel_mask;
-
-	return clk->clksel_reg;
-}
-
-/**
  * omap2_clksel_get_divisor - get current divider applied to parent clock.
  * @clk: OMAP struct clk to use.
  *
@@ -619,49 +700,41 @@
  */
 u32 omap2_clksel_get_divisor(struct clk *clk)
 {
-	u32 field_mask, field_val;
-	void __iomem *div_addr;
+	u32 v;
 
-	div_addr = omap2_get_clksel(clk, &field_mask);
-	if (div_addr == NULL)
+	if (!clk->clksel_mask)
 		return 0;
 
-	field_val = __raw_readl(div_addr) & field_mask;
-	field_val >>= __ffs(field_mask);
+	v = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
+	v >>= __ffs(clk->clksel_mask);
 
-	return omap2_clksel_to_divisor(clk, field_val);
+	return omap2_clksel_to_divisor(clk, v);
 }
 
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 {
-	u32 field_mask, field_val, reg_val, validrate, new_div = 0;
-	void __iomem *div_addr;
+	u32 v, field_val, validrate, new_div = 0;
+
+	if (!clk->clksel_mask)
+		return -EINVAL;
 
 	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
 	if (validrate != rate)
 		return -EINVAL;
 
-	div_addr = omap2_get_clksel(clk, &field_mask);
-	if (div_addr == NULL)
-		return -EINVAL;
-
 	field_val = omap2_divisor_to_clksel(clk, new_div);
 	if (field_val == ~0)
 		return -EINVAL;
 
-	reg_val = __raw_readl(div_addr);
-	reg_val &= ~field_mask;
-	reg_val |= (field_val << __ffs(field_mask));
-	__raw_writel(reg_val, div_addr);
-	wmb();
+	v = __raw_readl(clk->clksel_reg);
+	v &= ~clk->clksel_mask;
+	v |= field_val << __ffs(clk->clksel_mask);
+	__raw_writel(v, clk->clksel_reg);
+	v = __raw_readl(clk->clksel_reg); /* OCP barrier */
 
 	clk->rate = clk->parent->rate / new_div;
 
-	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
-		prm_write_mod_reg(OMAP24XX_VALID_CONFIG,
-			OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
-		wmb();
-	}
+	_omap2xxx_clk_commit(clk);
 
 	return 0;
 }
@@ -680,31 +753,24 @@
 		return -EINVAL;
 
 	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
-	if (clk->set_rate != NULL)
+	if (clk->set_rate)
 		ret = clk->set_rate(clk, rate);
 
-	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
-		propagate_rate(clk);
-
 	return ret;
 }
 
 /*
  * Converts encoded control register address into a full address
- * On error, *src_addr will be returned as 0.
+ * On error, the return value (parent_div) will be 0.
  */
-static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
-				      struct clk *src_clk, u32 *field_mask,
-				      struct clk *clk, u32 *parent_div)
+static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
+				       u32 *field_val)
 {
 	const struct clksel *clks;
 	const struct clksel_rate *clkr;
 
-	*parent_div = 0;
-	*src_addr = NULL;
-
 	clks = omap2_get_clksel_by_parent(clk, src_clk);
-	if (clks == NULL)
+	if (!clks)
 		return 0;
 
 	for (clkr = clks->rates; clkr->div; clkr++) {
@@ -722,47 +788,35 @@
 	/* Should never happen.  Add a clksel mask to the struct clk. */
 	WARN_ON(clk->clksel_mask == 0);
 
-	*field_mask = clk->clksel_mask;
-	*src_addr = clk->clksel_reg;
-	*parent_div = clkr->div;
+	*field_val = clkr->val;
 
-	return clkr->val;
+	return clkr->div;
 }
 
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 {
-	void __iomem *src_addr;
-	u32 field_val, field_mask, reg_val, parent_div;
+	u32 field_val, v, parent_div;
 
-	if (unlikely(clk->flags & CONFIG_PARTICIPANT))
+	if (clk->flags & CONFIG_PARTICIPANT)
 		return -EINVAL;
 
 	if (!clk->clksel)
 		return -EINVAL;
 
-	field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
-					       &field_mask, clk, &parent_div);
-	if (src_addr == NULL)
+	parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val);
+	if (!parent_div)
 		return -EINVAL;
 
-	if (clk->usecount > 0)
-		omap2_clk_disable(clk);
-
 	/* Set new source value (previous dividers if any in effect) */
-	reg_val = __raw_readl(src_addr) & ~field_mask;
-	reg_val |= (field_val << __ffs(field_mask));
-	__raw_writel(reg_val, src_addr);
-	wmb();
+	v = __raw_readl(clk->clksel_reg);
+	v &= ~clk->clksel_mask;
+	v |= field_val << __ffs(clk->clksel_mask);
+	__raw_writel(v, clk->clksel_reg);
+	v = __raw_readl(clk->clksel_reg);    /* OCP barrier */
 
-	if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
-		__raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
-		wmb();
-	}
+	_omap2xxx_clk_commit(clk);
 
-	clk->parent = new_parent;
-
-	if (clk->usecount > 0)
-		omap2_clk_enable(clk);
+	clk_reparent(clk, new_parent);
 
 	/* CLKSEL clocks follow their parents' rates, divided by a divisor */
 	clk->rate = new_parent->rate;
@@ -773,9 +827,6 @@
 	pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
 		 clk->name, clk->parent->name, clk->rate);
 
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
-
 	return 0;
 }
 
@@ -805,7 +856,8 @@
 	return 0;
 }
 
-static unsigned long _dpll_compute_new_rate(unsigned long parent_rate, unsigned int m, unsigned int n)
+static unsigned long _dpll_compute_new_rate(unsigned long parent_rate,
+					    unsigned int m, unsigned int n)
 {
 	unsigned long long num;
 
@@ -838,7 +890,7 @@
 			   unsigned long target_rate,
 			   unsigned long parent_rate)
 {
-	int flags = 0, carry = 0;
+	int r = 0, carry = 0;
 
 	/* Unscale m and round if necessary */
 	if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL)
@@ -859,13 +911,13 @@
 	if (*m < DPLL_MIN_MULTIPLIER) {
 		*m = DPLL_MIN_MULTIPLIER;
 		*new_rate = 0;
-		flags = DPLL_MULT_UNDERFLOW;
+		r = DPLL_MULT_UNDERFLOW;
 	}
 
 	if (*new_rate == 0)
 		*new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
 
-	return flags;
+	return r;
 }
 
 /**
@@ -889,54 +941,65 @@
 	int m, n, r, e, scaled_max_m;
 	unsigned long scaled_rt_rp, new_rate;
 	int min_e = -1, min_e_m = -1, min_e_n = -1;
+	struct dpll_data *dd;
 
 	if (!clk || !clk->dpll_data)
 		return ~0;
 
+	dd = clk->dpll_data;
+
 	pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
 		 "%ld\n", clk->name, target_rate);
 
-	scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR);
-	scaled_max_m = clk->dpll_data->max_multiplier * DPLL_SCALE_FACTOR;
+	scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
+	scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
 
-	clk->dpll_data->last_rounded_rate = 0;
+	dd->last_rounded_rate = 0;
 
-	for (n = clk->dpll_data->max_divider; n >= DPLL_MIN_DIVIDER; n--) {
+	for (n = dd->min_divider; n <= dd->max_divider; n++) {
+
+		/* Is the (input clk, divider) pair valid for the DPLL? */
+		r = _dpll_test_fint(clk, n);
+		if (r == DPLL_FINT_UNDERFLOW)
+			break;
+		else if (r == DPLL_FINT_INVALID)
+			continue;
 
 		/* Compute the scaled DPLL multiplier, based on the divider */
 		m = scaled_rt_rp * n;
 
 		/*
-		 * Since we're counting n down, a m overflow means we can
-		 * can immediately skip to the next n
+		 * Since we're counting n up, a m overflow means we
+		 * can bail out completely (since as n increases in
+		 * the next iteration, there's no way that m can
+		 * increase beyond the current m)
 		 */
 		if (m > scaled_max_m)
-			continue;
+			break;
 
 		r = _dpll_test_mult(&m, n, &new_rate, target_rate,
-				    clk->parent->rate);
+				    dd->clk_ref->rate);
+
+		/* m can't be set low enough for this n - try with a larger n */
+		if (r == DPLL_MULT_UNDERFLOW)
+			continue;
 
 		e = target_rate - new_rate;
 		pr_debug("clock: n = %d: m = %d: rate error is %d "
 			 "(new_rate = %ld)\n", n, m, e, new_rate);
 
 		if (min_e == -1 ||
-		    min_e >= (int)(abs(e) - clk->dpll_data->rate_tolerance)) {
+		    min_e >= (int)(abs(e) - dd->rate_tolerance)) {
 			min_e = e;
 			min_e_m = m;
 			min_e_n = n;
 
 			pr_debug("clock: found new least error %d\n", min_e);
-		}
 
-		/*
-		 * Since we're counting n down, a m underflow means we
-		 * can bail out completely (since as n decreases in
-		 * the next iteration, there's no way that m can
-		 * increase beyond the current m)
-		 */
-		if (r & DPLL_MULT_UNDERFLOW)
-			break;
+			/* We found good settings -- bail out now */
+			if (min_e <= dd->rate_tolerance)
+				break;
+		}
 	}
 
 	if (min_e < 0) {
@@ -944,17 +1007,17 @@
 		return ~0;
 	}
 
-	clk->dpll_data->last_rounded_m = min_e_m;
-	clk->dpll_data->last_rounded_n = min_e_n;
-	clk->dpll_data->last_rounded_rate =
-		_dpll_compute_new_rate(clk->parent->rate, min_e_m,  min_e_n);
+	dd->last_rounded_m = min_e_m;
+	dd->last_rounded_n = min_e_n;
+	dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
+						       min_e_m,  min_e_n);
 
 	pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
 		 min_e, min_e_m, min_e_n);
 	pr_debug("clock: final rate: %ld  (target rate: %ld)\n",
-		 clk->dpll_data->last_rounded_rate, target_rate);
+		 dd->last_rounded_rate, target_rate);
 
-	return clk->dpll_data->last_rounded_rate;
+	return dd->last_rounded_rate;
 }
 
 /*-------------------------------------------------------------------------
@@ -973,6 +1036,10 @@
 		return;
 
 	printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
-	_omap2_clk_disable(clk);
+	if (cpu_is_omap34xx()) {
+		omap2_clk_enable(clk);
+		omap2_clk_disable(clk);
+	} else
+		_omap2_clk_disable(clk);
 }
 #endif
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 1fb330e..2679ddf 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -21,13 +21,28 @@
 /* The maximum error between a target DPLL rate and the rounded rate in Hz */
 #define DEFAULT_DPLL_RATE_TOLERANCE	50000
 
+/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
+#define CORE_CLK_SRC_32K		0x0
+#define CORE_CLK_SRC_DPLL		0x1
+#define CORE_CLK_SRC_DPLL_X2		0x2
+
+/* OMAP2xxx CM_CLKEN_PLL.EN_DPLL bits - for omap2_get_dpll_rate() */
+#define OMAP2XXX_EN_DPLL_LPBYPASS		0x1
+#define OMAP2XXX_EN_DPLL_FRBYPASS		0x2
+#define OMAP2XXX_EN_DPLL_LOCKED			0x3
+
+/* OMAP3xxx CM_CLKEN_PLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */
+#define OMAP3XXX_EN_DPLL_LPBYPASS		0x5
+#define OMAP3XXX_EN_DPLL_FRBYPASS		0x6
+#define OMAP3XXX_EN_DPLL_LOCKED			0x7
+
 int omap2_clk_init(void);
 int omap2_clk_enable(struct clk *clk);
 void omap2_clk_disable(struct clk *clk);
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-int omap2_dpll_rate_tolerance_set(struct clk *clk, unsigned int tolerance);
+int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
@@ -36,7 +51,7 @@
 #define omap2_clk_disable_unused	NULL
 #endif
 
-void omap2_clksel_recalc(struct clk *clk);
+unsigned long omap2_clksel_recalc(struct clk *clk);
 void omap2_init_clk_clkdm(struct clk *clk);
 void omap2_init_clksel_parent(struct clk *clk);
 u32 omap2_clksel_get_divisor(struct clk *clk);
@@ -44,13 +59,16 @@
 				u32 *new_div);
 u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
 u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
-void omap2_fixed_divisor_recalc(struct clk *clk);
+unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
 long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 u32 omap2_get_dpll_rate(struct clk *clk);
 int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
 void omap2_clk_prepare_for_reboot(void);
 
+extern const struct clkops clkops_omap2_dflt_wait;
+extern const struct clkops clkops_omap2_dflt;
+
 extern u8 cpu_mask;
 
 /* clksel_rate data common to 24xx/343x */
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index d382eb0..1e839c5 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -31,15 +31,192 @@
 #include <mach/clock.h>
 #include <mach/sram.h>
 #include <asm/div64.h>
+#include <asm/clkdev.h>
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "clock.h"
-#include "clock24xx.h"
 #include "prm.h"
 #include "prm-regbits-24xx.h"
 #include "cm.h"
 #include "cm-regbits-24xx.h"
 
+static const struct clkops clkops_oscck;
+static const struct clkops clkops_fixed;
+
+#include "clock24xx.h"
+
+struct omap_clk {
+	u32		cpu;
+	struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck, cp) 		\
+	{				\
+		 .cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
+#define CK_243X	(1 << 0)
+#define CK_242X	(1 << 1)
+
+static struct omap_clk omap24xx_clks[] = {
+	/* external root sources */
+	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X | CK_242X),
+	/* internal analog sources */
+	CLK(NULL,	"dpll_ck",	&dpll_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"apll96_ck",	&apll96_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"apll54_ck",	&apll54_ck,	CK_243X | CK_242X),
+	/* internal prcm root sources */
+	CLK(NULL,	"func_54m_ck",	&func_54m_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"core_ck",	&core_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_243X | CK_242X),
+	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_243X | CK_242X),
+	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src, CK_242X),
+	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_242X),
+	CLK(NULL,	"emul_ck",	&emul_ck,	CK_242X),
+	/* mpu domain clocks */
+	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X | CK_242X),
+	/* dsp domain clocks */
+	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_243X | CK_242X),
+	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
+	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
+	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
+	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
+	/* GFX domain clocks */
+	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_243X | CK_242X),
+	/* Modem domain clocks */
+	CLK(NULL,	"mdm_ick",	&mdm_ick,	CK_243X),
+	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
+	/* DSS domain clocks */
+	CLK(NULL,	"dss_ick",	&dss_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"dss1_fck",	&dss1_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"dss2_fck",	&dss2_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"dss_54m_fck",	&dss_54m_fck,	CK_243X | CK_242X),
+	/* L3 domain clocks */
+	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X | CK_242X),
+	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X | CK_242X),
+	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_243X | CK_242X),
+	/* L4 domain clocks */
+	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X | CK_242X),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X | CK_242X),
+	/* virtual meta-group clock */
+	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X | CK_242X),
+	/* general l4 interface ck, multi-parent functional clk */
+	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_243X | CK_242X),
+	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_243X | CK_242X),
+	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_243X | CK_242X),
+	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_243X | CK_242X),
+	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_243X | CK_242X),
+	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_243X),
+	CLK("omap-mcbsp.3", "fck",	&mcbsp3_fck,	CK_243X),
+	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_243X),
+	CLK("omap-mcbsp.4", "fck",	&mcbsp4_fck,	CK_243X),
+	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_243X),
+	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_243X),
+	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_243X | CK_242X),
+	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_243X | CK_242X),
+	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_243X | CK_242X),
+	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_243X | CK_242X),
+	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_243X),
+	CLK("omap2_mcspi.3", "fck",	&mcspi3_fck,	CK_243X),
+	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"gpios_ick",	&gpios_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"gpios_fck",	&gpios_fck,	CK_243X | CK_242X),
+	CLK("omap_wdt",	"ick",		&mpu_wdt_ick,	CK_243X | CK_242X),
+	CLK("omap_wdt",	"fck",		&mpu_wdt_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"sync_32k_ick",	&sync_32k_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"icr_ick",	&icr_ick,	CK_243X),
+	CLK("omap24xxcam", "fck",	&cam_fck,	CK_243X | CK_242X),
+	CLK("omap24xxcam", "ick",	&cam_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"wdt4_ick",	&wdt4_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"wdt4_fck",	&wdt4_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_242X),
+	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_242X),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_243X | CK_242X),
+	CLK("mmci-omap.0", "ick",	&mmc_ick,	CK_242X),
+	CLK("mmci-omap.0", "fck",	&mmc_fck,	CK_242X),
+	CLK(NULL,	"fac_ick",	&fac_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"fac_fck",	&fac_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"eac_ick",	&eac_ick,	CK_242X),
+	CLK(NULL,	"eac_fck",	&eac_fck,	CK_242X),
+	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_243X | CK_242X),
+	CLK("omap_hdq.1", "fck",	&hdq_fck,	CK_243X | CK_242X),
+	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_243X | CK_242X),
+	CLK("i2c_omap.1", "fck",	&i2c1_fck,	CK_242X),
+	CLK("i2c_omap.1", "fck",	&i2chs1_fck,	CK_243X),
+	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_243X | CK_242X),
+	CLK("i2c_omap.2", "fck",	&i2c2_fck,	CK_242X),
+	CLK("i2c_omap.2", "fck",	&i2chs2_fck,	CK_243X),
+	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
+	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_243X),
+	CLK(NULL,	"des_ick",	&des_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"sha_ick",	&sha_ick,	CK_243X | CK_242X),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"aes_ick",	&aes_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X | CK_242X),
+	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X | CK_242X),
+	CLK(NULL,	"usbhs_ick",	&usbhs_ick,	CK_243X),
+	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
+	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
+	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
+	CLK("mmci-omap-hs.1", "fck",	&mmchs2_fck,	CK_243X),
+	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
+	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
+	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
+	CLK("mmci-omap-hs.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
+	CLK("mmci-omap-hs.1", "mmchsdb_fck", 	&mmchsdb2_fck,	CK_243X),
+};
+
 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
 #define EN_APLL_STOPPED			0
 #define EN_APLL_LOCKED			3
@@ -59,19 +236,32 @@
  * Omap24xx specific clock functions
  *-------------------------------------------------------------------------*/
 
-/* This actually returns the rate of core_ck, not dpll_ck. */
-static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
+/**
+ * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
+ * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
+ *
+ * Returns the CORE_CLK rate.  CORE_CLK can have one of three rate
+ * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
+ * (the latter is unusual).  This currently should be called with
+ * struct clk *dpll_ck, which is a composite clock of dpll_ck and
+ * core_ck.
+ */
+static unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
 {
-	long long dpll_clk;
-	u8 amult;
+	long long core_clk;
+	u32 v;
 
-	dpll_clk = omap2_get_dpll_rate(tclk);
+	core_clk = omap2_get_dpll_rate(clk);
 
-	amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-	amult &= OMAP24XX_CORE_CLK_SRC_MASK;
-	dpll_clk *= amult;
+	v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+	v &= OMAP24XX_CORE_CLK_SRC_MASK;
 
-	return dpll_clk;
+	if (v == CORE_CLK_SRC_32K)
+		core_clk = 32768;
+	else
+		core_clk *= v;
+
+	return core_clk;
 }
 
 static int omap2_enable_osc_ck(struct clk *clk)
@@ -96,6 +286,11 @@
 		      OMAP24XX_PRCM_CLKSRC_CTRL);
 }
 
+static const struct clkops clkops_oscck = {
+	.enable		= &omap2_enable_osc_ck,
+	.disable	= &omap2_disable_osc_ck,
+};
+
 #ifdef OLD_CK
 /* Recalculate SYST_CLK */
 static void omap2_sys_clk_recalc(struct clk * clk)
@@ -149,11 +344,16 @@
 	cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
 }
 
+static const struct clkops clkops_fixed = {
+	.enable		= &omap2_clk_fixed_enable,
+	.disable	= &omap2_clk_fixed_disable,
+};
+
 /*
  * Uses the current prcm set to tell if a rate is valid.
  * You can go slower, but not faster within a given rate set.
  */
-long omap2_dpllcore_round_rate(unsigned long target_rate)
+static long omap2_dpllcore_round_rate(unsigned long target_rate)
 {
 	u32 high, low, core_clk_src;
 
@@ -182,11 +382,9 @@
 
 }
 
-static void omap2_dpllcore_recalc(struct clk *clk)
+static unsigned long omap2_dpllcore_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_dpll_rate_24xx(clk);
-
-	propagate_rate(clk);
+	return omap2xxx_clk_get_core_rate(clk);
 }
 
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
@@ -195,22 +393,19 @@
 	u32 bypass = 0;
 	struct prcm_config tmpset;
 	const struct dpll_data *dd;
-	unsigned long flags;
-	int ret = -EINVAL;
 
-	local_irq_save(flags);
-	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
 	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
 
 	if ((rate == (cur_rate / 2)) && (mult == 2)) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
 	} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 	} else if (rate != cur_rate) {
 		valid_rate = omap2_dpllcore_round_rate(rate);
 		if (valid_rate != rate)
-			goto dpll_exit;
+			return -EINVAL;
 
 		if (mult == 1)
 			low = curr_prcm_set->dpll_speed;
@@ -219,7 +414,7 @@
 
 		dd = clk->dpll_data;
 		if (!dd)
-			goto dpll_exit;
+			return -EINVAL;
 
 		tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
 		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
@@ -245,22 +440,19 @@
 		if (rate == curr_prcm_set->xtal_speed)	/* If asking for 1-1 */
 			bypass = 1;
 
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
+		/* For omap2xxx_sdrc_init_params() */
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 
 		/* Force dll lock mode */
 		omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
 			       bypass);
 
 		/* Errata: ret dll entry state */
-		omap2_init_memory_params(omap2_dll_force_needed());
-		omap2_reprogram_sdrc(done_rate, 0);
+		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+		omap2xxx_sdrc_reprogram(done_rate, 0);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
-	ret = 0;
 
-dpll_exit:
-	local_irq_restore(flags);
-	return(ret);
+	return 0;
 }
 
 /**
@@ -269,9 +461,9 @@
  *
  * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
  */
-static void omap2_table_mpu_recalc(struct clk *clk)
+static unsigned long omap2_table_mpu_recalc(struct clk *clk)
 {
-	clk->rate = curr_prcm_set->mpu_speed;
+	return curr_prcm_set->mpu_speed;
 }
 
 /*
@@ -337,12 +529,12 @@
 	}
 
 	curr_prcm_set = prcm;
-	cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
+	cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck);
 
 	if (prcm->dpll_speed == cur_rate / 2) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
 	} else if (prcm->dpll_speed == cur_rate * 2) {
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 	} else if (prcm->dpll_speed != cur_rate) {
 		local_irq_save(flags);
 
@@ -366,27 +558,67 @@
 
 		/* Major subsystem dividers */
 		tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
-		cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
+		cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
+				 CM_CLKSEL1);
+
 		if (cpu_is_omap2430())
 			cm_write_mod_reg(prcm->cm_clksel_mdm,
 					 OMAP2430_MDM_MOD, CM_CLKSEL);
 
-		/* x2 to enter init_mem */
-		omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
+		/* x2 to enter omap2xxx_sdrc_init_params() */
+		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
 
 		omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
 			       bypass);
 
-		omap2_init_memory_params(omap2_dll_force_needed());
-		omap2_reprogram_sdrc(done_rate, 0);
+		omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
+		omap2xxx_sdrc_reprogram(done_rate, 0);
 
 		local_irq_restore(flags);
 	}
-	omap2_dpllcore_recalc(&dpll_ck);
 
 	return 0;
 }
 
+#ifdef CONFIG_CPU_FREQ
+/*
+ * Walk PRCM rate table and fillout cpufreq freq_table
+ */
+static struct cpufreq_frequency_table freq_table[ARRAY_SIZE(rate_table)];
+
+void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
+{
+	struct prcm_config *prcm;
+	int i = 0;
+
+	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+		if (!(prcm->flags & cpu_mask))
+			continue;
+		if (prcm->xtal_speed != sys_ck.rate)
+			continue;
+
+		/* don't put bypass rates in table */
+		if (prcm->dpll_speed == prcm->xtal_speed)
+			continue;
+
+		freq_table[i].index = i;
+		freq_table[i].frequency = prcm->mpu_speed / 1000;
+		i++;
+	}
+
+	if (i == 0) {
+		printk(KERN_WARNING "%s: failed to initialize frequency "
+		       "table\n", __func__);
+		return;
+	}
+
+	freq_table[i].index = i;
+	freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+	*table = &freq_table[0];
+}
+#endif
+
 static struct clk_functions omap2_clk_functions = {
 	.clk_enable		= omap2_clk_enable,
 	.clk_disable		= omap2_clk_disable,
@@ -394,24 +626,27 @@
 	.clk_set_rate		= omap2_clk_set_rate,
 	.clk_set_parent		= omap2_clk_set_parent,
 	.clk_disable_unused	= omap2_clk_disable_unused,
+#ifdef	CONFIG_CPU_FREQ
+	.clk_init_cpufreq_table	= omap2_clk_init_cpufreq_table,
+#endif
 };
 
 static u32 omap2_get_apll_clkin(void)
 {
-	u32 aplls, sclk = 0;
+	u32 aplls, srate = 0;
 
 	aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
 	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
 	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
 
 	if (aplls == APLLS_CLKIN_19_2MHZ)
-		sclk = 19200000;
+		srate = 19200000;
 	else if (aplls == APLLS_CLKIN_13MHZ)
-		sclk = 13000000;
+		srate = 13000000;
 	else if (aplls == APLLS_CLKIN_12MHZ)
-		sclk = 12000000;
+		srate = 12000000;
 
-	return sclk;
+	return srate;
 }
 
 static u32 omap2_get_sysclkdiv(void)
@@ -425,16 +660,14 @@
 	return div;
 }
 
-static void omap2_osc_clk_recalc(struct clk *clk)
+static unsigned long omap2_osc_clk_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
-	propagate_rate(clk);
+	return omap2_get_apll_clkin() * omap2_get_sysclkdiv();
 }
 
-static void omap2_sys_clk_recalc(struct clk *clk)
+static unsigned long omap2_sys_clk_recalc(struct clk *clk)
 {
-	clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
-	propagate_rate(clk);
+	return clk->parent->rate / omap2_get_sysclkdiv();
 }
 
 /*
@@ -460,7 +693,7 @@
 	if (!mpurate)
 		return -EINVAL;
 
-	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+	if (clk_set_rate(&virt_prcm_set, mpurate))
 		printk(KERN_ERR "Could not find matching MPU rate\n");
 
 	recalculate_root_clocks();
@@ -477,8 +710,8 @@
 int __init omap2_clk_init(void)
 {
 	struct prcm_config *prcm;
-	struct clk **clkp;
-	u32 clkrate;
+	struct omap_clk *c;
+	u32 clkrate, cpu_mask;
 
 	if (cpu_is_omap242x())
 		cpu_mask = RATE_IN_242X;
@@ -487,26 +720,28 @@
 
 	clk_init(&omap2_clk_functions);
 
-	omap2_osc_clk_recalc(&osc_ck);
-	omap2_sys_clk_recalc(&sys_ck);
+	osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
+	propagate_rate(&osc_ck);
+	sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
+	propagate_rate(&sys_ck);
 
-	for (clkp = onchip_24xx_clks;
-	     clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
-	     clkp++) {
+	for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
+		clk_init_one(c->lk.clk);
 
-		if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
-			clk_register(*clkp);
-			continue;
+	cpu_mask = 0;
+	if (cpu_is_omap2420())
+		cpu_mask |= CK_242X;
+	if (cpu_is_omap2430())
+		cpu_mask |= CK_243X;
+
+	for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
+		if (c->cpu & cpu_mask) {
+			clkdev_add(&c->lk);
+			clk_register(c->lk.clk);
 		}
 
-		if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) {
-			clk_register(*clkp);
-			continue;
-		}
-	}
-
 	/* Check the MPU rate set by bootloader */
-	clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
+	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
 		if (!(prcm->flags & cpu_mask))
 			continue;
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index ad6d98d..33c3e5b 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -24,17 +24,13 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 
-static void omap2_table_mpu_recalc(struct clk *clk);
+static unsigned long omap2_table_mpu_recalc(struct clk *clk);
 static int omap2_select_table_rate(struct clk *clk, unsigned long rate);
 static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
-static void omap2_sys_clk_recalc(struct clk *clk);
-static void omap2_osc_clk_recalc(struct clk *clk);
-static void omap2_sys_clk_recalc(struct clk *clk);
-static void omap2_dpllcore_recalc(struct clk *clk);
-static int omap2_clk_fixed_enable(struct clk *clk);
-static void omap2_clk_fixed_disable(struct clk *clk);
-static int omap2_enable_osc_ck(struct clk *clk);
-static void omap2_disable_osc_ck(struct clk *clk);
+static unsigned long omap2_sys_clk_recalc(struct clk *clk);
+static unsigned long omap2_osc_clk_recalc(struct clk *clk);
+static unsigned long omap2_sys_clk_recalc(struct clk *clk);
+static unsigned long omap2_dpllcore_recalc(struct clk *clk);
 static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
 
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
@@ -623,41 +619,35 @@
 /* Base external input clocks */
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
+	.ops		= &clkops_null,
 	.rate		= 32000,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+	.flags		= RATE_FIXED,
 	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &propagate_rate,
 };
 
 /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
 static struct clk osc_ck = {		/* (*12, *13, 19.2, *26, 38.4)MHz */
 	.name		= "osc_ck",
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
+	.ops		= &clkops_oscck,
 	.clkdm_name	= "wkup_clkdm",
-	.enable		= &omap2_enable_osc_ck,
-	.disable	= &omap2_disable_osc_ck,
 	.recalc		= &omap2_osc_clk_recalc,
 };
 
 /* Without modem likely 12MHz, with modem likely 13MHz */
 static struct clk sys_ck = {		/* (*12, *13, 19.2, 26, 38.4)MHz */
 	.name		= "sys_ck",		/* ~ ref_clk also */
+	.ops		= &clkops_null,
 	.parent		= &osc_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &omap2_sys_clk_recalc,
 };
 
 static struct clk alt_ck = {		/* Typical 54M or 48M, may not exist */
 	.name		= "alt_ck",
+	.ops		= &clkops_null,
 	.rate		= 54000000,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+	.flags		= RATE_FIXED,
 	.clkdm_name	= "wkup_clkdm",
-	.recalc		= &propagate_rate,
 };
 
 /*
@@ -673,7 +663,12 @@
 	.mult_div1_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.mult_mask		= OMAP24XX_DPLL_MULT_MASK,
 	.div1_mask		= OMAP24XX_DPLL_DIV_MASK,
+	.clk_bypass		= &sys_ck,
+	.clk_ref		= &sys_ck,
+	.control_reg		= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
+	.enable_mask		= OMAP24XX_EN_DPLL_MASK,
 	.max_multiplier		= 1024,
+	.min_divider		= 1,
 	.max_divider		= 16,
 	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
@@ -684,10 +679,9 @@
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
+	.ops		= &clkops_null,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &omap2_dpllcore_recalc,
 	.set_rate	= &omap2_reprogram_dpllcore,
@@ -695,30 +689,24 @@
 
 static struct clk apll96_ck = {
 	.name		= "apll96_ck",
+	.ops		= &clkops_fixed,
 	.parent		= &sys_ck,
 	.rate		= 96000000,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+	.flags		= RATE_FIXED | ENABLE_ON_INIT,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP24XX_EN_96M_PLL_SHIFT,
-	.enable		= &omap2_clk_fixed_enable,
-	.disable	= &omap2_clk_fixed_disable,
-	.recalc		= &propagate_rate,
 };
 
 static struct clk apll54_ck = {
 	.name		= "apll54_ck",
+	.ops		= &clkops_fixed,
 	.parent		= &sys_ck,
 	.rate		= 54000000,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+	.flags		= RATE_FIXED | ENABLE_ON_INIT,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP24XX_EN_54M_PLL_SHIFT,
-	.enable		= &omap2_clk_fixed_enable,
-	.disable	= &omap2_clk_fixed_disable,
-	.recalc		= &propagate_rate,
 };
 
 /*
@@ -745,9 +733,8 @@
 
 static struct clk func_54m_ck = {
 	.name		= "func_54m_ck",
+	.ops		= &clkops_null,
 	.parent		= &apll54_ck,	/* can also be alt_clk */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
@@ -758,9 +745,8 @@
 
 static struct clk core_ck = {
 	.name		= "core_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll_ck,		/* can also be 32k */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | RATE_PROPAGATES,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -785,9 +771,8 @@
 /* The parent of this clock is not selectable on 2420. */
 static struct clk func_96m_ck = {
 	.name		= "func_96m_ck",
+	.ops		= &clkops_null,
 	.parent		= &apll96_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
@@ -818,9 +803,8 @@
 
 static struct clk func_48m_ck = {
 	.name		= "func_48m_ck",
+	.ops		= &clkops_null,
 	.parent		= &apll96_ck,	 /* 96M or Alt */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
@@ -833,10 +817,9 @@
 
 static struct clk func_12m_ck = {
 	.name		= "func_12m_ck",
+	.ops		= &clkops_null,
 	.parent		= &func_48m_ck,
 	.fixed_div	= 4,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
@@ -844,8 +827,8 @@
 /* Secure timer, only available in secure mode */
 static struct clk wdt1_osc_ck = {
 	.name		= "ck_wdt1_osc",
+	.ops		= &clkops_null, /* RMK: missing? */
 	.parent		= &osc_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.recalc		= &followparent_recalc,
 };
 
@@ -887,9 +870,8 @@
 
 static struct clk sys_clkout_src = {
 	.name		= "sys_clkout_src",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				RATE_PROPAGATES,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP24XX_CLKOUT_EN_SHIFT,
@@ -918,9 +900,8 @@
 
 static struct clk sys_clkout = {
 	.name		= "sys_clkout",
+	.ops		= &clkops_null,
 	.parent		= &sys_clkout_src,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP24XX_CLKOUT_DIV_MASK,
@@ -933,8 +914,8 @@
 /* In 2430, new in 2420 ES2 */
 static struct clk sys_clkout2_src = {
 	.name		= "sys_clkout2_src",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X | RATE_PROPAGATES,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.enable_bit	= OMAP2420_CLKOUT2_EN_SHIFT,
@@ -955,8 +936,8 @@
 /* In 2430, new in 2420 ES2 */
 static struct clk sys_clkout2 = {
 	.name		= "sys_clkout2",
+	.ops		= &clkops_null,
 	.parent		= &sys_clkout2_src,
-	.flags		= CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "wkup_clkdm",
 	.clksel_reg	= OMAP24XX_PRCM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP2420_CLKOUT2_DIV_MASK,
@@ -968,8 +949,8 @@
 
 static struct clk emul_ck = {
 	.name		= "emul_ck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP24XX_PRCM_CLKEMUL_CTRL,
 	.enable_bit	= OMAP24XX_EMULATION_EN_SHIFT,
@@ -1003,10 +984,9 @@
 
 static struct clk mpu_ck = {	/* Control cpu */
 	.name		= "mpu_ck",
+	.ops		= &clkops_null,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP |
-				CONFIG_PARTICIPANT | RATE_PROPAGATES,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clkdm_name	= "mpu_clkdm",
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
@@ -1046,9 +1026,9 @@
 
 static struct clk dsp_fck = {
 	.name		= "dsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
-				CONFIG_PARTICIPANT | RATE_PROPAGATES,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
@@ -1076,9 +1056,9 @@
 /* This clock does not exist as such in the TRM. */
 static struct clk dsp_irate_ick = {
 	.name		= "dsp_irate_ick",
+	.ops		= &clkops_null,
 	.parent		= &dsp_fck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
-				CONFIG_PARTICIPANT | PARENT_CONTROLS_CLOCK,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
 	.clksel		= dsp_irate_ick_clksel,
@@ -1090,8 +1070,9 @@
 /* 2420 only */
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dsp_irate_ick,
-	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
 };
@@ -1099,8 +1080,9 @@
 /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dsp_irate_ick,
-	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
 };
@@ -1112,9 +1094,9 @@
  */
 static struct clk iva1_ifck = {
 	.name		= "iva1_ifck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
-				RATE_PROPAGATES | DELAYED_APP,
+	.flags		= CONFIG_PARTICIPANT | DELAYED_APP,
 	.clkdm_name	= "iva1_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_COP_SHIFT,
@@ -1129,8 +1111,8 @@
 /* IVA1 mpu/int/i/f clocks are /2 of parent */
 static struct clk iva1_mpu_int_ifck = {
 	.name		= "iva1_mpu_int_ifck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &iva1_ifck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "iva1_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP2420_EN_IVA_MPU_SHIFT,
@@ -1175,10 +1157,9 @@
 
 static struct clk core_l3_ck = {	/* Used for ick and fck, interconnect */
 	.name		= "core_l3_ck",
+	.ops		= &clkops_null,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP |
-				CONFIG_PARTICIPANT | RATE_PROPAGATES,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clkdm_name	= "core_l3_clkdm",
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L3_MASK,
@@ -1204,9 +1185,9 @@
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
@@ -1238,9 +1219,9 @@
 
 static struct clk l4_ck = {		/* used both as an ick and fck */
 	.name		= "l4_ck",
+	.ops		= &clkops_null,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
+	.flags		= DELAYED_APP,
 	.clkdm_name	= "core_l4_clkdm",
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP24XX_CLKSEL_L4_MASK,
@@ -1276,9 +1257,9 @@
 
 static struct clk ssi_ssr_sst_fck = {
 	.name		= "ssi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				DELAYED_APP,
+	.flags		= DELAYED_APP,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
@@ -1290,6 +1271,20 @@
 	.set_rate	= &omap2_clksel_set_rate
 };
 
+/*
+ * Presumably this is the same as SSI_ICLK.
+ * TRM contradicts itself on what clockdomain SSI_ICLK is in
+ */
+static struct clk ssi_l4_ick = {
+	.name		= "ssi_l4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
+	.enable_bit	= OMAP24XX_EN_SSI_SHIFT,
+	.recalc		= &followparent_recalc,
+};
+
 
 /*
  * GFX clock domain
@@ -1312,8 +1307,8 @@
 
 static struct clk gfx_3d_fck = {
 	.name		= "gfx_3d_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "gfx_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_3D_SHIFT,
@@ -1327,8 +1322,8 @@
 
 static struct clk gfx_2d_fck = {
 	.name		= "gfx_2d_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "gfx_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_2D_SHIFT,
@@ -1342,8 +1337,8 @@
 
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "gfx_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP_EN_GFX_SHIFT,
@@ -1372,8 +1367,9 @@
 
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_ck,
-	.flags		= CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
+	.flags		= DELAYED_APP | CONFIG_PARTICIPANT,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
@@ -1387,8 +1383,8 @@
 
 static struct clk mdm_osc_ck = {
 	.name		= "mdm_osc_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &osc_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP2430_EN_OSC_SHIFT,
@@ -1432,8 +1428,8 @@
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
@@ -1442,9 +1438,9 @@
 
 static struct clk dss1_fck = {
 	.name		= "dss1_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &core_ck,		/* Core or sys */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				DELAYED_APP,
+	.flags		= DELAYED_APP,
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS1_SHIFT,
@@ -1475,9 +1471,9 @@
 
 static struct clk dss2_fck = {		/* Alt clk used in power management */
 	.name		= "dss2_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &sys_ck,		/* fixed at sys_ck or 48MHz */
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				DELAYED_APP,
+	.flags		= DELAYED_APP,
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_DSS2_SHIFT,
@@ -1490,8 +1486,8 @@
 
 static struct clk dss_54m_fck = {	/* Alt clk used in power management */
 	.name		= "dss_54m_fck",	/* 54m tv clk */
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_54m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_TV_SHIFT,
@@ -1518,8 +1514,8 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
@@ -1528,8 +1524,8 @@
 
 static struct clk gpt1_fck = {
 	.name		= "gpt1_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
@@ -1544,8 +1540,8 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
@@ -1554,8 +1550,8 @@
 
 static struct clk gpt2_fck = {
 	.name		= "gpt2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT2_SHIFT,
@@ -1568,8 +1564,8 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
@@ -1578,8 +1574,8 @@
 
 static struct clk gpt3_fck = {
 	.name		= "gpt3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT3_SHIFT,
@@ -1592,8 +1588,8 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
@@ -1602,8 +1598,8 @@
 
 static struct clk gpt4_fck = {
 	.name		= "gpt4_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT4_SHIFT,
@@ -1616,8 +1612,8 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
@@ -1626,8 +1622,8 @@
 
 static struct clk gpt5_fck = {
 	.name		= "gpt5_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT5_SHIFT,
@@ -1640,8 +1636,8 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
@@ -1650,8 +1646,8 @@
 
 static struct clk gpt6_fck = {
 	.name		= "gpt6_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT6_SHIFT,
@@ -1664,8 +1660,8 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1673,8 +1669,8 @@
 
 static struct clk gpt7_fck = {
 	.name		= "gpt7_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
@@ -1687,8 +1683,8 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
@@ -1697,8 +1693,8 @@
 
 static struct clk gpt8_fck = {
 	.name		= "gpt8_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT8_SHIFT,
@@ -1711,8 +1707,8 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
@@ -1721,8 +1717,8 @@
 
 static struct clk gpt9_fck = {
 	.name		= "gpt9_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT9_SHIFT,
@@ -1735,8 +1731,8 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
@@ -1745,8 +1741,8 @@
 
 static struct clk gpt10_fck = {
 	.name		= "gpt10_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT10_SHIFT,
@@ -1759,8 +1755,8 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
@@ -1769,8 +1765,8 @@
 
 static struct clk gpt11_fck = {
 	.name		= "gpt11_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT11_SHIFT,
@@ -1783,8 +1779,8 @@
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
@@ -1793,8 +1789,8 @@
 
 static struct clk gpt12_fck = {
 	.name		= "gpt12_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT12_SHIFT,
@@ -1807,9 +1803,9 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
@@ -1818,9 +1814,9 @@
 
 static struct clk mcbsp1_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP1_SHIFT,
@@ -1829,9 +1825,9 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
@@ -1840,9 +1836,9 @@
 
 static struct clk mcbsp2_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCBSP2_SHIFT,
@@ -1851,9 +1847,9 @@
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
@@ -1862,9 +1858,9 @@
 
 static struct clk mcbsp3_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP3_SHIFT,
@@ -1873,9 +1869,9 @@
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
@@ -1884,9 +1880,9 @@
 
 static struct clk mcbsp4_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP4_SHIFT,
@@ -1895,9 +1891,9 @@
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 5,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
@@ -1906,9 +1902,9 @@
 
 static struct clk mcbsp5_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 5,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCBSP5_SHIFT,
@@ -1917,10 +1913,10 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1928,9 +1924,9 @@
 
 static struct clk mcspi1_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI1_SHIFT,
@@ -1939,9 +1935,9 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
@@ -1950,9 +1946,9 @@
 
 static struct clk mcspi2_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MCSPI2_SHIFT,
@@ -1961,9 +1957,9 @@
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
@@ -1972,9 +1968,9 @@
 
 static struct clk mcspi3_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MCSPI3_SHIFT,
@@ -1983,8 +1979,8 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
@@ -1993,8 +1989,8 @@
 
 static struct clk uart1_fck = {
 	.name		= "uart1_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART1_SHIFT,
@@ -2003,8 +1999,8 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
@@ -2013,8 +2009,8 @@
 
 static struct clk uart2_fck = {
 	.name		= "uart2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_UART2_SHIFT,
@@ -2023,8 +2019,8 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
@@ -2033,8 +2029,8 @@
 
 static struct clk uart3_fck = {
 	.name		= "uart3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP24XX_EN_UART3_SHIFT,
@@ -2043,8 +2039,8 @@
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
@@ -2053,8 +2049,8 @@
 
 static struct clk gpios_fck = {
 	.name		= "gpios_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
@@ -2063,8 +2059,8 @@
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
@@ -2073,8 +2069,8 @@
 
 static struct clk mpu_wdt_fck = {
 	.name		= "mpu_wdt_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
@@ -2083,9 +2079,9 @@
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
@@ -2094,8 +2090,8 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
@@ -2104,9 +2100,9 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
@@ -2115,8 +2111,8 @@
 
 static struct clk icr_ick = {
 	.name		= "icr_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
@@ -2125,8 +2121,8 @@
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
@@ -2140,8 +2136,8 @@
  */
 static struct clk cam_fck = {
 	.name		= "cam_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_CAM_SHIFT,
@@ -2150,8 +2146,8 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MAILBOXES_SHIFT,
@@ -2160,8 +2156,8 @@
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
@@ -2170,8 +2166,8 @@
 
 static struct clk wdt4_fck = {
 	.name		= "wdt4_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_WDT4_SHIFT,
@@ -2180,8 +2176,8 @@
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
@@ -2190,8 +2186,8 @@
 
 static struct clk wdt3_fck = {
 	.name		= "wdt3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_WDT3_SHIFT,
@@ -2200,8 +2196,8 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
@@ -2210,8 +2206,8 @@
 
 static struct clk mspro_fck = {
 	.name		= "mspro_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_MSPRO_SHIFT,
@@ -2220,8 +2216,8 @@
 
 static struct clk mmc_ick = {
 	.name		= "mmc_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
@@ -2230,8 +2226,8 @@
 
 static struct clk mmc_fck = {
 	.name		= "mmc_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_MMC_SHIFT,
@@ -2240,8 +2236,8 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
@@ -2250,8 +2246,8 @@
 
 static struct clk fac_fck = {
 	.name		= "fac_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_12m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_FAC_SHIFT,
@@ -2260,8 +2256,8 @@
 
 static struct clk eac_ick = {
 	.name		= "eac_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
@@ -2270,8 +2266,8 @@
 
 static struct clk eac_fck = {
 	.name		= "eac_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_EAC_SHIFT,
@@ -2280,8 +2276,8 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
@@ -2290,8 +2286,8 @@
 
 static struct clk hdq_fck = {
 	.name		= "hdq_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_12m_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP24XX_EN_HDQ_SHIFT,
@@ -2300,9 +2296,9 @@
 
 static struct clk i2c2_ick = {
 	.name		= "i2c_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
@@ -2311,9 +2307,9 @@
 
 static struct clk i2c2_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &func_12m_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C2_SHIFT,
@@ -2322,9 +2318,9 @@
 
 static struct clk i2chs2_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_I2CHS2_SHIFT,
@@ -2333,9 +2329,9 @@
 
 static struct clk i2c1_ick = {
 	.name		= "i2c_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
@@ -2344,9 +2340,9 @@
 
 static struct clk i2c1_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_12m_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_I2C1_SHIFT,
@@ -2355,9 +2351,9 @@
 
 static struct clk i2chs1_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_I2CHS1_SHIFT,
@@ -2366,33 +2362,33 @@
 
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
+	.ops		= &clkops_null, /* RMK: missing? */
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdma_fck = {
 	.name		= "sdma_fck",
+	.ops		= &clkops_null, /* RMK: missing? */
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
+	.ops		= &clkops_null, /* RMK: missing? */
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk vlynq_ick = {
 	.name		= "vlynq_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
@@ -2426,8 +2422,9 @@
 
 static struct clk vlynq_fck = {
 	.name		= "vlynq_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP242X | DELAYED_APP,
+	.flags		= DELAYED_APP,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP2420_EN_VLYNQ_SHIFT,
@@ -2442,8 +2439,9 @@
 
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
@@ -2452,8 +2450,8 @@
 
 static struct clk des_ick = {
 	.name		= "des_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_DES_SHIFT,
@@ -2462,8 +2460,8 @@
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_SHA_SHIFT,
@@ -2472,8 +2470,8 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_RNG_SHIFT,
@@ -2482,8 +2480,8 @@
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_AES_SHIFT,
@@ -2492,8 +2490,8 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
 	.enable_bit	= OMAP24XX_EN_PKA_SHIFT,
@@ -2502,8 +2500,8 @@
 
 static struct clk usb_fck = {
 	.name		= "usb_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_48m_ck,
-	.flags		= CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP24XX_EN_USB_SHIFT,
@@ -2512,8 +2510,8 @@
 
 static struct clk usbhs_ick = {
 	.name		= "usbhs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_USBHS_SHIFT,
@@ -2522,8 +2520,8 @@
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
@@ -2532,8 +2530,8 @@
 
 static struct clk mmchs1_fck = {
 	.name		= "mmchs_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
@@ -2542,9 +2540,9 @@
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
@@ -2553,9 +2551,9 @@
 
 static struct clk mmchs2_fck = {
 	.name		= "mmchs_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_96m_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -2563,8 +2561,8 @@
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
@@ -2573,8 +2571,8 @@
 
 static struct clk gpio5_fck = {
 	.name		= "gpio5_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_GPIO5_SHIFT,
@@ -2583,8 +2581,8 @@
 
 static struct clk mdm_intc_ick = {
 	.name		= "mdm_intc_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP2430_EN_MDM_INTC_SHIFT,
@@ -2593,8 +2591,8 @@
 
 static struct clk mmchsdb1_fck = {
 	.name		= "mmchsdb_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHSDB1_SHIFT,
@@ -2603,9 +2601,9 @@
 
 static struct clk mmchsdb2_fck = {
 	.name		= "mmchsdb_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &func_32k_ck,
-	.flags		= CLOCK_IN_OMAP243X,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHSDB2_SHIFT,
@@ -2628,166 +2626,13 @@
  */
 static struct clk virt_prcm_set = {
 	.name		= "virt_prcm_set",
-	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-				VIRTUAL_CLOCK | ALWAYS_ENABLED | DELAYED_APP,
+	.ops		= &clkops_null,
+	.flags		= DELAYED_APP,
 	.parent		= &mpu_ck,	/* Indexed by mpu speed, no parent */
 	.recalc		= &omap2_table_mpu_recalc,	/* sets are keyed on mpu rate */
 	.set_rate	= &omap2_select_table_rate,
 	.round_rate	= &omap2_round_to_table_rate,
 };
 
-static struct clk *onchip_24xx_clks[] __initdata = {
-	/* external root sources */
-	&func_32k_ck,
-	&osc_ck,
-	&sys_ck,
-	&alt_ck,
-	/* internal analog sources */
-	&dpll_ck,
-	&apll96_ck,
-	&apll54_ck,
-	/* internal prcm root sources */
-	&func_54m_ck,
-	&core_ck,
-	&func_96m_ck,
-	&func_48m_ck,
-	&func_12m_ck,
-	&wdt1_osc_ck,
-	&sys_clkout_src,
-	&sys_clkout,
-	&sys_clkout2_src,
-	&sys_clkout2,
-	&emul_ck,
-	/* mpu domain clocks */
-	&mpu_ck,
-	/* dsp domain clocks */
-	&dsp_fck,
-	&dsp_irate_ick,
-	&dsp_ick,		/* 242x */
-	&iva2_1_ick,		/* 243x */
-	&iva1_ifck,		/* 242x */
-	&iva1_mpu_int_ifck,	/* 242x */
-	/* GFX domain clocks */
-	&gfx_3d_fck,
-	&gfx_2d_fck,
-	&gfx_ick,
-	/* Modem domain clocks */
-	&mdm_ick,
-	&mdm_osc_ck,
-	/* DSS domain clocks */
-	&dss_ick,
-	&dss1_fck,
-	&dss2_fck,
-	&dss_54m_fck,
-	/* L3 domain clocks */
-	&core_l3_ck,
-	&ssi_ssr_sst_fck,
-	&usb_l4_ick,
-	/* L4 domain clocks */
-	&l4_ck,			/* used as both core_l4 and wu_l4 */
-	/* virtual meta-group clock */
-	&virt_prcm_set,
-	/* general l4 interface ck, multi-parent functional clk */
-	&gpt1_ick,
-	&gpt1_fck,
-	&gpt2_ick,
-	&gpt2_fck,
-	&gpt3_ick,
-	&gpt3_fck,
-	&gpt4_ick,
-	&gpt4_fck,
-	&gpt5_ick,
-	&gpt5_fck,
-	&gpt6_ick,
-	&gpt6_fck,
-	&gpt7_ick,
-	&gpt7_fck,
-	&gpt8_ick,
-	&gpt8_fck,
-	&gpt9_ick,
-	&gpt9_fck,
-	&gpt10_ick,
-	&gpt10_fck,
-	&gpt11_ick,
-	&gpt11_fck,
-	&gpt12_ick,
-	&gpt12_fck,
-	&mcbsp1_ick,
-	&mcbsp1_fck,
-	&mcbsp2_ick,
-	&mcbsp2_fck,
-	&mcbsp3_ick,
-	&mcbsp3_fck,
-	&mcbsp4_ick,
-	&mcbsp4_fck,
-	&mcbsp5_ick,
-	&mcbsp5_fck,
-	&mcspi1_ick,
-	&mcspi1_fck,
-	&mcspi2_ick,
-	&mcspi2_fck,
-	&mcspi3_ick,
-	&mcspi3_fck,
-	&uart1_ick,
-	&uart1_fck,
-	&uart2_ick,
-	&uart2_fck,
-	&uart3_ick,
-	&uart3_fck,
-	&gpios_ick,
-	&gpios_fck,
-	&mpu_wdt_ick,
-	&mpu_wdt_fck,
-	&sync_32k_ick,
-	&wdt1_ick,
-	&omapctrl_ick,
-	&icr_ick,
-	&cam_fck,
-	&cam_ick,
-	&mailboxes_ick,
-	&wdt4_ick,
-	&wdt4_fck,
-	&wdt3_ick,
-	&wdt3_fck,
-	&mspro_ick,
-	&mspro_fck,
-	&mmc_ick,
-	&mmc_fck,
-	&fac_ick,
-	&fac_fck,
-	&eac_ick,
-	&eac_fck,
-	&hdq_ick,
-	&hdq_fck,
-	&i2c1_ick,
-	&i2c1_fck,
-	&i2chs1_fck,
-	&i2c2_ick,
-	&i2c2_fck,
-	&i2chs2_fck,
-	&gpmc_fck,
-	&sdma_fck,
-	&sdma_ick,
-	&vlynq_ick,
-	&vlynq_fck,
-	&sdrc_ick,
-	&des_ick,
-	&sha_ick,
-	&rng_ick,
-	&aes_ick,
-	&pka_ick,
-	&usb_fck,
-	&usbhs_ick,
-	&mmchs1_ick,
-	&mmchs1_fck,
-	&mmchs2_ick,
-	&mmchs2_fck,
-	&gpio5_ick,
-	&gpio5_fck,
-	&mdm_intc_ick,
-	&mmchsdb1_fck,
-	&mmchsdb2_fck,
-};
-
 #endif
 
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 31bb701..0a14dca 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -30,15 +30,251 @@
 #include <mach/clock.h>
 #include <mach/sram.h>
 #include <asm/div64.h>
+#include <asm/clkdev.h>
 
-#include "memory.h"
+#include <mach/sdrc.h>
 #include "clock.h"
-#include "clock34xx.h"
 #include "prm.h"
 #include "prm-regbits-34xx.h"
 #include "cm.h"
 #include "cm-regbits-34xx.h"
 
+static const struct clkops clkops_noncore_dpll_ops;
+
+#include "clock34xx.h"
+
+struct omap_clk {
+	u32		cpu;
+	struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck, cp) 		\
+	{				\
+		 .cpu = cp,		\
+		.lk = {			\
+			.dev_id = dev,	\
+			.con_id = con,	\
+			.clk = ck,	\
+		},			\
+	}
+
+#define CK_343X		(1 << 0)
+#define CK_3430ES1	(1 << 1)
+#define CK_3430ES2	(1 << 2)
+
+static struct omap_clk omap34xx_clks[] = {
+	CLK(NULL,	"omap_32k_fck",	&omap_32k_fck,	CK_343X),
+	CLK(NULL,	"virt_12m_ck",	&virt_12m_ck,	CK_343X),
+	CLK(NULL,	"virt_13m_ck",	&virt_13m_ck,	CK_343X),
+	CLK(NULL,	"virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2),
+	CLK(NULL,	"virt_19_2m_ck", &virt_19_2m_ck, CK_343X),
+	CLK(NULL,	"virt_26m_ck",	&virt_26m_ck,	CK_343X),
+	CLK(NULL,	"virt_38_4m_ck", &virt_38_4m_ck, CK_343X),
+	CLK(NULL,	"osc_sys_ck",	&osc_sys_ck,	CK_343X),
+	CLK(NULL,	"sys_ck",	&sys_ck,	CK_343X),
+	CLK(NULL,	"sys_altclk",	&sys_altclk,	CK_343X),
+	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_343X),
+	CLK(NULL,	"sys_clkout1",	&sys_clkout1,	CK_343X),
+	CLK(NULL,	"dpll1_ck",	&dpll1_ck,	CK_343X),
+	CLK(NULL,	"dpll1_x2_ck",	&dpll1_x2_ck,	CK_343X),
+	CLK(NULL,	"dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_343X),
+	CLK(NULL,	"dpll2_ck",	&dpll2_ck,	CK_343X),
+	CLK(NULL,	"dpll2_m2_ck",	&dpll2_m2_ck,	CK_343X),
+	CLK(NULL,	"dpll3_ck",	&dpll3_ck,	CK_343X),
+	CLK(NULL,	"core_ck",	&core_ck,	CK_343X),
+	CLK(NULL,	"dpll3_x2_ck",	&dpll3_x2_ck,	CK_343X),
+	CLK(NULL,	"dpll3_m2_ck",	&dpll3_m2_ck,	CK_343X),
+	CLK(NULL,	"dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_343X),
+	CLK(NULL,	"dpll3_m3_ck",	&dpll3_m3_ck,	CK_343X),
+	CLK(NULL,	"dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_343X),
+	CLK(NULL,	"emu_core_alwon_ck", &emu_core_alwon_ck, CK_343X),
+	CLK(NULL,	"dpll4_ck",	&dpll4_ck,	CK_343X),
+	CLK(NULL,	"dpll4_x2_ck",	&dpll4_x2_ck,	CK_343X),
+	CLK(NULL,	"omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X),
+	CLK(NULL,	"omap_96m_fck",	&omap_96m_fck,	CK_343X),
+	CLK(NULL,	"cm_96m_fck",	&cm_96m_fck,	CK_343X),
+	CLK(NULL,	"omap_54m_fck",	&omap_54m_fck,	CK_343X),
+	CLK(NULL,	"omap_48m_fck",	&omap_48m_fck,	CK_343X),
+	CLK(NULL,	"omap_12m_fck",	&omap_12m_fck,	CK_343X),
+	CLK(NULL,	"dpll4_m2_ck",	&dpll4_m2_ck,	CK_343X),
+	CLK(NULL,	"dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_343X),
+	CLK(NULL,	"dpll4_m3_ck",	&dpll4_m3_ck,	CK_343X),
+	CLK(NULL,	"dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_343X),
+	CLK(NULL,	"dpll4_m4_ck",	&dpll4_m4_ck,	CK_343X),
+	CLK(NULL,	"dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_343X),
+	CLK(NULL,	"dpll4_m5_ck",	&dpll4_m5_ck,	CK_343X),
+	CLK(NULL,	"dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_343X),
+	CLK(NULL,	"dpll4_m6_ck",	&dpll4_m6_ck,	CK_343X),
+	CLK(NULL,	"dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_343X),
+	CLK(NULL,	"emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X),
+	CLK(NULL,	"dpll5_ck",	&dpll5_ck,	CK_3430ES2),
+	CLK(NULL,	"dpll5_m2_ck",	&dpll5_m2_ck,	CK_3430ES2),
+	CLK(NULL,	"clkout2_src_ck", &clkout2_src_ck, CK_343X),
+	CLK(NULL,	"sys_clkout2",	&sys_clkout2,	CK_343X),
+	CLK(NULL,	"corex2_fck",	&corex2_fck,	CK_343X),
+	CLK(NULL,	"dpll1_fck",	&dpll1_fck,	CK_343X),
+	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_343X),
+	CLK(NULL,	"arm_fck",	&arm_fck,	CK_343X),
+	CLK(NULL,	"emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_343X),
+	CLK(NULL,	"dpll2_fck",	&dpll2_fck,	CK_343X),
+	CLK(NULL,	"iva2_ck",	&iva2_ck,	CK_343X),
+	CLK(NULL,	"l3_ick",	&l3_ick,	CK_343X),
+	CLK(NULL,	"l4_ick",	&l4_ick,	CK_343X),
+	CLK(NULL,	"rm_ick",	&rm_ick,	CK_343X),
+	CLK(NULL,	"gfx_l3_ck",	&gfx_l3_ck,	CK_3430ES1),
+	CLK(NULL,	"gfx_l3_fck",	&gfx_l3_fck,	CK_3430ES1),
+	CLK(NULL,	"gfx_l3_ick",	&gfx_l3_ick,	CK_3430ES1),
+	CLK(NULL,	"gfx_cg1_ck",	&gfx_cg1_ck,	CK_3430ES1),
+	CLK(NULL,	"gfx_cg2_ck",	&gfx_cg2_ck,	CK_3430ES1),
+	CLK(NULL,	"sgx_fck",	&sgx_fck,	CK_3430ES2),
+	CLK(NULL,	"sgx_ick",	&sgx_ick,	CK_3430ES2),
+	CLK(NULL,	"d2d_26m_fck",	&d2d_26m_fck,	CK_3430ES1),
+	CLK(NULL,	"gpt10_fck",	&gpt10_fck,	CK_343X),
+	CLK(NULL,	"gpt11_fck",	&gpt11_fck,	CK_343X),
+	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2),
+	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2),
+	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2),
+	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_343X),
+	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2),
+	CLK("mmci-omap-hs.1",	"fck",	&mmchs2_fck,	CK_343X),
+	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_343X),
+	CLK("mmci-omap-hs.0",	"fck",	&mmchs1_fck,	CK_343X),
+	CLK("i2c_omap.3", "fck",	&i2c3_fck,	CK_343X),
+	CLK("i2c_omap.2", "fck",	&i2c2_fck,	CK_343X),
+	CLK("i2c_omap.1", "fck",	&i2c1_fck,	CK_343X),
+	CLK("omap-mcbsp.5", "fck",	&mcbsp5_fck,	CK_343X),
+	CLK("omap-mcbsp.1", "fck",	&mcbsp1_fck,	CK_343X),
+	CLK(NULL,	"core_48m_fck",	&core_48m_fck,	CK_343X),
+	CLK("omap2_mcspi.4", "fck",	&mcspi4_fck,	CK_343X),
+	CLK("omap2_mcspi.3", "fck",	&mcspi3_fck,	CK_343X),
+	CLK("omap2_mcspi.2", "fck",	&mcspi2_fck,	CK_343X),
+	CLK("omap2_mcspi.1", "fck",	&mcspi1_fck,	CK_343X),
+	CLK(NULL,	"uart2_fck",	&uart2_fck,	CK_343X),
+	CLK(NULL,	"uart1_fck",	&uart1_fck,	CK_343X),
+	CLK(NULL,	"fshostusb_fck", &fshostusb_fck, CK_3430ES1),
+	CLK(NULL,	"core_12m_fck",	&core_12m_fck,	CK_343X),
+	CLK("omap_hdq.0", "fck",	&hdq_fck,	CK_343X),
+	CLK(NULL,	"ssi_ssr_fck",	&ssi_ssr_fck,	CK_343X),
+	CLK(NULL,	"ssi_sst_fck",	&ssi_sst_fck,	CK_343X),
+	CLK(NULL,	"core_l3_ick",	&core_l3_ick,	CK_343X),
+	CLK(NULL,	"hsotgusb_ick",	&hsotgusb_ick,	CK_343X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_343X),
+	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_343X),
+	CLK(NULL,	"security_l3_ick", &security_l3_ick, CK_343X),
+	CLK(NULL,	"pka_ick",	&pka_ick,	CK_343X),
+	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_343X),
+	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2),
+	CLK("mmci-omap-hs.2",	"ick",	&mmchs3_ick,	CK_3430ES2),
+	CLK(NULL,	"icr_ick",	&icr_ick,	CK_343X),
+	CLK(NULL,	"aes2_ick",	&aes2_ick,	CK_343X),
+	CLK(NULL,	"sha12_ick",	&sha12_ick,	CK_343X),
+	CLK(NULL,	"des2_ick",	&des2_ick,	CK_343X),
+	CLK("mmci-omap-hs.1",	"ick",	&mmchs2_ick,	CK_343X),
+	CLK("mmci-omap-hs.0",	"ick",	&mmchs1_ick,	CK_343X),
+	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_343X),
+	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_343X),
+	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_343X),
+	CLK("omap2_mcspi.3", "ick",	&mcspi3_ick,	CK_343X),
+	CLK("omap2_mcspi.2", "ick",	&mcspi2_ick,	CK_343X),
+	CLK("omap2_mcspi.1", "ick",	&mcspi1_ick,	CK_343X),
+	CLK("i2c_omap.3", "ick",	&i2c3_ick,	CK_343X),
+	CLK("i2c_omap.2", "ick",	&i2c2_ick,	CK_343X),
+	CLK("i2c_omap.1", "ick",	&i2c1_ick,	CK_343X),
+	CLK(NULL,	"uart2_ick",	&uart2_ick,	CK_343X),
+	CLK(NULL,	"uart1_ick",	&uart1_ick,	CK_343X),
+	CLK(NULL,	"gpt11_ick",	&gpt11_ick,	CK_343X),
+	CLK(NULL,	"gpt10_ick",	&gpt10_ick,	CK_343X),
+	CLK("omap-mcbsp.5", "ick",	&mcbsp5_ick,	CK_343X),
+	CLK("omap-mcbsp.1", "ick",	&mcbsp1_ick,	CK_343X),
+	CLK(NULL,	"fac_ick",	&fac_ick,	CK_3430ES1),
+	CLK(NULL,	"mailboxes_ick", &mailboxes_ick, CK_343X),
+	CLK(NULL,	"omapctrl_ick",	&omapctrl_ick,	CK_343X),
+	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_343X),
+	CLK(NULL,	"ssi_ick",	&ssi_ick,	CK_343X),
+	CLK(NULL,	"usb_l4_ick",	&usb_l4_ick,	CK_3430ES1),
+	CLK(NULL,	"security_l4_ick2", &security_l4_ick2, CK_343X),
+	CLK(NULL,	"aes1_ick",	&aes1_ick,	CK_343X),
+	CLK("omap_rng",	"ick",		&rng_ick,	CK_343X),
+	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_343X),
+	CLK(NULL,	"des1_ick",	&des1_ick,	CK_343X),
+	CLK(NULL,	"dss1_alwon_fck", &dss1_alwon_fck, CK_343X),
+	CLK(NULL,	"dss_tv_fck",	&dss_tv_fck,	CK_343X),
+	CLK(NULL,	"dss_96m_fck",	&dss_96m_fck,	CK_343X),
+	CLK(NULL,	"dss2_alwon_fck", &dss2_alwon_fck, CK_343X),
+	CLK(NULL,	"dss_ick",	&dss_ick,	CK_343X),
+	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_343X),
+	CLK(NULL,	"cam_ick",	&cam_ick,	CK_343X),
+	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_343X),
+	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2),
+	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2),
+	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2),
+	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2),
+	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_343X),
+	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_343X),
+	CLK(NULL,	"gpio1_dbck",	&gpio1_dbck,	CK_343X),
+	CLK("omap_wdt",	"fck",		&wdt2_fck,	CK_343X),
+	CLK(NULL,	"wkup_l4_ick",	&wkup_l4_ick,	CK_343X),
+	CLK(NULL,	"usim_ick",	&usim_ick,	CK_3430ES2),
+	CLK("omap_wdt",	"ick",		&wdt2_ick,	CK_343X),
+	CLK(NULL,	"wdt1_ick",	&wdt1_ick,	CK_343X),
+	CLK(NULL,	"gpio1_ick",	&gpio1_ick,	CK_343X),
+	CLK(NULL,	"omap_32ksync_ick", &omap_32ksync_ick, CK_343X),
+	CLK(NULL,	"gpt12_ick",	&gpt12_ick,	CK_343X),
+	CLK(NULL,	"gpt1_ick",	&gpt1_ick,	CK_343X),
+	CLK(NULL,	"per_96m_fck",	&per_96m_fck,	CK_343X),
+	CLK(NULL,	"per_48m_fck",	&per_48m_fck,	CK_343X),
+	CLK(NULL,	"uart3_fck",	&uart3_fck,	CK_343X),
+	CLK(NULL,	"gpt2_fck",	&gpt2_fck,	CK_343X),
+	CLK(NULL,	"gpt3_fck",	&gpt3_fck,	CK_343X),
+	CLK(NULL,	"gpt4_fck",	&gpt4_fck,	CK_343X),
+	CLK(NULL,	"gpt5_fck",	&gpt5_fck,	CK_343X),
+	CLK(NULL,	"gpt6_fck",	&gpt6_fck,	CK_343X),
+	CLK(NULL,	"gpt7_fck",	&gpt7_fck,	CK_343X),
+	CLK(NULL,	"gpt8_fck",	&gpt8_fck,	CK_343X),
+	CLK(NULL,	"gpt9_fck",	&gpt9_fck,	CK_343X),
+	CLK(NULL,	"per_32k_alwon_fck", &per_32k_alwon_fck, CK_343X),
+	CLK(NULL,	"gpio6_dbck",	&gpio6_dbck,	CK_343X),
+	CLK(NULL,	"gpio5_dbck",	&gpio5_dbck,	CK_343X),
+	CLK(NULL,	"gpio4_dbck",	&gpio4_dbck,	CK_343X),
+	CLK(NULL,	"gpio3_dbck",	&gpio3_dbck,	CK_343X),
+	CLK(NULL,	"gpio2_dbck",	&gpio2_dbck,	CK_343X),
+	CLK(NULL,	"wdt3_fck",	&wdt3_fck,	CK_343X),
+	CLK(NULL,	"per_l4_ick",	&per_l4_ick,	CK_343X),
+	CLK(NULL,	"gpio6_ick",	&gpio6_ick,	CK_343X),
+	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_343X),
+	CLK(NULL,	"gpio4_ick",	&gpio4_ick,	CK_343X),
+	CLK(NULL,	"gpio3_ick",	&gpio3_ick,	CK_343X),
+	CLK(NULL,	"gpio2_ick",	&gpio2_ick,	CK_343X),
+	CLK(NULL,	"wdt3_ick",	&wdt3_ick,	CK_343X),
+	CLK(NULL,	"uart3_ick",	&uart3_ick,	CK_343X),
+	CLK(NULL,	"gpt9_ick",	&gpt9_ick,	CK_343X),
+	CLK(NULL,	"gpt8_ick",	&gpt8_ick,	CK_343X),
+	CLK(NULL,	"gpt7_ick",	&gpt7_ick,	CK_343X),
+	CLK(NULL,	"gpt6_ick",	&gpt6_ick,	CK_343X),
+	CLK(NULL,	"gpt5_ick",	&gpt5_ick,	CK_343X),
+	CLK(NULL,	"gpt4_ick",	&gpt4_ick,	CK_343X),
+	CLK(NULL,	"gpt3_ick",	&gpt3_ick,	CK_343X),
+	CLK(NULL,	"gpt2_ick",	&gpt2_ick,	CK_343X),
+	CLK("omap-mcbsp.2", "ick",	&mcbsp2_ick,	CK_343X),
+	CLK("omap-mcbsp.3", "ick",	&mcbsp3_ick,	CK_343X),
+	CLK("omap-mcbsp.4", "ick",	&mcbsp4_ick,	CK_343X),
+	CLK("omap-mcbsp.2", "fck",	&mcbsp2_fck,	CK_343X),
+	CLK("omap-mcbsp.3", "fck",	&mcbsp3_fck,	CK_343X),
+	CLK("omap-mcbsp.4", "fck",	&mcbsp4_fck,	CK_343X),
+	CLK(NULL,	"emu_src_ck",	&emu_src_ck,	CK_343X),
+	CLK(NULL,	"pclk_fck",	&pclk_fck,	CK_343X),
+	CLK(NULL,	"pclkx2_fck",	&pclkx2_fck,	CK_343X),
+	CLK(NULL,	"atclk_fck",	&atclk_fck,	CK_343X),
+	CLK(NULL,	"traceclk_src_fck", &traceclk_src_fck, CK_343X),
+	CLK(NULL,	"traceclk_fck",	&traceclk_fck,	CK_343X),
+	CLK(NULL,	"sr1_fck",	&sr1_fck,	CK_343X),
+	CLK(NULL,	"sr2_fck",	&sr2_fck,	CK_343X),
+	CLK(NULL,	"sr_l4_ick",	&sr_l4_ick,	CK_343X),
+	CLK(NULL,	"secure_32k_fck", &secure_32k_fck, CK_343X),
+	CLK(NULL,	"gpt12_fck",	&gpt12_fck,	CK_343X),
+	CLK(NULL,	"wdt1_fck",	&wdt1_fck,	CK_343X),
+};
+
 /* CM_AUTOIDLE_PLL*.AUTO_* bit values */
 #define DPLL_AUTOIDLE_DISABLE			0x0
 #define DPLL_AUTOIDLE_LOW_POWER_STOP		0x1
@@ -51,11 +287,9 @@
  *
  * Recalculate and propagate the DPLL rate.
  */
-static void omap3_dpll_recalc(struct clk *clk)
+static unsigned long omap3_dpll_recalc(struct clk *clk)
 {
-	clk->rate = omap2_get_dpll_rate(clk);
-
-	propagate_rate(clk);
+	return omap2_get_dpll_rate(clk);
 }
 
 /* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -78,14 +312,12 @@
 	const struct dpll_data *dd;
 	int i = 0;
 	int ret = -EINVAL;
-	u32 idlest_mask;
 
 	dd = clk->dpll_data;
 
-	state <<= dd->idlest_bit;
-	idlest_mask = 1 << dd->idlest_bit;
+	state <<= __ffs(dd->idlest_mask);
 
-	while (((__raw_readl(dd->idlest_reg) & idlest_mask) != state) &&
+	while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
 	       i < MAX_DPLL_WAIT_TRIES) {
 		i++;
 		udelay(1);
@@ -104,6 +336,42 @@
 	return ret;
 }
 
+/* From 3430 TRM ES2 4.7.6.2 */
+static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
+{
+	unsigned long fint;
+	u16 f = 0;
+
+	fint = clk->dpll_data->clk_ref->rate / (n + 1);
+
+	pr_debug("clock: fint is %lu\n", fint);
+
+	if (fint >= 750000 && fint <= 1000000)
+		f = 0x3;
+	else if (fint > 1000000 && fint <= 1250000)
+		f = 0x4;
+	else if (fint > 1250000 && fint <= 1500000)
+		f = 0x5;
+	else if (fint > 1500000 && fint <= 1750000)
+		f = 0x6;
+	else if (fint > 1750000 && fint <= 2100000)
+		f = 0x7;
+	else if (fint > 7500000 && fint <= 10000000)
+		f = 0xB;
+	else if (fint > 10000000 && fint <= 12500000)
+		f = 0xC;
+	else if (fint > 12500000 && fint <= 15000000)
+		f = 0xD;
+	else if (fint > 15000000 && fint <= 17500000)
+		f = 0xE;
+	else if (fint > 17500000 && fint <= 21000000)
+		f = 0xF;
+	else
+		pr_debug("clock: unknown freqsel setting for %d\n", n);
+
+	return f;
+}
+
 /* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
 
 /*
@@ -128,25 +396,20 @@
 
 	ai = omap3_dpll_autoidle_read(clk);
 
+	omap3_dpll_deny_idle(clk);
+
 	_omap3_dpll_write_clken(clk, DPLL_LOCKED);
 
-	if (ai) {
-		/*
-		 * If no downstream clocks are enabled, CM_IDLEST bit
-		 * may never become active, so don't wait for DPLL to lock.
-		 */
-		r = 0;
+	r = _omap3_wait_dpll_status(clk, 1);
+
+	if (ai)
 		omap3_dpll_allow_idle(clk);
-	} else {
-		r = _omap3_wait_dpll_status(clk, 1);
-		omap3_dpll_deny_idle(clk);
-	};
 
 	return r;
 }
 
 /*
- * omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
+ * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
  * @clk: pointer to a DPLL struct clk
  *
  * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
@@ -236,14 +499,25 @@
 static int omap3_noncore_dpll_enable(struct clk *clk)
 {
 	int r;
+	struct dpll_data *dd;
 
 	if (clk == &dpll3_ck)
 		return -EINVAL;
 
-	if (clk->parent->rate == clk_get_rate(clk))
+	dd = clk->dpll_data;
+	if (!dd)
+		return -EINVAL;
+
+	if (clk->rate == dd->clk_bypass->rate) {
+		WARN_ON(clk->parent != dd->clk_bypass);
 		r = _omap3_noncore_dpll_bypass(clk);
-	else
+	} else {
+		WARN_ON(clk->parent != dd->clk_ref);
 		r = _omap3_noncore_dpll_lock(clk);
+	}
+	/* FIXME: this is dubious - if clk->rate has changed, what about propagating? */
+	if (!r)
+		clk->rate = omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -270,6 +544,215 @@
 	_omap3_noncore_dpll_stop(clk);
 }
 
+
+/* Non-CORE DPLL rate set code */
+
+/*
+ * omap3_noncore_dpll_program - set non-core DPLL M,N values directly
+ * @clk: struct clk * of DPLL to set
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ * @freqsel: FREQSEL value to set
+ *
+ * Program the DPLL with the supplied M, N values, and wait for the DPLL to
+ * lock..  Returns -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
+{
+	struct dpll_data *dd = clk->dpll_data;
+	u32 v;
+
+	/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
+	_omap3_noncore_dpll_bypass(clk);
+
+	/* Set jitter correction */
+	v = __raw_readl(dd->control_reg);
+	v &= ~dd->freqsel_mask;
+	v |= freqsel << __ffs(dd->freqsel_mask);
+	__raw_writel(v, dd->control_reg);
+
+	/* Set DPLL multiplier, divider */
+	v = __raw_readl(dd->mult_div1_reg);
+	v &= ~(dd->mult_mask | dd->div1_mask);
+	v |= m << __ffs(dd->mult_mask);
+	v |= (n - 1) << __ffs(dd->div1_mask);
+	__raw_writel(v, dd->mult_div1_reg);
+
+	/* We let the clock framework set the other output dividers later */
+
+	/* REVISIT: Set ramp-up delay? */
+
+	_omap3_noncore_dpll_lock(clk);
+
+	return 0;
+}
+
+/**
+ * omap3_noncore_dpll_set_rate - set non-core DPLL rate
+ * @clk: struct clk * of DPLL to set
+ * @rate: rounded target rate
+ *
+ * Set the DPLL CLKOUT to the target rate.  If the DPLL can enter
+ * low-power bypass, and the target rate is the bypass source clock
+ * rate, then configure the DPLL for bypass.  Otherwise, round the
+ * target rate if it hasn't been done already, then program and lock
+ * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *new_parent = NULL;
+	u16 freqsel;
+	struct dpll_data *dd;
+	int ret;
+
+	if (!clk || !rate)
+		return -EINVAL;
+
+	dd = clk->dpll_data;
+	if (!dd)
+		return -EINVAL;
+
+	if (rate == omap2_get_dpll_rate(clk))
+		return 0;
+
+	/*
+	 * Ensure both the bypass and ref clocks are enabled prior to
+	 * doing anything; we need the bypass clock running to reprogram
+	 * the DPLL.
+	 */
+	omap2_clk_enable(dd->clk_bypass);
+	omap2_clk_enable(dd->clk_ref);
+
+	if (dd->clk_bypass->rate == rate &&
+	    (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+		pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
+
+		ret = _omap3_noncore_dpll_bypass(clk);
+		if (!ret)
+			new_parent = dd->clk_bypass;
+	} else {
+		if (dd->last_rounded_rate != rate)
+			omap2_dpll_round_rate(clk, rate);
+
+		if (dd->last_rounded_rate == 0)
+			return -EINVAL;
+
+		freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
+		if (!freqsel)
+			WARN_ON(1);
+
+		pr_debug("clock: %s: set rate: locking rate to %lu.\n",
+			 clk->name, rate);
+
+		ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
+						 dd->last_rounded_n, freqsel);
+		if (!ret)
+			new_parent = dd->clk_ref;
+	}
+	if (!ret) {
+		/*
+		 * Switch the parent clock in the heirarchy, and make sure
+		 * that the new parent's usecount is correct.  Note: we
+		 * enable the new parent before disabling the old to avoid
+		 * any unnecessary hardware disable->enable transitions.
+		 */
+		if (clk->usecount) {
+			omap2_clk_enable(new_parent);
+			omap2_clk_disable(clk->parent);
+		}
+		clk_reparent(clk, new_parent);
+		clk->rate = rate;
+	}
+	omap2_clk_disable(dd->clk_ref);
+	omap2_clk_disable(dd->clk_bypass);
+
+	return 0;
+}
+
+static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
+{
+	/*
+	 * According to the 12-5 CDP code from TI, "Limitation 2.5"
+	 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
+	 * on DPLL4.
+	 */
+	if (omap_rev() == OMAP3430_REV_ES1_0) {
+		printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
+		       "silicon 'Limitation 2.5' on 3430ES1.\n");
+		return -EINVAL;
+	}
+	return omap3_noncore_dpll_set_rate(clk, rate);
+}
+
+
+/*
+ * CORE DPLL (DPLL3) rate programming functions
+ *
+ * These call into SRAM code to do the actual CM writes, since the SDRAM
+ * is clocked from DPLL3.
+ */
+
+/**
+ * omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider
+ * @clk: struct clk * of DPLL to set
+ * @rate: rounded target rate
+ *
+ * Program the DPLL M2 divider with the rounded target rate.  Returns
+ * -EINVAL upon error, or 0 upon success.
+ */
+static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 new_div = 0;
+	unsigned long validrate, sdrcrate;
+	struct omap_sdrc_params *sp;
+
+	if (!clk || !rate)
+		return -EINVAL;
+
+	if (clk != &dpll3_m2_ck)
+		return -EINVAL;
+
+	if (rate == clk->rate)
+		return 0;
+
+	validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
+	if (validrate != rate)
+		return -EINVAL;
+
+	sdrcrate = sdrc_ick.rate;
+	if (rate > clk->rate)
+		sdrcrate <<= ((rate / clk->rate) - 1);
+	else
+		sdrcrate >>= ((clk->rate / rate) - 1);
+
+	sp = omap2_sdrc_get_params(sdrcrate);
+	if (!sp)
+		return -EINVAL;
+
+	pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
+		validrate);
+	pr_info("clock: SDRC timing params used: %08x %08x %08x\n",
+		sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
+
+	/* REVISIT: SRAM code doesn't support other M2 divisors yet */
+	WARN_ON(new_div != 1 && new_div != 2);
+
+	/* REVISIT: Add SDRC_MR changing to this code also */
+	omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
+				  sp->actim_ctrlb, new_div);
+
+	return 0;
+}
+
+
+static const struct clkops clkops_noncore_dpll_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+};
+
+/* DPLL autoidle read/set code */
+
+
 /**
  * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
  * @clk: struct clk * of the DPLL to read
@@ -356,9 +839,10 @@
  * Using parent clock DPLL data, look up DPLL state.  If locked, set our
  * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
  */
-static void omap3_clkoutx2_recalc(struct clk *clk)
+static unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 {
 	const struct dpll_data *dd;
+	unsigned long rate;
 	u32 v;
 	struct clk *pclk;
 
@@ -372,17 +856,15 @@
 
 	dd = pclk->dpll_data;
 
-	WARN_ON(!dd->control_reg || !dd->enable_mask);
+	WARN_ON(!dd->enable_mask);
 
 	v = __raw_readl(dd->control_reg) & dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
-	if (v != DPLL_LOCKED)
-		clk->rate = clk->parent->rate;
+	if (v != OMAP3XXX_EN_DPLL_LOCKED)
+		rate = clk->parent->rate;
 	else
-		clk->rate = clk->parent->rate * 2;
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
+		rate = clk->parent->rate * 2;
+	return rate;
 }
 
 /* Common clock code */
@@ -432,7 +914,7 @@
 
 	/* REVISIT: not yet ready for 343x */
 #if 0
-	if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+	if (clk_set_rate(&virt_prcm_set, mpurate))
 		printk(KERN_ERR "Could not find matching MPU rate\n");
 #endif
 
@@ -450,26 +932,13 @@
 int __init omap2_clk_init(void)
 {
 	/* struct prcm_config *prcm; */
-	struct clk **clkp;
+	struct omap_clk *c;
 	/* u32 clkrate; */
 	u32 cpu_clkflg;
 
-	/* REVISIT: Ultimately this will be used for multiboot */
-#if 0
-	if (cpu_is_omap242x()) {
-		cpu_mask = RATE_IN_242X;
-		cpu_clkflg = CLOCK_IN_OMAP242X;
-		clkp = onchip_24xx_clks;
-	} else if (cpu_is_omap2430()) {
-		cpu_mask = RATE_IN_243X;
-		cpu_clkflg = CLOCK_IN_OMAP243X;
-		clkp = onchip_24xx_clks;
-	}
-#endif
 	if (cpu_is_omap34xx()) {
 		cpu_mask = RATE_IN_343X;
-		cpu_clkflg = CLOCK_IN_OMAP343X;
-		clkp = onchip_34xx_clks;
+		cpu_clkflg = CK_343X;
 
 		/*
 		 * Update this if there are further clock changes between ES2
@@ -477,23 +946,24 @@
 		 */
 		if (omap_rev() == OMAP3430_REV_ES1_0) {
 			/* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
-			cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
+			cpu_clkflg |= CK_3430ES1;
 		} else {
 			cpu_mask |= RATE_IN_3430ES2;
-			cpu_clkflg |= CLOCK_IN_OMAP3430ES2;
+			cpu_clkflg |= CK_3430ES2;
 		}
 	}
 
 	clk_init(&omap2_clk_functions);
 
-	for (clkp = onchip_34xx_clks;
-	     clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
-	     clkp++) {
-		if ((*clkp)->flags & cpu_clkflg) {
-			clk_register(*clkp);
-			omap2_init_clk_clkdm(*clkp);
+	for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
+		clk_init_one(c->lk.clk);
+
+	for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
+		if (c->cpu & cpu_clkflg) {
+			clkdev_add(&c->lk);
+			clk_register(c->lk.clk);
+			omap2_init_clk_clkdm(c->lk.clk);
 		}
-	}
 
 	/* REVISIT: Not yet ready for OMAP3 */
 #if 0
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index a826094..70ec10d 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -27,13 +27,14 @@
 #include "prm.h"
 #include "prm-regbits-34xx.h"
 
-static void omap3_dpll_recalc(struct clk *clk);
-static void omap3_clkoutx2_recalc(struct clk *clk);
+static unsigned long omap3_dpll_recalc(struct clk *clk);
+static unsigned long omap3_clkoutx2_recalc(struct clk *clk);
 static void omap3_dpll_allow_idle(struct clk *clk);
 static void omap3_dpll_deny_idle(struct clk *clk);
 static u32 omap3_dpll_autoidle_read(struct clk *clk);
-static int omap3_noncore_dpll_enable(struct clk *clk);
-static void omap3_noncore_dpll_disable(struct clk *clk);
+static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
+static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
+static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
 
 /* Maximum DPLL multiplier, divider values for OMAP3 */
 #define OMAP3_MAX_DPLL_MULT		2048
@@ -47,6 +48,10 @@
  * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
  */
 
+/* Forward declarations for DPLL bypass clocks */
+static struct clk dpll1_fck;
+static struct clk dpll2_fck;
+
 /* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
 #define DPLL_LOW_POWER_STOP		0x1
 #define DPLL_LOW_POWER_BYPASS		0x5
@@ -57,67 +62,59 @@
 /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
 static struct clk omap_32k_fck = {
 	.name		= "omap_32k_fck",
+	.ops		= &clkops_null,
 	.rate		= 32768,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk secure_32k_fck = {
 	.name		= "secure_32k_fck",
+	.ops		= &clkops_null,
 	.rate		= 32768,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 /* Virtual source clocks for osc_sys_ck */
 static struct clk virt_12m_ck = {
 	.name		= "virt_12m_ck",
+	.ops		= &clkops_null,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk virt_13m_ck = {
 	.name		= "virt_13m_ck",
+	.ops		= &clkops_null,
 	.rate		= 13000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk virt_16_8m_ck = {
 	.name		= "virt_16_8m_ck",
+	.ops		= &clkops_null,
 	.rate		= 16800000,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk virt_19_2m_ck = {
 	.name		= "virt_19_2m_ck",
+	.ops		= &clkops_null,
 	.rate		= 19200000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk virt_26m_ck = {
 	.name		= "virt_26m_ck",
+	.ops		= &clkops_null,
 	.rate		= 26000000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static struct clk virt_38_4m_ck = {
 	.name		= "virt_38_4m_ck",
+	.ops		= &clkops_null,
 	.rate		= 38400000,
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.flags		= RATE_FIXED,
 };
 
 static const struct clksel_rate osc_sys_12m_rates[] = {
@@ -164,13 +161,13 @@
 /* 12, 13, 16.8, 19.2, 26, or 38.4 MHz */
 static struct clk osc_sys_ck = {
 	.name		= "osc_sys_ck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP3430_PRM_CLKSEL,
 	.clksel_mask	= OMAP3430_SYS_CLKIN_SEL_MASK,
 	.clksel		= osc_sys_clksel,
 	/* REVISIT: deal with autoextclkmode? */
-	.flags		= CLOCK_IN_OMAP343X | RATE_FIXED | RATE_PROPAGATES |
-				ALWAYS_ENABLED,
+	.flags		= RATE_FIXED,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -189,36 +186,34 @@
 /* Feeds DPLLs - divided first by PRM_CLKSRC_CTRL.SYSCLKDIV? */
 static struct clk sys_ck = {
 	.name		= "sys_ck",
+	.ops		= &clkops_null,
 	.parent		= &osc_sys_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP3430_PRM_CLKSRC_CTRL,
 	.clksel_mask	= OMAP_SYSCLKDIV_MASK,
 	.clksel		= sys_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk sys_altclk = {
 	.name		= "sys_altclk",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.ops		= &clkops_null,
 };
 
 /* Optional external clock input for some McBSPs */
 static struct clk mcbsp_clks = {
 	.name		= "mcbsp_clks",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
-	.recalc		= &propagate_rate,
+	.ops		= &clkops_null,
 };
 
 /* PRM EXTERNAL CLOCK OUTPUT */
 
 static struct clk sys_clkout1 = {
 	.name		= "sys_clkout1",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &osc_sys_ck,
 	.enable_reg	= OMAP3430_PRM_CLKOUT_CTRL,
 	.enable_bit	= OMAP3430_CLKOUT_EN_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
@@ -226,16 +221,6 @@
 
 /* CM CLOCKS */
 
-static const struct clksel_rate dpll_bypass_rates[] = {
-	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
-	{ .div = 0 }
-};
-
-static const struct clksel_rate dpll_locked_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
-	{ .div = 0 }
-};
-
 static const struct clksel_rate div16_dpll_rates[] = {
 	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
 	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
@@ -263,6 +248,9 @@
 	.mult_div1_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
 	.mult_mask	= OMAP3430_MPU_DPLL_MULT_MASK,
 	.div1_mask	= OMAP3430_MPU_DPLL_DIV_MASK,
+	.clk_bypass	= &dpll1_fck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_MPU_DPLL_FREQSEL_MASK,
 	.control_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
 	.enable_mask	= OMAP3430_EN_MPU_DPLL_MASK,
 	.modes		= (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -272,18 +260,21 @@
 	.autoidle_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
 	.autoidle_mask	= OMAP3430_AUTO_MPU_DPLL_MASK,
 	.idlest_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
-	.idlest_bit	= OMAP3430_ST_MPU_CLK_SHIFT,
+	.idlest_mask	= OMAP3430_ST_MPU_CLK_MASK,
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
 	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll1_ck = {
 	.name		= "dpll1_ck",
+	.ops		= &clkops_null,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll1_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.clkdm_name	= "dpll1_clkdm",
 	.recalc		= &omap3_dpll_recalc,
 };
 
@@ -293,9 +284,9 @@
  */
 static struct clk dpll1_x2_ck = {
 	.name		= "dpll1_x2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll1_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll1_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
@@ -311,13 +302,13 @@
  */
 static struct clk dpll1_x2m2_ck = {
 	.name		= "dpll1_x2m2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll1_x2_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
 	.clksel_mask	= OMAP3430_MPU_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll1_x2m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll1_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -329,6 +320,9 @@
 	.mult_div1_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
 	.mult_mask	= OMAP3430_IVA2_DPLL_MULT_MASK,
 	.div1_mask	= OMAP3430_IVA2_DPLL_DIV_MASK,
+	.clk_bypass	= &dpll2_fck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_IVA2_DPLL_FREQSEL_MASK,
 	.control_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
 	.enable_mask	= OMAP3430_EN_IVA2_DPLL_MASK,
 	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
@@ -339,20 +333,21 @@
 	.autoidle_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
 	.autoidle_mask	= OMAP3430_AUTO_IVA2_DPLL_MASK,
 	.idlest_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
-	.idlest_bit	= OMAP3430_ST_IVA2_CLK_SHIFT,
+	.idlest_mask	= OMAP3430_ST_IVA2_CLK_MASK,
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
 	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll2_ck = {
 	.name		= "dpll2_ck",
+	.ops		= &clkops_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll2_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
-	.enable		= &omap3_noncore_dpll_enable,
-	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.clkdm_name	= "dpll2_clkdm",
 	.recalc		= &omap3_dpll_recalc,
 };
 
@@ -367,14 +362,14 @@
  */
 static struct clk dpll2_m2_ck = {
 	.name		= "dpll2_m2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll2_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
 					  OMAP3430_CM_CLKSEL2_PLL),
 	.clksel_mask	= OMAP3430_IVA2_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div16_dpll2_m2x2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll2_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -387,6 +382,9 @@
 	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.mult_mask	= OMAP3430_CORE_DPLL_MULT_MASK,
 	.div1_mask	= OMAP3430_CORE_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_CORE_DPLL_FREQSEL_MASK,
 	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_mask	= OMAP3430_EN_CORE_DPLL_MASK,
 	.auto_recal_bit	= OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
@@ -394,17 +392,21 @@
 	.recal_st_bit	= OMAP3430_CORE_DPLL_ST_SHIFT,
 	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
 	.autoidle_mask	= OMAP3430_AUTO_CORE_DPLL_MASK,
+	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
+	.idlest_mask	= OMAP3430_ST_CORE_CLK_MASK,
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
 	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll3_ck = {
 	.name		= "dpll3_ck",
+	.ops		= &clkops_null,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll3_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.round_rate	= &omap2_dpll_round_rate,
+	.clkdm_name	= "dpll3_clkdm",
 	.recalc		= &omap3_dpll_recalc,
 };
 
@@ -414,9 +416,9 @@
  */
 static struct clk dpll3_x2_ck = {
 	.name		= "dpll3_x2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll3_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll3_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
@@ -460,55 +462,34 @@
 	{ .parent = NULL }
 };
 
-/*
- * DPLL3 output M2
- * REVISIT: This DPLL output divider must be changed in SRAM, so until
- * that code is ready, this should remain a 'read-only' clksel clock.
- */
+/* DPLL3 output M2 - primary control point for CORE speed */
 static struct clk dpll3_m2_ck = {
 	.name		= "dpll3_m2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll3_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK,
 	.clksel		= div31_dpll3m2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll3_clkdm",
+	.round_rate	= &omap2_clksel_round_rate,
+	.set_rate	= &omap3_core_dpll_m2_set_rate,
 	.recalc		= &omap2_clksel_recalc,
 };
 
-static const struct clksel core_ck_clksel[] = {
-	{ .parent = &sys_ck,	  .rates = dpll_bypass_rates },
-	{ .parent = &dpll3_m2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk core_ck = {
 	.name		= "core_ck",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_CORE_CLK_MASK,
-	.clksel		= core_ck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel dpll3_m2x2_ck_clksel[] = {
-	{ .parent = &sys_ck,	  .rates = dpll_bypass_rates },
-	{ .parent = &dpll3_x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
+	.ops		= &clkops_null,
+	.parent		= &dpll3_m2_ck,
+	.recalc		= &followparent_recalc,
 };
 
 static struct clk dpll3_m2x2_ck = {
 	.name		= "dpll3_m2x2_ck",
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_CORE_CLK_MASK,
-	.clksel		= dpll3_m2x2_ck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
+	.ops		= &clkops_null,
+	.parent		= &dpll3_x2_ck,
+	.clkdm_name	= "dpll3_clkdm",
+	.recalc		= &followparent_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
@@ -520,42 +501,34 @@
 /* This virtual clock is the source for dpll3_m3x2_ck */
 static struct clk dpll3_m3_ck = {
 	.name		= "dpll3_m3_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll3_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_DIV_DPLL3_MASK,
 	.clksel		= div16_dpll3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll3_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll3_m3x2_ck = {
 	.name		= "dpll3_m3x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll3_m3_ck,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_EMU_CORE_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll3_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel emu_core_alwon_ck_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk emu_core_alwon_ck = {
 	.name		= "emu_core_alwon_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll3_m3x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_CORE_CLK_MASK,
-	.clksel		= emu_core_alwon_ck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
+	.clkdm_name	= "dpll3_clkdm",
+	.recalc		= &followparent_recalc,
 };
 
 /* DPLL4 */
@@ -565,6 +538,9 @@
 	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
 	.mult_mask	= OMAP3430_PERIPH_DPLL_MULT_MASK,
 	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
 	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
 	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
@@ -574,20 +550,21 @@
 	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
 	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
 	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.idlest_bit	= OMAP3430_ST_PERIPH_CLK_SHIFT,
+	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
 	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll4_ck = {
 	.name		= "dpll4_ck",
+	.ops		= &clkops_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll4_dd,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
-	.enable		= &omap3_noncore_dpll_enable,
-	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_dpll4_set_rate,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_dpll_recalc,
 };
 
@@ -598,9 +575,9 @@
  */
 static struct clk dpll4_x2_ck = {
 	.name		= "dpll4_x2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
@@ -612,112 +589,101 @@
 /* This virtual clock is the source for dpll4_m2x2_ck */
 static struct clk dpll4_m2_ck = {
 	.name		= "dpll4_m2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
 	.clksel_mask	= OMAP3430_DIV_96M_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll4_m2x2_ck = {
 	.name		= "dpll4_m2x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m2_ck,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_96M_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel omap_96m_alwon_fck_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
+/*
+ * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as
+ * PRM_96M_ALWON_(F)CLK.  Two clocks then emerge from the PRM:
+ * 96M_ALWON_FCLK (called "omap_96m_alwon_fck" below) and
+ * CM_96K_(F)CLK.
+ */
 static struct clk omap_96m_alwon_fck = {
 	.name		= "omap_96m_alwon_fck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_m2x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.clksel		= omap_96m_alwon_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				 PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static struct clk omap_96m_fck = {
-	.name		= "omap_96m_fck",
-	.parent		= &omap_96m_alwon_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &followparent_recalc,
 };
 
-static const struct clksel cm_96m_fck_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk cm_96m_fck = {
 	.name		= "cm_96m_fck",
-	.parent		= &dpll4_m2x2_ck,
+	.ops		= &clkops_null,
+	.parent		= &omap_96m_alwon_fck,
+	.recalc		= &followparent_recalc,
+};
+
+static const struct clksel_rate omap_96m_dpll_rates[] = {
+	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel_rate omap_96m_sys_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
+	{ .div = 0 }
+};
+
+static const struct clksel omap_96m_fck_clksel[] = {
+	{ .parent = &cm_96m_fck, .rates = omap_96m_dpll_rates },
+	{ .parent = &sys_ck,	 .rates = omap_96m_sys_rates },
+	{ .parent = NULL }
+};
+
+static struct clk omap_96m_fck = {
+	.name		= "omap_96m_fck",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
 	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.clksel		= cm_96m_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
+	.clksel_mask	= OMAP3430_SOURCE_96M_MASK,
+	.clksel		= omap_96m_fck_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* This virtual clock is the source for dpll4_m3x2_ck */
 static struct clk dpll4_m3_ck = {
 	.name		= "dpll4_m3_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_TV_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll4_m3x2_ck = {
 	.name		= "dpll4_m3x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m3_ck,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_TV_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel virt_omap_54m_fck_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
-static struct clk virt_omap_54m_fck = {
-	.name		= "virt_omap_54m_fck",
-	.parent		= &dpll4_m3x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.clksel		= virt_omap_54m_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
 static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
 	{ .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
 	{ .div = 0 }
@@ -729,23 +695,22 @@
 };
 
 static const struct clksel omap_54m_clksel[] = {
-	{ .parent = &virt_omap_54m_fck, .rates = omap_54m_d4m3x2_rates },
+	{ .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates },
 	{ .parent = &sys_altclk,    .rates = omap_54m_alt_rates },
 	{ .parent = NULL }
 };
 
 static struct clk omap_54m_fck = {
 	.name		= "omap_54m_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_SOURCE_54M,
+	.clksel_mask	= OMAP3430_SOURCE_54M_MASK,
 	.clksel		= omap_54m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_clksel_recalc,
 };
 
-static const struct clksel_rate omap_48m_96md2_rates[] = {
+static const struct clksel_rate omap_48m_cm96m_rates[] = {
 	{ .div = 2, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
 	{ .div = 0 }
 };
@@ -756,106 +721,112 @@
 };
 
 static const struct clksel omap_48m_clksel[] = {
-	{ .parent = &cm_96m_fck, .rates = omap_48m_96md2_rates },
+	{ .parent = &cm_96m_fck, .rates = omap_48m_cm96m_rates },
 	{ .parent = &sys_altclk, .rates = omap_48m_alt_rates },
 	{ .parent = NULL }
 };
 
 static struct clk omap_48m_fck = {
 	.name		= "omap_48m_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
-	.clksel_mask	= OMAP3430_SOURCE_48M,
+	.clksel_mask	= OMAP3430_SOURCE_48M_MASK,
 	.clksel		= omap_48m_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk omap_12m_fck = {
 	.name		= "omap_12m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_48m_fck,
 	.fixed_div	= 4,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
 
 /* This virstual clock is the source for dpll4_m4x2_ck */
 static struct clk dpll4_m4_ck = {
 	.name		= "dpll4_m4_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_DSS1_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
+	.set_rate	= &omap2_clksel_set_rate,
+	.round_rate	= &omap2_clksel_round_rate,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll4_m4x2_ck = {
 	.name		= "dpll4_m4x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m4_ck,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
 /* This virtual clock is the source for dpll4_m5x2_ck */
 static struct clk dpll4_m5_ck = {
 	.name		= "dpll4_m5_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_CAM_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll4_m5x2_ck = {
 	.name		= "dpll4_m5x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m5_ck,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
 /* This virtual clock is the source for dpll4_m6x2_ck */
 static struct clk dpll4_m6_ck = {
 	.name		= "dpll4_m6_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_DIV_DPLL4_MASK,
 	.clksel		= div16_dpll4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
 static struct clk dpll4_m6x2_ck = {
 	.name		= "dpll4_m6x2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m6_ck,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
 	.enable_bit	= OMAP3430_PWRDN_EMU_PERIPH_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | INVERT_ENABLE,
+	.flags		= INVERT_ENABLE,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &omap3_clkoutx2_recalc,
 };
 
 static struct clk emu_per_alwon_ck = {
 	.name		= "emu_per_alwon_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll4_m6x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
@@ -867,6 +838,9 @@
 	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
 	.mult_mask	= OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
 	.div1_mask	= OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
+	.clk_bypass	= &sys_ck,
+	.clk_ref	= &sys_ck,
+	.freqsel_mask	= OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
 	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
 	.enable_mask	= OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
 	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
@@ -876,20 +850,21 @@
 	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
 	.autoidle_mask	= OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
 	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
-	.idlest_bit	= OMAP3430ES2_ST_PERIPH2_CLK_SHIFT,
+	.idlest_mask	= OMAP3430ES2_ST_PERIPH2_CLK_MASK,
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
+	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
 	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll5_ck = {
 	.name		= "dpll5_ck",
+	.ops		= &clkops_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll5_dd,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
-	.enable		= &omap3_noncore_dpll_enable,
-	.disable	= &omap3_noncore_dpll_disable,
 	.round_rate	= &omap2_dpll_round_rate,
+	.set_rate	= &omap3_noncore_dpll_set_rate,
+	.clkdm_name	= "dpll5_clkdm",
 	.recalc		= &omap3_dpll_recalc,
 };
 
@@ -900,31 +875,13 @@
 
 static struct clk dpll5_m2_ck = {
 	.name		= "dpll5_m2_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll5_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
 	.clksel_mask	= OMAP3430ES2_DIV_120M_MASK,
 	.clksel		= div16_dpll5_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-static const struct clksel omap_120m_fck_clksel[] = {
-	{ .parent = &sys_ck,	  .rates = dpll_bypass_rates },
-	{ .parent = &dpll5_m2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
-static struct clk omap_120m_fck = {
-	.name		= "omap_120m_fck",
-	.parent		= &dpll5_m2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
-	.clksel_mask	= OMAP3430ES2_ST_PERIPH2_CLK_MASK,
-	.clksel		= omap_120m_fck_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clkdm_name	= "dpll5_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -951,22 +908,23 @@
 };
 
 static const struct clksel clkout2_src_clksel[] = {
-	{ .parent = &core_ck,		  .rates = clkout2_src_core_rates },
-	{ .parent = &sys_ck,		  .rates = clkout2_src_sys_rates },
-	{ .parent = &omap_96m_alwon_fck,  .rates = clkout2_src_96m_rates },
-	{ .parent = &omap_54m_fck,	  .rates = clkout2_src_54m_rates },
+	{ .parent = &core_ck,		.rates = clkout2_src_core_rates },
+	{ .parent = &sys_ck,		.rates = clkout2_src_sys_rates },
+	{ .parent = &cm_96m_fck,	.rates = clkout2_src_96m_rates },
+	{ .parent = &omap_54m_fck,	.rates = clkout2_src_54m_rates },
 	{ .parent = NULL }
 };
 
 static struct clk clkout2_src_ck = {
 	.name		= "clkout2_src_ck",
+	.ops		= &clkops_omap2_dflt,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP3430_CM_CLKOUT_CTRL,
 	.enable_bit	= OMAP3430_CLKOUT2_EN_SHIFT,
 	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP3430_CLKOUT2SOURCE_MASK,
 	.clksel		= clkout2_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+	.clkdm_name	= "core_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -986,11 +944,11 @@
 
 static struct clk sys_clkout2 = {
 	.name		= "sys_clkout2",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP3430_CM_CLKOUT_CTRL,
 	.clksel_mask	= OMAP3430_CLKOUT2_DIV_MASK,
 	.clksel		= sys_clkout2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -998,16 +956,22 @@
 
 static struct clk corex2_fck = {
 	.name		= "corex2_fck",
+	.ops		= &clkops_null,
 	.parent		= &dpll3_m2x2_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &followparent_recalc,
 };
 
 /* DPLL power domain clock controls */
 
-static const struct clksel div2_core_clksel[] = {
-	{ .parent = &core_ck, .rates = div2_rates },
+static const struct clksel_rate div4_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
+	{ .div = 2, .val = 2, .flags = RATE_IN_343X },
+	{ .div = 4, .val = 4, .flags = RATE_IN_343X },
+	{ .div = 0 }
+};
+
+static const struct clksel div4_core_clksel[] = {
+	{ .parent = &core_ck, .rates = div4_rates },
 	{ .parent = NULL }
 };
 
@@ -1017,39 +981,21 @@
  */
 static struct clk dpll1_fck = {
 	.name		= "dpll1_fck",
+	.ops		= &clkops_null,
 	.parent		= &core_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
 	.clksel_mask	= OMAP3430_MPU_CLK_SRC_MASK,
-	.clksel		= div2_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clksel		= div4_core_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/*
- * MPU clksel:
- * If DPLL1 is locked, mpu_ck derives from DPLL1; otherwise, mpu_ck
- * derives from the high-frequency bypass clock originating from DPLL3,
- * called 'dpll1_fck'
- */
-static const struct clksel mpu_clksel[] = {
-	{ .parent = &dpll1_fck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk mpu_ck = {
 	.name		= "mpu_ck",
+	.ops		= &clkops_null,
 	.parent		= &dpll1_x2m2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
-	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
-	.clksel		= mpu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "mpu_clkdm",
-	.recalc		= &omap2_clksel_recalc,
+	.recalc		= &followparent_recalc,
 };
 
 /* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
@@ -1066,13 +1012,12 @@
 
 static struct clk arm_fck = {
 	.name		= "arm_fck",
+	.ops		= &clkops_null,
 	.parent		= &mpu_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
 	.clksel_mask	= OMAP3430_ST_MPU_CLK_MASK,
 	.clksel		= arm_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -1084,63 +1029,48 @@
  */
 static struct clk emu_mpu_alwon_ck = {
 	.name		= "emu_mpu_alwon_ck",
+	.ops		= &clkops_null,
 	.parent		= &mpu_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk dpll2_fck = {
 	.name		= "dpll2_fck",
+	.ops		= &clkops_null,
 	.parent		= &core_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
 	.clksel_mask	= OMAP3430_IVA2_CLK_SRC_MASK,
-	.clksel		= div2_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
+	.clksel		= div4_core_clksel,
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/*
- * IVA2 clksel:
- * If DPLL2 is locked, iva2_ck derives from DPLL2; otherwise, iva2_ck
- * derives from the high-frequency bypass clock originating from DPLL3,
- * called 'dpll2_fck'
- */
-
-static const struct clksel iva2_clksel[] = {
-	{ .parent = &dpll2_fck,	  .rates = dpll_bypass_rates },
-	{ .parent = &dpll2_m2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk iva2_ck = {
 	.name		= "iva2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll2_m2_ck,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
-					  OMAP3430_CM_IDLEST_PLL),
-	.clksel_mask	= OMAP3430_ST_IVA2_CLK_MASK,
-	.clksel		= iva2_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
 	.clkdm_name	= "iva2_clkdm",
-	.recalc		= &omap2_clksel_recalc,
+	.recalc		= &followparent_recalc,
 };
 
 /* Common interface clocks */
 
+static const struct clksel div2_core_clksel[] = {
+	{ .parent = &core_ck, .rates = div2_rates },
+	{ .parent = NULL }
+};
+
 static struct clk l3_ick = {
 	.name		= "l3_ick",
+	.ops		= &clkops_null,
 	.parent		= &core_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_L3_MASK,
 	.clksel		= div2_core_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1152,13 +1082,12 @@
 
 static struct clk l4_ick = {
 	.name		= "l4_ick",
+	.ops		= &clkops_null,
 	.parent		= &l3_ick,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_L4_MASK,
 	.clksel		= div2_l3_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 
@@ -1171,12 +1100,12 @@
 
 static struct clk rm_ick = {
 	.name		= "rm_ick",
+	.ops		= &clkops_null,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_RM_MASK,
 	.clksel		= div2_l4_clksel,
-	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -1192,53 +1121,52 @@
 /* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */
 static struct clk gfx_l3_ck = {
 	.name		= "gfx_l3_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l3_ick,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP_EN_GFX_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gfx_l3_fck = {
 	.name		= "gfx_l3_fck",
+	.ops		= &clkops_null,
 	.parent		= &gfx_l3_ck,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP_CLKSEL_GFX_MASK,
 	.clksel		= gfx_l3_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "gfx_3430es1_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gfx_l3_ick = {
 	.name		= "gfx_l3_ick",
+	.ops		= &clkops_null,
 	.parent		= &gfx_l3_ck,
-	.flags		= CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "gfx_3430es1_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gfx_cg1_ck = {
 	.name		= "gfx_cg1_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430ES1_EN_2D_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm_name	= "gfx_3430es1_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gfx_cg2_ck = {
 	.name		= "gfx_cg2_ck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &gfx_l3_fck, /* REVISIT: correct? */
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430ES1_EN_3D_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm_name	= "gfx_3430es1_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1265,24 +1193,24 @@
 
 static struct clk sgx_fck = {
 	.name		= "sgx_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_FCLKEN),
-	.enable_bit	= OMAP3430ES2_EN_SGX_SHIFT,
+	.enable_bit	= OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430ES2_CLKSEL_SGX_MASK,
 	.clksel		= sgx_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "sgx_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk sgx_ick = {
 	.name		= "sgx_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l3_ick,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
-	.enable_bit	= OMAP3430ES2_EN_SGX_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
+	.enable_bit	= OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT,
 	.clkdm_name	= "sgx_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1291,11 +1219,11 @@
 
 static struct clk d2d_26m_fck = {
 	.name		= "d2d_26m_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &sys_ck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_D2D_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm_name	= "d2d_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1308,6 +1236,7 @@
 
 static struct clk gpt10_fck = {
 	.name		= "gpt10_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &sys_ck,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
@@ -1315,13 +1244,13 @@
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT10_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt11_fck = {
 	.name		= "gpt11_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &sys_ck,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
@@ -1329,35 +1258,34 @@
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT11_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk cpefuse_fck = {
 	.name		= "cpefuse_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_CPEFUSE_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk ts_fck = {
 	.name		= "ts_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &omap_32k_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_TS_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk usbtll_fck = {
 	.name		= "usbtll_fck",
-	.parent		= &omap_120m_fck,
+	.ops		= &clkops_omap2_dflt,
+	.parent		= &dpll5_m2_ck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1365,84 +1293,83 @@
 
 static struct clk core_96m_fck = {
 	.name		= "core_96m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_96m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs3_fck = {
 	.name		= "mmchs_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs2_fck = {
 	.name		= "mmchs_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mspro_fck = {
 	.name		= "mspro_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs1_fck = {
 	.name		= "mmchs_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c3_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c2_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c1_fck = {
 	.name		= "i2c_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_96m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1469,6 +1396,7 @@
 
 static struct clk mcbsp5_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 5,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
@@ -1476,13 +1404,13 @@
 	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
 	.clksel_mask	= OMAP2_MCBSP5_CLKS_MASK,
 	.clksel		= mcbsp_15_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp1_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
@@ -1490,7 +1418,6 @@
 	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
 	.clksel_mask	= OMAP2_MCBSP1_CLKS_MASK,
 	.clksel		= mcbsp_15_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -1499,77 +1426,76 @@
 
 static struct clk core_48m_fck = {
 	.name		= "core_48m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_48m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi4_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi3_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi2_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi1_fck = {
 	.name		= "mcspi_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart2_fck = {
 	.name		= "uart2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart1_fck = {
 	.name		= "uart1_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk fshostusb_fck = {
 	.name		= "fshostusb_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1577,19 +1503,18 @@
 
 static struct clk core_12m_fck = {
 	.name		= "core_12m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_12m_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk hdq_fck = {
 	.name		= "hdq_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_12m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1612,22 +1537,22 @@
 
 static struct clk ssi_ssr_fck = {
 	.name		= "ssi_ssr_fck",
+	.ops		= &clkops_omap2_dflt,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_SSI_MASK,
 	.clksel		= ssi_ssr_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk ssi_sst_fck = {
 	.name		= "ssi_sst_fck",
+	.ops		= &clkops_null,
 	.parent		= &ssi_ssr_fck,
 	.fixed_div	= 2,
-	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK,
 	.recalc		= &omap2_fixed_divisor_recalc,
 };
 
@@ -1641,39 +1566,39 @@
  */
 static struct clk core_l3_ick = {
 	.name		= "core_l3_ick",
+	.ops		= &clkops_null,
 	.parent		= &l3_ick,
 	.init		= &omap2_init_clk_clkdm,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk hsotgusb_ick = {
 	.name		= "hsotgusb_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SDRC_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
+	.ops		= &clkops_null,
 	.parent		= &core_l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK |
-				ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT, /* huh? */
 	.clkdm_name	= "core_l3_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1682,18 +1607,17 @@
 
 static struct clk security_l3_ick = {
 	.name		= "security_l3_ick",
+	.ops		= &clkops_null,
 	.parent		= &l3_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &security_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1701,31 +1625,30 @@
 
 static struct clk core_l4_ick = {
 	.name		= "core_l4_ick",
+	.ops		= &clkops_null,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clk_clkdm,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk usbtll_ick = {
 	.name		= "usbtll_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs3_ick = {
 	.name		= "mmchs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -1733,250 +1656,251 @@
 /* Intersystem Communication Registers - chassis mode only */
 static struct clk icr_ick = {
 	.name		= "icr_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk aes2_ick = {
 	.name		= "aes2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sha12_ick = {
 	.name		= "sha12_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk des2_ick = {
 	.name		= "des2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi4_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c3_ick = {
 	.name		= "i2c_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c2_ick = {
 	.name		= "i2c_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk i2c1_ick = {
 	.name		= "i2c_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 5,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 1,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
+	.flags		= ENABLE_ON_INIT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1984,19 +1908,18 @@
 
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
+	.ops		= &clkops_null,
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk ssi_ick = {
 	.name		= "ssi_ick",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2011,6 +1934,7 @@
 
 static struct clk usb_l4_ick = {
 	.name		= "usb_l4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -2018,7 +1942,6 @@
 	.clksel_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
 	.clksel		= usb_l4_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES1,
 	.recalc		= &omap2_clksel_recalc,
 };
 
@@ -2028,98 +1951,87 @@
 
 static struct clk security_l4_ick2 = {
 	.name		= "security_l4_ick2",
+	.ops		= &clkops_null,
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk aes1_ick = {
 	.name		= "aes1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sha11_ick = {
 	.name		= "sha11_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk des1_ick = {
 	.name		= "des1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.recalc		= &followparent_recalc,
 };
 
 /* DSS */
-static const struct clksel dss1_alwon_fck_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk dss1_alwon_fck = {
 	.name		= "dss1_alwon_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &dpll4_m4x2_ck,
-	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_DSS1_SHIFT,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.clksel		= dss1_alwon_fck_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "dss_clkdm",
-	.recalc		= &omap2_clksel_recalc,
+	.recalc		= &followparent_recalc,
 };
 
 static struct clk dss_tv_fck = {
 	.name		= "dss_tv_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &omap_54m_fck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_TV_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "dss_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk dss_96m_fck = {
 	.name		= "dss_96m_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &omap_96m_fck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_TV_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "dss_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk dss2_alwon_fck = {
 	.name		= "dss2_alwon_fck",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &sys_ck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_DSS2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "dss_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2127,45 +2039,46 @@
 static struct clk dss_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
+	.ops		= &clkops_omap2_dflt,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "dss_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 /* CAM */
 
-static const struct clksel cam_mclk_clksel[] = {
-	{ .parent = &sys_ck,	    .rates = dpll_bypass_rates },
-	{ .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates },
-	{ .parent = NULL }
-};
-
 static struct clk cam_mclk = {
 	.name		= "cam_mclk",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &dpll4_m5x2_ck,
-	.init		= &omap2_init_clksel_parent,
-	.clksel_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-	.clksel_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
-	.clksel		= cam_mclk_clksel,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "cam_clkdm",
-	.recalc		= &omap2_clksel_recalc,
+	.recalc		= &followparent_recalc,
 };
 
 static struct clk cam_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "cam_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
+	.clkdm_name	= "cam_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk csi2_96m_fck = {
+	.name		= "csi2_96m_fck",
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &core_96m_fck,
+	.init		= &omap2_init_clk_clkdm,
+	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
+	.enable_bit	= OMAP3430_EN_CSI2_SHIFT,
 	.clkdm_name	= "cam_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2174,22 +2087,22 @@
 
 static struct clk usbhost_120m_fck = {
 	.name		= "usbhost_120m_fck",
-	.parent		= &omap_120m_fck,
+	.ops		= &clkops_omap2_dflt_wait,
+	.parent		= &dpll5_m2_ck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST2_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "usbhost_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk usbhost_48m_fck = {
 	.name		= "usbhost_48m_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &omap_48m_fck,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST1_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "usbhost_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2197,22 +2110,11 @@
 static struct clk usbhost_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "usbhost_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clk_clkdm,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
-	.clkdm_name	= "usbhost_clkdm",
-	.recalc		= &followparent_recalc,
-};
-
-static struct clk usbhost_sar_fck = {
-	.name		= "usbhost_sar_fck",
-	.parent		= &osc_sys_ck,
-	.init		= &omap2_init_clk_clkdm,
-	.enable_reg	= OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL),
-	.enable_bit	= OMAP3430ES2_SAVEANDRESTORE_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "usbhost_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2237,7 +2139,7 @@
 
 static const struct clksel usim_clksel[] = {
 	{ .parent = &omap_96m_fck,	.rates = usim_96m_rates },
-	{ .parent = &omap_120m_fck,	.rates = usim_120m_rates },
+	{ .parent = &dpll5_m2_ck,	.rates = usim_120m_rates },
 	{ .parent = &sys_ck,		.rates = div2_rates },
 	{ .parent = NULL },
 };
@@ -2245,63 +2147,63 @@
 /* 3430ES2 only */
 static struct clk usim_fck = {
 	.name		= "usim_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430ES2_CLKSEL_USIMOCP_MASK,
 	.clksel		= usim_clksel,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.recalc		= &omap2_clksel_recalc,
 };
 
 /* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */
 static struct clk gpt1_fck = {
 	.name		= "gpt1_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT1_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk wkup_32k_fck = {
 	.name		= "wkup_32k_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clk_clkdm,
 	.parent		= &omap_32k_fck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio1_dbck = {
 	.name		= "gpio1_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_32k_fck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt2_fck = {
 	.name		= "wdt2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_32k_fck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wkup_l4_ick = {
 	.name		= "wkup_l4_ick",
+	.ops		= &clkops_null,
 	.parent		= &sys_ck,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2310,50 +2212,50 @@
 /* Never specifically named in the TRM, so we have to infer a likely name */
 static struct clk usim_ick = {
 	.name		= "usim_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
-	.flags		= CLOCK_IN_OMAP3430ES2,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt2_ick = {
 	.name		= "wdt2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio1_ick = {
 	.name		= "gpio1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk omap_32ksync_ick = {
 	.name		= "omap_32ksync_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2361,20 +2263,20 @@
 /* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "wkup_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -2385,406 +2287,404 @@
 
 static struct clk per_96m_fck = {
 	.name		= "per_96m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_96m_alwon_fck,
 	.init		= &omap2_init_clk_clkdm,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk per_48m_fck = {
 	.name		= "per_48m_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_48m_fck,
 	.init		= &omap2_init_clk_clkdm,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart3_fck = {
 	.name		= "uart3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_48m_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt2_fck = {
 	.name		= "gpt2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT2_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt3_fck = {
 	.name		= "gpt3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT3_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt4_fck = {
 	.name		= "gpt4_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT4_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt5_fck = {
 	.name		= "gpt5_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT5_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt6_fck = {
 	.name		= "gpt6_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT6_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt7_fck = {
 	.name		= "gpt7_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT7_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt8_fck = {
 	.name		= "gpt8_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT8_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk gpt9_fck = {
 	.name		= "gpt9_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_CLKSEL),
 	.clksel_mask	= OMAP3430_CLKSEL_GPT9_MASK,
 	.clksel		= omap343x_gpt_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk per_32k_alwon_fck = {
 	.name		= "per_32k_alwon_fck",
+	.ops		= &clkops_null,
 	.parent		= &omap_32k_fck,
 	.clkdm_name	= "per_clkdm",
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio6_dbck = {
 	.name		= "gpio6_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio5_dbck = {
 	.name		= "gpio5_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio4_dbck = {
 	.name		= "gpio4_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio3_dbck = {
 	.name		= "gpio3_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio2_dbck = {
 	.name		= "gpio2_dbck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt3_fck = {
 	.name		= "wdt3_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_32k_alwon_fck,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk per_l4_ick = {
 	.name		= "per_l4_ick",
+	.ops		= &clkops_null,
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES |
-				PARENT_CONTROLS_CLOCK,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio6_ick = {
 	.name		= "gpio6_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio4_ick = {
 	.name		= "gpio4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio3_ick = {
 	.name		= "gpio3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpio2_ick = {
 	.name		= "gpio2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp_ick",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &followparent_recalc,
 };
 
 static const struct clksel mcbsp_234_clksel[] = {
-	{ .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
-	{ .parent = &mcbsp_clks,  .rates = common_mcbsp_mcbsp_rates },
+	{ .parent = &core_96m_fck, .rates = common_mcbsp_96m_rates },
+	{ .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
 	{ .parent = NULL }
 };
 
 static struct clk mcbsp2_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 2,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
@@ -2792,13 +2692,13 @@
 	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
 	.clksel_mask	= OMAP2_MCBSP2_CLKS_MASK,
 	.clksel		= mcbsp_234_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp3_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 3,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
@@ -2806,13 +2706,13 @@
 	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
 	.clksel_mask	= OMAP2_MCBSP3_CLKS_MASK,
 	.clksel		= mcbsp_234_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp4_fck = {
 	.name		= "mcbsp_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.id		= 4,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
@@ -2820,7 +2720,6 @@
 	.clksel_reg	= OMAP343X_CTRL_REGADDR(OMAP343X_CONTROL_DEVCONF1),
 	.clksel_mask	= OMAP2_MCBSP4_CLKS_MASK,
 	.clksel		= mcbsp_234_clksel,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "per_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2864,11 +2763,11 @@
  */
 static struct clk emu_src_ck = {
 	.name		= "emu_src_ck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2888,11 +2787,11 @@
 
 static struct clk pclk_fck = {
 	.name		= "pclk_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_CLKSEL_PCLK_MASK,
 	.clksel		= pclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2911,11 +2810,11 @@
 
 static struct clk pclkx2_fck = {
 	.name		= "pclkx2_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_CLKSEL_PCLKX2_MASK,
 	.clksel		= pclkx2_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2927,22 +2826,22 @@
 
 static struct clk atclk_fck = {
 	.name		= "atclk_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_CLKSEL_ATCLK_MASK,
 	.clksel		= atclk_emu_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
 
 static struct clk traceclk_src_fck = {
 	.name		= "traceclk_src_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_TRACE_MUX_CTRL_MASK,
 	.clksel		= emu_src_clksel,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2961,11 +2860,11 @@
 
 static struct clk traceclk_fck = {
 	.name		= "traceclk_fck",
+	.ops		= &clkops_null,
 	.init		= &omap2_init_clksel_parent,
 	.clksel_reg	= OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 	.clksel_mask	= OMAP3430_CLKSEL_TRACECLK_MASK,
 	.clksel		= traceclk_clksel,
-	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.clkdm_name	= "emu_clkdm",
 	.recalc		= &omap2_clksel_recalc,
 };
@@ -2975,27 +2874,27 @@
 /* SmartReflex fclk (VDD1) */
 static struct clk sr1_fck = {
 	.name		= "sr1_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_SR1_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
 	.recalc		= &followparent_recalc,
 };
 
 /* SmartReflex fclk (VDD2) */
 static struct clk sr2_fck = {
 	.name		= "sr2_fck",
+	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP3430_EN_SR2_SHIFT,
-	.flags		= CLOCK_IN_OMAP343X | RATE_PROPAGATES,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sr_l4_ick = {
 	.name		= "sr_l4_ick",
+	.ops		= &clkops_null, /* RMK: missing? */
 	.parent		= &l4_ick,
-	.flags		= CLOCK_IN_OMAP343X,
 	.clkdm_name	= "core_l4_clkdm",
 	.recalc		= &followparent_recalc,
 };
@@ -3005,231 +2904,16 @@
 /* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_fck = {
 	.name		= "gpt12_fck",
+	.ops		= &clkops_null,
 	.parent		= &secure_32k_fck,
-	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk wdt1_fck = {
 	.name		= "wdt1_fck",
+	.ops		= &clkops_null,
 	.parent		= &secure_32k_fck,
-	.flags		= CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 };
 
-static struct clk *onchip_34xx_clks[] __initdata = {
-	&omap_32k_fck,
-	&virt_12m_ck,
-	&virt_13m_ck,
-	&virt_16_8m_ck,
-	&virt_19_2m_ck,
-	&virt_26m_ck,
-	&virt_38_4m_ck,
-	&osc_sys_ck,
-	&sys_ck,
-	&sys_altclk,
-	&mcbsp_clks,
-	&sys_clkout1,
-	&dpll1_ck,
-	&dpll1_x2_ck,
-	&dpll1_x2m2_ck,
-	&dpll2_ck,
-	&dpll2_m2_ck,
-	&dpll3_ck,
-	&core_ck,
-	&dpll3_x2_ck,
-	&dpll3_m2_ck,
-	&dpll3_m2x2_ck,
-	&dpll3_m3_ck,
-	&dpll3_m3x2_ck,
-	&emu_core_alwon_ck,
-	&dpll4_ck,
-	&dpll4_x2_ck,
-	&omap_96m_alwon_fck,
-	&omap_96m_fck,
-	&cm_96m_fck,
-	&virt_omap_54m_fck,
-	&omap_54m_fck,
-	&omap_48m_fck,
-	&omap_12m_fck,
-	&dpll4_m2_ck,
-	&dpll4_m2x2_ck,
-	&dpll4_m3_ck,
-	&dpll4_m3x2_ck,
-	&dpll4_m4_ck,
-	&dpll4_m4x2_ck,
-	&dpll4_m5_ck,
-	&dpll4_m5x2_ck,
-	&dpll4_m6_ck,
-	&dpll4_m6x2_ck,
-	&emu_per_alwon_ck,
-	&dpll5_ck,
-	&dpll5_m2_ck,
-	&omap_120m_fck,
-	&clkout2_src_ck,
-	&sys_clkout2,
-	&corex2_fck,
-	&dpll1_fck,
-	&mpu_ck,
-	&arm_fck,
-	&emu_mpu_alwon_ck,
-	&dpll2_fck,
-	&iva2_ck,
-	&l3_ick,
-	&l4_ick,
-	&rm_ick,
-	&gfx_l3_ck,
-	&gfx_l3_fck,
-	&gfx_l3_ick,
-	&gfx_cg1_ck,
-	&gfx_cg2_ck,
-	&sgx_fck,
-	&sgx_ick,
-	&d2d_26m_fck,
-	&gpt10_fck,
-	&gpt11_fck,
-	&cpefuse_fck,
-	&ts_fck,
-	&usbtll_fck,
-	&core_96m_fck,
-	&mmchs3_fck,
-	&mmchs2_fck,
-	&mspro_fck,
-	&mmchs1_fck,
-	&i2c3_fck,
-	&i2c2_fck,
-	&i2c1_fck,
-	&mcbsp5_fck,
-	&mcbsp1_fck,
-	&core_48m_fck,
-	&mcspi4_fck,
-	&mcspi3_fck,
-	&mcspi2_fck,
-	&mcspi1_fck,
-	&uart2_fck,
-	&uart1_fck,
-	&fshostusb_fck,
-	&core_12m_fck,
-	&hdq_fck,
-	&ssi_ssr_fck,
-	&ssi_sst_fck,
-	&core_l3_ick,
-	&hsotgusb_ick,
-	&sdrc_ick,
-	&gpmc_fck,
-	&security_l3_ick,
-	&pka_ick,
-	&core_l4_ick,
-	&usbtll_ick,
-	&mmchs3_ick,
-	&icr_ick,
-	&aes2_ick,
-	&sha12_ick,
-	&des2_ick,
-	&mmchs2_ick,
-	&mmchs1_ick,
-	&mspro_ick,
-	&hdq_ick,
-	&mcspi4_ick,
-	&mcspi3_ick,
-	&mcspi2_ick,
-	&mcspi1_ick,
-	&i2c3_ick,
-	&i2c2_ick,
-	&i2c1_ick,
-	&uart2_ick,
-	&uart1_ick,
-	&gpt11_ick,
-	&gpt10_ick,
-	&mcbsp5_ick,
-	&mcbsp1_ick,
-	&fac_ick,
-	&mailboxes_ick,
-	&omapctrl_ick,
-	&ssi_l4_ick,
-	&ssi_ick,
-	&usb_l4_ick,
-	&security_l4_ick2,
-	&aes1_ick,
-	&rng_ick,
-	&sha11_ick,
-	&des1_ick,
-	&dss1_alwon_fck,
-	&dss_tv_fck,
-	&dss_96m_fck,
-	&dss2_alwon_fck,
-	&dss_ick,
-	&cam_mclk,
-	&cam_ick,
-	&usbhost_120m_fck,
-	&usbhost_48m_fck,
-	&usbhost_ick,
-	&usbhost_sar_fck,
-	&usim_fck,
-	&gpt1_fck,
-	&wkup_32k_fck,
-	&gpio1_dbck,
-	&wdt2_fck,
-	&wkup_l4_ick,
-	&usim_ick,
-	&wdt2_ick,
-	&wdt1_ick,
-	&gpio1_ick,
-	&omap_32ksync_ick,
-	&gpt12_ick,
-	&gpt1_ick,
-	&per_96m_fck,
-	&per_48m_fck,
-	&uart3_fck,
-	&gpt2_fck,
-	&gpt3_fck,
-	&gpt4_fck,
-	&gpt5_fck,
-	&gpt6_fck,
-	&gpt7_fck,
-	&gpt8_fck,
-	&gpt9_fck,
-	&per_32k_alwon_fck,
-	&gpio6_dbck,
-	&gpio5_dbck,
-	&gpio4_dbck,
-	&gpio3_dbck,
-	&gpio2_dbck,
-	&wdt3_fck,
-	&per_l4_ick,
-	&gpio6_ick,
-	&gpio5_ick,
-	&gpio4_ick,
-	&gpio3_ick,
-	&gpio2_ick,
-	&wdt3_ick,
-	&uart3_ick,
-	&gpt9_ick,
-	&gpt8_ick,
-	&gpt7_ick,
-	&gpt6_ick,
-	&gpt5_ick,
-	&gpt4_ick,
-	&gpt3_ick,
-	&gpt2_ick,
-	&mcbsp2_ick,
-	&mcbsp3_ick,
-	&mcbsp4_ick,
-	&mcbsp2_fck,
-	&mcbsp3_fck,
-	&mcbsp4_fck,
-	&emu_src_ck,
-	&pclk_fck,
-	&pclkx2_fck,
-	&atclk_fck,
-	&traceclk_src_fck,
-	&traceclk_fck,
-	&sr1_fck,
-	&sr2_fck,
-	&sr_l4_ick,
-	&secure_32k_fck,
-	&gpt12_fck,
-	&wdt1_fck,
-};
-
 #endif
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 4c3ce9c..0e7d501 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/limits.h>
+#include <linux/err.h>
 
 #include <linux/io.h>
 
@@ -71,16 +72,13 @@
 	if (!omap_chip_is(autodep->omap_chip))
 		return;
 
-	pwrdm = pwrdm_lookup(autodep->pwrdm_name);
+	pwrdm = pwrdm_lookup(autodep->pwrdm.name);
 	if (!pwrdm) {
-		pr_debug("clockdomain: _autodep_lookup: powerdomain %s "
-			 "does not exist\n", autodep->pwrdm_name);
-		WARN_ON(1);
-		return;
+		pr_err("clockdomain: autodeps: powerdomain %s does not exist\n",
+			 autodep->pwrdm.name);
+		pwrdm = ERR_PTR(-ENOENT);
 	}
-	autodep->pwrdm = pwrdm;
-
-	return;
+	autodep->pwrdm.ptr = pwrdm;
 }
 
 /*
@@ -95,16 +93,19 @@
 {
 	struct clkdm_pwrdm_autodep *autodep;
 
-	for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
-		if (!autodep->pwrdm)
+	for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
+		if (IS_ERR(autodep->pwrdm.ptr))
+			continue;
+
+		if (!omap_chip_is(autodep->omap_chip))
 			continue;
 
 		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
-			 "pwrdm %s\n", autodep->pwrdm_name,
-			 clkdm->pwrdm->name);
+			 "pwrdm %s\n", autodep->pwrdm.ptr->name,
+			 clkdm->pwrdm.ptr->name);
 
-		pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm);
-		pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm);
+		pwrdm_add_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
+		pwrdm_add_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 	}
 }
 
@@ -120,16 +121,19 @@
 {
 	struct clkdm_pwrdm_autodep *autodep;
 
-	for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
-		if (!autodep->pwrdm)
+	for (autodep = autodeps; autodep->pwrdm.ptr; autodep++) {
+		if (IS_ERR(autodep->pwrdm.ptr))
+			continue;
+
+		if (!omap_chip_is(autodep->omap_chip))
 			continue;
 
 		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
-			 "pwrdm %s\n", autodep->pwrdm_name,
-			 clkdm->pwrdm->name);
+			 "pwrdm %s\n", autodep->pwrdm.ptr->name,
+			 clkdm->pwrdm.ptr->name);
 
-		pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm);
-		pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm);
+		pwrdm_del_sleepdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
+		pwrdm_del_wkdep(clkdm->pwrdm.ptr, autodep->pwrdm.ptr);
 	}
 }
 
@@ -179,7 +183,7 @@
 
 	autodeps = init_autodeps;
 	if (autodeps)
-		for (autodep = autodeps; autodep->pwrdm_name; autodep++)
+		for (autodep = autodeps; autodep->pwrdm.ptr; autodep++)
 			_autodep_lookup(autodep);
 }
 
@@ -202,20 +206,20 @@
 	if (!omap_chip_is(clkdm->omap_chip))
 		return -EINVAL;
 
-	pwrdm = pwrdm_lookup(clkdm->pwrdm_name);
+	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
 	if (!pwrdm) {
-		pr_debug("clockdomain: clkdm_register %s: powerdomain %s "
-			 "does not exist\n", clkdm->name, clkdm->pwrdm_name);
+		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
+			clkdm->name, clkdm->pwrdm.name);
 		return -EINVAL;
 	}
-	clkdm->pwrdm = pwrdm;
+	clkdm->pwrdm.ptr = pwrdm;
 
 	mutex_lock(&clkdm_mutex);
 	/* Verify that the clockdomain is not already registered */
 	if (_clkdm_lookup(clkdm->name)) {
 		ret = -EEXIST;
 		goto cr_unlock;
-	};
+	}
 
 	list_add(&clkdm->node, &clkdm_list);
 
@@ -242,7 +246,7 @@
 	if (!clkdm)
 		return -EINVAL;
 
-	pwrdm_del_clkdm(clkdm->pwrdm, clkdm);
+	pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm);
 
 	mutex_lock(&clkdm_mutex);
 	list_del(&clkdm->node);
@@ -327,7 +331,7 @@
 	if (!clkdm)
 		return NULL;
 
-	return clkdm->pwrdm;
+	return clkdm->pwrdm.ptr;
 }
 
 
@@ -348,7 +352,7 @@
 	if (!clkdm)
 		return -EINVAL;
 
-	v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+	v = cm_read_mod_reg(clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 	v &= clkdm->clktrctrl_mask;
 	v >>= __ffs(clkdm->clktrctrl_mask);
 
@@ -380,7 +384,7 @@
 	if (cpu_is_omap24xx()) {
 
 		cm_set_mod_reg_bits(OMAP24XX_FORCESTATE,
-				    clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
+				    clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
 
 	} else if (cpu_is_omap34xx()) {
 
@@ -388,7 +392,7 @@
 			 __ffs(clkdm->clktrctrl_mask));
 
 		cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
-				    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+				    clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 
 	} else {
 		BUG();
@@ -422,7 +426,7 @@
 	if (cpu_is_omap24xx()) {
 
 		cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE,
-				      clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
+				      clkdm->pwrdm.ptr->prcm_offs, PM_PWSTCTRL);
 
 	} else if (cpu_is_omap34xx()) {
 
@@ -430,7 +434,7 @@
 			 __ffs(clkdm->clktrctrl_mask));
 
 		cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
-				    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+				    clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 
 	} else {
 		BUG();
@@ -478,7 +482,7 @@
 
 	cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
 			    v << __ffs(clkdm->clktrctrl_mask),
-			    clkdm->pwrdm->prcm_offs,
+			    clkdm->pwrdm.ptr->prcm_offs,
 			    CM_CLKSTCTRL);
 }
 
@@ -516,7 +520,7 @@
 
 	cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
 			    v << __ffs(clkdm->clktrctrl_mask),
-			    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+			    clkdm->pwrdm.ptr->prcm_offs, CM_CLKSTCTRL);
 
 	if (atomic_read(&clkdm->usecount) > 0)
 		_clkdm_del_autodeps(clkdm);
@@ -567,6 +571,8 @@
 	else
 		omap2_clkdm_wakeup(clkdm);
 
+	pwrdm_wait_transition(clkdm->pwrdm.ptr);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
index cd86dcc..281d5da 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -14,12 +14,29 @@
 
 /*
  * OMAP2/3-common clockdomains
+ *
+ * Even though the 2420 has a single PRCM module from the
+ * interconnect's perspective, internally it does appear to have
+ * separate PRM and CM clockdomains.  The usual test case is
+ * sys_clkout/sys_clkout2.
  */
 
 /* This is an implicit clockdomain - it is never defined as such in TRM */
 static struct clockdomain wkup_clkdm = {
 	.name		= "wkup_clkdm",
-	.pwrdm_name	= "wkup_pwrdm",
+	.pwrdm		= { .name = "wkup_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain prm_clkdm = {
+	.name		= "prm_clkdm",
+	.pwrdm		= { .name = "wkup_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain cm_clkdm = {
+	.name		= "cm_clkdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
 };
 
@@ -31,7 +48,7 @@
 
 static struct clockdomain mpu_2420_clkdm = {
 	.name		= "mpu_clkdm",
-	.pwrdm_name	= "mpu_pwrdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -39,7 +56,7 @@
 
 static struct clockdomain iva1_2420_clkdm = {
 	.name		= "iva1_clkdm",
-	.pwrdm_name	= "dsp_pwrdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
@@ -56,7 +73,7 @@
 
 static struct clockdomain mpu_2430_clkdm = {
 	.name		= "mpu_clkdm",
-	.pwrdm_name	= "mpu_pwrdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -64,7 +81,7 @@
 
 static struct clockdomain mdm_clkdm = {
 	.name		= "mdm_clkdm",
-	.pwrdm_name	= "mdm_pwrdm",
+	.pwrdm		= { .name = "mdm_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
@@ -81,7 +98,7 @@
 
 static struct clockdomain dsp_clkdm = {
 	.name		= "dsp_clkdm",
-	.pwrdm_name	= "dsp_pwrdm",
+	.pwrdm		= { .name = "dsp_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
@@ -89,7 +106,7 @@
 
 static struct clockdomain gfx_24xx_clkdm = {
 	.name		= "gfx_clkdm",
-	.pwrdm_name	= "gfx_pwrdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
@@ -97,7 +114,7 @@
 
 static struct clockdomain core_l3_24xx_clkdm = {
 	.name		= "core_l3_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
@@ -105,7 +122,7 @@
 
 static struct clockdomain core_l4_24xx_clkdm = {
 	.name		= "core_l4_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
@@ -113,7 +130,7 @@
 
 static struct clockdomain dss_24xx_clkdm = {
 	.name		= "dss_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
@@ -130,7 +147,7 @@
 
 static struct clockdomain mpu_34xx_clkdm = {
 	.name		= "mpu_clkdm",
-	.pwrdm_name	= "mpu_pwrdm",
+	.pwrdm		= { .name = "mpu_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -138,7 +155,7 @@
 
 static struct clockdomain neon_clkdm = {
 	.name		= "neon_clkdm",
-	.pwrdm_name	= "neon_pwrdm",
+	.pwrdm		= { .name = "neon_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -146,7 +163,7 @@
 
 static struct clockdomain iva2_clkdm = {
 	.name		= "iva2_clkdm",
-	.pwrdm_name	= "iva2_pwrdm",
+	.pwrdm		= { .name = "iva2_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -154,7 +171,7 @@
 
 static struct clockdomain gfx_3430es1_clkdm = {
 	.name		= "gfx_clkdm",
-	.pwrdm_name	= "gfx_pwrdm",
+	.pwrdm		= { .name = "gfx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
@@ -162,10 +179,10 @@
 
 static struct clockdomain sgx_clkdm = {
 	.name		= "sgx_clkdm",
-	.pwrdm_name	= "sgx_pwrdm",
+	.pwrdm		= { .name = "sgx_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
 
 /*
@@ -177,7 +194,7 @@
  */
 static struct clockdomain d2d_clkdm = {
 	.name		= "d2d_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -185,7 +202,7 @@
 
 static struct clockdomain core_l3_34xx_clkdm = {
 	.name		= "core_l3_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -193,7 +210,7 @@
 
 static struct clockdomain core_l4_34xx_clkdm = {
 	.name		= "core_l4_clkdm",
-	.pwrdm_name	= "core_pwrdm",
+	.pwrdm		= { .name = "core_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -201,7 +218,7 @@
 
 static struct clockdomain dss_34xx_clkdm = {
 	.name		= "dss_clkdm",
-	.pwrdm_name	= "dss_pwrdm",
+	.pwrdm		= { .name = "dss_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -209,7 +226,7 @@
 
 static struct clockdomain cam_clkdm = {
 	.name		= "cam_clkdm",
-	.pwrdm_name	= "cam_pwrdm",
+	.pwrdm		= { .name = "cam_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -217,28 +234,62 @@
 
 static struct clockdomain usbhost_clkdm = {
 	.name		= "usbhost_clkdm",
-	.pwrdm_name	= "usbhost_pwrdm",
+	.pwrdm		= { .name = "usbhost_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 };
 
 static struct clockdomain per_clkdm = {
 	.name		= "per_clkdm",
-	.pwrdm_name	= "per_pwrdm",
+	.pwrdm		= { .name = "per_pwrdm" },
 	.flags		= CLKDM_CAN_HWSUP_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/*
+ * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
+ * switched of even if sdti is in use
+ */
 static struct clockdomain emu_clkdm = {
 	.name		= "emu_clkdm",
-	.pwrdm_name	= "emu_pwrdm",
-	.flags		= CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP,
+	.pwrdm		= { .name = "emu_pwrdm" },
+	.flags		= /* CLKDM_CAN_ENABLE_AUTO |  */CLKDM_CAN_SWSUP,
 	.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+static struct clockdomain dpll1_clkdm = {
+	.name		= "dpll1_clkdm",
+	.pwrdm		= { .name = "dpll1_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain dpll2_clkdm = {
+	.name		= "dpll2_clkdm",
+	.pwrdm		= { .name = "dpll2_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain dpll3_clkdm = {
+	.name		= "dpll3_clkdm",
+	.pwrdm		= { .name = "dpll3_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain dpll4_clkdm = {
+	.name		= "dpll4_clkdm",
+	.pwrdm		= { .name = "dpll4_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain dpll5_clkdm = {
+	.name		= "dpll5_clkdm",
+	.pwrdm		= { .name = "dpll5_pwrdm" },
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+};
+
 #endif   /* CONFIG_ARCH_OMAP34XX */
 
 /*
@@ -247,14 +298,16 @@
 
 static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
 	{
-		.pwrdm_name = "mpu_pwrdm",
+		.pwrdm	   = { .name = "mpu_pwrdm" },
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 	},
 	{
-		.pwrdm_name = "iva2_pwrdm",
+		.pwrdm	   = { .name = "iva2_pwrdm" },
 		.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 	},
-	{ NULL }
+	{
+		.pwrdm	   = { .name = NULL },
+	}
 };
 
 /*
@@ -264,6 +317,8 @@
 static struct clockdomain *clockdomains_omap[] = {
 
 	&wkup_clkdm,
+	&cm_clkdm,
+	&prm_clkdm,
 
 #ifdef CONFIG_ARCH_OMAP2420
 	&mpu_2420_clkdm,
@@ -297,6 +352,11 @@
 	&usbhost_clkdm,
 	&per_clkdm,
 	&emu_clkdm,
+	&dpll1_clkdm,
+	&dpll2_clkdm,
+	&dpll3_clkdm,
+	&dpll4_clkdm,
+	&dpll5_clkdm,
 #endif
 
 	NULL,
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index 1098ecf..297a2fe 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -110,35 +110,56 @@
 #define OMAP24XX_EN_DES					(1 << 0)
 
 /* CM_IDLEST1_CORE specific bits */
-#define OMAP24XX_ST_MAILBOXES				(1 << 30)
-#define OMAP24XX_ST_WDT4				(1 << 29)
-#define OMAP2420_ST_WDT3				(1 << 28)
-#define OMAP24XX_ST_MSPRO				(1 << 27)
-#define OMAP24XX_ST_FAC					(1 << 25)
-#define OMAP2420_ST_EAC					(1 << 24)
-#define OMAP24XX_ST_HDQ					(1 << 23)
-#define OMAP24XX_ST_I2C2				(1 << 20)
-#define OMAP24XX_ST_I2C1				(1 << 19)
-#define OMAP24XX_ST_MCBSP2				(1 << 16)
-#define OMAP24XX_ST_MCBSP1				(1 << 15)
-#define OMAP24XX_ST_DSS					(1 << 0)
+#define OMAP24XX_ST_MAILBOXES_SHIFT			30
+#define OMAP24XX_ST_MAILBOXES_MASK			(1 << 30)
+#define OMAP24XX_ST_WDT4_SHIFT				29
+#define OMAP24XX_ST_WDT4_MASK				(1 << 29)
+#define OMAP2420_ST_WDT3_SHIFT				28
+#define OMAP2420_ST_WDT3_MASK				(1 << 28)
+#define OMAP24XX_ST_MSPRO_SHIFT				27
+#define OMAP24XX_ST_MSPRO_MASK				(1 << 27)
+#define OMAP24XX_ST_FAC_SHIFT				25
+#define OMAP24XX_ST_FAC_MASK				(1 << 25)
+#define OMAP2420_ST_EAC_SHIFT				24
+#define OMAP2420_ST_EAC_MASK				(1 << 24)
+#define OMAP24XX_ST_HDQ_SHIFT				23
+#define OMAP24XX_ST_HDQ_MASK				(1 << 23)
+#define OMAP2420_ST_I2C2_SHIFT				20
+#define OMAP2420_ST_I2C2_MASK				(1 << 20)
+#define OMAP2420_ST_I2C1_SHIFT				19
+#define OMAP2420_ST_I2C1_MASK				(1 << 19)
+#define OMAP24XX_ST_MCBSP2_SHIFT			16
+#define OMAP24XX_ST_MCBSP2_MASK				(1 << 16)
+#define OMAP24XX_ST_MCBSP1_SHIFT			15
+#define OMAP24XX_ST_MCBSP1_MASK				(1 << 15)
+#define OMAP24XX_ST_DSS_SHIFT				0
+#define OMAP24XX_ST_DSS_MASK				(1 << 0)
 
 /* CM_IDLEST2_CORE */
-#define OMAP2430_ST_MCBSP5				(1 << 5)
-#define OMAP2430_ST_MCBSP4				(1 << 4)
-#define OMAP2430_ST_MCBSP3				(1 << 3)
-#define OMAP24XX_ST_SSI					(1 << 1)
+#define OMAP2430_ST_MCBSP5_SHIFT			5
+#define OMAP2430_ST_MCBSP5_MASK				(1 << 5)
+#define OMAP2430_ST_MCBSP4_SHIFT				4
+#define OMAP2430_ST_MCBSP4_MASK				(1 << 4)
+#define OMAP2430_ST_MCBSP3_SHIFT				3
+#define OMAP2430_ST_MCBSP3_MASK				(1 << 3)
+#define OMAP24XX_ST_SSI_SHIFT				1
+#define OMAP24XX_ST_SSI_MASK				(1 << 1)
 
 /* CM_IDLEST3_CORE */
 /* 2430 only */
-#define OMAP2430_ST_SDRC				(1 << 2)
+#define OMAP2430_ST_SDRC_MASK				(1 << 2)
 
 /* CM_IDLEST4_CORE */
-#define OMAP24XX_ST_PKA					(1 << 4)
-#define OMAP24XX_ST_AES					(1 << 3)
-#define OMAP24XX_ST_RNG					(1 << 2)
-#define OMAP24XX_ST_SHA					(1 << 1)
-#define OMAP24XX_ST_DES					(1 << 0)
+#define OMAP24XX_ST_PKA_SHIFT				4
+#define OMAP24XX_ST_PKA_MASK				(1 << 4)
+#define OMAP24XX_ST_AES_SHIFT				3
+#define OMAP24XX_ST_AES_MASK				(1 << 3)
+#define OMAP24XX_ST_RNG_SHIFT				2
+#define OMAP24XX_ST_RNG_MASK				(1 << 2)
+#define OMAP24XX_ST_SHA_SHIFT				1
+#define OMAP24XX_ST_SHA_MASK				(1 << 1)
+#define OMAP24XX_ST_DES_SHIFT				0
+#define OMAP24XX_ST_DES_MASK				(1 << 0)
 
 /* CM_AUTOIDLE1_CORE */
 #define OMAP24XX_AUTO_CAM				(1 << 31)
@@ -275,11 +296,16 @@
 #define OMAP24XX_EN_32KSYNC				(1 << 1)
 
 /* CM_IDLEST_WKUP specific bits */
-#define OMAP2430_ST_ICR					(1 << 6)
-#define OMAP24XX_ST_OMAPCTRL				(1 << 5)
-#define OMAP24XX_ST_WDT1				(1 << 4)
-#define OMAP24XX_ST_MPU_WDT				(1 << 3)
-#define OMAP24XX_ST_32KSYNC				(1 << 1)
+#define OMAP2430_ST_ICR_SHIFT				6
+#define OMAP2430_ST_ICR_MASK				(1 << 6)
+#define OMAP24XX_ST_OMAPCTRL_SHIFT			5
+#define OMAP24XX_ST_OMAPCTRL_MASK			(1 << 5)
+#define OMAP24XX_ST_WDT1_SHIFT				4
+#define OMAP24XX_ST_WDT1_MASK				(1 << 4)
+#define OMAP24XX_ST_MPU_WDT_SHIFT			3
+#define OMAP24XX_ST_MPU_WDT_MASK			(1 << 3)
+#define OMAP24XX_ST_32KSYNC_SHIFT			1
+#define OMAP24XX_ST_32KSYNC_MASK			(1 << 1)
 
 /* CM_AUTOIDLE_WKUP */
 #define OMAP24XX_AUTO_OMAPCTRL				(1 << 5)
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 219f5c8..6f3f5a3 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -183,31 +183,58 @@
 #define OMAP3430ES2_EN_CPEFUSE_MASK			(1 << 0)
 
 /* CM_IDLEST1_CORE specific bits */
-#define OMAP3430_ST_ICR					(1 << 29)
-#define OMAP3430_ST_AES2				(1 << 28)
-#define OMAP3430_ST_SHA12				(1 << 27)
-#define OMAP3430_ST_DES2				(1 << 26)
-#define OMAP3430_ST_MSPRO				(1 << 23)
-#define OMAP3430_ST_HDQ					(1 << 22)
-#define OMAP3430ES1_ST_FAC				(1 << 8)
-#define OMAP3430ES1_ST_MAILBOXES			(1 << 7)
-#define OMAP3430_ST_OMAPCTRL				(1 << 6)
-#define OMAP3430_ST_SDMA				(1 << 2)
-#define OMAP3430_ST_SDRC				(1 << 1)
-#define OMAP3430_ST_SSI					(1 << 0)
+#define OMAP3430ES2_ST_MMC3_SHIFT			30
+#define OMAP3430ES2_ST_MMC3_MASK			(1 << 30)
+#define OMAP3430_ST_ICR_SHIFT				29
+#define OMAP3430_ST_ICR_MASK				(1 << 29)
+#define OMAP3430_ST_AES2_SHIFT				28
+#define OMAP3430_ST_AES2_MASK				(1 << 28)
+#define OMAP3430_ST_SHA12_SHIFT				27
+#define OMAP3430_ST_SHA12_MASK				(1 << 27)
+#define OMAP3430_ST_DES2_SHIFT				26
+#define OMAP3430_ST_DES2_MASK				(1 << 26)
+#define OMAP3430_ST_MSPRO_SHIFT				23
+#define OMAP3430_ST_MSPRO_MASK				(1 << 23)
+#define OMAP3430_ST_HDQ_SHIFT				22
+#define OMAP3430_ST_HDQ_MASK				(1 << 22)
+#define OMAP3430ES1_ST_FAC_SHIFT			8
+#define OMAP3430ES1_ST_FAC_MASK				(1 << 8)
+#define OMAP3430ES2_ST_SSI_IDLE_SHIFT			8
+#define OMAP3430ES2_ST_SSI_IDLE_MASK			(1 << 8)
+#define OMAP3430_ST_MAILBOXES_SHIFT			7
+#define OMAP3430_ST_MAILBOXES_MASK			(1 << 7)
+#define OMAP3430_ST_OMAPCTRL_SHIFT			6
+#define OMAP3430_ST_OMAPCTRL_MASK			(1 << 6)
+#define OMAP3430_ST_SDMA_SHIFT				2
+#define OMAP3430_ST_SDMA_MASK				(1 << 2)
+#define OMAP3430_ST_SDRC_SHIFT				1
+#define OMAP3430_ST_SDRC_MASK				(1 << 1)
+#define OMAP3430_ST_SSI_STDBY_SHIFT			0
+#define OMAP3430_ST_SSI_STDBY_MASK			(1 << 0)
 
 /* CM_IDLEST2_CORE */
-#define OMAP3430_ST_PKA					(1 << 4)
-#define OMAP3430_ST_AES1				(1 << 3)
-#define OMAP3430_ST_RNG					(1 << 2)
-#define OMAP3430_ST_SHA11				(1 << 1)
-#define OMAP3430_ST_DES1				(1 << 0)
+#define OMAP3430_ST_PKA_SHIFT				4
+#define OMAP3430_ST_PKA_MASK				(1 << 4)
+#define OMAP3430_ST_AES1_SHIFT				3
+#define OMAP3430_ST_AES1_MASK				(1 << 3)
+#define OMAP3430_ST_RNG_SHIFT				2
+#define OMAP3430_ST_RNG_MASK				(1 << 2)
+#define OMAP3430_ST_SHA11_SHIFT				1
+#define OMAP3430_ST_SHA11_MASK				(1 << 1)
+#define OMAP3430_ST_DES1_SHIFT				0
+#define OMAP3430_ST_DES1_MASK				(1 << 0)
 
 /* CM_IDLEST3_CORE */
 #define OMAP3430ES2_ST_USBTLL_SHIFT			2
 #define OMAP3430ES2_ST_USBTLL_MASK			(1 << 2)
+#define OMAP3430ES2_ST_CPEFUSE_SHIFT			0
+#define OMAP3430ES2_ST_CPEFUSE_MASK			(1 << 0)
 
 /* CM_AUTOIDLE1_CORE */
+#define OMAP3430ES2_AUTO_MMC3				(1 << 30)
+#define OMAP3430ES2_AUTO_MMC3_SHIFT			30
+#define OMAP3430ES2_AUTO_ICR				(1 << 29)
+#define OMAP3430ES2_AUTO_ICR_SHIFT			29
 #define OMAP3430_AUTO_AES2				(1 << 28)
 #define OMAP3430_AUTO_AES2_SHIFT			28
 #define OMAP3430_AUTO_SHA12				(1 << 27)
@@ -276,6 +303,9 @@
 #define OMAP3430_AUTO_DES1_SHIFT			0
 
 /* CM_AUTOIDLE3_CORE */
+#define	OMAP3430ES2_AUTO_USBHOST			(1 << 0)
+#define	OMAP3430ES2_AUTO_USBHOST_SHIFT			0
+#define	OMAP3430ES2_AUTO_USBTLL				(1 << 2)
 #define OMAP3430ES2_AUTO_USBTLL_SHIFT			2
 #define OMAP3430ES2_AUTO_USBTLL_MASK			(1 << 2)
 
@@ -332,8 +362,12 @@
 #define OMAP3430ES1_CLKACTIVITY_GFX_MASK		(1 << 0)
 
 /* CM_FCLKEN_SGX */
-#define OMAP3430ES2_EN_SGX_SHIFT			1
-#define OMAP3430ES2_EN_SGX_MASK				(1 << 1)
+#define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT		1
+#define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_MASK		(1 << 1)
+
+/* CM_ICLKEN_SGX */
+#define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT		0
+#define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_MASK		(1 << 0)
 
 /* CM_CLKSEL_SGX */
 #define OMAP3430ES2_CLKSEL_SGX_SHIFT			0
@@ -349,6 +383,7 @@
 
 /* CM_FCLKEN_WKUP specific bits */
 #define OMAP3430ES2_EN_USIMOCP_SHIFT			9
+#define OMAP3430ES2_EN_USIMOCP_MASK			(1 << 9)
 
 /* CM_ICLKEN_WKUP specific bits */
 #define OMAP3430_EN_WDT1				(1 << 4)
@@ -357,11 +392,18 @@
 #define OMAP3430_EN_32KSYNC_SHIFT			2
 
 /* CM_IDLEST_WKUP specific bits */
-#define OMAP3430_ST_WDT2				(1 << 5)
-#define OMAP3430_ST_WDT1				(1 << 4)
-#define OMAP3430_ST_32KSYNC				(1 << 2)
+#define OMAP3430ES2_ST_USIMOCP_SHIFT			9
+#define OMAP3430ES2_ST_USIMOCP_MASK			(1 << 9)
+#define OMAP3430_ST_WDT2_SHIFT				5
+#define OMAP3430_ST_WDT2_MASK				(1 << 5)
+#define OMAP3430_ST_WDT1_SHIFT				4
+#define OMAP3430_ST_WDT1_MASK				(1 << 4)
+#define OMAP3430_ST_32KSYNC_SHIFT			2
+#define OMAP3430_ST_32KSYNC_MASK			(1 << 2)
 
 /* CM_AUTOIDLE_WKUP */
+#define OMAP3430ES2_AUTO_USIMOCP				(1 << 9)
+#define OMAP3430ES2_AUTO_USIMOCP_SHIFT			9
 #define OMAP3430_AUTO_WDT2				(1 << 5)
 #define OMAP3430_AUTO_WDT2_SHIFT			5
 #define OMAP3430_AUTO_WDT1				(1 << 4)
@@ -426,6 +468,8 @@
 #define OMAP3430_ST_CORE_CLK_MASK			(1 << 0)
 
 /* CM_IDLEST2_CKGEN */
+#define OMAP3430ES2_ST_USIM_CLK_SHIFT			2
+#define OMAP3430ES2_ST_USIM_CLK_MASK			(1 << 2)
 #define OMAP3430ES2_ST_120M_CLK_SHIFT			1
 #define OMAP3430ES2_ST_120M_CLK_MASK			(1 << 1)
 #define OMAP3430ES2_ST_PERIPH2_CLK_SHIFT		0
@@ -449,8 +493,12 @@
 #define OMAP3430_CORE_DPLL_MULT_MASK			(0x7ff << 16)
 #define OMAP3430_CORE_DPLL_DIV_SHIFT			8
 #define OMAP3430_CORE_DPLL_DIV_MASK			(0x7f << 8)
-#define OMAP3430_SOURCE_54M				(1 << 5)
-#define OMAP3430_SOURCE_48M				(1 << 3)
+#define OMAP3430_SOURCE_96M_SHIFT			6
+#define OMAP3430_SOURCE_96M_MASK			(1 << 6)
+#define OMAP3430_SOURCE_54M_SHIFT			5
+#define OMAP3430_SOURCE_54M_MASK			(1 << 5)
+#define OMAP3430_SOURCE_48M_SHIFT			3
+#define OMAP3430_SOURCE_48M_MASK			(1 << 3)
 
 /* CM_CLKSEL2_PLL */
 #define OMAP3430_PERIPH_DPLL_MULT_SHIFT			8
@@ -493,7 +541,12 @@
 #define OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT		0
 
 /* CM_IDLEST_DSS */
-#define OMAP3430_ST_DSS					(1 << 0)
+#define OMAP3430ES2_ST_DSS_IDLE_SHIFT			1
+#define OMAP3430ES2_ST_DSS_IDLE_MASK			(1 << 1)
+#define OMAP3430ES2_ST_DSS_STDBY_SHIFT			0
+#define OMAP3430ES2_ST_DSS_STDBY_MASK			(1 << 0)
+#define OMAP3430ES1_ST_DSS_SHIFT			0
+#define OMAP3430ES1_ST_DSS_MASK				(1 << 0)
 
 /* CM_AUTOIDLE_DSS */
 #define OMAP3430_AUTO_DSS				(1 << 0)
@@ -516,6 +569,8 @@
 #define OMAP3430_CLKACTIVITY_DSS_MASK			(1 << 0)
 
 /* CM_FCLKEN_CAM specific bits */
+#define OMAP3430_EN_CSI2				(1 << 1)
+#define OMAP3430_EN_CSI2_SHIFT				1
 
 /* CM_ICLKEN_CAM specific bits */
 
@@ -545,10 +600,14 @@
 /* CM_ICLKEN_PER specific bits */
 
 /* CM_IDLEST_PER */
-#define OMAP3430_ST_WDT3				(1 << 12)
-#define OMAP3430_ST_MCBSP4				(1 << 2)
-#define OMAP3430_ST_MCBSP3				(1 << 1)
-#define OMAP3430_ST_MCBSP2				(1 << 0)
+#define OMAP3430_ST_WDT3_SHIFT				12
+#define OMAP3430_ST_WDT3_MASK				(1 << 12)
+#define OMAP3430_ST_MCBSP4_SHIFT			2
+#define OMAP3430_ST_MCBSP4_MASK				(1 << 2)
+#define OMAP3430_ST_MCBSP3_SHIFT			1
+#define OMAP3430_ST_MCBSP3_MASK				(1 << 1)
+#define OMAP3430_ST_MCBSP2_SHIFT			0
+#define OMAP3430_ST_MCBSP2_MASK				(1 << 0)
 
 /* CM_AUTOIDLE_PER */
 #define OMAP3430_AUTO_GPIO6				(1 << 17)
@@ -676,6 +735,10 @@
 #define OMAP3430ES2_EN_USBHOST_MASK			(1 << 0)
 
 /* CM_IDLEST_USBHOST */
+#define OMAP3430ES2_ST_USBHOST_IDLE_SHIFT		1
+#define OMAP3430ES2_ST_USBHOST_IDLE_MASK		(1 << 1)
+#define OMAP3430ES2_ST_USBHOST_STDBY_SHIFT		0
+#define OMAP3430ES2_ST_USBHOST_STDBY_MASK		(1 << 0)
 
 /* CM_AUTOIDLE_USBHOST */
 #define OMAP3430ES2_AUTO_USBHOST_SHIFT			0
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index ce03fa7..d6b4b2f 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -28,13 +28,121 @@
 #include <mach/eac.h>
 #include <mach/mmc.h>
 
-#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
-#define OMAP2_MBOX_BASE		IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
+#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
-static struct resource mbox_resources[] = {
+static struct resource cam_resources[] = {
 	{
-		.start		= OMAP2_MBOX_BASE,
-		.end		= OMAP2_MBOX_BASE + 0x11f,
+		.start		= OMAP24XX_CAMERA_BASE,
+		.end		= OMAP24XX_CAMERA_BASE + 0xfff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= INT_24XX_CAM_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device omap_cam_device = {
+	.name		= "omap24xxcam",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(cam_resources),
+	.resource	= cam_resources,
+};
+
+static inline void omap_init_camera(void)
+{
+	platform_device_register(&omap_cam_device);
+}
+
+#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
+
+static struct resource omap3isp_resources[] = {
+	{
+		.start		= OMAP3430_ISP_BASE,
+		.end		= OMAP3430_ISP_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CBUFF_BASE,
+		.end		= OMAP3430_ISP_CBUFF_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CCP2_BASE,
+		.end		= OMAP3430_ISP_CCP2_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CCDC_BASE,
+		.end		= OMAP3430_ISP_CCDC_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_HIST_BASE,
+		.end		= OMAP3430_ISP_HIST_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_H3A_BASE,
+		.end		= OMAP3430_ISP_H3A_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_PREV_BASE,
+		.end		= OMAP3430_ISP_PREV_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_RESZ_BASE,
+		.end		= OMAP3430_ISP_RESZ_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_SBL_BASE,
+		.end		= OMAP3430_ISP_SBL_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CSI2A_BASE,
+		.end		= OMAP3430_ISP_CSI2A_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3430_ISP_CSI2PHY_BASE,
+		.end		= OMAP3430_ISP_CSI2PHY_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= INT_34XX_CAM_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device omap3isp_device = {
+	.name		= "omap3isp",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(omap3isp_resources),
+	.resource	= omap3isp_resources,
+};
+
+static inline void omap_init_camera(void)
+{
+	platform_device_register(&omap3isp_device);
+}
+#else
+static inline void omap_init_camera(void)
+{
+}
+#endif
+
+#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+
+#define MBOX_REG_SIZE	0x120
+
+static struct resource omap2_mbox_resources[] = {
+	{
+		.start		= OMAP24XX_MAILBOX_BASE,
+		.end		= OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -47,20 +155,40 @@
 	},
 };
 
+static struct resource omap3_mbox_resources[] = {
+	{
+		.start		= OMAP34XX_MAILBOX_BASE,
+		.end		= OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= INT_24XX_MAIL_U0_MPU,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device mbox_device = {
-	.name		= "mailbox",
+	.name		= "omap2-mailbox",
 	.id		= -1,
-	.num_resources	= ARRAY_SIZE(mbox_resources),
-	.resource	= mbox_resources,
 };
 
 static inline void omap_init_mbox(void)
 {
+	if (cpu_is_omap2420()) {
+		mbox_device.num_resources = ARRAY_SIZE(omap2_mbox_resources);
+		mbox_device.resource = omap2_mbox_resources;
+	} else if (cpu_is_omap3430()) {
+		mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
+		mbox_device.resource = omap3_mbox_resources;
+	} else {
+		pr_err("%s: platform not supported\n", __func__);
+		return;
+	}
 	platform_device_register(&mbox_device);
 }
 #else
 static inline void omap_init_mbox(void) { }
-#endif
+#endif /* CONFIG_OMAP_MBOX_FWK */
 
 #if defined(CONFIG_OMAP_STI)
 
@@ -348,11 +476,12 @@
 		}
 
 		dummy_pdev.id = i;
-		iclk = clk_get(dev, "mmchs_ick");
+		dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
+		iclk = clk_get(dev, "ick");
 		if (iclk && clk_enable(iclk))
 			iclk = NULL;
 
-		fclk = clk_get(dev, "mmchs_fck");
+		fclk = clk_get(dev, "fck");
 		if (fclk && clk_enable(fclk))
 			fclk = NULL;
 
@@ -506,6 +635,7 @@
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_hsmmc_reset();
+	omap_init_camera();
 	omap_init_mbox();
 	omap_init_mcspi();
 	omap_hdq_init();
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index b52a02f..34b5914 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -217,8 +217,13 @@
 		omap_chip.oc = CHIP_IS_OMAP3430;
 		if (omap_rev() == OMAP3430_REV_ES1_0)
 			omap_chip.oc |= CHIP_IS_OMAP3430ES1;
-		else if (omap_rev() > OMAP3430_REV_ES1_0)
+		else if (omap_rev() >= OMAP3430_REV_ES2_0 &&
+			 omap_rev() <= OMAP3430_REV_ES2_1)
 			omap_chip.oc |= CHIP_IS_OMAP3430ES2;
+		else if (omap_rev() == OMAP3430_REV_ES3_0)
+			omap_chip.oc |= CHIP_IS_OMAP3430ES3_0;
+		else if (omap_rev() == OMAP3430_REV_ES3_1)
+			omap_chip.oc |= CHIP_IS_OMAP3430ES3_1;
 	} else {
 		pr_err("Uninitialized omap_chip, please fix!\n");
 	}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 5ea64f9..916fcd3 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -27,8 +27,8 @@
 #include <mach/mux.h>
 #include <mach/omapfb.h>
 #include <mach/sram.h>
-
-#include "memory.h"
+#include <mach/sdrc.h>
+#include <mach/gpmc.h>
 
 #include "clock.h"
 
@@ -195,12 +195,12 @@
 	omapfb_reserve_sdram();
 }
 
-void __init omap2_init_common_hw(void)
+void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
 {
 	omap2_mux_init();
 	pwrdm_init(powerdomains_omap);
 	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
 	omap2_clk_init();
-	omap2_init_memory();
+	omap2_sdrc_init(sp);
 	gpmc_init();
 }
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 32b7af3..fd5b8a5 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -1,9 +1,9 @@
 /*
- * Mailbox reservation modules for OMAP2
+ * Mailbox reservation modules for OMAP2/3
  *
- * Copyright (C) 2006 Nokia Corporation
+ * Copyright (C) 2006-2009 Nokia Corporation
  * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *        and  Paul Mundt <paul.mundt@nokia.com>
+ *        and  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
@@ -18,40 +18,22 @@
 #include <mach/mailbox.h>
 #include <mach/irqs.h>
 
-#define MAILBOX_REVISION		0x00
-#define MAILBOX_SYSCONFIG		0x10
-#define MAILBOX_SYSSTATUS		0x14
-#define MAILBOX_MESSAGE_0		0x40
-#define MAILBOX_MESSAGE_1		0x44
-#define MAILBOX_MESSAGE_2		0x48
-#define MAILBOX_MESSAGE_3		0x4c
-#define MAILBOX_MESSAGE_4		0x50
-#define MAILBOX_MESSAGE_5		0x54
-#define MAILBOX_FIFOSTATUS_0		0x80
-#define MAILBOX_FIFOSTATUS_1		0x84
-#define MAILBOX_FIFOSTATUS_2		0x88
-#define MAILBOX_FIFOSTATUS_3		0x8c
-#define MAILBOX_FIFOSTATUS_4		0x90
-#define MAILBOX_FIFOSTATUS_5		0x94
-#define MAILBOX_MSGSTATUS_0		0xc0
-#define MAILBOX_MSGSTATUS_1		0xc4
-#define MAILBOX_MSGSTATUS_2		0xc8
-#define MAILBOX_MSGSTATUS_3		0xcc
-#define MAILBOX_MSGSTATUS_4		0xd0
-#define MAILBOX_MSGSTATUS_5		0xd4
-#define MAILBOX_IRQSTATUS_0		0x100
-#define MAILBOX_IRQENABLE_0		0x104
-#define MAILBOX_IRQSTATUS_1		0x108
-#define MAILBOX_IRQENABLE_1		0x10c
-#define MAILBOX_IRQSTATUS_2		0x110
-#define MAILBOX_IRQENABLE_2		0x114
-#define MAILBOX_IRQSTATUS_3		0x118
-#define MAILBOX_IRQENABLE_3		0x11c
+#define MAILBOX_REVISION		0x000
+#define MAILBOX_SYSCONFIG		0x010
+#define MAILBOX_SYSSTATUS		0x014
+#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
+#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
+#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
+#define MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
+#define MAILBOX_IRQENABLE(u)		(0x104 + 8 * (u))
 
-static unsigned long mbox_base;
+#define MAILBOX_IRQ_NEWMSG(u)		(1 << (2 * (u)))
+#define MAILBOX_IRQ_NOTFULL(u)		(1 << (2 * (u) + 1))
 
-#define MAILBOX_IRQ_NOTFULL(n)		(1 << (2 * (n) + 1))
-#define MAILBOX_IRQ_NEWMSG(n)		(1 << (2 * (n)))
+#define MBOX_REG_SIZE			0x120
+#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
+
+static void __iomem *mbox_base;
 
 struct omap_mbox2_fifo {
 	unsigned long msg;
@@ -66,6 +48,7 @@
 	unsigned long irqstatus;
 	u32 newmsg_bit;
 	u32 notfull_bit;
+	u32 ctx[MBOX_NR_REGS];
 };
 
 static struct clk *mbox_ick_handle;
@@ -73,14 +56,14 @@
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 				  omap_mbox_type_t irq);
 
-static inline unsigned int mbox_read_reg(unsigned int reg)
+static inline unsigned int mbox_read_reg(size_t ofs)
 {
-	return __raw_readl(mbox_base + reg);
+	return __raw_readl(mbox_base + ofs);
 }
 
-static inline void mbox_write_reg(unsigned int val, unsigned int reg)
+static inline void mbox_write_reg(u32 val, size_t ofs)
 {
-	__raw_writel(val, mbox_base + reg);
+	__raw_writel(val, mbox_base + ofs);
 }
 
 /* Mailbox H/W preparations */
@@ -95,6 +78,9 @@
 	}
 	clk_enable(mbox_ick_handle);
 
+	l = mbox_read_reg(MAILBOX_REVISION);
+	pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
+
 	/* set smart-idle & autoidle */
 	l = mbox_read_reg(MAILBOX_SYSCONFIG);
 	l |= 0x00000011;
@@ -183,6 +169,32 @@
 	return (enable & status & bit);
 }
 
+static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
+{
+	int i;
+	struct omap_mbox2_priv *p = mbox->priv;
+
+	for (i = 0; i < MBOX_NR_REGS; i++) {
+		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, p->ctx[i]);
+	}
+}
+
+static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
+{
+	int i;
+	struct omap_mbox2_priv *p = mbox->priv;
+
+	for (i = 0; i < MBOX_NR_REGS; i++) {
+		mbox_write_reg(p->ctx[i], i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, p->ctx[i]);
+	}
+}
+
 static struct omap_mbox_ops omap2_mbox_ops = {
 	.type		= OMAP_MBOX_TYPE2,
 	.startup	= omap2_mbox_startup,
@@ -195,6 +207,8 @@
 	.disable_irq	= omap2_mbox_disable_irq,
 	.ack_irq	= omap2_mbox_ack_irq,
 	.is_irq		= omap2_mbox_is_irq,
+	.save_ctx	= omap2_mbox_save_ctx,
+	.restore_ctx	= omap2_mbox_restore_ctx,
 };
 
 /*
@@ -209,15 +223,15 @@
 /* DSP */
 static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
 	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE_0,
-		.fifo_stat	= MAILBOX_FIFOSTATUS_0,
+		.msg		= MAILBOX_MESSAGE(0),
+		.fifo_stat	= MAILBOX_FIFOSTATUS(0),
 	},
 	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE_1,
-		.msg_stat	= MAILBOX_MSGSTATUS_1,
+		.msg		= MAILBOX_MESSAGE(1),
+		.msg_stat	= MAILBOX_MSGSTATUS(1),
 	},
-	.irqenable	= MAILBOX_IRQENABLE_0,
-	.irqstatus	= MAILBOX_IRQSTATUS_0,
+	.irqenable	= MAILBOX_IRQENABLE(0),
+	.irqstatus	= MAILBOX_IRQSTATUS(0),
 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
 };
@@ -229,18 +243,18 @@
 };
 EXPORT_SYMBOL(mbox_dsp_info);
 
-/* IVA */
+#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
 static struct omap_mbox2_priv omap2_mbox_iva_priv = {
 	.tx_fifo = {
-		.msg		= MAILBOX_MESSAGE_2,
-		.fifo_stat	= MAILBOX_FIFOSTATUS_2,
+		.msg		= MAILBOX_MESSAGE(2),
+		.fifo_stat	= MAILBOX_FIFOSTATUS(2),
 	},
 	.rx_fifo = {
-		.msg		= MAILBOX_MESSAGE_3,
-		.msg_stat	= MAILBOX_MSGSTATUS_3,
+		.msg		= MAILBOX_MESSAGE(3),
+		.msg_stat	= MAILBOX_MSGSTATUS(3),
 	},
-	.irqenable	= MAILBOX_IRQENABLE_3,
-	.irqstatus	= MAILBOX_IRQSTATUS_3,
+	.irqenable	= MAILBOX_IRQENABLE(3),
+	.irqstatus	= MAILBOX_IRQSTATUS(3),
 	.notfull_bit	= MAILBOX_IRQ_NOTFULL(2),
 	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(3),
 };
@@ -250,17 +264,12 @@
 	.ops	= &omap2_mbox_ops,
 	.priv	= &omap2_mbox_iva_priv,
 };
+#endif
 
-static int __init omap2_mbox_probe(struct platform_device *pdev)
+static int __devinit omap2_mbox_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	int ret = 0;
-
-	if (pdev->num_resources != 3) {
-		dev_err(&pdev->dev, "invalid number of resources: %d\n",
-			pdev->num_resources);
-		return -ENODEV;
-	}
+	int ret;
 
 	/* MBOX base */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -268,42 +277,61 @@
 		dev_err(&pdev->dev, "invalid mem resource\n");
 		return -ENODEV;
 	}
-	mbox_base = res->start;
+	mbox_base = ioremap(res->start, res->end - res->start);
+	if (!mbox_base)
+		return -ENOMEM;
 
-	/* DSP IRQ */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (unlikely(!res)) {
+	/* DSP or IVA2 IRQ */
+	mbox_dsp_info.irq = platform_get_irq(pdev, 0);
+	if (mbox_dsp_info.irq < 0) {
 		dev_err(&pdev->dev, "invalid irq resource\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_dsp;
 	}
-	mbox_dsp_info.irq = res->start;
 
-	ret = omap_mbox_register(&mbox_dsp_info);
+	ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
+	if (ret)
+		goto err_dsp;
 
-	/* IVA IRQ */
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-	if (unlikely(!res)) {
-		dev_err(&pdev->dev, "invalid irq resource\n");
-		return -ENODEV;
+#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
+	if (cpu_is_omap2420()) {
+		/* IVA IRQ */
+		res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+		if (unlikely(!res)) {
+			dev_err(&pdev->dev, "invalid irq resource\n");
+			ret = -ENODEV;
+			goto err_iva1;
+		}
+		mbox_iva_info.irq = res->start;
+		ret = omap_mbox_register(&pdev->dev, &mbox_iva_info);
+		if (ret)
+			goto err_iva1;
 	}
-	mbox_iva_info.irq = res->start;
+#endif
+	return 0;
 
-	ret = omap_mbox_register(&mbox_iva_info);
-
+err_iva1:
+	omap_mbox_unregister(&mbox_dsp_info);
+err_dsp:
+	iounmap(mbox_base);
 	return ret;
 }
 
-static int omap2_mbox_remove(struct platform_device *pdev)
+static int __devexit omap2_mbox_remove(struct platform_device *pdev)
 {
+#if defined(CONFIG_ARCH_OMAP2420)
+	omap_mbox_unregister(&mbox_iva_info);
+#endif
 	omap_mbox_unregister(&mbox_dsp_info);
+	iounmap(mbox_base);
 	return 0;
 }
 
 static struct platform_driver omap2_mbox_driver = {
 	.probe = omap2_mbox_probe,
-	.remove = omap2_mbox_remove,
+	.remove = __devexit_p(omap2_mbox_remove),
 	.driver = {
-		.name = "mailbox",
+		.name = "omap2-mailbox",
 	},
 };
 
@@ -320,4 +348,7 @@
 module_init(omap2_mbox_init);
 module_exit(omap2_mbox_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
+MODULE_ALIAS("platform:omap2-mailbox");
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index a9e631f..a5c0f04 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -24,8 +24,6 @@
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
 
-const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
-
 static void omap2_mcbsp2_mux_setup(void)
 {
 	omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
@@ -57,8 +55,6 @@
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP24XX_MCBSP2_BASE,
@@ -67,8 +63,6 @@
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 };
 #define OMAP2420_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -86,8 +80,6 @@
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP24XX_MCBSP2_BASE,
@@ -96,8 +88,6 @@
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP3_BASE,
@@ -106,8 +96,6 @@
 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP4_BASE,
@@ -116,8 +104,6 @@
 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP2430_MCBSP5_BASE,
@@ -126,8 +112,6 @@
 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 };
 #define OMAP2430_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -145,8 +129,6 @@
 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP34XX_MCBSP2_BASE,
@@ -155,8 +137,6 @@
 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP34XX_MCBSP3_BASE,
@@ -165,8 +145,6 @@
 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP34XX_MCBSP4_BASE,
@@ -175,8 +153,6 @@
 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 	{
 		.phys_base	= OMAP34XX_MCBSP5_BASE,
@@ -185,8 +161,6 @@
 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
 		.ops		= &omap2_mcbsp_ops,
-		.clk_names	= clk_names,
-		.num_clks	= 2,
 	},
 };
 #define OMAP34XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap34xx_mcbsp_pdata)
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
deleted file mode 100644
index bb3db80..0000000
--- a/arch/arm/mach-omap2/memory.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/memory.h
- *
- * Interface for memory timing related functions for OMAP24XX
- *
- * Copyright (C) 2005 Texas Instruments Inc.
- * Richard Woodruff <r-woodruff2@ti.com>
- *
- * Copyright (C) 2005 Nokia Corporation
- * Tony Lindgren <tony@atomide.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 ARCH_ARM_MACH_OMAP2_MEMORY_H
-#define ARCH_ARM_MACH_OMAP2_MEMORY_H
-
-/* Memory timings */
-#define M_DDR		1
-#define M_LOCK_CTRL	(1 << 2)
-#define M_UNLOCK	0
-#define M_LOCK		1
-
-struct memory_timings {
-	u32 m_type;		/* ddr = 1, sdr = 0 */
-	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
-	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
-	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
-	u32 base_cs;		/* base chip select to use for calculations */
-};
-
-extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
-extern u32 omap2_memory_get_slow_dll_ctrl(void);
-extern u32 omap2_memory_get_fast_dll_ctrl(void);
-extern u32 omap2_memory_get_type(void);
-u32 omap2_dll_force_needed(void);
-u32 omap2_reprogram_sdrc(u32 level, u32 force);
-void __init omap2_init_memory(void);
-void __init gpmc_init(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c
index 437f520..dc40b3e 100644
--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/regulator/machine.h>
 
 #include <mach/hardware.h>
 #include <mach/control.h>
@@ -44,6 +45,7 @@
 #define VMMC2_315V		0x0c
 #define VMMC2_300V		0x0b
 #define VMMC2_285V		0x0a
+#define VMMC2_280V		0x09
 #define VMMC2_260V		0x08
 #define VMMC2_185V		0x06
 #define VMMC2_DEDICATED		0x2E
@@ -59,8 +61,8 @@
 	struct omap_mmc_platform_data	*mmc;
 	u8		twl_vmmc_dev_grp;
 	u8		twl_mmc_dedicated;
-	char		name[HSMMC_NAME_LEN];
-} hsmmc[] = {
+	char		name[HSMMC_NAME_LEN + 1];
+} hsmmc[OMAP34XX_NR_MMC] = {
 	{
 		.twl_vmmc_dev_grp		= VMMC1_DEV_GRP,
 		.twl_mmc_dedicated		= VMMC1_DEDICATED,
@@ -98,6 +100,14 @@
 	return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
 }
 
+static int twl_mmc_get_cover_state(struct device *dev, int slot)
+{
+	struct omap_mmc_platform_data *mmc = dev->platform_data;
+
+	/* NOTE: assumes card detect signal is active-low */
+	return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+}
+
 /*
  * MMC Slot Initialization.
  */
@@ -166,66 +176,85 @@
 /*
  * Sets the MMC voltage in twl4030
  */
+
+#define MMC1_OCR	(MMC_VDD_165_195 \
+		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
+#define MMC2_OCR	(MMC_VDD_165_195 \
+		|MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \
+		|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32)
+
 static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd)
 {
 	int ret;
-	u8 vmmc, dev_grp_val;
+	u8 vmmc = 0, dev_grp_val;
 
-	switch (1 << vdd) {
-	case MMC_VDD_35_36:
-	case MMC_VDD_34_35:
-	case MMC_VDD_33_34:
-	case MMC_VDD_32_33:
-	case MMC_VDD_31_32:
-	case MMC_VDD_30_31:
-		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
-			vmmc = VMMC1_315V;
-		else
-			vmmc = VMMC2_315V;
-		break;
-	case MMC_VDD_29_30:
-		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
-			vmmc = VMMC1_315V;
-		else
-			vmmc = VMMC2_300V;
-		break;
-	case MMC_VDD_27_28:
-	case MMC_VDD_26_27:
-		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
-			vmmc = VMMC1_285V;
-		else
-			vmmc = VMMC2_285V;
-		break;
-	case MMC_VDD_25_26:
-	case MMC_VDD_24_25:
-	case MMC_VDD_23_24:
-	case MMC_VDD_22_23:
-	case MMC_VDD_21_22:
-	case MMC_VDD_20_21:
-		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
-			vmmc = VMMC1_285V;
-		else
-			vmmc = VMMC2_260V;
-		break;
-	case MMC_VDD_165_195:
-		if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP)
+	if (!vdd)
+		goto doit;
+
+	if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) {
+		/* VMMC1:  max 220 mA.  And for 8-bit mode,
+		 * VSIM:  max 50 mA
+		 */
+		switch (1 << vdd) {
+		case MMC_VDD_165_195:
 			vmmc = VMMC1_185V;
-		else
+			/* and VSIM_180V */
+			break;
+		case MMC_VDD_28_29:
+			vmmc = VMMC1_285V;
+			/* and VSIM_280V */
+			break;
+		case MMC_VDD_29_30:
+		case MMC_VDD_30_31:
+			vmmc = VMMC1_300V;
+			/* and VSIM_300V */
+			break;
+		case MMC_VDD_31_32:
+			vmmc = VMMC1_315V;
+			/* error if VSIM needed */
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) {
+		/* VMMC2:  max 100 mA */
+		switch (1 << vdd) {
+		case MMC_VDD_165_195:
 			vmmc = VMMC2_185V;
-		break;
-	default:
-		vmmc = 0;
-		break;
+			break;
+		case MMC_VDD_25_26:
+		case MMC_VDD_26_27:
+			vmmc = VMMC2_260V;
+			break;
+		case MMC_VDD_27_28:
+			vmmc = VMMC2_280V;
+			break;
+		case MMC_VDD_28_29:
+			vmmc = VMMC2_285V;
+			break;
+		case MMC_VDD_29_30:
+		case MMC_VDD_30_31:
+			vmmc = VMMC2_300V;
+			break;
+		case MMC_VDD_31_32:
+			vmmc = VMMC2_315V;
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
 	}
 
-	if (vmmc)
+doit:
+	if (vdd)
 		dev_grp_val = VMMC_DEV_GRP_P1;	/* Power up */
 	else
 		dev_grp_val = LDO_CLR;		/* Power down */
 
 	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
 					dev_grp_val, c->twl_vmmc_dev_grp);
-	if (ret)
+	if (ret || !vdd)
 		return ret;
 
 	ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
@@ -242,6 +271,14 @@
 	struct twl_mmc_controller *c = &hsmmc[0];
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
 
+	/*
+	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
+	 * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both
+	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
+	 *
+	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
+	 * is most naturally TWL VSIM; those pins also use PBIAS.
+	 */
 	if (power_on) {
 		if (cpu_is_omap2430()) {
 			reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
@@ -298,6 +335,12 @@
 	struct twl_mmc_controller *c = &hsmmc[1];
 	struct omap_mmc_platform_data *mmc = dev->platform_data;
 
+	/*
+	 * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP
+	 * VDDS is used to power the pins, optionally with a transceiver to
+	 * support cards using voltages other than VDDS (1.8V nominal).  When a
+	 * transceiver is used, DAT3..7 are muxed as transceiver control pins.
+	 */
 	if (power_on) {
 		if (mmc->slots[0].internal_clock) {
 			u32 reg;
@@ -314,6 +357,16 @@
 	return ret;
 }
 
+static int twl_mmc3_set_power(struct device *dev, int slot, int power_on,
+		int vdd)
+{
+	/*
+	 * Assume MMC3 has self-powered device connected, for example on-board
+	 * chip with external power source.
+	 */
+	return 0;
+}
+
 static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
 
 void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
@@ -349,13 +402,13 @@
 			return;
 		}
 
-		sprintf(twl->name, "mmc%islot%i", c->mmc, 1);
+		if (c->name)
+			strncpy(twl->name, c->name, HSMMC_NAME_LEN);
+		else
+			snprintf(twl->name, ARRAY_SIZE(twl->name),
+				"mmc%islot%i", c->mmc, 1);
 		mmc->slots[0].name = twl->name;
 		mmc->nr_slots = 1;
-		mmc->slots[0].ocr_mask = MMC_VDD_165_195 |
-					MMC_VDD_26_27 | MMC_VDD_27_28 |
-					MMC_VDD_29_30 |
-					MMC_VDD_30_31 | MMC_VDD_31_32;
 		mmc->slots[0].wires = c->wires;
 		mmc->slots[0].internal_clock = !c->ext_clock;
 		mmc->dma_mask = 0xffffffff;
@@ -369,7 +422,10 @@
 
 			mmc->slots[0].switch_pin = c->gpio_cd;
 			mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd);
-			mmc->slots[0].card_detect = twl_mmc_card_detect;
+			if (c->cover_only)
+				mmc->slots[0].get_cover_state = twl_mmc_get_cover_state;
+			else
+				mmc->slots[0].card_detect = twl_mmc_card_detect;
 		} else
 			mmc->slots[0].switch_pin = -EINVAL;
 
@@ -385,24 +441,43 @@
 
 		/* NOTE:  we assume OMAP's MMC1 and MMC2 use
 		 * the TWL4030's VMMC1 and VMMC2, respectively;
-		 * and that OMAP's MMC3 isn't used.
+		 * and that MMC3 device has it's own power source.
 		 */
 
 		switch (c->mmc) {
 		case 1:
 			mmc->slots[0].set_power = twl_mmc1_set_power;
+			mmc->slots[0].ocr_mask = MMC1_OCR;
 			break;
 		case 2:
 			mmc->slots[0].set_power = twl_mmc2_set_power;
+			if (c->transceiver)
+				mmc->slots[0].ocr_mask = MMC2_OCR;
+			else
+				mmc->slots[0].ocr_mask = MMC_VDD_165_195;
+			break;
+		case 3:
+			mmc->slots[0].set_power = twl_mmc3_set_power;
+			mmc->slots[0].ocr_mask = MMC_VDD_165_195;
 			break;
 		default:
 			pr_err("MMC%d configuration not supported!\n", c->mmc);
+			kfree(mmc);
 			continue;
 		}
 		hsmmc_data[c->mmc - 1] = mmc;
 	}
 
 	omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
+
+	/* pass the device nodes back to board setup code */
+	for (c = controllers; c->mmc; c++) {
+		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
+
+		if (!c->mmc || c->mmc > nr_hsmmc)
+			continue;
+		c->dev = mmc->dev;
+	}
 }
 
 #endif
diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h
index e1c8076..ea59e86 100644
--- a/arch/arm/mach-omap2/mmc-twl4030.h
+++ b/arch/arm/mach-omap2/mmc-twl4030.h
@@ -9,9 +9,13 @@
 struct twl4030_hsmmc_info {
 	u8	mmc;		/* controller 1/2/3 */
 	u8	wires;		/* 1/4/8 wires */
+	bool	transceiver;	/* MMC-2 option */
+	bool	ext_clock;	/* use external pin for input clock */
+	bool	cover_only;	/* No card detect - just cover switch */
 	int	gpio_cd;	/* or -EINVAL */
 	int	gpio_wp;	/* or -EINVAL */
-	int	ext_clock:1;	/* use external pin for input clock */
+	char	*name;		/* or NULL for default */
+	struct device *dev;	/* returned: pointer to mmc adapter */
 };
 
 #if	defined(CONFIG_TWL4030_CORE) && \
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index dacb41f..026c4fc 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -453,10 +453,37 @@
 
 
 /* 34XX GPIO - bidirectional, unless the name has an "_OUT" suffix.
+ * (Always specify PIN_INPUT, except for names suffixed by "_OUT".)
  * No internal pullup/pulldown without "_UP" or "_DOWN" suffix.
  */
+MUX_CFG_34XX("AF26_34XX_GPIO0", 0x1e0,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AF22_34XX_GPIO9", 0xa18,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
 MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa,
 		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("U8_34XX_GPIO54_OUT", 0x0b4,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("U8_34XX_GPIO54_DOWN", 0x0b4,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("L8_34XX_GPIO63", 0x0ce,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("G25_34XX_GPIO86_OUT", 0x0fc,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AG4_34XX_GPIO134_OUT", 0x160,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AE4_34XX_GPIO136_OUT", 0x164,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AF6_34XX_GPIO140_UP", 0x16c,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AE6_34XX_GPIO141", 0x16e,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AF5_34XX_GPIO142", 0x170,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AE5_34XX_GPIO143", 0x172,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c,
+		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
 MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6,
 		OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
 };
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 55361c1..ea8ceae 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -103,7 +103,7 @@
 	.valid		= suspend_valid_only_mem,
 };
 
-int __init omap2_pm_init(void)
+static int __init omap2_pm_init(void)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
index 1e151fa..691470e 100644
--- a/arch/arm/mach-omap2/powerdomains.h
+++ b/arch/arm/mach-omap2/powerdomains.h
@@ -171,13 +171,19 @@
 	&iva2_pwrdm,
 	&mpu_34xx_pwrdm,
 	&neon_pwrdm,
-	&core_34xx_pwrdm,
+	&core_34xx_pre_es3_1_pwrdm,
+	&core_34xx_es3_1_pwrdm,
 	&cam_pwrdm,
 	&dss_pwrdm,
 	&per_pwrdm,
 	&emu_pwrdm,
 	&sgx_pwrdm,
 	&usbhost_pwrdm,
+	&dpll1_pwrdm,
+	&dpll2_pwrdm,
+	&dpll3_pwrdm,
+	&dpll4_pwrdm,
+	&dpll5_pwrdm,
 #endif
 
 	NULL
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
index f573f71..4dcf94b 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -200,10 +200,12 @@
 };
 
 /* No wkdeps or sleepdeps for 34xx core apparently */
-static struct powerdomain core_34xx_pwrdm = {
+static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+					   CHIP_IS_OMAP3430ES2 |
+					   CHIP_IS_OMAP3430ES3_0),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.dep_bit	  = OMAP3430_EN_CORE_SHIFT,
 	.banks		  = 2,
@@ -217,6 +219,25 @@
 	},
 };
 
+/* No wkdeps or sleepdeps for 34xx core apparently */
+static struct powerdomain core_34xx_es3_1_pwrdm = {
+	.name		  = "core_pwrdm",
+	.prcm_offs	  = CORE_MOD,
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES3_1),
+	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.dep_bit	  = OMAP3430_EN_CORE_SHIFT,
+	.flags		  = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
+	.banks		  = 2,
+	.pwrsts_mem_ret	  = {
+		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
+		[1] = PWRSTS_OFF_RET,	 /* MEM2RETSTATE */
+	},
+	.pwrsts_mem_on	  = {
+		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+	},
+};
+
 /* Another case of bit name collisions between several registers: EN_DSS */
 static struct powerdomain dss_pwrdm = {
 	.name		  = "dss_pwrdm",
@@ -236,14 +257,19 @@
 	},
 };
 
+/*
+ * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
+ * possible SGX powerstate, the SGX device itself does not support
+ * retention.
+ */
 static struct powerdomain sgx_pwrdm = {
 	.name		  = "sgx_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_SGX_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.wkdep_srcs	  = gfx_sgx_wkdeps,
 	.sleepdep_srcs	  = cam_gfx_sleepdeps,
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.pwrsts		  = PWRSTS_OFF_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
@@ -307,11 +333,12 @@
 static struct powerdomain usbhost_pwrdm = {
 	.name		  = "usbhost_pwrdm",
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
-	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.wkdep_srcs	  = per_usbhost_wkdeps,
 	.sleepdep_srcs	  = dss_per_usbhost_sleepdeps,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.flags		  = PWRDM_HAS_HDWR_SAR, /* for USBHOST ctrlr only */
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
 		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
@@ -321,6 +348,37 @@
 	},
 };
 
+static struct powerdomain dpll1_pwrdm = {
+	.name		= "dpll1_pwrdm",
+	.prcm_offs	= MPU_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll2_pwrdm = {
+	.name		= "dpll2_pwrdm",
+	.prcm_offs	= OMAP3430_IVA2_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll3_pwrdm = {
+	.name		= "dpll3_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll4_pwrdm = {
+	.name		= "dpll4_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain dpll5_pwrdm = {
+	.name		= "dpll5_pwrdm",
+	.prcm_offs	= PLL_MOD,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+};
+
+
 #endif    /* CONFIG_ARCH_OMAP34XX */
 
 
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 4a32822..812d50e 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -113,33 +113,58 @@
 #define OMAP2430_EN_USBHS				(1 << 6)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
-#define OMAP2420_ST_MMC					(1 << 26)
-#define OMAP24XX_ST_UART2				(1 << 22)
-#define OMAP24XX_ST_UART1				(1 << 21)
-#define OMAP24XX_ST_MCSPI2				(1 << 18)
-#define OMAP24XX_ST_MCSPI1				(1 << 17)
-#define OMAP24XX_ST_GPT12				(1 << 14)
-#define OMAP24XX_ST_GPT11				(1 << 13)
-#define OMAP24XX_ST_GPT10				(1 << 12)
-#define OMAP24XX_ST_GPT9				(1 << 11)
-#define OMAP24XX_ST_GPT8				(1 << 10)
-#define OMAP24XX_ST_GPT7				(1 << 9)
-#define OMAP24XX_ST_GPT6				(1 << 8)
-#define OMAP24XX_ST_GPT5				(1 << 7)
-#define OMAP24XX_ST_GPT4				(1 << 6)
-#define OMAP24XX_ST_GPT3				(1 << 5)
-#define OMAP24XX_ST_GPT2				(1 << 4)
-#define OMAP2420_ST_VLYNQ				(1 << 3)
+#define OMAP2420_ST_MMC_SHIFT				26
+#define OMAP2420_ST_MMC_MASK				(1 << 26)
+#define OMAP24XX_ST_UART2_SHIFT				22
+#define OMAP24XX_ST_UART2_MASK				(1 << 22)
+#define OMAP24XX_ST_UART1_SHIFT				21
+#define OMAP24XX_ST_UART1_MASK				(1 << 21)
+#define OMAP24XX_ST_MCSPI2_SHIFT			18
+#define OMAP24XX_ST_MCSPI2_MASK				(1 << 18)
+#define OMAP24XX_ST_MCSPI1_SHIFT			17
+#define OMAP24XX_ST_MCSPI1_MASK				(1 << 17)
+#define OMAP24XX_ST_GPT12_SHIFT				14
+#define OMAP24XX_ST_GPT12_MASK				(1 << 14)
+#define OMAP24XX_ST_GPT11_SHIFT				13
+#define OMAP24XX_ST_GPT11_MASK				(1 << 13)
+#define OMAP24XX_ST_GPT10_SHIFT				12
+#define OMAP24XX_ST_GPT10_MASK				(1 << 12)
+#define OMAP24XX_ST_GPT9_SHIFT				11
+#define OMAP24XX_ST_GPT9_MASK				(1 << 11)
+#define OMAP24XX_ST_GPT8_SHIFT				10
+#define OMAP24XX_ST_GPT8_MASK				(1 << 10)
+#define OMAP24XX_ST_GPT7_SHIFT				9
+#define OMAP24XX_ST_GPT7_MASK				(1 << 9)
+#define OMAP24XX_ST_GPT6_SHIFT				8
+#define OMAP24XX_ST_GPT6_MASK				(1 << 8)
+#define OMAP24XX_ST_GPT5_SHIFT				7
+#define OMAP24XX_ST_GPT5_MASK				(1 << 7)
+#define OMAP24XX_ST_GPT4_SHIFT				6
+#define OMAP24XX_ST_GPT4_MASK				(1 << 6)
+#define OMAP24XX_ST_GPT3_SHIFT				5
+#define OMAP24XX_ST_GPT3_MASK				(1 << 5)
+#define OMAP24XX_ST_GPT2_SHIFT				4
+#define OMAP24XX_ST_GPT2_MASK				(1 << 4)
+#define OMAP2420_ST_VLYNQ_SHIFT				3
+#define OMAP2420_ST_VLYNQ_MASK				(1 << 3)
 
 /* CM_IDLEST2_CORE, PM_WKST2_CORE shared bits */
-#define OMAP2430_ST_MDM_INTC				(1 << 11)
-#define OMAP2430_ST_GPIO5				(1 << 10)
-#define OMAP2430_ST_MCSPI3				(1 << 9)
-#define OMAP2430_ST_MMCHS2				(1 << 8)
-#define OMAP2430_ST_MMCHS1				(1 << 7)
-#define OMAP2430_ST_USBHS				(1 << 6)
-#define OMAP24XX_ST_UART3				(1 << 2)
-#define OMAP24XX_ST_USB					(1 << 0)
+#define OMAP2430_ST_MDM_INTC_SHIFT			11
+#define OMAP2430_ST_MDM_INTC_MASK			(1 << 11)
+#define OMAP2430_ST_GPIO5_SHIFT				10
+#define OMAP2430_ST_GPIO5_MASK				(1 << 10)
+#define OMAP2430_ST_MCSPI3_SHIFT			9
+#define OMAP2430_ST_MCSPI3_MASK				(1 << 9)
+#define OMAP2430_ST_MMCHS2_SHIFT			8
+#define OMAP2430_ST_MMCHS2_MASK				(1 << 8)
+#define OMAP2430_ST_MMCHS1_SHIFT			7
+#define OMAP2430_ST_MMCHS1_MASK				(1 << 7)
+#define OMAP2430_ST_USBHS_SHIFT				6
+#define OMAP2430_ST_USBHS_MASK				(1 << 6)
+#define OMAP24XX_ST_UART3_SHIFT				2
+#define OMAP24XX_ST_UART3_MASK				(1 << 2)
+#define OMAP24XX_ST_USB_SHIFT				0
+#define OMAP24XX_ST_USB_MASK				(1 << 0)
 
 /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
 #define OMAP24XX_EN_GPIOS_SHIFT				2
@@ -148,11 +173,13 @@
 #define OMAP24XX_EN_GPT1				(1 << 0)
 
 /* PM_WKST_WKUP, CM_IDLEST_WKUP shared bits */
-#define OMAP24XX_ST_GPIOS				(1 << 2)
-#define OMAP24XX_ST_GPT1				(1 << 0)
+#define OMAP24XX_ST_GPIOS_SHIFT				(1 << 2)
+#define OMAP24XX_ST_GPIOS_MASK				2
+#define OMAP24XX_ST_GPT1_SHIFT				(1 << 0)
+#define OMAP24XX_ST_GPT1_MASK				0
 
 /* CM_IDLEST_MDM and PM_WKST_MDM shared bits */
-#define OMAP2430_ST_MDM					(1 << 0)
+#define OMAP2430_ST_MDM_SHIFT				(1 << 0)
 
 
 /* 3430 register bits shared between CM & PRM registers */
@@ -205,24 +232,46 @@
 #define OMAP3430_EN_HSOTGUSB_SHIFT				4
 
 /* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */
-#define OMAP3430_ST_MMC2				(1 << 25)
-#define OMAP3430_ST_MMC1				(1 << 24)
-#define OMAP3430_ST_MCSPI4				(1 << 21)
-#define OMAP3430_ST_MCSPI3				(1 << 20)
-#define OMAP3430_ST_MCSPI2				(1 << 19)
-#define OMAP3430_ST_MCSPI1				(1 << 18)
-#define OMAP3430_ST_I2C3				(1 << 17)
-#define OMAP3430_ST_I2C2				(1 << 16)
-#define OMAP3430_ST_I2C1				(1 << 15)
-#define OMAP3430_ST_UART2				(1 << 14)
-#define OMAP3430_ST_UART1				(1 << 13)
-#define OMAP3430_ST_GPT11				(1 << 12)
-#define OMAP3430_ST_GPT10				(1 << 11)
-#define OMAP3430_ST_MCBSP5				(1 << 10)
-#define OMAP3430_ST_MCBSP1				(1 << 9)
-#define OMAP3430_ST_FSHOSTUSB				(1 << 5)
-#define OMAP3430_ST_HSOTGUSB				(1 << 4)
-#define OMAP3430_ST_D2D					(1 << 3)
+#define OMAP3430_ST_MMC2_SHIFT				25
+#define OMAP3430_ST_MMC2_MASK				(1 << 25)
+#define OMAP3430_ST_MMC1_SHIFT				24
+#define OMAP3430_ST_MMC1_MASK				(1 << 24)
+#define OMAP3430_ST_MCSPI4_SHIFT			21
+#define OMAP3430_ST_MCSPI4_MASK				(1 << 21)
+#define OMAP3430_ST_MCSPI3_SHIFT			20
+#define OMAP3430_ST_MCSPI3_MASK				(1 << 20)
+#define OMAP3430_ST_MCSPI2_SHIFT			19
+#define OMAP3430_ST_MCSPI2_MASK				(1 << 19)
+#define OMAP3430_ST_MCSPI1_SHIFT			18
+#define OMAP3430_ST_MCSPI1_MASK				(1 << 18)
+#define OMAP3430_ST_I2C3_SHIFT				17
+#define OMAP3430_ST_I2C3_MASK				(1 << 17)
+#define OMAP3430_ST_I2C2_SHIFT				16
+#define OMAP3430_ST_I2C2_MASK				(1 << 16)
+#define OMAP3430_ST_I2C1_SHIFT				15
+#define OMAP3430_ST_I2C1_MASK				(1 << 15)
+#define OMAP3430_ST_UART2_SHIFT				14
+#define OMAP3430_ST_UART2_MASK				(1 << 14)
+#define OMAP3430_ST_UART1_SHIFT				13
+#define OMAP3430_ST_UART1_MASK				(1 << 13)
+#define OMAP3430_ST_GPT11_SHIFT				12
+#define OMAP3430_ST_GPT11_MASK				(1 << 12)
+#define OMAP3430_ST_GPT10_SHIFT				11
+#define OMAP3430_ST_GPT10_MASK				(1 << 11)
+#define OMAP3430_ST_MCBSP5_SHIFT			10
+#define OMAP3430_ST_MCBSP5_MASK				(1 << 10)
+#define OMAP3430_ST_MCBSP1_SHIFT			9
+#define OMAP3430_ST_MCBSP1_MASK				(1 << 9)
+#define OMAP3430ES1_ST_FSHOSTUSB_SHIFT			5
+#define OMAP3430ES1_ST_FSHOSTUSB_MASK			(1 << 5)
+#define OMAP3430ES1_ST_HSOTGUSB_SHIFT			4
+#define OMAP3430ES1_ST_HSOTGUSB_MASK			(1 << 4)
+#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT		5
+#define OMAP3430ES2_ST_HSOTGUSB_IDLE_MASK		(1 << 5)
+#define OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT		4
+#define OMAP3430ES2_ST_HSOTGUSB_STDBY_MASK		(1 << 4)
+#define OMAP3430_ST_D2D_SHIFT				3
+#define OMAP3430_ST_D2D_MASK				(1 << 3)
 
 /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */
 #define OMAP3430_EN_GPIO1				(1 << 3)
@@ -241,11 +290,16 @@
 #define OMAP3430_EN_GPT12_SHIFT				1
 
 /* CM_IDLEST_WKUP, PM_WKST_WKUP shared bits */
-#define OMAP3430_ST_SR2					(1 << 7)
-#define OMAP3430_ST_SR1					(1 << 6)
-#define OMAP3430_ST_GPIO1				(1 << 3)
-#define OMAP3430_ST_GPT12				(1 << 1)
-#define OMAP3430_ST_GPT1				(1 << 0)
+#define OMAP3430_ST_SR2_SHIFT				7
+#define OMAP3430_ST_SR2_MASK				(1 << 7)
+#define OMAP3430_ST_SR1_SHIFT				6
+#define OMAP3430_ST_SR1_MASK				(1 << 6)
+#define OMAP3430_ST_GPIO1_SHIFT				3
+#define OMAP3430_ST_GPIO1_MASK				(1 << 3)
+#define OMAP3430_ST_GPT12_SHIFT				1
+#define OMAP3430_ST_GPT12_MASK				(1 << 1)
+#define OMAP3430_ST_GPT1_SHIFT				0
+#define OMAP3430_ST_GPT1_MASK				(1 << 0)
 
 /*
  * CM_SLEEPDEP_GFX, CM_SLEEPDEP_DSS, CM_SLEEPDEP_CAM,
@@ -296,20 +350,34 @@
 #define OMAP3430_EN_MCBSP2_SHIFT			0
 
 /* CM_IDLEST_PER, PM_WKST_PER shared bits */
-#define OMAP3430_ST_GPIO6				(1 << 17)
-#define OMAP3430_ST_GPIO5				(1 << 16)
-#define OMAP3430_ST_GPIO4				(1 << 15)
-#define OMAP3430_ST_GPIO3				(1 << 14)
-#define OMAP3430_ST_GPIO2				(1 << 13)
-#define OMAP3430_ST_UART3				(1 << 11)
-#define OMAP3430_ST_GPT9				(1 << 10)
-#define OMAP3430_ST_GPT8				(1 << 9)
-#define OMAP3430_ST_GPT7				(1 << 8)
-#define OMAP3430_ST_GPT6				(1 << 7)
-#define OMAP3430_ST_GPT5				(1 << 6)
-#define OMAP3430_ST_GPT4				(1 << 5)
-#define OMAP3430_ST_GPT3				(1 << 4)
-#define OMAP3430_ST_GPT2				(1 << 3)
+#define OMAP3430_ST_GPIO6_SHIFT				17
+#define OMAP3430_ST_GPIO6_MASK				(1 << 17)
+#define OMAP3430_ST_GPIO5_SHIFT				16
+#define OMAP3430_ST_GPIO5_MASK				(1 << 16)
+#define OMAP3430_ST_GPIO4_SHIFT				15
+#define OMAP3430_ST_GPIO4_MASK				(1 << 15)
+#define OMAP3430_ST_GPIO3_SHIFT				14
+#define OMAP3430_ST_GPIO3_MASK				(1 << 14)
+#define OMAP3430_ST_GPIO2_SHIFT				13
+#define OMAP3430_ST_GPIO2_MASK				(1 << 13)
+#define OMAP3430_ST_UART3_SHIFT				11
+#define OMAP3430_ST_UART3_MASK				(1 << 11)
+#define OMAP3430_ST_GPT9_SHIFT				10
+#define OMAP3430_ST_GPT9_MASK				(1 << 10)
+#define OMAP3430_ST_GPT8_SHIFT				9
+#define OMAP3430_ST_GPT8_MASK				(1 << 9)
+#define OMAP3430_ST_GPT7_SHIFT				8
+#define OMAP3430_ST_GPT7_MASK				(1 << 8)
+#define OMAP3430_ST_GPT6_SHIFT				7
+#define OMAP3430_ST_GPT6_MASK				(1 << 7)
+#define OMAP3430_ST_GPT5_SHIFT				6
+#define OMAP3430_ST_GPT5_MASK				(1 << 6)
+#define OMAP3430_ST_GPT4_SHIFT				5
+#define OMAP3430_ST_GPT4_MASK				(1 << 5)
+#define OMAP3430_ST_GPT3_SHIFT				4
+#define OMAP3430_ST_GPT3_MASK				(1 << 4)
+#define OMAP3430_ST_GPT2_SHIFT				3
+#define OMAP3430_ST_GPT2_MASK				(1 << 3)
 
 /* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */
 #define OMAP3430_EN_CORE_SHIFT				0
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 5b5ecfe..c6a7940 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -366,6 +366,7 @@
 
 /* PM_WKEN_WKUP specific bits */
 #define OMAP3430_EN_IO					(1 << 8)
+#define OMAP3430_EN_GPIO1				(1 << 3)
 
 /* PM_MPUGRPSEL_WKUP specific bits */
 
@@ -452,6 +453,14 @@
 #define OMAP3430_CMDRA0_MASK				(0xff << 0)
 
 /* PRM_VC_CMD_VAL_0 specific bits */
+#define OMAP3430_VC_CMD_ON_SHIFT			24
+#define OMAP3430_VC_CMD_ON_MASK				(0xFF << 24)
+#define OMAP3430_VC_CMD_ONLP_SHIFT			16
+#define OMAP3430_VC_CMD_ONLP_MASK			(0xFF << 16)
+#define OMAP3430_VC_CMD_RET_SHIFT			8
+#define OMAP3430_VC_CMD_RET_MASK			(0xFF << 8)
+#define OMAP3430_VC_CMD_OFF_SHIFT			0
+#define OMAP3430_VC_CMD_OFF_MASK			(0xFF << 0)
 
 /* PRM_VC_CMD_VAL_1 specific bits */
 
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index e4dc4b1..826d326 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -141,6 +141,19 @@
 #define PM_PWSTCTRL					0x00e0
 #define PM_PWSTST					0x00e4
 
+/* Omap2 specific registers */
+#define OMAP24XX_PM_WKEN2				0x00a4
+#define OMAP24XX_PM_WKST2				0x00b4
+
+#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
+#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
+#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
+#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
+
+/* Omap3 specific registers */
+#define OMAP3430ES2_PM_WKEN3				0x00f0
+#define OMAP3430ES2_PM_WKST3				0x00b8
+
 #define OMAP3430_PM_MPUGRPSEL				0x00a4
 #define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL
 
@@ -153,16 +166,6 @@
 #define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc
 
 
-/* Architecture-specific registers */
-
-#define OMAP24XX_PM_WKEN2				0x00a4
-#define OMAP24XX_PM_WKST2				0x00b4
-
-#define OMAP24XX_PRCM_IRQSTATUS_DSP			0x00f0	/* IVA mod */
-#define OMAP24XX_PRCM_IRQENABLE_DSP			0x00f4	/* IVA mod */
-#define OMAP24XX_PRCM_IRQSTATUS_IVA			0x00f8
-#define OMAP24XX_PRCM_IRQENABLE_IVA			0x00fc
-
 #ifndef __ASSEMBLER__
 
 /* Power/reset management domain register get/set */
@@ -228,7 +231,6 @@
 #define OMAP_RSTTIME1_SHIFT				0
 #define OMAP_RSTTIME1_MASK				(0xff << 0)
 
-
 /* PRM_RSTCTRL */
 /* Named RM_RSTCTRL_WKUP on the 24xx */
 /* 2420 calls RST_DPLL3 'RST_DPLL' */
diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c
new file mode 100644
index 0000000..2a30060
--- /dev/null
+++ b/arch/arm/mach-omap2/sdrc.c
@@ -0,0 +1,93 @@
+/*
+ * SMS/SDRC (SDRAM controller) common code for OMAP2/3
+ *
+ * Copyright (C) 2005, 2008 Texas Instruments Inc.
+ * Copyright (C) 2005, 2008 Nokia Corporation
+ *
+ * Tony Lindgren <tony@atomide.com>
+ * Paul Walmsley
+ * Richard Woodruff <r-woodruff2@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.
+ */
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/sram.h>
+
+#include "prm.h"
+
+#include <mach/sdrc.h>
+#include "sdrc.h"
+
+static struct omap_sdrc_params *sdrc_init_params;
+
+void __iomem *omap2_sdrc_base;
+void __iomem *omap2_sms_base;
+
+
+/**
+ * omap2_sdrc_get_params - return SDRC register values for a given clock rate
+ * @r: SDRC clock rate (in Hz)
+ *
+ * Return pre-calculated values for the SDRC_ACTIM_CTRLA,
+ * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given
+ * SDRC clock rate 'r'.  These parameters control various timing
+ * delays in the SDRAM controller that are expressed in terms of the
+ * number of SDRC clock cycles to wait; hence the clock rate
+ * dependency. Note that sdrc_init_params must be sorted rate
+ * descending.  Also assumes that both chip-selects use the same
+ * timing parameters.  Returns a struct omap_sdrc_params * upon
+ * success, or NULL upon failure.
+ */
+struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
+{
+	struct omap_sdrc_params *sp;
+
+	sp = sdrc_init_params;
+
+	while (sp->rate != r)
+		sp++;
+
+	if (!sp->rate)
+		return NULL;
+
+	return sp;
+}
+
+
+void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
+{
+	omap2_sdrc_base = omap2_globals->sdrc;
+	omap2_sms_base = omap2_globals->sms;
+}
+
+/* turn on smart idle modes for SDRAM scheduler and controller */
+void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
+{
+	u32 l;
+
+	l = sms_read_reg(SMS_SYSCONFIG);
+	l &= ~(0x3 << 3);
+	l |= (0x2 << 3);
+	sms_write_reg(l, SMS_SYSCONFIG);
+
+	l = sdrc_read_reg(SDRC_SYSCONFIG);
+	l &= ~(0x3 << 3);
+	l |= (0x2 << 3);
+	sdrc_write_reg(l, SDRC_SYSCONFIG);
+
+	sdrc_init_params = sp;
+}
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/sdrc2xxx.c
similarity index 67%
rename from arch/arm/mach-omap2/memory.c
rename to arch/arm/mach-omap2/sdrc2xxx.c
index 882c702..0afdad5 100644
--- a/arch/arm/mach-omap2/memory.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -1,13 +1,14 @@
 /*
- * linux/arch/arm/mach-omap2/memory.c
+ * linux/arch/arm/mach-omap2/sdrc2xxx.c
  *
- * Memory timing related functions for OMAP24XX
+ * SDRAM timing related functions for OMAP2xxx
  *
- * Copyright (C) 2005 Texas Instruments Inc.
- * Richard Woodruff <r-woodruff2@ti.com>
+ * Copyright (C) 2005, 2008 Texas Instruments Inc.
+ * Copyright (C) 2005, 2008 Nokia Corporation
  *
- * Copyright (C) 2005 Nokia Corporation
  * Tony Lindgren <tony@atomide.com>
+ * Paul Walmsley
+ * Richard Woodruff <r-woodruff2@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
@@ -28,27 +29,31 @@
 #include <mach/sram.h>
 
 #include "prm.h"
-
-#include "memory.h"
+#include "clock.h"
+#include <mach/sdrc.h>
 #include "sdrc.h"
 
-void __iomem *omap2_sdrc_base;
-void __iomem *omap2_sms_base;
+/* Memory timing, DLL mode flags */
+#define M_DDR		1
+#define M_LOCK_CTRL	(1 << 2)
+#define M_UNLOCK	0
+#define M_LOCK		1
+
 
 static struct memory_timings mem_timings;
 static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
 
-u32 omap2_memory_get_slow_dll_ctrl(void)
+static u32 omap2xxx_sdrc_get_slow_dll_ctrl(void)
 {
 	return mem_timings.slow_dll_ctrl;
 }
 
-u32 omap2_memory_get_fast_dll_ctrl(void)
+static u32 omap2xxx_sdrc_get_fast_dll_ctrl(void)
 {
 	return mem_timings.fast_dll_ctrl;
 }
 
-u32 omap2_memory_get_type(void)
+static u32 omap2xxx_sdrc_get_type(void)
 {
 	return mem_timings.m_type;
 }
@@ -57,7 +62,7 @@
  * Check the DLL lock state, and return tue if running in unlock mode.
  * This is needed to compensate for the shifted DLL value in unlock mode.
  */
-u32 omap2_dll_force_needed(void)
+u32 omap2xxx_sdrc_dll_is_unlocked(void)
 {
 	/* dlla and dllb are a set */
 	u32 dll_state = sdrc_read_reg(SDRC_DLLA_CTRL);
@@ -72,8 +77,10 @@
  * 'level' is the value to store to CM_CLKSEL2_PLL.CORE_CLK_SRC.
  * Practical values are CORE_CLK_SRC_DPLL (for CORE_CLK = DPLL_CLK) or
  * CORE_CLK_SRC_DPLL_X2 (for CORE_CLK = * DPLL_CLK * 2)
+ *
+ * Used by the clock framework during CORE DPLL changes
  */
-u32 omap2_reprogram_sdrc(u32 level, u32 force)
+u32 omap2xxx_sdrc_reprogram(u32 level, u32 force)
 {
 	u32 dll_ctrl, m_type;
 	u32 prev = curr_perf_level;
@@ -82,15 +89,14 @@
 	if ((curr_perf_level == level) && !force)
 		return prev;
 
-	if (level == CORE_CLK_SRC_DPLL) {
-		dll_ctrl = omap2_memory_get_slow_dll_ctrl();
-	} else if (level == CORE_CLK_SRC_DPLL_X2) {
-		dll_ctrl = omap2_memory_get_fast_dll_ctrl();
-	} else {
+	if (level == CORE_CLK_SRC_DPLL)
+		dll_ctrl = omap2xxx_sdrc_get_slow_dll_ctrl();
+	else if (level == CORE_CLK_SRC_DPLL_X2)
+		dll_ctrl = omap2xxx_sdrc_get_fast_dll_ctrl();
+	else
 		return prev;
-	}
 
-	m_type = omap2_memory_get_type();
+	m_type = omap2xxx_sdrc_get_type();
 
 	local_irq_save(flags);
 	__raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP);
@@ -101,23 +107,14 @@
 	return prev;
 }
 
-#if !defined(CONFIG_ARCH_OMAP2)
-void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
-				u32 base_cs, u32 force_unlock)
-{
-}
-void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
-				      u32 mem_type)
-{
-}
-#endif
-
-void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+/* Used by the clock framework during CORE DPLL changes */
+void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode)
 {
 	unsigned long dll_cnt;
 	u32 fast_dll = 0;
 
-	mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+	/* DDR = 1, SDR = 0 */
+	mem_timings.m_type = !((sdrc_read_reg(SDRC_MR_0) & 0x3) == 0x1);
 
 	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
 	 * In the case of 2422, its ok to use CS1 instead of CS0.
@@ -164,28 +161,3 @@
 	/* 90 degree phase for anything below 133Mhz + disable DLL filter */
 	mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
 }
-
-void __init omap2_set_globals_memory(struct omap_globals *omap2_globals)
-{
-	omap2_sdrc_base = omap2_globals->sdrc;
-	omap2_sms_base = omap2_globals->sms;
-}
-
-/* turn on smart idle modes for SDRAM scheduler and controller */
-void __init omap2_init_memory(void)
-{
-	u32 l;
-
-	if (!cpu_is_omap2420())
-		return;
-
-	l = sms_read_reg(SMS_SYSCONFIG);
-	l &= ~(0x3 << 3);
-	l |= (0x2 << 3);
-	sms_write_reg(l, SMS_SYSCONFIG);
-
-	l = sdrc_read_reg(SDRC_SYSCONFIG);
-	l &= ~(0x3 << 3);
-	l |= (0x2 << 3);
-	sdrc_write_reg(l, SDRC_SYSCONFIG);
-}
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
new file mode 100644
index 0000000..fc74e91
--- /dev/null
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -0,0 +1,187 @@
+/*
+ * linux/arch/arm/mach-omap2/usb-musb.c
+ *
+ * This file will contain the board specific details for the
+ * MENTOR USB OTG controller on OMAP3430
+ *
+ * Copyright (C) 2007-2008 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Author: Vikram Pandita
+ *
+ * Generalization by:
+ * Felipe Balbi <felipe.balbi@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.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include <linux/usb/musb.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/pm.h>
+#include <mach/mux.h>
+#include <mach/usb.h>
+
+static struct resource musb_resources[] = {
+	[0] = { /* start and end set dynamically */
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {	/* general IRQ */
+		.start	= INT_243X_HS_USB_MC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {	/* DMA IRQ */
+		.start	= INT_243X_HS_USB_DMA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static int clk_on;
+
+static int musb_set_clock(struct clk *clk, int state)
+{
+	if (state) {
+		if (clk_on > 0)
+			return -ENODEV;
+
+		clk_enable(clk);
+		clk_on = 1;
+	} else {
+		if (clk_on == 0)
+			return -ENODEV;
+
+		clk_disable(clk);
+		clk_on = 0;
+	}
+
+	return 0;
+}
+
+static struct musb_hdrc_eps_bits musb_eps[] = {
+	{	"ep1_tx", 10,	},
+	{	"ep1_rx", 10,	},
+	{	"ep2_tx", 9,	},
+	{	"ep2_rx", 9,	},
+	{	"ep3_tx", 3,	},
+	{	"ep3_rx", 3,	},
+	{	"ep4_tx", 3,	},
+	{	"ep4_rx", 3,	},
+	{	"ep5_tx", 3,	},
+	{	"ep5_rx", 3,	},
+	{	"ep6_tx", 3,	},
+	{	"ep6_rx", 3,	},
+	{	"ep7_tx", 3,	},
+	{	"ep7_rx", 3,	},
+	{	"ep8_tx", 2,	},
+	{	"ep8_rx", 2,	},
+	{	"ep9_tx", 2,	},
+	{	"ep9_rx", 2,	},
+	{	"ep10_tx", 2,	},
+	{	"ep10_rx", 2,	},
+	{	"ep11_tx", 2,	},
+	{	"ep11_rx", 2,	},
+	{	"ep12_tx", 2,	},
+	{	"ep12_rx", 2,	},
+	{	"ep13_tx", 2,	},
+	{	"ep13_rx", 2,	},
+	{	"ep14_tx", 2,	},
+	{	"ep14_rx", 2,	},
+	{	"ep15_tx", 2,	},
+	{	"ep15_rx", 2,	},
+};
+
+static struct musb_hdrc_config musb_config = {
+	.multipoint	= 1,
+	.dyn_fifo	= 1,
+	.soft_con	= 1,
+	.dma		= 1,
+	.num_eps	= 16,
+	.dma_channels	= 7,
+	.dma_req_chan	= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
+	.ram_bits	= 12,
+	.eps_bits	= musb_eps,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#ifdef CONFIG_USB_MUSB_OTG
+	.mode		= MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+	.mode		= MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+	.mode		= MUSB_PERIPHERAL,
+#endif
+	/* .clock is set dynamically */
+	.set_clock	= musb_set_clock,
+	.config		= &musb_config,
+
+	/* REVISIT charge pump on TWL4030 can supply up to
+	 * 100 mA ... but this value is board-specific, like
+	 * "mode", and should be passed to usb_musb_init().
+	 */
+	.power		= 50,			/* up to 100 mA */
+};
+
+static u64 musb_dmamask = DMA_32BIT_MASK;
+
+static struct platform_device musb_device = {
+	.name		= "musb_hdrc",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &musb_dmamask,
+		.coherent_dma_mask	= DMA_32BIT_MASK,
+		.platform_data		= &musb_plat,
+	},
+	.num_resources	= ARRAY_SIZE(musb_resources),
+	.resource	= musb_resources,
+};
+
+#ifdef CONFIG_NOP_USB_XCEIV
+static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
+
+static struct platform_device nop_xceiv_device = {
+	.name		= "nop_usb_xceiv",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &nop_xceiv_dmamask,
+		.coherent_dma_mask	= DMA_32BIT_MASK,
+		.platform_data		= NULL,
+	},
+};
+#endif
+
+void __init usb_musb_init(void)
+{
+	if (cpu_is_omap243x())
+		musb_resources[0].start = OMAP243X_HS_BASE;
+	else
+		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
+	musb_resources[0].end = musb_resources[0].start + SZ_8K - 1;
+
+	/*
+	 * REVISIT: This line can be removed once all the platforms using
+	 * musb_core.c have been converted to use use clkdev.
+	 */
+	musb_plat.clock = "ick";
+
+#ifdef CONFIG_NOP_USB_XCEIV
+	if (platform_device_register(&nop_xceiv_device) < 0) {
+		printk(KERN_ERR "Unable to register NOP-XCEIV device\n");
+		return;
+	}
+#endif
+
+	if (platform_device_register(&musb_device) < 0) {
+		printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
+		return;
+	}
+}
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index f59a8d0..2c7035d 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -71,6 +71,7 @@
 
 config MACH_TS78XX
 	bool "Technologic Systems TS-78xx"
+	select PM
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Technologic Systems TS-78xx platform.
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 0722d65..b31ca4c 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -76,7 +76,7 @@
 
 static int __init dns323_pci_init(void)
 {
-	/* The 5182 doesn't really use it's PCI bus, and initialising PCI
+	/* The 5182 doesn't really use its PCI bus, and initialising PCI
 	 * gets in the way of initialising the SATA controller.
 	 */
 	if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID)
@@ -418,7 +418,7 @@
 	orion5x_i2c_init();
 	orion5x_uart0_init();
 
-	/* The 5182 has it's SATA controller on-chip, and needs it's own little
+	/* The 5182 has its SATA controller on-chip, and needs its own little
 	 * init routine.
 	 */
 	if (dns323_dev_id() == MV88F5182_DEV_ID)
diff --git a/arch/arm/mach-orion5x/include/mach/system.h b/arch/arm/mach-orion5x/include/mach/system.h
index 08e4307..9b8db1d 100644
--- a/arch/arm/mach-orion5x/include/mach/system.h
+++ b/arch/arm/mach-orion5x/include/mach/system.h
@@ -19,7 +19,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	/*
 	 * Enable and issue soft reset
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index e0c43b8..c9bf6b8 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -186,7 +186,7 @@
 
 static void lsmini_power_off(void)
 {
-	arch_reset(0);
+	arch_reset(0, NULL);
 }
 
 
diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h
new file mode 100644
index 0000000..0f9cdf4
--- /dev/null
+++ b/arch/arm/mach-orion5x/ts78xx-fpga.h
@@ -0,0 +1,35 @@
+#define FPGAID(_magic, _rev) ((_magic << 8) + _rev)
+
+/*
+ * get yer id's from http://ts78xx.digriz.org.uk/
+ * do *not* make up your own or 'borrow' any!
+ */
+enum fpga_ids {
+	/* Technologic Systems */
+	TS7800_REV_1	= FPGAID(0x00b480, 0x01),
+	TS7800_REV_2	= FPGAID(0x00b480, 0x02),
+	TS7800_REV_3	= FPGAID(0x00b480, 0x03),
+	TS7800_REV_4	= FPGAID(0x00b480, 0x04),
+	TS7800_REV_5	= FPGAID(0x00b480, 0x05),
+
+	/* Unaffordable & Expensive */
+	UAE_DUMMY	= FPGAID(0xffffff, 0x01),
+};
+
+struct fpga_device {
+	unsigned		present:1;
+	unsigned		init:1;
+};
+
+struct fpga_devices {
+	/* Technologic Systems */
+	struct fpga_device 	ts_rtc;
+	struct fpga_device 	ts_nand;
+};
+
+struct ts78xx_fpga_data {
+	unsigned int		id;
+	int			state;
+
+	struct fpga_devices	supports;
+};
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 1368e9f..9a6b397 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -10,17 +10,20 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sysfs.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ata_platform.h>
 #include <linux/m48t86.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/orion5x.h>
 #include "common.h"
 #include "mpp.h"
+#include "ts78xx-fpga.h"
 
 /*****************************************************************************
  * TS-78xx Info
@@ -33,18 +36,11 @@
 #define TS78XX_FPGA_REGS_VIRT_BASE	0xff900000
 #define TS78XX_FPGA_REGS_SIZE		SZ_1M
 
-#define TS78XX_FPGA_REGS_SYSCON_ID	(TS78XX_FPGA_REGS_VIRT_BASE | 0x000)
-#define TS78XX_FPGA_REGS_SYSCON_LCDI	(TS78XX_FPGA_REGS_VIRT_BASE | 0x004)
-#define TS78XX_FPGA_REGS_SYSCON_LCDO	(TS78XX_FPGA_REGS_VIRT_BASE | 0x008)
-
-#define TS78XX_FPGA_REGS_RTC_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE | 0x808)
-#define TS78XX_FPGA_REGS_RTC_DATA	(TS78XX_FPGA_REGS_VIRT_BASE | 0x80c)
-
-/*
- * 512kB NOR flash Device
- */
-#define TS78XX_NOR_BOOT_BASE		0xff800000
-#define TS78XX_NOR_BOOT_SIZE		SZ_512K
+static struct ts78xx_fpga_data ts78xx_fpga = {
+	.id		= 0,
+	.state		= 1,
+/*	.supports	= ... - populated by ts78xx_fpga_supports() */
+};
 
 /*****************************************************************************
  * I/O Address Mapping
@@ -65,41 +61,6 @@
 }
 
 /*****************************************************************************
- * 512kB NOR Boot Flash - the chip is a M25P40
- ****************************************************************************/
-static struct mtd_partition ts78xx_nor_boot_flash_resources[] = {
-	{
-		.name		= "ts-bootrom",
-		.offset		= 0,
-		/* only the first 256kB is used */
-		.size		= SZ_256K,
-		.mask_flags	= MTD_WRITEABLE,
-	},
-};
-
-static struct physmap_flash_data ts78xx_nor_boot_flash_data = {
-	.width		= 1,
-	.parts		= ts78xx_nor_boot_flash_resources,
-	.nr_parts	= ARRAY_SIZE(ts78xx_nor_boot_flash_resources),
-};
-
-static struct resource ts78xx_nor_boot_flash_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= TS78XX_NOR_BOOT_BASE,
-	.end		= TS78XX_NOR_BOOT_BASE + TS78XX_NOR_BOOT_SIZE - 1,
-};
-
-static struct platform_device ts78xx_nor_boot_flash = {
-	.name		= "physmap-flash",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &ts78xx_nor_boot_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &ts78xx_nor_boot_flash_resource,
-};
-
-/*****************************************************************************
  * Ethernet
  ****************************************************************************/
 static struct mv643xx_eth_platform_data ts78xx_eth_data = {
@@ -107,31 +68,40 @@
 };
 
 /*****************************************************************************
- * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
+ * SATA
  ****************************************************************************/
-#ifdef CONFIG_RTC_DRV_M48T86
-static unsigned char ts78xx_rtc_readbyte(unsigned long addr)
-{
-	writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
-	return readb(TS78XX_FPGA_REGS_RTC_DATA);
-}
-
-static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr)
-{
-	writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
-	writeb(value, TS78XX_FPGA_REGS_RTC_DATA);
-}
-
-static struct m48t86_ops ts78xx_rtc_ops = {
-	.readbyte	= ts78xx_rtc_readbyte,
-	.writebyte	= ts78xx_rtc_writebyte,
+static struct mv_sata_platform_data ts78xx_sata_data = {
+	.n_ports	= 2,
 };
 
-static struct platform_device ts78xx_rtc_device = {
+/*****************************************************************************
+ * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
+ ****************************************************************************/
+#define TS_RTC_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE | 0x808)
+#define TS_RTC_DATA	(TS78XX_FPGA_REGS_VIRT_BASE | 0x80c)
+
+static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr)
+{
+	writeb(addr, TS_RTC_CTRL);
+	return readb(TS_RTC_DATA);
+}
+
+static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr)
+{
+	writeb(addr, TS_RTC_CTRL);
+	writeb(value, TS_RTC_DATA);
+}
+
+static struct m48t86_ops ts78xx_ts_rtc_ops = {
+	.readbyte	= ts78xx_ts_rtc_readbyte,
+	.writebyte	= ts78xx_ts_rtc_writebyte,
+};
+
+static struct platform_device ts78xx_ts_rtc_device = {
 	.name		= "rtc-m48t86",
 	.id		= -1,
 	.dev		= {
-		.platform_data	= &ts78xx_rtc_ops,
+		.platform_data	= &ts78xx_ts_rtc_ops,
 	},
 	.num_resources	= 0,
 };
@@ -146,58 +116,313 @@
  * TODO: track down a guinea pig without an RTC to see if we can work out a
  * 		better RTC detection routine
  */
-static int __init ts78xx_rtc_init(void)
+static int ts78xx_ts_rtc_load(void)
 {
+	int rc;
 	unsigned char tmp_rtc0, tmp_rtc1;
 
-	tmp_rtc0 = ts78xx_rtc_readbyte(126);
-	tmp_rtc1 = ts78xx_rtc_readbyte(127);
+	tmp_rtc0 = ts78xx_ts_rtc_readbyte(126);
+	tmp_rtc1 = ts78xx_ts_rtc_readbyte(127);
 
-	ts78xx_rtc_writebyte(0x00, 126);
-	ts78xx_rtc_writebyte(0x55, 127);
-	if (ts78xx_rtc_readbyte(127) == 0x55) {
-		ts78xx_rtc_writebyte(0xaa, 127);
-		if (ts78xx_rtc_readbyte(127) == 0xaa
-				&& ts78xx_rtc_readbyte(126) == 0x00) {
-			ts78xx_rtc_writebyte(tmp_rtc0, 126);
-			ts78xx_rtc_writebyte(tmp_rtc1, 127);
-			platform_device_register(&ts78xx_rtc_device);
-			return 1;
+	ts78xx_ts_rtc_writebyte(0x00, 126);
+	ts78xx_ts_rtc_writebyte(0x55, 127);
+	if (ts78xx_ts_rtc_readbyte(127) == 0x55) {
+		ts78xx_ts_rtc_writebyte(0xaa, 127);
+		if (ts78xx_ts_rtc_readbyte(127) == 0xaa
+				&& ts78xx_ts_rtc_readbyte(126) == 0x00) {
+			ts78xx_ts_rtc_writebyte(tmp_rtc0, 126);
+			ts78xx_ts_rtc_writebyte(tmp_rtc1, 127);
+
+			if (ts78xx_fpga.supports.ts_rtc.init == 0) {
+				rc = platform_device_register(&ts78xx_ts_rtc_device);
+				if (!rc)
+					ts78xx_fpga.supports.ts_rtc.init = 1;
+			} else
+				rc = platform_device_add(&ts78xx_ts_rtc_device);
+
+			return rc;
 		}
 	}
 
+	return -ENODEV;
+};
+
+static void ts78xx_ts_rtc_unload(void)
+{
+	platform_device_del(&ts78xx_ts_rtc_device);
+}
+
+/*****************************************************************************
+ * NAND Flash
+ ****************************************************************************/
+#define TS_NAND_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE | 0x800)	/* VIRT */
+#define TS_NAND_DATA	(TS78XX_FPGA_REGS_PHYS_BASE | 0x804)	/* PHYS */
+
+/*
+ * hardware specific access to control-lines
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 1
+ * NAND_ALE: bit 2 -> bit 0
+ */
+static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+			unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned char bits;
+
+		bits = (ctrl & NAND_NCE) << 2;
+		bits |= ctrl & NAND_CLE;
+		bits |= (ctrl & NAND_ALE) >> 2;
+
+		writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W);
+}
+
+static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
+{
+	return readb(TS_NAND_CTRL) & 0x20;
+}
+
+const char *ts_nand_part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ts78xx_ts_nand_parts[] = {
+	{
+		.name		= "mbr",
+		.offset		= 0,
+		.size		= SZ_128K,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_4M,
+	}, {
+		.name		= "initrd",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_4M,
+	}, {
+		.name		= "rootfs",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct platform_nand_data ts78xx_ts_nand_data = {
+	.chip	= {
+		.part_probe_types	= ts_nand_part_probes,
+		.partitions		= ts78xx_ts_nand_parts,
+		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
+		.chip_delay		= 15,
+		.options		= NAND_USE_FLASH_BBT,
+	},
+	.ctrl	= {
+		/*
+		 * The HW ECC offloading functions, used to give about a 9%
+		 * performance increase for 'dd if=/dev/mtdblockX' and 5% for
+		 * nanddump.  This all however was changed by git commit
+		 * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is
+		 * no performance advantage to be had so we no longer bother
+		 */
+		.cmd_ctrl		= ts78xx_ts_nand_cmd_ctrl,
+		.dev_ready		= ts78xx_ts_nand_dev_ready,
+	},
+};
+
+static struct resource ts78xx_ts_nand_resources = {
+	.start		= TS_NAND_DATA,
+	.end		= TS_NAND_DATA + 4,
+	.flags		= IORESOURCE_IO,
+};
+
+static struct platform_device ts78xx_ts_nand_device = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &ts78xx_ts_nand_data,
+	},
+	.resource	= &ts78xx_ts_nand_resources,
+	.num_resources	= 1,
+};
+
+static int ts78xx_ts_nand_load(void)
+{
+	int rc;
+
+	if (ts78xx_fpga.supports.ts_nand.init == 0) {
+		rc = platform_device_register(&ts78xx_ts_nand_device);
+		if (!rc)
+			ts78xx_fpga.supports.ts_nand.init = 1;
+	} else
+		rc = platform_device_add(&ts78xx_ts_nand_device);
+
+	return rc;
+};
+
+static void ts78xx_ts_nand_unload(void)
+{
+	platform_device_del(&ts78xx_ts_nand_device);
+}
+
+/*****************************************************************************
+ * FPGA 'hotplug' support code
+ ****************************************************************************/
+static void ts78xx_fpga_devices_zero_init(void)
+{
+	ts78xx_fpga.supports.ts_rtc.init = 0;
+	ts78xx_fpga.supports.ts_nand.init = 0;
+}
+
+static void ts78xx_fpga_supports(void)
+{
+	/* TODO: put this 'table' into ts78xx-fpga.h */
+	switch (ts78xx_fpga.id) {
+	case TS7800_REV_1:
+	case TS7800_REV_2:
+	case TS7800_REV_3:
+	case TS7800_REV_4:
+	case TS7800_REV_5:
+		ts78xx_fpga.supports.ts_rtc.present = 1;
+		ts78xx_fpga.supports.ts_nand.present = 1;
+		break;
+	default:
+		ts78xx_fpga.supports.ts_rtc.present = 0;
+		ts78xx_fpga.supports.ts_nand.present = 0;
+	}
+}
+
+static int ts78xx_fpga_load_devices(void)
+{
+	int tmp, ret = 0;
+
+	if (ts78xx_fpga.supports.ts_rtc.present == 1) {
+		tmp = ts78xx_ts_rtc_load();
+		if (tmp) {
+			printk(KERN_INFO "TS-78xx: RTC not registered\n");
+			ts78xx_fpga.supports.ts_rtc.present = 0;
+		}
+		ret |= tmp;
+	}
+	if (ts78xx_fpga.supports.ts_nand.present == 1) {
+		tmp = ts78xx_ts_nand_load();
+		if (tmp) {
+			printk(KERN_INFO "TS-78xx: NAND not registered\n");
+			ts78xx_fpga.supports.ts_nand.present = 0;
+		}
+		ret |= tmp;
+	}
+
+	return ret;
+}
+
+static int ts78xx_fpga_unload_devices(void)
+{
+	int ret = 0;
+
+	if (ts78xx_fpga.supports.ts_rtc.present == 1)
+		ts78xx_ts_rtc_unload();
+	if (ts78xx_fpga.supports.ts_nand.present == 1)
+		ts78xx_ts_nand_unload();
+
+	return ret;
+}
+
+static int ts78xx_fpga_load(void)
+{
+	ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
+
+	printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n",
+			(ts78xx_fpga.id >> 8) & 0xffffff,
+			ts78xx_fpga.id & 0xff);
+
+	ts78xx_fpga_supports();
+
+	if (ts78xx_fpga_load_devices()) {
+		ts78xx_fpga.state = -1;
+		return -EBUSY;
+	}
+
 	return 0;
 };
-#else
-static int __init ts78xx_rtc_init(void)
+
+static int ts78xx_fpga_unload(void)
 {
+	unsigned int fpga_id;
+
+	fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
+
+	/*
+	 * There does not seem to be a feasible way to block access to the GPIO
+	 * pins from userspace (/dev/mem).  This if clause should hopefully warn
+	 * those foolish enough not to follow 'policy' :)
+	 *
+	 * UrJTAG SVN since r1381 can be used to reprogram the FPGA
+	 */
+	if (ts78xx_fpga.id != fpga_id) {
+		printk(KERN_ERR	"TS-78xx FPGA: magic/rev mismatch\n"
+			"TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n",
+			(ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff,
+			(fpga_id >> 8) & 0xffffff, fpga_id & 0xff);
+		ts78xx_fpga.state = -1;
+		return -EBUSY;
+	}
+
+	if (ts78xx_fpga_unload_devices()) {
+		ts78xx_fpga.state = -1;
+		return -EBUSY;
+	}
+
 	return 0;
-}
-#endif
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-static struct mv_sata_platform_data ts78xx_sata_data = {
-	.n_ports	= 2,
 };
 
-/*****************************************************************************
- * print some information regarding the board
- ****************************************************************************/
-static void __init ts78xx_print_board_id(void)
+static ssize_t ts78xx_fpga_show(struct kobject *kobj,
+			struct kobj_attribute *attr, char *buf)
 {
-	unsigned int board_info;
+	if (ts78xx_fpga.state < 0)
+		return sprintf(buf, "borked\n");
 
-	board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID);
-	printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ",
-				board_info & 0xff,
-				(board_info >> 8) & 0xffffff);
-	board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI);
-	printk("JP1=%d, JP2=%d\n",
-				(board_info >> 30) & 0x1,
-				(board_info >> 31) & 0x1);
-};
+	return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline");
+}
+
+static ssize_t ts78xx_fpga_store(struct kobject *kobj,
+			struct kobj_attribute *attr, const char *buf, size_t n)
+{
+	int value, ret;
+
+	if (ts78xx_fpga.state < 0) {
+		printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n");
+		return -EBUSY;
+	}
+
+	if (strncmp(buf, "online", sizeof("online") - 1) == 0)
+		value = 1;
+	else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
+		value = 0;
+	else {
+		printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n");
+		return -EINVAL;
+	}
+
+	if (ts78xx_fpga.state == value)
+		return n;
+
+	ret = (ts78xx_fpga.state == 0)
+		? ts78xx_fpga_load()
+		: ts78xx_fpga_unload();
+
+	if (!(ret < 0))
+		ts78xx_fpga.state = value;
+
+	return n;
+}
+
+static struct kobj_attribute ts78xx_fpga_attr =
+	__ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store);
 
 /*****************************************************************************
  * General Setup
@@ -223,20 +448,6 @@
 	{ 17, MPP_UART },
 	{ 18, MPP_UART },
 	{ 19, MPP_UART },
-	{ -1 },
-};
-
-static void __init ts78xx_init(void)
-{
-	/*
-	 * Setup basic Orion functions. Need to be called early.
-	 */
-	orion5x_init();
-
-	ts78xx_print_board_id();
-
-	orion5x_mpp_conf(ts78xx_mpp_modes);
-
 	/*
 	 * MPP[20] PCI Clock Out 1
 	 * MPP[21] PCI Clock Out 0
@@ -245,6 +456,19 @@
 	 * MPP[24] Unused
 	 * MPP[25] Unused
 	 */
+	{ -1 },
+};
+
+static void __init ts78xx_init(void)
+{
+	int ret;
+
+	/*
+	 * Setup basic Orion functions. Need to be called early.
+	 */
+	orion5x_init();
+
+	orion5x_mpp_conf(ts78xx_mpp_modes);
 
 	/*
 	 * Configure peripherals.
@@ -257,12 +481,12 @@
 	orion5x_uart1_init();
 	orion5x_xor_init();
 
-	orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE,
-				   TS78XX_NOR_BOOT_SIZE);
-	platform_device_register(&ts78xx_nor_boot_flash);
-
-	if (!ts78xx_rtc_init())
-		printk(KERN_INFO "TS-78xx RTC not detected or enabled\n");
+	/* FPGA init */
+	ts78xx_fpga_devices_zero_init();
+	ret = ts78xx_fpga_load();
+	ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr);
+	if (ret)
+		printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
 }
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
diff --git a/arch/arm/mach-pnx4008/include/mach/system.h b/arch/arm/mach-pnx4008/include/mach/system.h
index e12e7ab..5dda2bb 100644
--- a/arch/arm/mach-pnx4008/include/mach/system.h
+++ b/arch/arm/mach-pnx4008/include/mach/system.h
@@ -30,7 +30,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	cpu_reset(0);
 }
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 8eea730..96a2006 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -40,6 +40,9 @@
 config GUMSTIX_AM200EPD
 	bool "Enable AM200EPD board support"
 
+config GUMSTIX_AM300EPD
+	bool "Enable AM300EPD board support"
+
 endchoice
 
 config MACH_INTELMOTE2
@@ -254,10 +257,24 @@
 	bool "CompuLab EM-x270 platform"
 	select PXA27x
 
-config MACH_COLIBRI
-	bool "Toradex Colibri PX27x"
+config MACH_EXEDA
+	bool "CompuLab eXeda platform"
 	select PXA27x
 
+config MACH_COLIBRI
+	bool "Toradex Colibri PXA270"
+	select PXA27x
+
+config MACH_COLIBRI300
+	bool "Toradex Colibri PXA300/310"
+	select PXA3xx
+	select CPU_PXA300
+
+config MACH_COLIBRI320
+	bool "Toradex Colibri PXA320"
+	select PXA3xx
+	select CPU_PXA320
+
 config MACH_ZYLONITE
 	bool "PXA3xx Development Platform (aka Zylonite)"
 	select PXA3xx
@@ -295,8 +312,15 @@
 	bool "Enable HTC Magician Support"
 	select PXA27x
 	select IWMMXT
+	select PXA_SSP
+	select HAVE_PWM
 	select PXA_HAVE_BOARD_IRQS
 
+config MACH_HIMALAYA
+	bool "HTC Himalaya Support"
+	select CPU_PXA26x
+	select FB_W100
+
 config MACH_MIOA701
 	bool "Mitac Mio A701 Support"
 	select PXA27x
@@ -319,6 +343,16 @@
 	bool "PXA based Palm PDAs"
 	select HAVE_PWM
 
+config MACH_PALMT5
+	bool "Palm Tungsten|T5"
+	default y
+	depends on ARCH_PXA_PALM
+	select PXA27x
+	select IWMMXT
+	help
+	  Say Y here if you intend to run this kernel on a Palm Tungsten|T5
+	  handheld computer.
+
 config MACH_PALMTX
 	bool "Palm T|X"
 	default y
@@ -339,6 +373,16 @@
 	  Say Y here if you intend to run this kernel on Palm Zire 72
 	  handheld computer.
 
+config MACH_PALMLD
+	bool "Palm LifeDrive"
+	default y
+	depends on ARCH_PXA_PALM
+	select PXA27x
+	select IWMMXT
+	help
+	  Say Y here if you intend to run this kernel on a Palm LifeDrive
+	  handheld computer.
+
 config MACH_PCM990_BASEBOARD
 	bool "PHYTEC PCM-990 development board"
 	select HAVE_PWM
@@ -359,6 +403,18 @@
 
 endchoice
 
+config MACH_CSB726
+	bool "Enable Cogent CSB726 System On a Module"
+	select PXA27x
+	select IWMMXT
+	help
+	  Say Y here if you intend to run this kernel on a Cogent
+	  CSB726 System On Module.
+
+config CSB726_CSB701
+	bool "Enable supprot for CSB701 baseboard"
+	depends on MACH_CSB726
+
 config PXA_EZX
 	bool "Motorola EZX Platform"
 	select PXA27x
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 7b28bb5..c80e1ba 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,8 +3,8 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y				+= clock.o devices.o generic.o irq.o dma.o \
-				   time.o gpio.o reset.o
+obj-y				+= clock.o devices.o generic.o irq.o \
+				   time.o reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 
 ifeq ($(CONFIG_CPU_FREQ),y)
@@ -28,13 +28,16 @@
 # Specific board support
 obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
 obj-$(CONFIG_GUMSTIX_AM200EPD)	+= am200epd.o
+obj-$(CONFIG_GUMSTIX_AM300EPD)	+= am300epd.o
 obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
 obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
 obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
 obj-$(CONFIG_MACH_MP900C)	+= mp900.o
 obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
 obj-$(CONFIG_MACH_TRIZEPS4)	+= trizeps4.o
-obj-$(CONFIG_MACH_COLIBRI)	+= colibri.o
+obj-$(CONFIG_MACH_COLIBRI)	+= colibri-pxa270.o
+obj-$(CONFIG_MACH_COLIBRI300)	+= colibri-pxa3xx.o colibri-pxa300.o
+obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o
 obj-$(CONFIG_MACH_H5000)	+= h5000.o
 obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o sharpsl_pm.o corgi_pm.o
 obj-$(CONFIG_PXA_SHARP_Cxx00)	+= spitz.o sharpsl_pm.o spitz_pm.o
@@ -45,6 +48,7 @@
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
 obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
+obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
 obj-$(CONFIG_MACH_MIOA701)	+= mioa701.o mioa701_bootresume.o
 obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o
 obj-$(CONFIG_MACH_E330)		+= e330.o
@@ -53,7 +57,9 @@
 obj-$(CONFIG_MACH_E750)		+= e750.o
 obj-$(CONFIG_MACH_E400)		+= e400.o
 obj-$(CONFIG_MACH_E800)		+= e800.o
+obj-$(CONFIG_MACH_PALMT5)	+= palmt5.o
 obj-$(CONFIG_MACH_PALMTX)	+= palmtx.o
+obj-$(CONFIG_MACH_PALMLD)	+= palmld.o
 obj-$(CONFIG_MACH_PALMZ72)	+= palmz72.o
 obj-$(CONFIG_ARCH_VIPER)	+= viper.o
 
@@ -71,6 +77,8 @@
 obj-$(CONFIG_PXA_EZX)           += ezx.o
 
 obj-$(CONFIG_MACH_INTELMOTE2)   += imote2.o
+obj-$(CONFIG_MACH_CSB726)	+= csb726.o
+obj-$(CONFIG_CSB726_CSB701)	+= csb701.o
 
 # Support for blinky lights
 led-y := leds.o
diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
index 77ee80e..3499fad 100644
--- a/arch/arm/mach-pxa/am200epd.c
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -30,8 +30,8 @@
 #include <linux/irq.h>
 #include <linux/gpio.h>
 
+#include <mach/pxa25x.h>
 #include <mach/gumstix.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/pxafb.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
new file mode 100644
index 0000000..4bd10a1
--- /dev/null
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -0,0 +1,295 @@
+/*
+ * am300epd.c -- Platform device for AM300 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.
+ *
+ * This work was made possible by help and equipment support from E-Ink
+ * Corporation. http://support.eink.com/community
+ *
+ * This driver is written to be used with the Broadsheet display controller.
+ * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
+ * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
+ *
+ */
+
+#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/irq.h>
+#include <linux/gpio.h>
+
+#include <mach/gumstix.h>
+#include <mach/mfp-pxa25x.h>
+#include <mach/pxafb.h>
+
+#include "generic.h"
+
+#include <video/broadsheetfb.h>
+
+static unsigned int panel_type = 6;
+static struct platform_device *am300_device;
+static struct broadsheet_board am300_board;
+
+static unsigned long am300_pin_config[] __initdata = {
+	GPIO16_GPIO,
+	GPIO17_GPIO,
+	GPIO32_GPIO,
+	GPIO48_GPIO,
+	GPIO49_GPIO,
+	GPIO51_GPIO,
+	GPIO74_GPIO,
+	GPIO75_GPIO,
+	GPIO76_GPIO,
+	GPIO77_GPIO,
+
+	/* this is the 16-bit hdb bus 58-73 */
+	GPIO58_GPIO,
+	GPIO59_GPIO,
+	GPIO60_GPIO,
+	GPIO61_GPIO,
+
+	GPIO62_GPIO,
+	GPIO63_GPIO,
+	GPIO64_GPIO,
+	GPIO65_GPIO,
+
+	GPIO66_GPIO,
+	GPIO67_GPIO,
+	GPIO68_GPIO,
+	GPIO69_GPIO,
+
+	GPIO70_GPIO,
+	GPIO71_GPIO,
+	GPIO72_GPIO,
+	GPIO73_GPIO,
+};
+
+/* register offsets for gpio control */
+#define PWR_GPIO_PIN	16
+#define CFG_GPIO_PIN	17
+#define RDY_GPIO_PIN	32
+#define DC_GPIO_PIN	48
+#define RST_GPIO_PIN	49
+#define LED_GPIO_PIN	51
+#define RD_GPIO_PIN	74
+#define WR_GPIO_PIN	75
+#define CS_GPIO_PIN	76
+#define IRQ_GPIO_PIN	77
+
+/* hdb bus */
+#define DB0_GPIO_PIN	58
+#define DB15_GPIO_PIN	73
+
+static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
+			RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
+			IRQ_GPIO_PIN, LED_GPIO_PIN };
+static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
+				"CS", "IRQ", "LED" };
+
+static int am300_wait_event(struct broadsheetfb_par *par)
+{
+	/* todo: improve err recovery */
+	wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN));
+	return 0;
+}
+
+static int am300_init_gpio_regs(struct broadsheetfb_par *par)
+{
+	int i;
+	int err;
+	char dbname[8];
+
+	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
+		err = gpio_request(gpios[i], gpio_names[i]);
+		if (err) {
+			dev_err(&am300_device->dev, "failed requesting "
+				"gpio %s, err=%d\n", gpio_names[i], err);
+			goto err_req_gpio;
+		}
+	}
+
+	/* we also need to take care of the hdb bus */
+	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
+		sprintf(dbname, "DB%d", i);
+		err = gpio_request(i, dbname);
+		if (err) {
+			dev_err(&am300_device->dev, "failed requesting "
+				"gpio %d, err=%d\n", i, err);
+			while (i >= DB0_GPIO_PIN)
+				gpio_free(i--);
+			i = ARRAY_SIZE(gpios) - 1;
+			goto err_req_gpio;
+		}
+	}
+
+	/* setup the outputs and init values */
+	gpio_direction_output(PWR_GPIO_PIN, 0);
+	gpio_direction_output(CFG_GPIO_PIN, 1);
+	gpio_direction_output(DC_GPIO_PIN, 0);
+	gpio_direction_output(RD_GPIO_PIN, 1);
+	gpio_direction_output(WR_GPIO_PIN, 1);
+	gpio_direction_output(CS_GPIO_PIN, 1);
+	gpio_direction_output(RST_GPIO_PIN, 0);
+
+	/* setup the inputs */
+	gpio_direction_input(RDY_GPIO_PIN);
+	gpio_direction_input(IRQ_GPIO_PIN);
+
+	/* start the hdb bus as an input */
+	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+		gpio_direction_output(i, 0);
+
+	/* go into command mode */
+	gpio_set_value(CFG_GPIO_PIN, 1);
+	gpio_set_value(RST_GPIO_PIN, 0);
+	msleep(10);
+	gpio_set_value(RST_GPIO_PIN, 1);
+	msleep(10);
+	am300_wait_event(par);
+
+	return 0;
+
+err_req_gpio:
+	while (i > 0)
+		gpio_free(gpios[i--]);
+
+	return err;
+}
+
+static int am300_init_board(struct broadsheetfb_par *par)
+{
+	return am300_init_gpio_regs(par);
+}
+
+static void am300_cleanup(struct broadsheetfb_par *par)
+{
+	int i;
+
+	free_irq(IRQ_GPIO(RDY_GPIO_PIN), par);
+
+	for (i = 0; i < ARRAY_SIZE(gpios); i++)
+		gpio_free(gpios[i]);
+
+	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
+		gpio_free(i);
+
+}
+
+static u16 am300_get_hdb(struct broadsheetfb_par *par)
+{
+	u16 res = 0;
+	int i;
+
+	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+		res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;
+
+	return res;
+}
+
+static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
+{
+	int i;
+
+	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
+		gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+}
+
+
+static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
+				u8 state)
+{
+	switch (bit) {
+	case BS_CS:
+		gpio_set_value(CS_GPIO_PIN, state);
+		break;
+	case BS_DC:
+		gpio_set_value(DC_GPIO_PIN, state);
+		break;
+	case BS_WR:
+		gpio_set_value(WR_GPIO_PIN, state);
+		break;
+	}
+}
+
+static int am300_get_panel_type(void)
+{
+	return panel_type;
+}
+
+static irqreturn_t am300_handle_irq(int irq, void *dev_id)
+{
+	struct broadsheetfb_par *par = dev_id;
+
+	wake_up(&par->waitq);
+	return IRQ_HANDLED;
+}
+
+static int am300_setup_irq(struct fb_info *info)
+{
+	int ret;
+	struct broadsheetfb_par *par = info->par;
+
+	ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am300_handle_irq,
+				IRQF_DISABLED|IRQF_TRIGGER_RISING,
+				"AM300", par);
+	if (ret)
+		dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);
+
+	return ret;
+}
+
+static struct broadsheet_board am300_board = {
+	.owner			= THIS_MODULE,
+	.init			= am300_init_board,
+	.cleanup		= am300_cleanup,
+	.set_hdb		= am300_set_hdb,
+	.get_hdb		= am300_get_hdb,
+	.set_ctl		= am300_set_ctl,
+	.wait_for_rdy		= am300_wait_event,
+	.get_panel_type		= am300_get_panel_type,
+	.setup_irq		= am300_setup_irq,
+};
+
+int __init am300_init(void)
+{
+	int ret;
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));
+
+	/* request our platform independent driver */
+	request_module("broadsheetfb");
+
+	am300_device = platform_device_alloc("broadsheetfb", -1);
+	if (!am300_device)
+		return -ENOMEM;
+
+	/* the am300_board that will be seen by broadsheetfb is a copy */
+	platform_device_add_data(am300_device, &am300_board,
+					sizeof(am300_board));
+
+	ret = platform_device_add(am300_device);
+
+	if (ret) {
+		platform_device_put(am300_device);
+		return ret;
+	}
+
+	return 0;
+}
+
+module_param(panel_type, uint, 0);
+MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+
+MODULE_DESCRIPTION("board driver for am300 epd kit");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 40b7740..db52d2c 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -87,7 +87,7 @@
 		clkdev_add(&clks[i]);
 }
 
-int clk_add_alias(char *alias, struct device *alias_dev, char *id,
+int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
 	struct device *dev)
 {
 	struct clk *r = clk_get(dev, id);
@@ -96,7 +96,7 @@
 	if (!r)
 		return -ENODEV;
 
-	l = clkdev_alloc(r, alias, alias_dev ? dev_name(alias_dev) : NULL);
+	l = clkdev_alloc(r, alias, alias_dev_name);
 	clk_put(r);
 	if (!l)
 		return -ENODEV;
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 4e9c613..5599bce 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -69,6 +69,6 @@
 #endif
 
 void clks_register(struct clk_lookup *clks, size_t num);
-int clk_add_alias(char *alias, struct device *alias_dev, char *id,
+int clk_add_alias(const char *alias, const char *alias_name, char *id,
 	struct device *dev);
 
diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index 83a4cdf..253fd76 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -22,10 +22,8 @@
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/pxa2xx_spi.h>
-#include <mach/bitfield.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index df83b97..34576ba 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -17,7 +17,7 @@
 #include <linux/rtc-v3020.h>
 #include <video/mbxfb.h>
 
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 3156b25..7873fa3 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 
 #include <asm/mach/pci.h>
-#include <mach/pxa-regs.h>
 #include <asm/mach-types.h>
 
 #include <asm/hardware/it8152.h>
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index d99fd9e..117b5435f 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -22,8 +22,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
-#include <mach/pxa-regs.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 
@@ -96,7 +94,7 @@
 };
 
 static struct dm9000_plat_data cmx270_dm9000_platdata = {
-	.flags		= DM9000_PLATF_32BITONLY,
+	.flags		= DM9000_PLATF_32BITONLY | DM9000_PLATF_NO_EEPROM,
 };
 
 static struct platform_device cmx2xx_dm9000_device = {
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index ff0c577..a9f48b1 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -28,9 +28,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/mfp-pxa300.h>
-
-#include <mach/hardware.h>
+#include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
@@ -162,7 +160,7 @@
 };
 
 static struct dm9000_plat_data cm_x300_dm9000_platdata = {
-	.flags		= DM9000_PLATF_16BITONLY,
+	.flags		= DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
 };
 
 static struct platform_device dm9000_device = {
diff --git a/arch/arm/mach-pxa/colibri.c b/arch/arm/mach-pxa/colibri-pxa270.c
similarity index 67%
rename from arch/arm/mach-pxa/colibri.c
rename to arch/arm/mach-pxa/colibri-pxa270.c
index e847362..01bcfaa 100644
--- a/arch/arm/mach-pxa/colibri.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -1,7 +1,7 @@
 /*
- *  linux/arch/arm/mach-pxa/colibri.c
+ *  linux/arch/arm/mach-pxa/colibri-pxa270.c
  *
- *  Support for Toradex PXA27x based Colibri module
+ *  Support for Toradex PXA270 based Colibri module
  *  Daniel Mack <daniel@caiaq.de>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/gpio.h>
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -28,20 +29,23 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
-#include <mach/pxa-regs.h>
-#include <mach/mfp-pxa27x.h>
+
+#include <mach/pxa27x.h>
 #include <mach/colibri.h>
 
 #include "generic.h"
 #include "devices.h"
 
-static unsigned long colibri_pin_config[] __initdata = {
+/*
+ * GPIO configuration
+ */
+static mfp_cfg_t colibri_pxa270_pin_config[] __initdata = {
 	GPIO78_nCS_2,	/* Ethernet CS */
 	GPIO114_GPIO,	/* Ethernet IRQ */
 };
 
 /*
- * Flash
+ * NOR flash
  */
 static struct mtd_partition colibri_partitions[] = {
 	{
@@ -70,39 +74,40 @@
 	}
 };
 
-static struct resource flash_resource = {
+static struct resource colibri_pxa270_flash_resource = {
 	.start	= PXA_CS0_PHYS,
 	.end	= PXA_CS0_PHYS + SZ_32M - 1,
 	.flags	= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
+static struct platform_device colibri_pxa270_flash_device = {
 	.name	= "physmap-flash",
 	.id	= 0,
 	.dev 	= {
 		.platform_data = colibri_flash_data,
 	},
-	.resource = &flash_resource,
+	.resource = &colibri_pxa270_flash_resource,
 	.num_resources = 1,
 };
 
 /*
  * DM9000 Ethernet
  */
+#if defined(CONFIG_DM9000)
 static struct resource dm9000_resources[] = {
 	[0] = {
-		.start	= COLIBRI_ETH_PHYS,
-		.end	= COLIBRI_ETH_PHYS + 3,
+		.start	= COLIBRI_PXA270_ETH_PHYS,
+		.end	= COLIBRI_PXA270_ETH_PHYS + 3,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= COLIBRI_ETH_PHYS + 4,
-		.end	= COLIBRI_ETH_PHYS + 4 + 500,
+		.start	= COLIBRI_PXA270_ETH_PHYS + 4,
+		.end	= COLIBRI_PXA270_ETH_PHYS + 4 + 500,
 		.flags	= IORESOURCE_MEM,
 	},
 	[2] = {
-		.start	= COLIBRI_ETH_IRQ,
-		.end	= COLIBRI_ETH_IRQ,
+		.start	= COLIBRI_PXA270_ETH_IRQ,
+		.end	= COLIBRI_PXA270_ETH_IRQ,
 		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
 	},
 };
@@ -113,25 +118,28 @@
 	.num_resources	= ARRAY_SIZE(dm9000_resources),
 	.resource	= dm9000_resources,
 };
+#endif /* CONFIG_DM9000 */
 
-static struct platform_device *colibri_devices[] __initdata = {
-	&flash_device,
+static struct platform_device *colibri_pxa270_devices[] __initdata = {
+	&colibri_pxa270_flash_device,
+#if defined(CONFIG_DM9000)
 	&dm9000_device,
+#endif
 };
 
-static void __init colibri_init(void)
+static void __init colibri_pxa270_init(void)
 {
-	pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pin_config));
-
-	platform_add_devices(colibri_devices, ARRAY_SIZE(colibri_devices));
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_pin_config));
+	platform_add_devices(ARRAY_AND_SIZE(colibri_pxa270_devices));
 }
 
-MACHINE_START(COLIBRI, "Toradex Colibri PXA27x")
+MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
-	.init_machine	= colibri_init,
+	.init_machine	= colibri_pxa270_init,
 	.map_io		= pxa_map_io,
 	.init_irq	= pxa27x_init_irq,
 	.timer		= &pxa_timer,
 MACHINE_END
+
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
new file mode 100644
index 0000000..10c2eaf
--- /dev/null
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -0,0 +1,190 @@
+/*
+ *  arch/arm/mach-pxa/colibri-pxa300.c
+ *
+ *  Support for Toradex PXA300/310 based Colibri module
+ *
+ *  Daniel Mack <daniel@caiaq.de>
+ *  Matthias Meier <matthias.j.meier@gmx.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/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <net/ax88796.h>
+
+#include <asm/mach-types.h>
+#include <asm/sizes.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+
+#include <mach/pxa300.h>
+#include <mach/colibri.h>
+#include <mach/ohci.h>
+#include <mach/pxafb.h>
+
+#include "generic.h"
+#include "devices.h"
+
+#if defined(CONFIG_AX88796)
+#define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO26_GPIO)
+/*
+ * Asix AX88796 Ethernet
+ */
+static struct ax_plat_data colibri_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2
+};
+
+static struct resource colibri_asix_resource[] = {
+	[0] = {
+		.start = PXA3xx_CS2_PHYS,
+		.end   = PXA3xx_CS2_PHYS + (0x20 * 2) - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
+		.end   = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device asix_device = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources 	= ARRAY_SIZE(colibri_asix_resource),
+	.resource	= colibri_asix_resource,
+	.dev		= {
+		.platform_data = &colibri_asix_platdata
+	}
+};
+
+static mfp_cfg_t colibri_pxa300_eth_pin_config[] __initdata = {
+	GPIO1_nCS2,			/* AX88796 chip select */
+	GPIO26_GPIO | MFP_PULL_HIGH	/* AX88796 IRQ */
+};
+
+static void __init colibri_pxa300_init_eth(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_eth_pin_config));
+	set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING);
+	platform_device_register(&asix_device);
+}
+#else
+static inline void __init colibri_pxa300_init_eth(void) {}
+#endif /* CONFIG_AX88796 */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static mfp_cfg_t colibri_pxa300_usb_pin_config[] __initdata = {
+	GPIO0_2_USBH_PEN,
+	GPIO1_2_USBH_PWR,
+};
+
+static struct pxaohci_platform_data colibri_pxa300_ohci_info = {
+	.port_mode	= PMM_GLOBAL_MODE,
+	.flags		= ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
+};
+
+void __init colibri_pxa300_init_ohci(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_usb_pin_config));
+	pxa_set_ohci_info(&colibri_pxa300_ohci_info);
+}
+#else
+static inline void colibri_pxa300_init_ohci(void) {}
+#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
+
+static mfp_cfg_t colibri_pxa300_mmc_pin_config[] __initdata = {
+	GPIO7_MMC1_CLK,
+	GPIO14_MMC1_CMD,
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+};
+
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static mfp_cfg_t colibri_pxa300_lcd_pin_config[] __initdata = {
+	GPIO54_LCD_LDD_0,
+	GPIO55_LCD_LDD_1,
+	GPIO56_LCD_LDD_2,
+	GPIO57_LCD_LDD_3,
+	GPIO58_LCD_LDD_4,
+	GPIO59_LCD_LDD_5,
+	GPIO60_LCD_LDD_6,
+	GPIO61_LCD_LDD_7,
+	GPIO62_LCD_LDD_8,
+	GPIO63_LCD_LDD_9,
+	GPIO64_LCD_LDD_10,
+	GPIO65_LCD_LDD_11,
+	GPIO66_LCD_LDD_12,
+	GPIO67_LCD_LDD_13,
+	GPIO68_LCD_LDD_14,
+	GPIO69_LCD_LDD_15,
+	GPIO70_LCD_LDD_16,
+	GPIO71_LCD_LDD_17,
+	GPIO62_LCD_CS_N,
+	GPIO72_LCD_FCLK,
+	GPIO73_LCD_LCLK,
+	GPIO74_LCD_PCLK,
+	GPIO75_LCD_BIAS,
+	GPIO76_LCD_VSYNC,
+};
+
+static void __init colibri_pxa300_init_lcd(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_lcd_pin_config));
+}
+
+#else
+static inline void colibri_pxa300_init_lcd(void) {}
+#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
+
+#if defined(SND_AC97_CODEC) || defined(SND_AC97_CODEC_MODULE)
+static mfp_cfg_t colibri_pxa310_ac97_pin_config[] __initdata = {
+	GPIO24_AC97_SYSCLK,
+	GPIO23_AC97_nACRESET,
+	GPIO25_AC97_SDATA_IN_0,
+	GPIO27_AC97_SDATA_OUT,
+	GPIO28_AC97_SYNC,
+	GPIO29_AC97_BITCLK
+};
+
+static inline void __init colibri_pxa310_init_ac97(void)
+{
+	/* no AC97 codec on Colibri PXA300 */
+	if (!cpu_is_pxa310())
+		return;
+
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa310_ac97_pin_config));
+	pxa_set_ac97_info(NULL);
+}
+#else
+static inline void colibri_pxa310_init_ac97(void) {}
+#endif
+
+void __init colibri_pxa300_init(void)
+{
+	colibri_pxa300_init_eth();
+	colibri_pxa300_init_ohci();
+	colibri_pxa300_init_lcd();
+	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO));
+	colibri_pxa310_init_ac97();
+	colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa300_mmc_pin_config),
+				mfp_to_gpio(MFP_PIN_GPIO13));
+}
+
+MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.init_machine	= colibri_pxa300_init,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
new file mode 100644
index 0000000..55b74a7
--- /dev/null
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -0,0 +1,187 @@
+/*
+ *  arch/arm/mach-pxa/colibri-pxa320.c
+ *
+ *  Support for Toradex PXA320/310 based Colibri module
+ *
+ *  Daniel Mack <daniel@caiaq.de>
+ *  Matthias Meier <matthias.j.meier@gmx.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/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <net/ax88796.h>
+
+#include <asm/mach-types.h>
+#include <asm/sizes.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa320.h>
+#include <mach/colibri.h>
+#include <mach/pxafb.h>
+#include <mach/ohci.h>
+
+#include "generic.h"
+#include "devices.h"
+
+#if defined(CONFIG_AX88796)
+#define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO36_GPIO)
+
+/*
+ * Asix AX88796 Ethernet
+ */
+static struct ax_plat_data colibri_asix_platdata = {
+	.flags		= AXFLG_MAC_FROMDEV,
+	.wordlength	= 2
+};
+
+static struct resource colibri_asix_resource[] = {
+	[0] = {
+		.start = PXA3xx_CS2_PHYS,
+		.end   = PXA3xx_CS2_PHYS + (0x20 * 2) - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
+		.end   = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO),
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device asix_device = {
+	.name		= "ax88796",
+	.id		= 0,
+	.num_resources 	= ARRAY_SIZE(colibri_asix_resource),
+	.resource	= colibri_asix_resource,
+	.dev		= {
+		.platform_data = &colibri_asix_platdata
+	}
+};
+
+static mfp_cfg_t colibri_pxa320_eth_pin_config[] __initdata = {
+	GPIO3_nCS2,			/* AX88796 chip select */
+	GPIO36_GPIO | MFP_PULL_HIGH	/* AX88796 IRQ */
+};
+
+static void __init colibri_pxa320_init_eth(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_eth_pin_config));
+	set_irq_type(gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), IRQ_TYPE_EDGE_FALLING);
+	platform_device_register(&asix_device);
+}
+#else
+static inline void __init colibri_pxa320_init_eth(void) {}
+#endif /* CONFIG_AX88796 */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static mfp_cfg_t colibri_pxa320_usb_pin_config[] __initdata = {
+	GPIO2_2_USBH_PEN,
+	GPIO3_2_USBH_PWR,
+};
+
+static struct pxaohci_platform_data colibri_pxa320_ohci_info = {
+	.port_mode	= PMM_GLOBAL_MODE,
+	.flags		= ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
+};
+
+void __init colibri_pxa320_init_ohci(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_usb_pin_config));
+	pxa_set_ohci_info(&colibri_pxa320_ohci_info);
+}
+#else
+static inline void colibri_pxa320_init_ohci(void) {}
+#endif /* CONFIG_USB_OHCI_HCD || CONFIG_USB_OHCI_HCD_MODULE */
+
+static mfp_cfg_t colibri_pxa320_mmc_pin_config[] __initdata = {
+	GPIO22_MMC1_CLK,
+	GPIO23_MMC1_CMD,
+	GPIO18_MMC1_DAT0,
+	GPIO19_MMC1_DAT1,
+	GPIO20_MMC1_DAT2,
+	GPIO21_MMC1_DAT3
+};
+
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static mfp_cfg_t colibri_pxa320_lcd_pin_config[] __initdata = {
+	GPIO6_2_LCD_LDD_0,
+	GPIO7_2_LCD_LDD_1,
+	GPIO8_2_LCD_LDD_2,
+	GPIO9_2_LCD_LDD_3,
+	GPIO10_2_LCD_LDD_4,
+	GPIO11_2_LCD_LDD_5,
+	GPIO12_2_LCD_LDD_6,
+	GPIO13_2_LCD_LDD_7,
+	GPIO63_LCD_LDD_8,
+	GPIO64_LCD_LDD_9,
+	GPIO65_LCD_LDD_10,
+	GPIO66_LCD_LDD_11,
+	GPIO67_LCD_LDD_12,
+	GPIO68_LCD_LDD_13,
+	GPIO69_LCD_LDD_14,
+	GPIO70_LCD_LDD_15,
+	GPIO71_LCD_LDD_16,
+	GPIO72_LCD_LDD_17,
+	GPIO73_LCD_CS_N,
+	GPIO74_LCD_VSYNC,
+	GPIO14_2_LCD_FCLK,
+	GPIO15_2_LCD_LCLK,
+	GPIO16_2_LCD_PCLK,
+	GPIO17_2_LCD_BIAS,
+};
+
+static void __init colibri_pxa320_init_lcd(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_lcd_pin_config));
+}
+#else
+static inline void colibri_pxa320_init_lcd(void) {}
+#endif
+
+#if defined(SND_AC97_CODEC) || defined(SND_AC97_CODEC_MODULE)
+static mfp_cfg_t colibri_pxa320_ac97_pin_config[] __initdata = {
+	GPIO34_AC97_SYSCLK,
+	GPIO35_AC97_SDATA_IN_0,
+	GPIO37_AC97_SDATA_OUT,
+	GPIO38_AC97_SYNC,
+	GPIO39_AC97_BITCLK,
+	GPIO40_AC97_nACRESET
+};
+
+static inline void __init colibri_pxa320_init_ac97(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_ac97_pin_config));
+	pxa_set_ac97_info(NULL);
+}
+#else
+static inline void colibri_pxa320_init_ac97(void) {}
+#endif
+
+void __init colibri_pxa320_init(void)
+{
+	colibri_pxa320_init_eth();
+	colibri_pxa320_init_ohci();
+	colibri_pxa320_init_lcd();
+	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO));
+	colibri_pxa320_init_ac97();
+	colibri_pxa3xx_init_mmc(ARRAY_AND_SIZE(colibri_pxa320_mmc_pin_config),
+				mfp_to_gpio(MFP_PIN_GPIO28));
+}
+
+MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= COLIBRI_SDRAM_BASE + 0x100,
+	.init_machine	= colibri_pxa320_init,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c
new file mode 100644
index 0000000..12d0afc
--- /dev/null
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -0,0 +1,121 @@
+/*
+ *  arch/arm/mach-pxa/colibri-pxa3xx.c
+ *
+ *  Common functions for all Toradex PXA3xx modules
+ *
+ *  Daniel Mack <daniel@caiaq.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/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa300.h>
+#include <mach/colibri.h>
+#include <mach/mmc.h>
+#include <mach/pxafb.h>
+
+#include "generic.h"
+#include "devices.h"
+
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+static int mmc_detect_pin;
+
+static int colibri_pxa3xx_mci_init(struct device *dev,
+				   irq_handler_t colibri_mmc_detect_int,
+				   void *data)
+{
+	int ret;
+
+	ret = gpio_request(mmc_detect_pin, "mmc card detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(mmc_detect_pin);
+	ret = request_irq(gpio_to_irq(mmc_detect_pin), colibri_mmc_detect_int,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+			  "MMC card detect", data);
+	if (ret) {
+		gpio_free(mmc_detect_pin);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void colibri_pxa3xx_mci_exit(struct device *dev, void *data)
+{
+	free_irq(mmc_detect_pin, data);
+	gpio_free(gpio_to_irq(mmc_detect_pin));
+}
+
+static struct pxamci_platform_data colibri_pxa3xx_mci_platform_data = {
+	.detect_delay	= 20,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.init		= colibri_pxa3xx_mci_init,
+	.exit		= colibri_pxa3xx_mci_exit,
+};
+
+void __init colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin)
+{
+	pxa3xx_mfp_config(pins, len);
+	mmc_detect_pin = detect_pin;
+	pxa_set_mci_info(&colibri_pxa3xx_mci_platform_data);
+}
+#endif /* CONFIG_MMC_PXA || CONFIG_MMC_PXA_MODULE */
+
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+static int lcd_bl_pin;
+
+/*
+ * LCD panel (Sharp LQ043T3DX02)
+ */
+static void colibri_lcd_backlight(int on)
+{
+	gpio_set_value(lcd_bl_pin, !!on);
+}
+
+static struct pxafb_mode_info sharp_lq43_mode = {
+	.pixclock	= 101936,
+	.xres		= 480,
+	.yres		= 272,
+	.bpp		= 32,
+	.depth		= 18,
+	.hsync_len      = 41,
+	.left_margin    = 2,
+	.right_margin   = 2,
+	.vsync_len      = 10,
+	.upper_margin   = 2,
+	.lower_margin   = 2,
+	.sync	   	= 0,
+	.cmap_greyscale = 0,
+};
+
+static struct pxafb_mach_info sharp_lq43_info = {
+	.modes		= &sharp_lq43_mode,
+	.num_modes	= 1,
+	.cmap_inverse	= 0,
+	.cmap_static	= 0,
+	.lcd_conn	= LCD_COLOR_TFT_18BPP,
+	.pxafb_backlight_power = colibri_lcd_backlight,
+};
+
+void __init colibri_pxa3xx_init_lcd(int bl_pin)
+{
+	lcd_bl_pin = bl_pin;
+	gpio_request(bl_pin, "lcd backlight");
+	gpio_direction_output(bl_pin, 0);
+	set_pxa_fb_info(&sharp_lq43_info);
+}
+#endif
+
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a8d91b6..cdf21dd 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -41,9 +41,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
@@ -637,16 +635,16 @@
 		/* Green LED off tells the bootloader to halt */
 		gpio_set_value(CORGI_GPIO_LED_GREEN, 0);
 
-	arm_machine_restart('h');
+	arm_machine_restart('h', NULL);
 }
 
-static void corgi_restart(char mode)
+static void corgi_restart(char mode, const char *cmd)
 {
 	if (!machine_is_corgi())
 		/* Green LED on tells the bootloader to reboot */
 		gpio_set_value(CORGI_GPIO_LED_GREEN, 1);
 
-	arm_machine_restart('h');
+	arm_machine_restart('h', cmd);
 }
 
 static void __init corgi_init(void)
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index 411607b..d9b9631 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -22,7 +22,6 @@
 #include <linux/string.h>
 #include <mach/corgi.h>
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/sharpsl.h>
 #include <mach/spitz.h>
 #include <asm/hardware/scoop.h>
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index e352590..7f04b3a 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -24,7 +24,6 @@
 
 #include <mach/sharpsl.h>
 #include <mach/corgi.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/pxa2xx-gpio.h>
 #include "sharpsl.h"
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 8e2f221..a5ee707 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -20,7 +20,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/ssp.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-gpio.h>
 #include <mach/regs-ssp.h>
 #include "sharpsl.h"
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
index 771dd4e..083a1d8 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
@@ -37,8 +37,6 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 
 #ifdef DEBUG
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
index 968c830..67f34a8 100644
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
@@ -15,8 +15,6 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa3xx-regs.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/csb701.c b/arch/arm/mach-pxa/csb701.c
new file mode 100644
index 0000000..4a2a295
--- /dev/null
+++ b/arch/arm/mach-pxa/csb701.c
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+
+static struct gpio_keys_button csb701_buttons[] = {
+	{
+		.code	= 0x7,
+		.gpio	= 1,
+		.active_low = 1,
+		.desc	= "SW2",
+		.type	= EV_SW,
+		.wakeup = 1,
+	},
+};
+
+static struct gpio_keys_platform_data csb701_gpio_keys_data = {
+	.buttons = csb701_buttons,
+	.nbuttons = ARRAY_SIZE(csb701_buttons),
+};
+
+static struct gpio_led csb701_leds[] = {
+	{
+		.name	= "csb701:yellow:heartbeat",
+		.default_trigger = "heartbeat",
+		.gpio	= 11,
+		.active_low = 1,
+	},
+};
+
+static struct platform_device csb701_gpio_keys = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev.platform_data = &csb701_gpio_keys_data,
+};
+
+static struct gpio_led_platform_data csb701_leds_gpio_data = {
+	.leds		= csb701_leds,
+	.num_leds	= ARRAY_SIZE(csb701_leds),
+};
+
+static struct platform_device csb701_leds_gpio = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev.platform_data = &csb701_leds_gpio_data,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&csb701_gpio_keys,
+	&csb701_leds_gpio,
+};
+
+static int __init csb701_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+module_init(csb701_init);
+
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
new file mode 100644
index 0000000..2b289f8
--- /dev/null
+++ b/arch/arm/mach-pxa/csb726.c
@@ -0,0 +1,318 @@
+/*
+ *  Support for Cogent CSB726
+ *
+ *  Copyright (c) 2008 Dmitry Eremin-Solenikov
+ *
+ *  This program is free software; you can 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/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sm501.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/csb726.h>
+#include <mach/mfp-pxa27x.h>
+#include <mach/i2c.h>
+#include <mach/mmc.h>
+#include <mach/ohci.h>
+#include <mach/pxa2xx-regs.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/*
+ * n/a: 2, 5, 6, 7, 8, 23, 24, 25, 26, 27, 87, 88, 89,
+ * nu: 58 -- 77, 90, 91, 93, 102, 105-108, 114-116,
+ * XXX: 21,
+ * XXX: 79 CS_3 for LAN9215 or PSKTSEL on R2, R3
+ * XXX: 33 CS_5 for LAN9215 on R1
+ */
+
+static unsigned long csb726_pin_config[] = {
+	GPIO78_nCS_2, /* EXP_CS */
+	GPIO79_nCS_3, /* SMSC9215 */
+	GPIO80_nCS_4, /* SM501 */
+
+	GPIO52_GPIO, /* #SMSC9251 int */
+	GPIO53_GPIO, /* SM501 int */
+
+	GPIO1_GPIO, /* GPIO0 */
+	GPIO11_GPIO, /* GPIO1 */
+	GPIO9_GPIO, /* GPIO2 */
+	GPIO10_GPIO, /* GPIO3 */
+	GPIO16_PWM0_OUT, /* or GPIO4 */
+	GPIO17_PWM1_OUT, /* or GPIO5 */
+	GPIO94_GPIO, /* GPIO6 */
+	GPIO95_GPIO, /* GPIO7 */
+	GPIO96_GPIO, /* GPIO8 */
+	GPIO97_GPIO, /* GPIO9 */
+	GPIO15_GPIO, /* EXP_IRQ */
+	GPIO18_RDY, /* EXP_WAIT */
+
+	GPIO0_GPIO, /* PWR_INT */
+	GPIO104_GPIO, /* PWR_OFF */
+
+	GPIO12_GPIO, /* touch irq */
+
+	GPIO13_SSP2_TXD,
+	GPIO14_SSP2_SFRM,
+	MFP_CFG_OUT(GPIO19, AF1, DRIVE_LOW),/* SSP2_SYSCLK */
+	GPIO22_SSP2_SCLK,
+
+	GPIO81_SSP3_TXD,
+	GPIO82_SSP3_RXD,
+	GPIO83_SSP3_SFRM,
+	GPIO84_SSP3_SCLK,
+
+	GPIO20_GPIO, /* SDIO int */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO100_GPIO, /* SD CD */
+	GPIO101_GPIO, /* SD WP */
+
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO113_AC97_nRESET,
+
+	GPIO34_FFUART_RXD,
+	GPIO35_FFUART_CTS,
+	GPIO36_FFUART_DCD,
+	GPIO37_FFUART_DSR,
+	GPIO38_FFUART_RI,
+	GPIO39_FFUART_TXD,
+	GPIO40_FFUART_DTR,
+	GPIO41_FFUART_RTS,
+
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16, /* maybe unused */
+	GPIO85_nPCE_1,
+	GPIO98_GPIO, /* CF IRQ */
+	GPIO99_GPIO, /* CF CD */
+	GPIO103_GPIO, /* Reset */
+
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+};
+
+static struct pxamci_platform_data csb726_mci_data;
+
+static int csb726_mci_init(struct device *dev,
+		irq_handler_t detect, void *data)
+{
+	int err;
+
+	csb726_mci_data.detect_delay = msecs_to_jiffies(500);
+
+	err = gpio_request(CSB726_GPIO_MMC_DETECT, "MMC detect");
+	if (err)
+		goto err_det_req;
+
+	err = gpio_direction_input(CSB726_GPIO_MMC_DETECT);
+	if (err)
+		goto err_det_dir;
+
+	err = gpio_request(CSB726_GPIO_MMC_RO, "MMC ro");
+	if (err)
+		goto err_ro_req;
+
+	err = gpio_direction_input(CSB726_GPIO_MMC_RO);
+	if (err)
+		goto err_ro_dir;
+
+	err = request_irq(gpio_to_irq(CSB726_GPIO_MMC_DETECT), detect,
+			IRQF_DISABLED, "MMC card detect", data);
+	if (err)
+		goto err_irq;
+
+	return 0;
+
+err_irq:
+err_ro_dir:
+	gpio_free(CSB726_GPIO_MMC_RO);
+err_ro_req:
+err_det_dir:
+	gpio_free(CSB726_GPIO_MMC_DETECT);
+err_det_req:
+	return err;
+}
+
+static int csb726_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(CSB726_GPIO_MMC_RO);
+}
+
+static void csb726_mci_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(CSB726_GPIO_MMC_DETECT), data);
+	gpio_free(CSB726_GPIO_MMC_RO);
+	gpio_free(CSB726_GPIO_MMC_DETECT);
+}
+
+static struct pxamci_platform_data csb726_mci = {
+	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init		= csb726_mci_init,
+	.get_ro		= csb726_mci_get_ro,
+	/* FIXME setpower */
+	.exit		= csb726_mci_exit,
+};
+
+static struct pxaohci_platform_data csb726_ohci_platform_data = {
+	.port_mode	= PMM_NPS_MODE,
+	.flags		= ENABLE_PORT1 | NO_OC_PROTECTION,
+};
+
+static struct mtd_partition csb726_flash_partitions[] = {
+	{
+		.name		= "Bootloader",
+		.offset		= 0,
+		.size		= CSB726_FLASH_uMON,
+		.mask_flags	= MTD_WRITEABLE  /* force read-only */
+	},
+	{
+		.name		= "root",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	}
+};
+
+static struct physmap_flash_data csb726_flash_data = {
+	.width		= 2,
+	.parts		= csb726_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(csb726_flash_partitions),
+};
+
+static struct resource csb726_flash_resources[] = {
+	{
+		.start          = PXA_CS0_PHYS,
+		.end            = PXA_CS0_PHYS + CSB726_FLASH_SIZE - 1 ,
+		.flags          = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device csb726_flash = {
+	.name           = "physmap-flash",
+	.dev            = {
+		.platform_data  = &csb726_flash_data,
+	},
+	.resource       = csb726_flash_resources,
+	.num_resources  = ARRAY_SIZE(csb726_flash_resources),
+};
+
+static struct resource csb726_sm501_resources[] = {
+	{
+		.start          = PXA_CS4_PHYS,
+		.end            = PXA_CS4_PHYS + SZ_8M - 1,
+		.flags          = IORESOURCE_MEM,
+		.name		= "sm501-localmem",
+	},
+	{
+		.start          = PXA_CS4_PHYS + SZ_64M - SZ_2M,
+		.end            = PXA_CS4_PHYS + SZ_64M - 1,
+		.flags          = IORESOURCE_MEM,
+		.name		= "sm501-regs",
+	},
+	{
+		.start		= CSB726_IRQ_SM501,
+		.end		= CSB726_IRQ_SM501,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct sm501_initdata csb726_sm501_initdata = {
+/*	.devices	= SM501_USE_USB_HOST, */
+	.devices	= SM501_USE_USB_HOST | SM501_USE_UART0 | SM501_USE_UART1,
+};
+
+static struct sm501_platdata csb726_sm501_platdata = {
+	.init		= &csb726_sm501_initdata,
+};
+
+static struct platform_device csb726_sm501 = {
+	.name		= "sm501",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(csb726_sm501_resources),
+	.resource	= csb726_sm501_resources,
+	.dev		= {
+		.platform_data = &csb726_sm501_platdata,
+	},
+};
+
+static struct resource csb726_lan_resources[] = {
+	{
+		.start	= PXA_CS3_PHYS,
+		.end	= PXA_CS3_PHYS + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= CSB726_IRQ_LAN,
+		.end	= CSB726_IRQ_LAN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device csb726_lan = {
+	.name		= "smc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(csb726_lan_resources),
+	.resource	= csb726_lan_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&csb726_flash,
+	&csb726_sm501,
+	&csb726_lan,
+};
+
+static void __init csb726_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(csb726_pin_config));
+/*	MSC1 = 0x7ffc3ffc; *//* LAN9215/EXP_CS */
+/*	MSC2 = 0x06697ff4; *//* none/SM501 */
+	MSC2 = (MSC2 & ~0xffff) | 0x7ff4; /* SM501 */
+
+	pxa_set_i2c_info(NULL);
+	pxa27x_set_i2c_power_info(NULL);
+	pxa_set_mci_info(&csb726_mci);
+	pxa_set_ohci_info(&csb726_ohci_platform_data);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(CSB726, "Cogent CSB726")
+	.phys_io	= 0x40000000,
+	.boot_params	= 0xa0000100,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.init_machine   = csb726_init,
+	.timer          = &pxa_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index e16f8e3..d245e59c 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -4,7 +4,6 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 
-#include <mach/pxa-regs.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
diff --git a/arch/arm/mach-pxa/e330.c b/arch/arm/mach-pxa/e330.c
index 1bd7f74..74d3f89 100644
--- a/arch/arm/mach-pxa/e330.c
+++ b/arch/arm/mach-pxa/e330.c
@@ -20,9 +20,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 
diff --git a/arch/arm/mach-pxa/e350.c b/arch/arm/mach-pxa/e350.c
index edcd9d5..0800362 100644
--- a/arch/arm/mach-pxa/e350.c
+++ b/arch/arm/mach-pxa/e350.c
@@ -21,9 +21,7 @@
 #include <asm/mach-types.h>
 
 #include <mach/irqs.h>
-#include <mach/mfp-pxa25x.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 
diff --git a/arch/arm/mach-pxa/e400.c b/arch/arm/mach-pxa/e400.c
index 77bb8e2..ed9c0c3 100644
--- a/arch/arm/mach-pxa/e400.c
+++ b/arch/arm/mach-pxa/e400.c
@@ -22,9 +22,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/pxafb.h>
 #include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c
index a6fff78..07500a0 100644
--- a/arch/arm/mach-pxa/e740.c
+++ b/arch/arm/mach-pxa/e740.c
@@ -24,9 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 #include <mach/irda.h>
@@ -194,7 +192,7 @@
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(e740_pin_config));
 	eseries_register_clks();
-	clk_add_alias("CLK_CK48M", &e740_t7l66xb_device.dev,
+	clk_add_alias("CLK_CK48M", e740_t7l66xb_device.name,
 			"UDCCLK", &pxa25x_device_udc.dev),
 	eseries_get_tmio_gpios();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c
index 665066f..6126c04 100644
--- a/arch/arm/mach-pxa/e750.c
+++ b/arch/arm/mach-pxa/e750.c
@@ -23,9 +23,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 #include <mach/irda.h>
@@ -195,7 +193,7 @@
 static void __init e750_init(void)
 {
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(e750_pin_config));
-	clk_add_alias("CLK_CK3P6MI", &e750_tc6393xb_device.dev,
+	clk_add_alias("CLK_CK3P6MI", e750_tc6393xb_device.name,
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c
index cc9b129..74ab098 100644
--- a/arch/arm/mach-pxa/e800.c
+++ b/arch/arm/mach-pxa/e800.c
@@ -23,9 +23,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 #include <mach/irqs.h>
@@ -196,7 +194,7 @@
 
 static void __init e800_init(void)
 {
-	clk_add_alias("CLK_CK3P6MI", &e800_tc6393xb_device.dev,
+	clk_add_alias("CLK_CK3P6MI", e800_tc6393xb_device.name,
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index f5ed803..920dfb8 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -11,40 +11,63 @@
 
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include <linux/dm9000.h>
 #include <linux/rtc-v3020.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/gpio.h>
+#include <linux/mfd/da903x.h>
+#include <linux/regulator/machine.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/tdo24m.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#include <media/soc_camera.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/mfp-pxa27x.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <mach/pxa27x_keypad.h>
+#include <mach/i2c.h>
+#include <mach/camera.h>
+#include <mach/pxa2xx_spi.h>
 
 #include "generic.h"
+#include "devices.h"
 
-/* GPIO IRQ usage */
-#define GPIO41_ETHIRQ		(41)
+/* EM-X270 specific GPIOs */
 #define GPIO13_MMC_CD		(13)
+#define GPIO95_MMC_WP		(95)
+#define GPIO56_NAND_RB		(56)
+
+/* eXeda specific GPIOs */
+#define GPIO114_MMC_CD		(114)
+#define GPIO20_NAND_RB		(20)
+#define GPIO38_SD_PWEN		(38)
+
+/* common  GPIOs */
+#define GPIO11_NAND_CS		(11)
+#define GPIO93_CAM_RESET	(93)
+#define GPIO41_ETHIRQ		(41)
 #define EM_X270_ETHIRQ		IRQ_GPIO(GPIO41_ETHIRQ)
-#define EM_X270_MMC_CD		IRQ_GPIO(GPIO13_MMC_CD)
 
-/* NAND control GPIOs */
-#define GPIO11_NAND_CS	(11)
-#define GPIO56_NAND_RB	(56)
+static int mmc_cd;
+static int nand_rb;
+static int dm9000_flags;
 
-static unsigned long em_x270_pin_config[] = {
+static unsigned long common_pin_config[] = {
 	/* AC'97 */
 	GPIO28_AC97_BITCLK,
 	GPIO29_AC97_SDATA_IN_0,
@@ -150,21 +173,32 @@
 	GPIO18_RDY,
 
 	/* GPIO */
-	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
+	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,	/* sleep/resume button */
 
 	/* power controls */
 	GPIO20_GPIO	| MFP_LPM_DRIVE_LOW,	/* GPRS_PWEN */
+	GPIO93_GPIO	| MFP_LPM_DRIVE_LOW,	/* Camera reset */
 	GPIO115_GPIO	| MFP_LPM_DRIVE_LOW,	/* WLAN_PWEN */
 
 	/* NAND controls */
 	GPIO11_GPIO	| MFP_LPM_DRIVE_HIGH,	/* NAND CE# */
-	GPIO56_GPIO,				/* NAND Ready/Busy */
 
 	/* interrupts */
-	GPIO13_GPIO,	/* MMC card detect */
 	GPIO41_GPIO,	/* DM9000 interrupt */
 };
 
+static unsigned long em_x270_pin_config[] = {
+	GPIO13_GPIO,	/* MMC card detect */
+	GPIO56_GPIO,	/* NAND Ready/Busy */
+	GPIO95_GPIO,	/* MMC Write protect */
+};
+
+static unsigned long exeda_pin_config[] = {
+	GPIO20_GPIO,				/* NAND Ready/Busy */
+	GPIO38_GPIO	| MFP_LPM_DRIVE_LOW,	/* SD slot power */
+	GPIO114_GPIO,				/* MMC card detect */
+};
+
 #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
 static struct resource em_x270_dm9000_resource[] = {
 	[0] = {
@@ -185,7 +219,7 @@
 };
 
 static struct dm9000_plat_data em_x270_dm9000_platdata = {
-	.flags		= DM9000_PLATF_32BITONLY,
+	.flags		= DM9000_PLATF_NO_EEPROM,
 };
 
 static struct platform_device em_x270_dm9000 = {
@@ -200,6 +234,7 @@
 
 static void __init em_x270_init_dm9000(void)
 {
+	em_x270_dm9000_platdata.flags |= dm9000_flags;
 	platform_device_register(&em_x270_dm9000);
 }
 #else
@@ -289,7 +324,7 @@
 {
 	dsb();
 
-	return gpio_get_value(GPIO56_NAND_RB);
+	return gpio_get_value(nand_rb);
 }
 
 static struct mtd_partition em_x270_partition_info[] = {
@@ -354,14 +389,14 @@
 
 	gpio_direction_output(GPIO11_NAND_CS, 1);
 
-	err = gpio_request(GPIO56_NAND_RB, "NAND R/B");
+	err = gpio_request(nand_rb, "NAND R/B");
 	if (err) {
 		pr_warning("EM-X270: failed to request NAND R/B gpio\n");
 		gpio_free(GPIO11_NAND_CS);
 		return;
 	}
 
-	gpio_direction_input(GPIO56_NAND_RB);
+	gpio_direction_input(nand_rb);
 
 	platform_device_register(&em_x270_nand);
 }
@@ -369,6 +404,61 @@
 static inline void em_x270_init_nand(void) {}
 #endif
 
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition em_x270_nor_parts[] = {
+	{
+		.name =		"Bootloader",
+		.offset =	0x00000000,
+		.size =		0x00050000,
+		.mask_flags =	MTD_WRITEABLE  /* force read-only */
+	}, {
+		.name =		"Environment",
+		.offset =	0x00050000,
+		.size =		0x00010000,
+	}, {
+		.name =		"Reserved",
+		.offset =	0x00060000,
+		.size =		0x00050000,
+		.mask_flags =	MTD_WRITEABLE  /* force read-only */
+	}, {
+		.name =		"Splashscreen",
+		.offset =	0x000b0000,
+		.size =		0x00050000,
+	}
+};
+
+static struct physmap_flash_data em_x270_nor_data[] = {
+	[0] = {
+		.width = 2,
+		.parts = em_x270_nor_parts,
+		.nr_parts = ARRAY_SIZE(em_x270_nor_parts),
+	},
+};
+
+static struct resource em_x270_nor_flash_resource = {
+	.start	= PXA_CS0_PHYS,
+	.end	= PXA_CS0_PHYS + SZ_1M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device em_x270_physmap_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.num_resources	= 1,
+	.resource	= &em_x270_nor_flash_resource,
+	.dev		= {
+		.platform_data	= &em_x270_nor_data,
+	},
+};
+
+static void __init em_x270_init_nor(void)
+{
+	platform_device_register(&em_x270_physmap_flash);
+}
+#else
+static inline void em_x270_init_nor(void) {}
+#endif
+
 /* PXA27x OHCI controller setup */
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int em_x270_ohci_init(struct device *dev)
@@ -395,40 +485,93 @@
 
 /* MCI controller setup */
 #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
+static struct regulator *em_x270_sdio_ldo;
+
 static int em_x270_mci_init(struct device *dev,
 			    irq_handler_t em_x270_detect_int,
 			    void *data)
 {
-	int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int,
-			      IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+	int err;
+
+	em_x270_sdio_ldo = regulator_get(dev, "vcc sdio");
+	if (IS_ERR(em_x270_sdio_ldo)) {
+		dev_err(dev, "can't request SDIO power supply: %ld\n",
+			PTR_ERR(em_x270_sdio_ldo));
+		return PTR_ERR(em_x270_sdio_ldo);
+	}
+
+	err = request_irq(gpio_to_irq(mmc_cd), em_x270_detect_int,
+			      IRQF_DISABLED | IRQF_TRIGGER_RISING |
+			      IRQF_TRIGGER_FALLING,
 			      "MMC card detect", data);
 	if (err) {
-		printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
-		       __func__, err);
-		return err;
+		dev_err(dev, "can't request MMC card detect IRQ: %d\n", err);
+		goto err_irq;
+	}
+
+	if (machine_is_em_x270()) {
+		err = gpio_request(GPIO95_MMC_WP, "MMC WP");
+		if (err) {
+			dev_err(dev, "can't request MMC write protect: %d\n",
+				err);
+			goto err_gpio_wp;
+		}
+		gpio_direction_input(GPIO95_MMC_WP);
+	} else {
+		err = gpio_request(GPIO38_SD_PWEN, "sdio power");
+		if (err) {
+			dev_err(dev, "can't request MMC power control : %d\n",
+				err);
+			goto err_gpio_wp;
+		}
+		gpio_direction_output(GPIO38_SD_PWEN, 1);
 	}
 
 	return 0;
+
+err_gpio_wp:
+	free_irq(gpio_to_irq(mmc_cd), data);
+err_irq:
+	regulator_put(em_x270_sdio_ldo);
+
+	return err;
 }
 
 static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
 {
-	/*
-	   FIXME: current hardware implementation does not allow to
-	   enable/disable MMC power. This will be fixed in next HW releases,
-	   and we'll need to add implmentation here.
-	*/
-	return;
+	struct pxamci_platform_data* p_d = dev->platform_data;
+
+	if ((1 << vdd) & p_d->ocr_mask) {
+		int vdd_uV = (2000 + (vdd - __ffs(MMC_VDD_20_21)) * 100) * 1000;
+
+		regulator_set_voltage(em_x270_sdio_ldo, vdd_uV, vdd_uV);
+		regulator_enable(em_x270_sdio_ldo);
+	} else {
+		regulator_disable(em_x270_sdio_ldo);
+	}
 }
 
 static void em_x270_mci_exit(struct device *dev, void *data)
 {
-	int irq = gpio_to_irq(GPIO13_MMC_CD);
-	free_irq(irq, data);
+	free_irq(gpio_to_irq(mmc_cd), data);
+	regulator_put(em_x270_sdio_ldo);
+
+	if (machine_is_em_x270())
+		gpio_free(GPIO95_MMC_WP);
+	else
+		gpio_free(GPIO38_SD_PWEN);
+}
+
+static int em_x270_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO95_MMC_WP);
 }
 
 static struct pxamci_platform_data em_x270_mci_platform_data = {
-	.ocr_mask	= MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31,
+	.ocr_mask	= MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23|
+			  MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27|
+			  MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30|
+			  MMC_VDD_30_31|MMC_VDD_31_32,
 	.init 		= em_x270_mci_init,
 	.setpower 	= em_x270_mci_setpower,
 	.exit		= em_x270_mci_exit,
@@ -436,33 +579,53 @@
 
 static void __init em_x270_init_mmc(void)
 {
+	if (machine_is_em_x270())
+		em_x270_mci_platform_data.get_ro = em_x270_mci_get_ro;
+
+	em_x270_mci_platform_data.detect_delay	= msecs_to_jiffies(250);
 	pxa_set_mci_info(&em_x270_mci_platform_data);
 }
 #else
 static inline void em_x270_init_mmc(void) {}
 #endif
 
-/* LCD 480x640 */
+/* LCD */
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
-static struct pxafb_mode_info em_x270_lcd_mode = {
-	.pixclock	= 50000,
-	.bpp		= 16,
-	.xres		= 480,
-	.yres		= 640,
-	.hsync_len	= 8,
-	.vsync_len	= 2,
-	.left_margin	= 8,
-	.upper_margin	= 0,
-	.right_margin	= 24,
-	.lower_margin	= 4,
-	.cmap_greyscale	= 0,
+static struct pxafb_mode_info em_x270_lcd_modes[] = {
+	[0] = {
+		.pixclock	= 38250,
+		.bpp		= 16,
+		.xres		= 480,
+		.yres		= 640,
+		.hsync_len	= 8,
+		.vsync_len	= 2,
+		.left_margin	= 8,
+		.upper_margin	= 2,
+		.right_margin	= 24,
+		.lower_margin	= 4,
+		.sync		= 0,
+	},
+	[1] = {
+		.pixclock       = 153800,
+		.bpp		= 16,
+		.xres		= 240,
+		.yres		= 320,
+		.hsync_len	= 8,
+		.vsync_len	= 2,
+		.left_margin	= 8,
+		.upper_margin	= 2,
+		.right_margin	= 88,
+		.lower_margin	= 2,
+		.sync		= 0,
+	},
 };
 
 static struct pxafb_mach_info em_x270_lcd = {
-	.modes		= &em_x270_lcd_mode,
-	.num_modes	= 1,
+	.modes		= em_x270_lcd_modes,
+	.num_modes	= 2,
 	.lcd_conn	= LCD_COLOR_TFT_16BPP,
 };
+
 static void __init em_x270_init_lcd(void)
 {
 	set_pxa_fb_info(&em_x270_lcd);
@@ -471,6 +634,40 @@
 static inline void em_x270_init_lcd(void) {}
 #endif
 
+#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
+static struct pxa2xx_spi_master em_x270_spi_info = {
+	.num_chipselect	= 1,
+};
+
+static struct pxa2xx_spi_chip em_x270_tdo24m_chip = {
+	.rx_threshold = 1,
+	.tx_threshold = 1,
+};
+
+static struct tdo24m_platform_data em_x270_tdo24m_pdata = {
+	.model = TDO35S,
+};
+
+static struct spi_board_info em_x270_spi_devices[] __initdata = {
+	{
+		.modalias = "tdo24m",
+		.max_speed_hz = 1000000,
+		.bus_num = 1,
+		.chip_select = 0,
+		.controller_data = &em_x270_tdo24m_chip,
+		.platform_data = &em_x270_tdo24m_pdata,
+	},
+};
+
+static void __init em_x270_init_spi(void)
+{
+	pxa2xx_set_spi_info(1, &em_x270_spi_info);
+	spi_register_board_info(ARRAY_AND_SIZE(em_x270_spi_devices));
+}
+#else
+static inline void em_x270_init_spi(void) {}
+#endif
+
 #if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
 static void __init em_x270_init_ac97(void)
 {
@@ -481,23 +678,76 @@
 #endif
 
 #if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
-static unsigned int em_x270_matrix_keys[] = {
+static unsigned int em_x270_module_matrix_keys[] = {
 	KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B),
 	KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT),
 	KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D),
 };
 
-struct pxa27x_keypad_platform_data em_x270_keypad_info = {
+struct pxa27x_keypad_platform_data em_x270_module_keypad_info = {
 	/* code map for the matrix keys */
 	.matrix_key_rows	= 3,
 	.matrix_key_cols	= 3,
-	.matrix_key_map		= em_x270_matrix_keys,
-	.matrix_key_map_size	= ARRAY_SIZE(em_x270_matrix_keys),
+	.matrix_key_map		= em_x270_module_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(em_x270_module_matrix_keys),
+};
+
+static unsigned int em_x270_exeda_matrix_keys[] = {
+	KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL),
+	KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE),
+	KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL),
+	KEY(0, 6, KEY_ENTER), KEY(0, 7, KEY_SLASH),
+
+	KEY(1, 0, KEY_DOT), KEY(1, 1, KEY_M),
+	KEY(1, 2, KEY_N), KEY(1, 3, KEY_B),
+	KEY(1, 4, KEY_V), KEY(1, 5, KEY_C),
+	KEY(1, 6, KEY_X), KEY(1, 7, KEY_Z),
+
+	KEY(2, 0, KEY_LEFTSHIFT), KEY(2, 1, KEY_SEMICOLON),
+	KEY(2, 2, KEY_L), KEY(2, 3, KEY_K),
+	KEY(2, 4, KEY_J), KEY(2, 5, KEY_H),
+	KEY(2, 6, KEY_G), KEY(2, 7, KEY_F),
+
+	KEY(3, 0, KEY_D), KEY(3, 1, KEY_S),
+	KEY(3, 2, KEY_A), KEY(3, 3, KEY_TAB),
+	KEY(3, 4, KEY_BACKSPACE), KEY(3, 5, KEY_P),
+	KEY(3, 6, KEY_O), KEY(3, 7, KEY_I),
+
+	KEY(4, 0, KEY_U), KEY(4, 1, KEY_Y),
+	KEY(4, 2, KEY_T), KEY(4, 3, KEY_R),
+	KEY(4, 4, KEY_E), KEY(4, 5, KEY_W),
+	KEY(4, 6, KEY_Q), KEY(4, 7, KEY_MINUS),
+
+	KEY(5, 0, KEY_0), KEY(5, 1, KEY_9),
+	KEY(5, 2, KEY_8), KEY(5, 3, KEY_7),
+	KEY(5, 4, KEY_6), KEY(5, 5, KEY_5),
+	KEY(5, 6, KEY_4), KEY(5, 7, KEY_3),
+
+	KEY(6, 0, KEY_2), KEY(6, 1, KEY_1),
+	KEY(6, 2, KEY_ENTER), KEY(6, 3, KEY_END),
+	KEY(6, 4, KEY_DOWN), KEY(6, 5, KEY_UP),
+	KEY(6, 6, KEY_MENU), KEY(6, 7, KEY_F1),
+
+	KEY(7, 0, KEY_LEFT), KEY(7, 1, KEY_RIGHT),
+	KEY(7, 2, KEY_BACK), KEY(7, 3, KEY_HOME),
+	KEY(7, 4, 0), KEY(7, 5, 0),
+	KEY(7, 6, 0), KEY(7, 7, 0),
+};
+
+struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = {
+	/* code map for the matrix keys */
+	.matrix_key_rows	= 8,
+	.matrix_key_cols	= 8,
+	.matrix_key_map		= em_x270_exeda_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(em_x270_exeda_matrix_keys),
 };
 
 static void __init em_x270_init_keypad(void)
 {
-	pxa_set_keypad_info(&em_x270_keypad_info);
+	if (machine_is_em_x270())
+		pxa_set_keypad_info(&em_x270_module_keypad_info);
+	else
+		pxa_set_keypad_info(&em_x270_exeda_keypad_info);
 }
 #else
 static inline void em_x270_init_keypad(void) {}
@@ -535,19 +785,264 @@
 static inline void em_x270_init_gpio_keys(void) {}
 #endif
 
-static void __init em_x270_init(void)
+/* Quick Capture Interface and sensor setup */
+#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
+static struct regulator *em_x270_camera_ldo;
+
+static int em_x270_sensor_init(struct device *dev)
 {
+	int ret;
+
+	ret = gpio_request(GPIO93_CAM_RESET, "camera reset");
+	if (ret)
+		return ret;
+
+	gpio_direction_output(GPIO93_CAM_RESET, 0);
+
+	em_x270_camera_ldo = regulator_get(NULL, "vcc cam");
+	if (em_x270_camera_ldo == NULL) {
+		gpio_free(GPIO93_CAM_RESET);
+		return -ENODEV;
+	}
+
+	ret = regulator_enable(em_x270_camera_ldo);
+	if (ret) {
+		regulator_put(em_x270_camera_ldo);
+		gpio_free(GPIO93_CAM_RESET);
+		return ret;
+	}
+
+	gpio_set_value(GPIO93_CAM_RESET, 1);
+
+	return 0;
+}
+
+struct pxacamera_platform_data em_x270_camera_platform_data = {
+	.init	= em_x270_sensor_init,
+	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
+		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+	.mclk_10khz = 2600,
+};
+
+static int em_x270_sensor_power(struct device *dev, int on)
+{
+	int ret;
+	int is_on = regulator_is_enabled(em_x270_camera_ldo);
+
+	if (on == is_on)
+		return 0;
+
+	gpio_set_value(GPIO93_CAM_RESET, !on);
+
+	if (on)
+		ret = regulator_enable(em_x270_camera_ldo);
+	else
+		ret = regulator_disable(em_x270_camera_ldo);
+
+	if (ret)
+		return ret;
+
+	gpio_set_value(GPIO93_CAM_RESET, on);
+
+	return 0;
+}
+
+static struct soc_camera_link iclink = {
+	.bus_id	= 0,
+	.power = em_x270_sensor_power,
+};
+
+static struct i2c_board_info em_x270_i2c_cam_info[] = {
+	{
+		I2C_BOARD_INFO("mt9m111", 0x48),
+		.platform_data = &iclink,
+	},
+};
+
+static struct i2c_pxa_platform_data em_x270_i2c_info = {
+	.fast_mode = 1,
+};
+
+static void  __init em_x270_init_camera(void)
+{
+	pxa_set_i2c_info(&em_x270_i2c_info);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
+	pxa_set_camera_info(&em_x270_camera_platform_data);
+}
+#else
+static inline void em_x270_init_camera(void) {}
+#endif
+
+/* DA9030 related initializations */
+#define REGULATOR_CONSUMER(_name, _dev, _supply)			       \
+	static struct regulator_consumer_supply _name##_consumers[] = {	\
+		{							\
+			.dev = _dev,					\
+			.supply = _supply,				\
+		},							\
+	}
+
+REGULATOR_CONSUMER(ldo3, NULL, "vcc gps");
+REGULATOR_CONSUMER(ldo5, NULL, "vcc cam");
+REGULATOR_CONSUMER(ldo10, &pxa_device_mci.dev, "vcc sdio");
+REGULATOR_CONSUMER(ldo12, NULL, "vcc usb");
+REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs");
+
+#define REGULATOR_INIT(_ldo, _min_uV, _max_uV, _ops_mask)		\
+	static struct regulator_init_data _ldo##_data = {		\
+		.constraints = {					\
+			.min_uV = _min_uV,				\
+			.max_uV = _max_uV,				\
+			.state_mem = {					\
+				.enabled = 0,				\
+			},						\
+			.valid_ops_mask = _ops_mask,			\
+		},							\
+		.num_consumer_supplies = ARRAY_SIZE(_ldo##_consumers),	\
+		.consumer_supplies = _ldo##_consumers,			\
+	};
+
+REGULATOR_INIT(ldo3, 3200000, 3200000, REGULATOR_CHANGE_STATUS);
+REGULATOR_INIT(ldo5, 3000000, 3000000, REGULATOR_CHANGE_STATUS);
+REGULATOR_INIT(ldo10, 2000000, 3200000,
+	       REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE);
+REGULATOR_INIT(ldo12, 3000000, 3000000, REGULATOR_CHANGE_STATUS);
+REGULATOR_INIT(ldo19, 3200000, 3200000, REGULATOR_CHANGE_STATUS);
+
+struct led_info em_x270_led_info = {
+	.name = "em-x270:orange",
+	.default_trigger = "battery-charging-or-full",
+};
+
+struct power_supply_info em_x270_psy_info = {
+	.name = "LP555597P6H-FPS",
+	.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.voltage_max_design = 4200000,
+	.voltage_min_design = 3000000,
+	.use_for_apm = 1,
+};
+
+static void em_x270_battery_low(void)
+{
+	apm_queue_event(APM_LOW_BATTERY);
+}
+
+static void em_x270_battery_critical(void)
+{
+	apm_queue_event(APM_CRITICAL_SUSPEND);
+}
+
+struct da9030_battery_info em_x270_batterty_info = {
+	.battery_info = &em_x270_psy_info,
+
+	.charge_milliamp = 1000,
+	.charge_millivolt = 4200,
+
+	.vbat_low = 3600,
+	.vbat_crit = 3400,
+	.vbat_charge_start = 4100,
+	.vbat_charge_stop = 4200,
+	.vbat_charge_restart = 4000,
+
+	.vcharge_min = 3200,
+	.vcharge_max = 5500,
+
+	.tbat_low = 197,
+	.tbat_high = 78,
+	.tbat_restart = 100,
+
+	.batmon_interval = 0,
+
+	.battery_low = em_x270_battery_low,
+	.battery_critical = em_x270_battery_critical,
+};
+
+#define DA9030_SUBDEV(_name, _id, _pdata)	\
+	{					\
+		.name = "da903x-" #_name,	\
+		.id = DA9030_ID_##_id,		\
+		.platform_data = _pdata,	\
+	}
+
+#define DA9030_LDO(num)	DA9030_SUBDEV(regulator, LDO##num, &ldo##num##_data)
+
+struct da903x_subdev_info em_x270_da9030_subdevs[] = {
+	DA9030_LDO(3),
+	DA9030_LDO(5),
+	DA9030_LDO(10),
+	DA9030_LDO(12),
+	DA9030_LDO(19),
+
+	DA9030_SUBDEV(led, LED_PC, &em_x270_led_info),
+	DA9030_SUBDEV(backlight, WLED, &em_x270_led_info),
+	DA9030_SUBDEV(battery, BAT, &em_x270_batterty_info),
+};
+
+static struct da903x_platform_data em_x270_da9030_info = {
+	.num_subdevs = ARRAY_SIZE(em_x270_da9030_subdevs),
+	.subdevs = em_x270_da9030_subdevs,
+};
+
+static struct i2c_board_info em_x270_i2c_pmic_info = {
+	I2C_BOARD_INFO("da9030", 0x49),
+	.irq = IRQ_GPIO(0),
+	.platform_data = &em_x270_da9030_info,
+};
+
+static struct i2c_pxa_platform_data em_x270_pwr_i2c_info = {
+	.use_pio = 1,
+};
+
+static void __init em_x270_init_da9030(void)
+{
+	pxa27x_set_i2c_power_info(&em_x270_pwr_i2c_info);
+	i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1);
+}
+
+static void __init em_x270_module_init(void)
+{
+	pr_info("%s\n", __func__);
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));
 
+	mmc_cd = GPIO13_MMC_CD;
+	nand_rb = GPIO56_NAND_RB;
+	dm9000_flags = DM9000_PLATF_32BITONLY;
+}
+
+static void __init em_x270_exeda_init(void)
+{
+	pr_info("%s\n", __func__);
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(exeda_pin_config));
+
+	mmc_cd = GPIO114_MMC_CD;
+	nand_rb = GPIO20_NAND_RB;
+	dm9000_flags = DM9000_PLATF_16BITONLY;
+}
+
+static void __init em_x270_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config));
+
+	if (machine_is_em_x270())
+		em_x270_module_init();
+	else if (machine_is_exeda())
+		em_x270_exeda_init();
+	else
+		panic("Unsupported machine: %d\n", machine_arch_type);
+
+	em_x270_init_da9030();
 	em_x270_init_dm9000();
 	em_x270_init_rtc();
 	em_x270_init_nand();
+	em_x270_init_nor();
 	em_x270_init_lcd();
 	em_x270_init_mmc();
 	em_x270_init_ohci();
 	em_x270_init_keypad();
 	em_x270_init_gpio_keys();
 	em_x270_init_ac97();
+	em_x270_init_camera();
+	em_x270_init_spi();
 }
 
 MACHINE_START(EM_X270, "Compulab EM-X270")
@@ -559,3 +1054,13 @@
 	.timer		= &pxa_timer,
 	.init_machine	= em_x270_init,
 MACHINE_END
+
+MACHINE_START(EXEDA, "Compulab eXeda")
+	.boot_params	= 0xa0000100,
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa27x_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= em_x270_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index dfce7d5..c60dadf 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -20,8 +20,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/mfp-pxa25x.h>
-#include <mach/hardware.h>
+#include <mach/pxa25x.h>
 #include <mach/eseries-gpio.h>
 #include <mach/udc.h>
 #include <mach/irda.h>
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index df5f822..92ba16e 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -19,18 +19,16 @@
 #include <linux/input.h>
 
 #include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa27x.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
 #include <mach/i2c.h>
 #include <mach/hardware.h>
 #include <mach/pxa27x_keypad.h>
 
-#include <mach/mfp-pxa27x.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
 #include "devices.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 0ccc91c..3126a35 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -26,8 +26,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 
-#include <mach/pxa-regs.h>
 #include <mach/reset.h>
+#include <mach/gpio.h>
+#include <mach/pxa2xx-gpio.h>
 
 #include "generic.h"
 
@@ -127,3 +128,33 @@
 	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
 	get_clk_frequency_khz(1);
 }
+
+/*
+ * Configure pins for GPIO or other functions
+ */
+int pxa_gpio_mode(int gpio_mode)
+{
+	unsigned long flags;
+	int gpio = gpio_mode & GPIO_MD_MASK_NR;
+	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+	int gafr;
+
+	if (gpio > pxa_last_gpio)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	if (gpio_mode & GPIO_DFLT_LOW)
+		GPCR(gpio) = GPIO_bit(gpio);
+	else if (gpio_mode & GPIO_DFLT_HIGH)
+		GPSR(gpio) = GPIO_bit(gpio);
+	if (gpio_mode & GPIO_MD_MASK_DIR)
+		GPDR(gpio) |= GPIO_bit(gpio);
+	else
+		GPDR(gpio) &= ~GPIO_bit(gpio);
+	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(pxa_gpio_mode);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index dc876a8..3465268 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -9,20 +9,17 @@
  * published by the Free Software Foundation.
  */
 
-typedef int (*set_wake_t)(unsigned int, unsigned int);
-
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
-extern void __init pxa_init_irq(int irq_nr, set_wake_t fn);
-extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn);
+extern void __init pxa_init_irq(int irq_nr,
+				int (*set_wake)(unsigned int, unsigned int));
 extern void __init pxa25x_init_irq(void);
 extern void __init pxa27x_init_irq(void);
 extern void __init pxa3xx_init_irq(void);
 extern void __init pxa_map_io(void);
 
 extern unsigned int get_clk_frequency_khz(int info);
-extern int pxa_last_gpio;
 
 #define SET_BANK(__nr,__start,__size) \
 	mi->bank[__nr].start = (__start), \
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
deleted file mode 100644
index 5fec1e4..0000000
--- a/arch/arm/mach-pxa/gpio.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- *  linux/arch/arm/mach-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  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.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <asm/gpio.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-gpio.h>
-
-#include "generic.h"
-
-#define GPIO0_BASE	((void __iomem *)io_p2v(0x40E00000))
-#define GPIO1_BASE	((void __iomem *)io_p2v(0x40E00004))
-#define GPIO2_BASE	((void __iomem *)io_p2v(0x40E00008))
-#define GPIO3_BASE	((void __iomem *)io_p2v(0x40E00100))
-
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem     *regbase;
-};
-
-int pxa_last_gpio;
-
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static int __gpio_is_inverted(unsigned gpio)
-{
-	return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-#define __gpio_is_inverted(gpio)	(0)
-#endif
-
-/*
- * Configure pins for GPIO or other functions
- */
-int pxa_gpio_mode(int gpio_mode)
-{
-	unsigned long flags;
-	int gpio = gpio_mode & GPIO_MD_MASK_NR;
-	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
-	int gafr;
-
-	if (gpio > pxa_last_gpio)
-		return -EINVAL;
-
-	local_irq_save(flags);
-	if (gpio_mode & GPIO_DFLT_LOW)
-		GPCR(gpio) = GPIO_bit(gpio);
-	else if (gpio_mode & GPIO_DFLT_HIGH)
-		GPSR(gpio) = GPIO_bit(gpio);
-	if (gpio_mode & GPIO_MD_MASK_DIR)
-		GPDR(gpio) |= GPIO_bit(gpio);
-	else
-		GPDR(gpio) &= ~GPIO_bit(gpio);
-	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
-	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
-	local_irq_restore(flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(pxa_gpio_mode);
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	unsigned long        flags;
-	u32                  mask = 1 << offset;
-	u32                  value;
-	struct pxa_gpio_chip *pxa;
-	void __iomem         *gpdr;
-
-	pxa = container_of(chip, struct pxa_gpio_chip, chip);
-	gpdr = pxa->regbase + GPDR_OFFSET;
-	local_irq_save(flags);
-	value = __raw_readl(gpdr);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, gpdr);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	unsigned long        flags;
-	u32                  mask = 1 << offset;
-	u32                  tmp;
-	struct pxa_gpio_chip *pxa;
-	void __iomem         *gpdr;
-
-	pxa = container_of(chip, struct pxa_gpio_chip, chip);
-	__raw_writel(mask,
-			pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
-	gpdr = pxa->regbase + GPDR_OFFSET;
-	local_irq_save(flags);
-	tmp = __raw_readl(gpdr);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, gpdr);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-/*
- * Return GPIO level
- */
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	u32                  mask = 1 << offset;
-	struct pxa_gpio_chip *pxa;
-
-	pxa = container_of(chip, struct pxa_gpio_chip, chip);
-	return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
-}
-
-/*
- * Set output GPIO level
- */
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	u32                  mask = 1 << offset;
-	struct pxa_gpio_chip *pxa;
-
-	pxa = container_of(chip, struct pxa_gpio_chip, chip);
-
-	if (value)
-		__raw_writel(mask, pxa->regbase + GPSR_OFFSET);
-	else
-		__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
-}
-
-#define GPIO_CHIP(_n)							\
-	[_n] = {							\
-		.regbase = GPIO##_n##_BASE,				\
-		.chip = {						\
-			.label		  = "gpio-" #_n,		\
-			.direction_input  = pxa_gpio_direction_input,	\
-			.direction_output = pxa_gpio_direction_output,	\
-			.get		  = pxa_gpio_get,		\
-			.set		  = pxa_gpio_set,		\
-			.base		  = (_n) * 32,			\
-			.ngpio		  = 32,				\
-		},							\
-	}
-
-static struct pxa_gpio_chip pxa_gpio_chip[] = {
-	GPIO_CHIP(0),
-	GPIO_CHIP(1),
-	GPIO_CHIP(2),
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-	GPIO_CHIP(3),
-#endif
-};
-
-/*
- * PXA GPIO edge detection for IRQs:
- * IRQs are generated on Falling-Edge, Rising-Edge, or both.
- * Use this instead of directly setting GRER/GFER.
- */
-
-static unsigned long GPIO_IRQ_rising_edge[4];
-static unsigned long GPIO_IRQ_falling_edge[4];
-static unsigned long GPIO_IRQ_mask[4];
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static int __gpio_is_occupied(unsigned gpio)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-		int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-		if (__gpio_is_inverted(gpio))
-			return af != 1 || dir == 0;
-		else
-			return af != 0 || dir != 0;
-	}
-
-	return 0;
-}
-
-static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
-{
-	int gpio, idx;
-
-	gpio = IRQ_TO_GPIO(irq);
-	idx = gpio >> 5;
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((GPIO_IRQ_rising_edge[idx] & GPIO_bit(gpio)) ||
-		    (GPIO_IRQ_falling_edge[idx] & GPIO_bit(gpio)))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	if (__gpio_is_inverted(gpio))
-		GPDR(gpio) |= GPIO_bit(gpio);
-	else
-		GPDR(gpio) &= ~GPIO_bit(gpio);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		__set_bit(gpio, GPIO_IRQ_rising_edge);
-	else
-		__clear_bit(gpio, GPIO_IRQ_rising_edge);
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		__set_bit(gpio, GPIO_IRQ_falling_edge);
-	else
-		__clear_bit(gpio, GPIO_IRQ_falling_edge);
-
-	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
-	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-/*
- * GPIO IRQs must be acknowledged.  This is for GPIO 0 and 1.
- */
-
-static void pxa_ack_low_gpio(unsigned int irq)
-{
-	GEDR0 = (1 << (irq - IRQ_GPIO0));
-}
-
-static void pxa_mask_low_gpio(unsigned int irq)
-{
-	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
-}
-
-static void pxa_unmask_low_gpio(unsigned int irq)
-{
-	ICMR |= 1 << (irq - PXA_IRQ(0));
-}
-
-static struct irq_chip pxa_low_gpio_chip = {
-	.name		= "GPIO-l",
-	.ack		= pxa_ack_low_gpio,
-	.mask		= pxa_mask_low_gpio,
-	.unmask		= pxa_unmask_low_gpio,
-	.set_type	= pxa_gpio_irq_type,
-};
-
-/*
- * Demux handler for GPIO>=2 edge detect interrupts
- */
-
-#define GEDR_BITS	(sizeof(gedr) * BITS_PER_BYTE)
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	int loop, bit, n;
-	unsigned long gedr[4];
-
-	do {
-		gedr[0] = GEDR0 & GPIO_IRQ_mask[0] & ~3;
-		gedr[1] = GEDR1 & GPIO_IRQ_mask[1];
-		gedr[2] = GEDR2 & GPIO_IRQ_mask[2];
-		gedr[3] = GEDR3 & GPIO_IRQ_mask[3];
-
-		GEDR0 = gedr[0]; GEDR1 = gedr[1];
-		GEDR2 = gedr[2]; GEDR3 = gedr[3];
-
-		loop = 0;
-		bit = find_first_bit(gedr, GEDR_BITS);
-		while (bit < GEDR_BITS) {
-			loop = 1;
-
-			n = PXA_GPIO_IRQ_BASE + bit;
-			generic_handle_irq(n);
-
-			bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(unsigned int irq)
-{
-	int gpio = irq - IRQ_GPIO(2) + 2;
-	GEDR(gpio) = GPIO_bit(gpio);
-}
-
-static void pxa_mask_muxed_gpio(unsigned int irq)
-{
-	int gpio = irq - IRQ_GPIO(2) + 2;
-	__clear_bit(gpio, GPIO_IRQ_mask);
-	GRER(gpio) &= ~GPIO_bit(gpio);
-	GFER(gpio) &= ~GPIO_bit(gpio);
-}
-
-static void pxa_unmask_muxed_gpio(unsigned int irq)
-{
-	int gpio = irq - IRQ_GPIO(2) + 2;
-	int idx = gpio >> 5;
-	__set_bit(gpio, GPIO_IRQ_mask);
-	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
-	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.ack		= pxa_ack_muxed_gpio,
-	.mask		= pxa_mask_muxed_gpio,
-	.unmask		= pxa_unmask_muxed_gpio,
-	.set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int gpio_nr, set_wake_t fn)
-{
-	int irq, i, gpio;
-
-	pxa_last_gpio = gpio_nr - 1;
-
-	/* clear all GPIO edge detects */
-	for (i = 0; i < gpio_nr; i += 32) {
-		GFER(i) = 0;
-		GRER(i) = 0;
-		GEDR(i) = GEDR(i);
-	}
-
-	/* GPIO 0 and 1 must have their mask bit always set */
-	GPIO_IRQ_mask[0] = 3;
-
-	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-		set_irq_chip(irq, &pxa_low_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
-		set_irq_chip(irq, &pxa_muxed_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Install handler for GPIO>=2 edge detect interrupts */
-	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
-
-	pxa_low_gpio_chip.set_wake = fn;
-	pxa_muxed_gpio_chip.set_wake = fn;
-
-	/* add a GPIO chip for each register bank.
-	 * the last PXA25x register only contains 21 GPIOs
-	 */
-	for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
-		if (gpio + 32 > gpio_nr)
-			pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
-		gpiochip_add(&pxa_gpio_chip[i].chip);
-	}
-}
-
-#ifdef CONFIG_PM
-
-static unsigned long saved_gplr[4];
-static unsigned long saved_gpdr[4];
-static unsigned long saved_grer[4];
-static unsigned long saved_gfer[4];
-
-static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
-{
-	int i, gpio;
-
-	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
-		saved_gplr[i] = GPLR(gpio);
-		saved_gpdr[i] = GPDR(gpio);
-		saved_grer[i] = GRER(gpio);
-		saved_gfer[i] = GFER(gpio);
-
-		/* Clear GPIO transition detect bits */
-		GEDR(gpio) = GEDR(gpio);
-	}
-	return 0;
-}
-
-static int pxa_gpio_resume(struct sys_device *dev)
-{
-	int i, gpio;
-
-	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
-		/* restore level with set/clear */
-		GPSR(gpio) = saved_gplr[i];
-		GPCR(gpio) = ~saved_gplr[i];
-
-		GRER(gpio) = saved_grer[i];
-		GFER(gpio) = saved_gfer[i];
-		GPDR(gpio) = saved_gpdr[i];
-	}
-	return 0;
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct sysdev_class pxa_gpio_sysclass = {
-	.name		= "gpio",
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
-
-static int __init pxa_gpio_init(void)
-{
-	return sysdev_class_register(&pxa_gpio_sysclass);
-}
-
-core_initcall(pxa_gpio_init);
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index e296ce1..ca9912e 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -38,14 +38,12 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
+
+#include <mach/pxa25x.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/gumstix.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
-
 #include "generic.h"
 
 static struct resource flash_resource = {
@@ -191,6 +189,11 @@
 	return 0;
 }
 
+int __attribute__((weak)) am300_init(void)
+{
+	return 0;
+}
+
 static void __init carrier_board_init(void)
 {
 	/*
@@ -198,6 +201,7 @@
 	 * they cannot be detected programatically
 	 */
 	am200_init();
+	am300_init();
 }
 
 static void __init gumstix_init(void)
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index 295ec41..f3d220c 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -24,14 +24,15 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+
+#include <mach/pxa25x.h>
 #include <mach/h5000.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/udc.h>
+
 #include "generic.h"
 
 /*
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
new file mode 100644
index 0000000..cea99fe
--- /dev/null
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -0,0 +1,166 @@
+/*
+ * linux/arch/arm/mach-pxa/himalaya.c
+ *
+ * Hardware definitions for the HTC Himalaya
+ *
+ * Based on 2.6.21-hh20's himalaya.c and himalaya_lcd.c
+ *
+ * Copyright (c) 2008 Zbynek Michl <Zbynek.Michl@seznam.cz>
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+
+#include <video/w100fb.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/mfp-pxa25x.h>
+#include <mach/hardware.h>
+
+#include "generic.h"
+
+/* ---------------------- Himalaya LCD definitions -------------------- */
+
+static struct w100_gen_regs himalaya_lcd_regs = {
+	.lcd_format =        0x00000003,
+	.lcdd_cntl1 =        0x00000000,
+	.lcdd_cntl2 =        0x0003ffff,
+	.genlcd_cntl1 =      0x00fff003,
+	.genlcd_cntl2 =      0x00000003,
+	.genlcd_cntl3 =      0x000102aa,
+};
+
+static struct w100_mode himalaya4_lcd_mode = {
+	.xres 		= 240,
+	.yres 		= 320,
+	.left_margin 	= 0,
+	.right_margin 	= 31,
+	.upper_margin 	= 15,
+	.lower_margin 	= 0,
+	.crtc_ss	= 0x80150014,
+	.crtc_ls	= 0xa0fb00f7,
+	.crtc_gs	= 0xc0080007,
+	.crtc_vpos_gs	= 0x00080007,
+	.crtc_rev	= 0x0000000a,
+	.crtc_dclk	= 0x81700030,
+	.crtc_gclk	= 0x8015010f,
+	.crtc_goe	= 0x00000000,
+	.pll_freq 	= 80,
+	.pixclk_divider = 15,
+	.pixclk_divider_rotated = 15,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 0,
+	.sysclk_src     = CLK_SRC_PLL,
+};
+
+static struct w100_mode himalaya6_lcd_mode = {
+	.xres 		= 240,
+	.yres 		= 320,
+	.left_margin 	= 9,
+	.right_margin 	= 8,
+	.upper_margin 	= 5,
+	.lower_margin 	= 4,
+	.crtc_ss	= 0x80150014,
+	.crtc_ls	= 0xa0fb00f7,
+	.crtc_gs	= 0xc0080007,
+	.crtc_vpos_gs	= 0x00080007,
+	.crtc_rev	= 0x0000000a,
+	.crtc_dclk	= 0xa1700030,
+	.crtc_gclk	= 0x8015010f,
+	.crtc_goe	= 0x00000000,
+	.pll_freq 	= 95,
+	.pixclk_divider = 0xb,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_PLL,
+	.sysclk_divider = 1,
+	.sysclk_src     = CLK_SRC_PLL,
+};
+
+static struct w100_gpio_regs himalaya_w100_gpio_info = {
+	.init_data1 = 0xffff0000,	/* GPIO_DATA  */
+	.gpio_dir1  = 0x00000000,	/* GPIO_CNTL1 */
+	.gpio_oe1   = 0x003c0000,	/* GPIO_CNTL2 */
+	.init_data2 = 0x00000000,	/* GPIO_DATA2 */
+	.gpio_dir2  = 0x00000000,	/* GPIO_CNTL3 */
+	.gpio_oe2   = 0x00000000,	/* GPIO_CNTL4 */
+};
+
+static struct w100fb_mach_info himalaya_fb_info = {
+	.num_modes  = 1,
+	.regs       = &himalaya_lcd_regs,
+	.gpio       = &himalaya_w100_gpio_info,
+	.xtal_freq = 16000000,
+};
+
+static struct resource himalaya_fb_resources[] = {
+	[0] = {
+		.start	= 0x08000000,
+		.end	= 0x08ffffff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device himalaya_fb_device = {
+	.name           = "w100fb",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &himalaya_fb_info,
+	},
+	.num_resources  = ARRAY_SIZE(himalaya_fb_resources),
+	.resource       = himalaya_fb_resources,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct platform_device *devices[] __initdata = {
+	&himalaya_fb_device,
+};
+
+static void __init himalaya_lcd_init(void)
+{
+	int himalaya_boardid;
+
+	himalaya_boardid = 0x4; /* hardcoded (detection needs ASIC3 functions) */
+	printk(KERN_INFO "himalaya LCD Driver init. boardid=%d\n",
+		himalaya_boardid);
+
+	switch (himalaya_boardid) {
+	case 0x4:
+		himalaya_fb_info.modelist = &himalaya4_lcd_mode;
+	break;
+	case 0x6:
+		himalaya_fb_info.modelist = &himalaya6_lcd_mode;
+	break;
+	default:
+		printk(KERN_INFO "himalaya lcd_init: unknown boardid=%d. Using 0x4\n",
+			himalaya_boardid);
+		himalaya_fb_info.modelist = &himalaya4_lcd_mode;
+	}
+}
+
+static void __init himalaya_init(void)
+{
+	himalaya_lcd_init();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+
+MACHINE_START(HIMALAYA, "HTC Himalaya")
+	.phys_io = 0x40000000,
+	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params = 0xa0000100,
+	.map_io = pxa_map_io,
+	.init_irq = pxa25x_init_irq,
+	.init_machine = himalaya_init,
+	.timer = &pxa_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 013b15b..b6243b5 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -31,8 +31,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/idp.h>
 #include <mach/pxafb.h>
 #include <mach/bitfield.h>
diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c
index 364c5e2..2121309 100644
--- a/arch/arm/mach-pxa/imote2.c
+++ b/arch/arm/mach-pxa/imote2.c
@@ -28,11 +28,8 @@
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
+#include <mach/pxa27x.h>
 #include <mach/i2c.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
-#include <mach/regs-ssp.h>
 #include <mach/udc.h>
 #include <mach/mmc.h>
 #include <mach/pxa2xx_spi.h>
diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h
index 2ae373f..3f2a01d 100644
--- a/arch/arm/mach-pxa/include/mach/colibri.h
+++ b/arch/arm/mach-pxa/include/mach/colibri.h
@@ -1,19 +1,31 @@
 #ifndef _COLIBRI_H_
 #define _COLIBRI_H_
+/*
+ * common settings for all modules
+ */
+
+#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
+extern void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin);
+#else
+static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *, int, int) {}
+#endif
+
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
+extern void colibri_pxa3xx_init_lcd(int bl_pin);
+#else
+static inline void colibri_pxa3xx_init_lcd(int) {}
+#endif
 
 /* physical memory regions */
-#define COLIBRI_FLASH_PHYS	(PXA_CS0_PHYS)  /* Flash region */
-#define COLIBRI_ETH_PHYS	(PXA_CS2_PHYS)  /* Ethernet DM9000 region */
 #define COLIBRI_SDRAM_BASE	0xa0000000      /* SDRAM region */
 
-/* virtual memory regions */
-#define COLIBRI_DISK_VIRT	0xF0000000	/* Disk On Chip region */
+/* definitions for Colibri PXA270 */
 
-/* size of flash */
-#define COLIBRI_FLASH_SIZE	0x02000000	/* Flash size 32 MB */
-
-/* Ethernet Controller Davicom DM9000 */
-#define GPIO_DM9000		114
-#define COLIBRI_ETH_IRQ	IRQ_GPIO(GPIO_DM9000)
+#define COLIBRI_PXA270_FLASH_PHYS	(PXA_CS0_PHYS)  /* Flash region */
+#define COLIBRI_PXA270_ETH_PHYS		(PXA_CS2_PHYS)  /* Ethernet */
+#define COLIBRI_PXA270_ETH_IRQ_GPIO	114
+#define COLIBRI_PXA270_ETH_IRQ		\
+	gpio_to_irq(mfp_to_gpio(COLIBRI_PXA270_ETH_IRQ_GPIO))
 
 #endif /* _COLIBRI_H_ */
+
diff --git a/arch/arm/mach-pxa/include/mach/csb726.h b/arch/arm/mach-pxa/include/mach/csb726.h
new file mode 100644
index 0000000..747ab1a
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/csb726.h
@@ -0,0 +1,26 @@
+/*
+ *  Support for Cogent CSB726
+ *
+ *  Copyright (c) 2008 Dmitry Baryshkov
+ *
+ *  This program is free software; you can 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 CSB726_H
+#define CSB726_H
+
+#define CSB726_GPIO_IRQ_LAN	52
+#define CSB726_GPIO_IRQ_SM501	53
+#define CSB726_GPIO_MMC_DETECT	100
+#define CSB726_GPIO_MMC_RO	101
+
+#define CSB726_FLASH_SIZE	(64 * 1024 * 1024)
+#define CSB726_FLASH_uMON	(8 * 1024 * 1024)
+
+#define CSB726_IRQ_LAN		gpio_to_irq(CSB726_GPIO_IRQ_LAN)
+#define CSB726_IRQ_SM501	gpio_to_irq(CSB726_GPIO_IRQ_SM501)
+
+#endif
+
diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h
index 7804637..5bd5589 100644
--- a/arch/arm/mach-pxa/include/mach/dma.h
+++ b/arch/arm/mach-pxa/include/mach/dma.h
@@ -12,35 +12,10 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/*
- * Descriptor structure for PXA's DMA engine
- * Note: this structure must always be aligned to a 16-byte boundary.
- */
+#include <mach/hardware.h>
 
-typedef struct pxa_dma_desc {
-	volatile u32 ddadr;	/* Points to the next descriptor + flags */
-	volatile u32 dsadr;	/* DSADR value for the current transfer */
-	volatile u32 dtadr;	/* DTADR value for the current transfer */
-	volatile u32 dcmd;	/* DCMD value for the current transfer */
-} pxa_dma_desc;
+/* DMA Controller Registers Definitions */
+#define DMAC_REGS_VIRT	io_p2v(0x40000000)
 
-typedef enum {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-} pxa_dma_prio;
-
-/*
- * DMA registration
- */
-
-int __init pxa_init_dma(int num_ch);
-
-int pxa_request_dma (char *name,
-			 pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *),
-			 void *data);
-
-void pxa_free_dma (int dma_ch);
-
+#include <plat/dma.h>
 #endif /* _ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index 2c538d8..b024a8b 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -24,42 +24,118 @@
 #ifndef __ASM_ARCH_PXA_GPIO_H
 #define __ASM_ARCH_PXA_GPIO_H
 
-#include <mach/pxa-regs.h>
-#include <asm/irq.h>
+#include <mach/irqs.h>
 #include <mach/hardware.h>
-
 #include <asm-generic/gpio.h>
 
+#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
 
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space.
- */
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+/* GPIO Pin Level Registers */
+#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L		GPIO_REG(0x0054)
+#define GAFR0_U		GPIO_REG(0x0058)
+#define GAFR1_L		GPIO_REG(0x005C)
+#define GAFR1_U		GPIO_REG(0x0060)
+#define GAFR2_L		GPIO_REG(0x0064)
+#define GAFR2_U		GPIO_REG(0x0068)
+#define GAFR3_L		GPIO_REG(0x006C)
+#define GAFR3_U		GPIO_REG(0x0070)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
 #define NR_BUILTIN_GPIO 128
 
-static inline int gpio_get_value(unsigned gpio)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
-		return GPLR(gpio) & GPIO_bit(gpio);
-	else
-		return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
-		if (value)
-			GPSR(gpio) = GPIO_bit(gpio);
-		else
-			GPCR(gpio) = GPIO_bit(gpio);
-	} else {
-		__gpio_set_value(gpio, value);
-	}
-}
-
-#define gpio_cansleep __gpio_cansleep
-
+#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
 #define irq_to_gpio(irq)	IRQ_TO_GPIO(irq)
 
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+	return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
 
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+		if (__gpio_is_inverted(gpio))
+			return af != 1 || dir == 0;
+		else
+			return af != 0 || dir != 0;
+	} else
+		return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio.h>
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h
index 099f54a..06abd41 100644
--- a/arch/arm/mach-pxa/include/mach/gumstix.h
+++ b/arch/arm/mach-pxa/include/mach/gumstix.h
@@ -97,4 +97,5 @@
 
 /* for expansion boards that can't be programatically detected */
 extern int am200_init(void);
+extern int am300_init(void);
 
diff --git a/arch/arm/mach-pxa/include/mach/lubbock.h b/arch/arm/mach-pxa/include/mach/lubbock.h
index 4cb2415..751b748 100644
--- a/arch/arm/mach-pxa/include/mach/lubbock.h
+++ b/arch/arm/mach-pxa/include/mach/lubbock.h
@@ -25,7 +25,6 @@
 
 /* FPGA register virtual addresses */
 #define LUB_WHOAMI		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x000)
-#define LUB_HEXLED		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x010)
 #define LUB_DISC_BLNK_LED	__LUB_REG(LUBBOCK_FPGA_PHYS + 0x040)
 #define LUB_CONF_SWITCHES	__LUB_REG(LUBBOCK_FPGA_PHYS + 0x050)
 #define LUB_USER_SWITCHES	__LUB_REG(LUBBOCK_FPGA_PHYS + 0x060)
diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h
index 38d68d9..82a399f 100644
--- a/arch/arm/mach-pxa/include/mach/magician.h
+++ b/arch/arm/mach-pxa/include/mach/magician.h
@@ -69,7 +69,7 @@
 #define IRQ_MAGICIAN_SD		(IRQ_BOARD_START + 0)
 #define IRQ_MAGICIAN_EP		(IRQ_BOARD_START + 1)
 #define IRQ_MAGICIAN_BT		(IRQ_BOARD_START + 2)
-#define IRQ_MAGICIAN_AC		(IRQ_BOARD_START + 3)
+#define IRQ_MAGICIAN_VBUS	(IRQ_BOARD_START + 3)
 
 /*
  * CPLD EGPIOs
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
index a72869b..b13dc02 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_ARCH_MFP_PXA25X_H
 #define __ASM_ARCH_MFP_PXA25X_H
 
-#include <mach/mfp.h>
 #include <mach/mfp-pxa2xx.h>
 
 /* GPIO */
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
index da4f85a..6543c05 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
@@ -8,7 +8,6 @@
  * specific controller, and this should work in most cases.
  */
 
-#include <mach/mfp.h>
 #include <mach/mfp-pxa2xx.h>
 
 /* Note: GPIO3/GPIO4 will be driven by Power I2C when PCFR/PI2C_EN
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
index 3e92115..658b28e 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARCH_MFP_PXA2XX_H
 #define __ASM_ARCH_MFP_PXA2XX_H
 
-#include <mach/mfp.h>
+#include <plat/mfp.h>
 
 /*
  * the following MFP_xxx bit definitions in mfp.h are re-used for pxa2xx:
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h
index bc1fb33..ae84411 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h
@@ -15,7 +15,6 @@
 #ifndef __ASM_ARCH_MFP_PXA300_H
 #define __ASM_ARCH_MFP_PXA300_H
 
-#include <mach/mfp.h>
 #include <mach/mfp-pxa3xx.h>
 
 /* GPIO */
@@ -41,6 +40,7 @@
 #endif
 
 /* Chip Select */
+#define GPIO1_nCS2		MFP_CFG(GPIO1,	AF1)
 #define GPIO2_nCS3		MFP_CFG(GPIO2,  AF1)
 
 /* AC97 */
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
index 67f8385..07897e6 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h
@@ -15,7 +15,6 @@
 #ifndef __ASM_ARCH_MFP_PXA320_H
 #define __ASM_ARCH_MFP_PXA320_H
 
-#include <mach/mfp.h>
 #include <mach/mfp-pxa3xx.h>
 
 /* GPIO */
@@ -38,6 +37,7 @@
 #define GPIO17_2_GPIO		MFP_CFG(GPIO17_2, AF0)
 
 /* Chip Select */
+#define GPIO3_nCS2		MFP_CFG(GPIO3, AF1)
 #define GPIO4_nCS3		MFP_CFG(GPIO4, AF1)
 
 /* AC97 */
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h
index 1f6b35c..d375195 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa3xx.h
@@ -1,68 +1,9 @@
 #ifndef __ASM_ARCH_MFP_PXA3XX_H
 #define __ASM_ARCH_MFP_PXA3XX_H
 
+#include <plat/mfp.h>
+
 #define MFPR_BASE	(0x40e10000)
-#define MFPR_SIZE	(PAGE_SIZE)
-
-/* MFPR register bit definitions */
-#define MFPR_PULL_SEL		(0x1 << 15)
-#define MFPR_PULLUP_EN		(0x1 << 14)
-#define MFPR_PULLDOWN_EN	(0x1 << 13)
-#define MFPR_SLEEP_SEL		(0x1 << 9)
-#define MFPR_SLEEP_OE_N		(0x1 << 7)
-#define MFPR_EDGE_CLEAR		(0x1 << 6)
-#define MFPR_EDGE_FALL_EN	(0x1 << 5)
-#define MFPR_EDGE_RISE_EN	(0x1 << 4)
-
-#define MFPR_SLEEP_DATA(x)	((x) << 8)
-#define MFPR_DRIVE(x)		(((x) & 0x7) << 10)
-#define MFPR_AF_SEL(x)		(((x) & 0x7) << 0)
-
-#define MFPR_EDGE_NONE		(0)
-#define MFPR_EDGE_RISE		(MFPR_EDGE_RISE_EN)
-#define MFPR_EDGE_FALL		(MFPR_EDGE_FALL_EN)
-#define MFPR_EDGE_BOTH		(MFPR_EDGE_RISE | MFPR_EDGE_FALL)
-
-/*
- * Table that determines the low power modes outputs, with actual settings
- * used in parentheses for don't-care values. Except for the float output,
- * the configured driven and pulled levels match, so if there is a need for
- * non-LPM pulled output, the same configuration could probably be used.
- *
- * Output value  sleep_oe_n  sleep_data  pullup_en  pulldown_en  pull_sel
- *                 (bit 7)    (bit 8)    (bit 14)     (bit 13)   (bit 15)
- *
- * Input            0          X(0)        X(0)        X(0)       0
- * Drive 0          0          0           0           X(1)       0
- * Drive 1          0          1           X(1)        0	  0
- * Pull hi (1)      1          X(1)        1           0	  0
- * Pull lo (0)      1          X(0)        0           1	  0
- * Z (float)        1          X(0)        0           0	  0
- */
-#define MFPR_LPM_INPUT		(0)
-#define MFPR_LPM_DRIVE_LOW	(MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN)
-#define MFPR_LPM_DRIVE_HIGH    	(MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN)
-#define MFPR_LPM_PULL_LOW      	(MFPR_LPM_DRIVE_LOW  | MFPR_SLEEP_OE_N)
-#define MFPR_LPM_PULL_HIGH     	(MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N)
-#define MFPR_LPM_FLOAT         	(MFPR_SLEEP_OE_N)
-#define MFPR_LPM_MASK		(0xe080)
-
-/*
- * The pullup and pulldown state of the MFP pin at run mode is by default
- * determined by the selected alternate function. In case that some buggy
- * devices need to override this default behavior,  the definitions below
- * indicates the setting of corresponding MFPR bits
- *
- * Definition       pull_sel  pullup_en  pulldown_en
- * MFPR_PULL_NONE       0         0        0
- * MFPR_PULL_LOW        1         0        1
- * MFPR_PULL_HIGH       1         1        0
- * MFPR_PULL_BOTH       1         1        1
- */
-#define MFPR_PULL_NONE		(0)
-#define MFPR_PULL_LOW		(MFPR_PULL_SEL | MFPR_PULLDOWN_EN)
-#define MFPR_PULL_BOTH		(MFPR_PULL_LOW | MFPR_PULLUP_EN)
-#define MFPR_PULL_HIGH		(MFPR_PULL_SEL | MFPR_PULLUP_EN)
 
 /* PXA3xx common MFP configurations - processor specific ones defined
  * in mfp-pxa300.h and mfp-pxa320.h
@@ -197,56 +138,21 @@
 #define GPIO5_2_GPIO		MFP_CFG(GPIO5_2, AF0)
 #define GPIO6_2_GPIO		MFP_CFG(GPIO6_2, AF0)
 
-/*
- * each MFP pin will have a MFPR register, since the offset of the
- * register varies between processors, the processor specific code
- * should initialize the pin offsets by pxa3xx_mfp_init_addr()
- *
- * pxa3xx_mfp_init_addr - accepts a table of "pxa3xx_mfp_addr_map"
- * structure, which represents a range of MFP pins from "start" to
- * "end", with the offset begining at "offset", to define a single
- * pin, let "end" = -1
- *
- * use
- *
- * MFP_ADDR_X() to define a range of pins
- * MFP_ADDR()   to define a single pin
- * MFP_ADDR_END to signal the end of pin offset definitions
+/* NOTE: usage of these two functions is not recommended,
+ * use pxa3xx_mfp_config() instead.
  */
-struct pxa3xx_mfp_addr_map {
-	unsigned int	start;
-	unsigned int	end;
-	unsigned long	offset;
-};
+static inline unsigned long pxa3xx_mfp_read(int mfp)
+{
+	return mfp_read(mfp);
+}
 
-#define MFP_ADDR_X(start, end, offset) \
-	{ MFP_PIN_##start, MFP_PIN_##end, offset }
+static inline void pxa3xx_mfp_write(int mfp, unsigned long val)
+{
+	mfp_write(mfp, val);
+}
 
-#define MFP_ADDR(pin, offset) \
-	{ MFP_PIN_##pin, -1, offset }
-
-#define MFP_ADDR_END	{ MFP_PIN_INVALID, 0 }
-
-/*
- * pxa3xx_mfp_read()/pxa3xx_mfp_write() - for direct read/write access
- * to the MFPR register
- */
-unsigned long pxa3xx_mfp_read(int mfp);
-void pxa3xx_mfp_write(int mfp, unsigned long mfpr_val);
-
-/*
- * pxa3xx_mfp_config - configure the MFPR registers
- *
- * used by board specific initialization code
- */
-void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num);
-
-/*
- * pxa3xx_mfp_init_addr() - initialize the mapping between mfp pin
- * index and MFPR register offset
- *
- * used by processor specific code
- */
-void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *);
-void __init pxa3xx_init_mfp(void);
+static inline void pxa3xx_mfp_config(unsigned long *mfp_cfg, int num)
+{
+	mfp_config(mfp_cfg, num);
+}
 #endif /* __ASM_ARCH_MFP_PXA3XX_H */
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
index fa73f56..0d119d3 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa930.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_MFP_PXA9xx_H
 #define __ASM_ARCH_MFP_PXA9xx_H
 
-#include <mach/mfp.h>
 #include <mach/mfp-pxa3xx.h>
 
 /* GPIO */
diff --git a/arch/arm/mach-pxa/include/mach/mtd-xip.h b/arch/arm/mach-pxa/include/mach/mtd-xip.h
index cfca815..297387e 100644
--- a/arch/arm/mach-pxa/include/mach/mtd-xip.h
+++ b/arch/arm/mach-pxa/include/mach/mtd-xip.h
@@ -15,8 +15,8 @@
 #ifndef __ARCH_PXA_MTD_XIP_H__
 #define __ARCH_PXA_MTD_XIP_H__
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/regs-ost.h>
+#include <mach/regs-intc.h>
 
 #define xip_irqpending()	(ICIP & ICMR)
 
diff --git a/arch/arm/mach-pxa/include/mach/palmld.h b/arch/arm/mach-pxa/include/mach/palmld.h
new file mode 100644
index 0000000..7c295a4
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/palmld.h
@@ -0,0 +1,109 @@
+/*
+ * GPIOs and interrupts for Palm LifeDrive Handheld Computer
+ *
+ * Authors:	Alex Osborne <ato@meshy.org>
+ *		Marek Vasut <marek.vasut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _INCLUDE_PALMLD_H_
+#define _INCLUDE_PALMLD_H_
+
+/** HERE ARE GPIOs **/
+
+/* GPIOs */
+#define GPIO_NR_PALMLD_GPIO_RESET	1
+#define GPIO_NR_PALMLD_POWER_DETECT	4
+#define GPIO_NR_PALMLD_HOTSYNC_BUTTON_N	10
+#define GPIO_NR_PALMLD_POWER_SWITCH	12
+#define GPIO_NR_PALMLD_EARPHONE_DETECT 	13
+#define GPIO_NR_PALMLD_LOCK_SWITCH	15
+
+/* SD/MMC */
+#define GPIO_NR_PALMLD_SD_DETECT_N	14
+#define GPIO_NR_PALMLD_SD_POWER		114
+#define GPIO_NR_PALMLD_SD_READONLY	116
+
+/* TOUCHSCREEN */
+#define GPIO_NR_PALMLD_WM9712_IRQ	27
+
+/* IRDA */
+#define GPIO_NR_PALMLD_IR_DISABLE	108
+
+/* LCD/BACKLIGHT */
+#define GPIO_NR_PALMLD_BL_POWER		19
+#define GPIO_NR_PALMLD_LCD_POWER	96
+
+/* LCD BORDER */
+#define GPIO_NR_PALMLD_BORDER_SWITCH	21
+#define GPIO_NR_PALMLD_BORDER_SELECT	22
+
+/* BLUETOOTH */
+#define GPIO_NR_PALMLD_BT_POWER		17
+#define GPIO_NR_PALMLD_BT_RESET		83
+
+/* PCMCIA (WiFi) */
+#define GPIO_NR_PALMLD_PCMCIA_READY	38
+#define GPIO_NR_PALMLD_PCMCIA_POWER	36
+#define GPIO_NR_PALMLD_PCMCIA_RESET	81
+
+/* LEDs */
+#define GPIO_NR_PALMLD_LED_GREEN	52
+#define GPIO_NR_PALMLD_LED_AMBER	94
+
+/* IDE */
+#define GPIO_NR_PALMLD_IDE_IRQ		95
+#define GPIO_NR_PALMLD_IDE_RESET	98
+#define GPIO_NR_PALMLD_IDE_PWEN		115
+
+/* USB */
+#define GPIO_NR_PALMLD_USB_DETECT_N	3
+#define GPIO_NR_PALMLD_USB_READY	86
+#define GPIO_NR_PALMLD_USB_RESET	88
+#define GPIO_NR_PALMLD_USB_INT		106
+#define GPIO_NR_PALMLD_USB_POWER	118
+/* 20, 53 and 86 are usb related too */
+
+/* INTERRUPTS */
+#define IRQ_GPIO_PALMLD_GPIO_RESET	IRQ_GPIO(GPIO_NR_PALMLD_GPIO_RESET)
+#define IRQ_GPIO_PALMLD_SD_DETECT_N	IRQ_GPIO(GPIO_NR_PALMLD_SD_DETECT_N)
+#define IRQ_GPIO_PALMLD_WM9712_IRQ	IRQ_GPIO(GPIO_NR_PALMLD_WM9712_IRQ)
+#define IRQ_GPIO_PALMLD_IDE_IRQ		IRQ_GPIO(GPIO_NR_PALMLD_IDE_IRQ)
+
+
+/** HERE ARE INIT VALUES **/
+
+/* IO mappings */
+#define PALMLD_USB_PHYS		PXA_CS2_PHYS
+#define PALMLD_USB_VIRT		0xf0000000
+#define PALMLD_USB_SIZE		0x00100000
+
+#define PALMLD_IDE_PHYS		0x20000000
+#define PALMLD_IDE_VIRT		0xf1000000
+#define PALMLD_IDE_SIZE		0x00100000
+
+#define PALMLD_PHYS_IO_START	0x40000000
+
+/* BATTERY */
+#define PALMLD_BAT_MAX_VOLTAGE		4000	/* 4.00V maximum voltage */
+#define PALMLD_BAT_MIN_VOLTAGE		3550	/* 3.55V critical voltage */
+#define PALMLD_BAT_MAX_CURRENT		0	/* unknokn */
+#define PALMLD_BAT_MIN_CURRENT		0	/* unknown */
+#define PALMLD_BAT_MAX_CHARGE		1	/* unknown */
+#define PALMLD_BAT_MIN_CHARGE		1	/* unknown */
+#define PALMLD_MAX_LIFE_MINS		240	/* on-life in minutes */
+
+#define PALMLD_BAT_MEASURE_DELAY	(HZ * 1)
+
+/* BACKLIGHT */
+#define PALMLD_MAX_INTENSITY		0xFE
+#define PALMLD_DEFAULT_INTENSITY	0x7E
+#define PALMLD_LIMIT_MASK		0x7F
+#define PALMLD_PRESCALER		0x3F
+#define PALMLD_PERIOD_NS		3500
+
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/palmt5.h b/arch/arm/mach-pxa/include/mach/palmt5.h
new file mode 100644
index 0000000..94db288
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/palmt5.h
@@ -0,0 +1,84 @@
+/*
+ * GPIOs and interrupts for Palm Tungsten|T5 Handheld Computer
+ *
+ * Authors:	Ales Snuparek <snuparek@atlas.cz>
+ *		Marek Vasut <marek.vasut@gmail.com>
+ *		Justin Kendrick <twilightsentry@gmail.com>
+ *		RichardT5 <richard_t5@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.
+ *
+ */
+
+#ifndef _INCLUDE_PALMT5_H_
+#define _INCLUDE_PALMT5_H_
+
+/** HERE ARE GPIOs **/
+
+/* GPIOs */
+#define GPIO_NR_PALMT5_GPIO_RESET		1
+
+#define GPIO_NR_PALMT5_POWER_DETECT		90
+#define GPIO_NR_PALMT5_HOTSYNC_BUTTON_N		10
+#define GPIO_NR_PALMT5_EARPHONE_DETECT		107
+
+/* SD/MMC */
+#define GPIO_NR_PALMT5_SD_DETECT_N		14
+#define GPIO_NR_PALMT5_SD_POWER			114
+#define GPIO_NR_PALMT5_SD_READONLY		115
+
+/* TOUCHSCREEN */
+#define GPIO_NR_PALMT5_WM9712_IRQ		27
+
+/* IRDA - disable GPIO connected to SD pin of tranceiver (TFBS4710?) ? */
+#define GPIO_NR_PALMT5_IR_DISABLE		40
+
+/* USB */
+#define GPIO_NR_PALMT5_USB_DETECT_N		15
+#define GPIO_NR_PALMT5_USB_POWER		95
+#define GPIO_NR_PALMT5_USB_PULLUP		93
+
+/* LCD/BACKLIGHT */
+#define GPIO_NR_PALMT5_BL_POWER			84
+#define GPIO_NR_PALMT5_LCD_POWER		96
+
+/* BLUETOOTH */
+#define GPIO_NR_PALMT5_BT_POWER			17
+#define GPIO_NR_PALMT5_BT_RESET			83
+
+/* INTERRUPTS */
+#define IRQ_GPIO_PALMT5_SD_DETECT_N	IRQ_GPIO(GPIO_NR_PALMT5_SD_DETECT_N)
+#define IRQ_GPIO_PALMT5_WM9712_IRQ	IRQ_GPIO(GPIO_NR_PALMT5_WM9712_IRQ)
+#define IRQ_GPIO_PALMT5_USB_DETECT	IRQ_GPIO(GPIO_NR_PALMT5_USB_DETECT)
+#define IRQ_GPIO_PALMT5_GPIO_RESET	IRQ_GPIO(GPIO_NR_PALMT5_GPIO_RESET)
+
+/** HERE ARE INIT VALUES **/
+
+/* Various addresses  */
+#define PALMT5_PHYS_RAM_START	0xa0000000
+#define PALMT5_PHYS_IO_START	0x40000000
+
+/* TOUCHSCREEN */
+#define AC97_LINK_FRAME		21
+
+/* BATTERY */
+#define PALMT5_BAT_MAX_VOLTAGE		4000	/* 4.00v current voltage */
+#define PALMT5_BAT_MIN_VOLTAGE		3550	/* 3.55v critical voltage */
+#define PALMT5_BAT_MAX_CURRENT		0	/* unknokn */
+#define PALMT5_BAT_MIN_CURRENT		0	/* unknown */
+#define PALMT5_BAT_MAX_CHARGE		1	/* unknown */
+#define PALMT5_BAT_MIN_CHARGE		1	/* unknown */
+#define PALMT5_MAX_LIFE_MINS		360    /* on-life in minutes */
+
+#define PALMT5_BAT_MEASURE_DELAY	(HZ * 1)
+
+/* BACKLIGHT */
+#define PALMT5_MAX_INTENSITY		0xFE
+#define PALMT5_DEFAULT_INTENSITY	0x7E
+#define PALMT5_LIMIT_MASK		0x7F
+#define PALMT5_PRESCALER		0x3F
+#define PALMT5_PERIOD_NS		3500
+
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index 8334246..a6eeef8 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -27,3 +27,13 @@
 extern void pxa_cpu_resume(void);
 
 extern int pxa_pm_enter(suspend_state_t state);
+
+/* NOTE: this is for PM debugging on Lubbock,  it's really a big
+ * ugly, but let's keep the crap minimum here, instead of direct
+ * accessing the LUBBOCK CPLD registers in arch/arm/mach-pxa/pm.c
+ */
+#ifdef CONFIG_ARCH_LUBBOCK
+extern void lubbock_set_hexled(uint32_t value);
+#else
+#define lubbock_set_hexled(x)
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/pxa-regs.h b/arch/arm/mach-pxa/include/mach/pxa-regs.h
deleted file mode 100644
index 31d615a..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa-regs.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *  arch/arm/mach-pxa/include/mach/pxa-regs.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.
- */
-
-#ifndef __PXA_REGS_H
-#define __PXA_REGS_H
-
-#include <mach/hardware.h>
-
-/*
- * PXA Chip selects
- */
-
-#define PXA_CS0_PHYS	0x00000000
-#define PXA_CS1_PHYS	0x04000000
-#define PXA_CS2_PHYS	0x08000000
-#define PXA_CS3_PHYS	0x0C000000
-#define PXA_CS4_PHYS	0x10000000
-#define PXA_CS5_PHYS	0x14000000
-
-
-/*
- * Personal Computer Memory Card International Association (PCMCIA) sockets
- */
-
-#define PCMCIAPrtSp	0x04000000	/* PCMCIA Partition Space [byte]   */
-#define PCMCIASp	(4*PCMCIAPrtSp)	/* PCMCIA Space [byte]             */
-#define PCMCIAIOSp	PCMCIAPrtSp	/* PCMCIA I/O Space [byte]         */
-#define PCMCIAAttrSp	PCMCIAPrtSp	/* PCMCIA Attribute Space [byte]   */
-#define PCMCIAMemSp	PCMCIAPrtSp	/* PCMCIA Memory Space [byte]      */
-
-#define PCMCIA0Sp	PCMCIASp	/* PCMCIA 0 Space [byte]           */
-#define PCMCIA0IOSp	PCMCIAIOSp	/* PCMCIA 0 I/O Space [byte]       */
-#define PCMCIA0AttrSp	PCMCIAAttrSp	/* PCMCIA 0 Attribute Space [byte] */
-#define PCMCIA0MemSp	PCMCIAMemSp	/* PCMCIA 0 Memory Space [byte]    */
-
-#define PCMCIA1Sp	PCMCIASp	/* PCMCIA 1 Space [byte]           */
-#define PCMCIA1IOSp	PCMCIAIOSp	/* PCMCIA 1 I/O Space [byte]       */
-#define PCMCIA1AttrSp	PCMCIAAttrSp	/* PCMCIA 1 Attribute Space [byte] */
-#define PCMCIA1MemSp	PCMCIAMemSp	/* PCMCIA 1 Memory Space [byte]    */
-
-#define _PCMCIA(Nb)	        	/* PCMCIA [0..1]                   */ \
-                	(0x20000000 + (Nb)*PCMCIASp)
-#define _PCMCIAIO(Nb)	_PCMCIA (Nb)	/* PCMCIA I/O [0..1]               */
-#define _PCMCIAAttr(Nb)	        	/* PCMCIA Attribute [0..1]         */ \
-                	(_PCMCIA (Nb) + 2*PCMCIAPrtSp)
-#define _PCMCIAMem(Nb)	        	/* PCMCIA Memory [0..1]            */ \
-                	(_PCMCIA (Nb) + 3*PCMCIAPrtSp)
-
-#define _PCMCIA0	_PCMCIA (0)	/* PCMCIA 0                        */
-#define _PCMCIA0IO	_PCMCIAIO (0)	/* PCMCIA 0 I/O                    */
-#define _PCMCIA0Attr	_PCMCIAAttr (0)	/* PCMCIA 0 Attribute              */
-#define _PCMCIA0Mem	_PCMCIAMem (0)	/* PCMCIA 0 Memory                 */
-
-#define _PCMCIA1	_PCMCIA (1)	/* PCMCIA 1                        */
-#define _PCMCIA1IO	_PCMCIAIO (1)	/* PCMCIA 1 I/O                    */
-#define _PCMCIA1Attr	_PCMCIAAttr (1)	/* PCMCIA 1 Attribute              */
-#define _PCMCIA1Mem	_PCMCIAMem (1)	/* PCMCIA 1 Memory                 */
-
-
-
-/*
- * DMA Controller
- */
-#define DCSR(x)		__REG2(0x40000000, (x) << 2)
-
-#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
-#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
-#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
-#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
-#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
-#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
-#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
-#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
-
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-#define DCSR_EORIRQEN	(1 << 28)       /* End of Receive Interrupt Enable (R/W) */
-#define DCSR_EORJMPEN	(1 << 27)       /* Jump to next descriptor on EOR */
-#define DCSR_EORSTOPEN	(1 << 26)       /* STOP on an EOR */
-#define DCSR_SETCMPST	(1 << 25)       /* Set Descriptor Compare Status */
-#define DCSR_CLRCMPST	(1 << 24)       /* Clear Descriptor Compare Status */
-#define DCSR_CMPST	(1 << 10)       /* The Descriptor Compare Status */
-#define DCSR_EORINTR	(1 << 9)        /* The end of Receive */
-#endif
-
-#define DALGN		__REG(0x400000a0)  /* DMA Alignment Register */
-#define DINT		__REG(0x400000f0)  /* DMA Interrupt Register */
-
-#define DRCMR(n)	(*(((n) < 64) ? \
-			&__REG2(0x40000100, ((n) & 0x3f) << 2) : \
-			&__REG2(0x40001100, ((n) & 0x3f) << 2)))
-
-#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
-#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number (read / write) */
-
-#define DDADR(x)	__REG2(0x40000200, (x) << 4)
-#define DSADR(x)	__REG2(0x40000204, (x) << 4)
-#define DTADR(x)	__REG2(0x40000208, (x) << 4)
-#define DCMD(x)		__REG2(0x4000020c, (x) << 4)
-
-#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
-#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
-
-#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
-#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
-#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
-#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
-#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
-#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
-#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
-#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
-#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
-#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
-#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
-#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
-#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
-#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
-
-/*
- * Real Time Clock
- */
-
-#define RCNR		__REG(0x40900000)  /* RTC Count Register */
-#define RTAR		__REG(0x40900004)  /* RTC Alarm Register */
-#define RTSR		__REG(0x40900008)  /* RTC Status Register */
-#define RTTR		__REG(0x4090000C)  /* RTC Timer Trim Register */
-#define PIAR		__REG(0x40900038)  /* Periodic Interrupt Alarm Register */
-
-#define RTSR_PICE	(1 << 15)	/* Periodic interrupt count enable */
-#define RTSR_PIALE	(1 << 14)	/* Periodic interrupt Alarm enable */
-#define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
-#define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
-#define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
-#define RTSR_AL		(1 << 0)	/* RTC alarm detected */
-
-
-/*
- * OS Timer & Match Registers
- */
-
-#define OSMR0		__REG(0x40A00000)  /* */
-#define OSMR1		__REG(0x40A00004)  /* */
-#define OSMR2		__REG(0x40A00008)  /* */
-#define OSMR3		__REG(0x40A0000C)  /* */
-#define OSMR4		__REG(0x40A00080)  /* */
-#define OSCR		__REG(0x40A00010)  /* OS Timer Counter Register */
-#define OSCR4		__REG(0x40A00040)  /* OS Timer Counter Register */
-#define OMCR4		__REG(0x40A000C0)  /* */
-#define OSSR		__REG(0x40A00014)  /* OS Timer Status Register */
-#define OWER		__REG(0x40A00018)  /* OS Timer Watchdog Enable Register */
-#define OIER		__REG(0x40A0001C)  /* OS Timer Interrupt Enable Register */
-
-#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
-#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
-#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
-#define OSSR_M0		(1 << 0)	/* Match status channel 0 */
-
-#define OWER_WME	(1 << 0)	/* Watchdog Match Enable */
-
-#define OIER_E3		(1 << 3)	/* Interrupt enable channel 3 */
-#define OIER_E2		(1 << 2)	/* Interrupt enable channel 2 */
-#define OIER_E1		(1 << 1)	/* Interrupt enable channel 1 */
-#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */
-
-
-/*
- * Interrupt Controller
- */
-
-#define ICIP		__REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
-#define ICMR		__REG(0x40D00004)  /* Interrupt Controller Mask Register */
-#define ICLR		__REG(0x40D00008)  /* Interrupt Controller Level Register */
-#define ICFP		__REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
-#define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
-#define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
-
-#define ICIP2		__REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
-#define ICMR2		__REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
-#define ICLR2		__REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
-#define ICFP2		__REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
-#define ICPR2		__REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
-
-/*
- * General Purpose I/O
- */
-
-#define GPLR0		__REG(0x40E00000)  /* GPIO Pin-Level Register GPIO<31:0> */
-#define GPLR1		__REG(0x40E00004)  /* GPIO Pin-Level Register GPIO<63:32> */
-#define GPLR2		__REG(0x40E00008)  /* GPIO Pin-Level Register GPIO<80:64> */
-
-#define GPDR0		__REG(0x40E0000C)  /* GPIO Pin Direction Register GPIO<31:0> */
-#define GPDR1		__REG(0x40E00010)  /* GPIO Pin Direction Register GPIO<63:32> */
-#define GPDR2		__REG(0x40E00014)  /* GPIO Pin Direction Register GPIO<80:64> */
-
-#define GPSR0		__REG(0x40E00018)  /* GPIO Pin Output Set Register GPIO<31:0> */
-#define GPSR1		__REG(0x40E0001C)  /* GPIO Pin Output Set Register GPIO<63:32> */
-#define GPSR2		__REG(0x40E00020)  /* GPIO Pin Output Set Register GPIO<80:64> */
-
-#define GPCR0		__REG(0x40E00024)  /* GPIO Pin Output Clear Register GPIO<31:0> */
-#define GPCR1		__REG(0x40E00028)  /* GPIO Pin Output Clear Register GPIO <63:32> */
-#define GPCR2		__REG(0x40E0002C)  /* GPIO Pin Output Clear Register GPIO <80:64> */
-
-#define GRER0		__REG(0x40E00030)  /* GPIO Rising-Edge Detect Register GPIO<31:0> */
-#define GRER1		__REG(0x40E00034)  /* GPIO Rising-Edge Detect Register GPIO<63:32> */
-#define GRER2		__REG(0x40E00038)  /* GPIO Rising-Edge Detect Register GPIO<80:64> */
-
-#define GFER0		__REG(0x40E0003C)  /* GPIO Falling-Edge Detect Register GPIO<31:0> */
-#define GFER1		__REG(0x40E00040)  /* GPIO Falling-Edge Detect Register GPIO<63:32> */
-#define GFER2		__REG(0x40E00044)  /* GPIO Falling-Edge Detect Register GPIO<80:64> */
-
-#define GEDR0		__REG(0x40E00048)  /* GPIO Edge Detect Status Register GPIO<31:0> */
-#define GEDR1		__REG(0x40E0004C)  /* GPIO Edge Detect Status Register GPIO<63:32> */
-#define GEDR2		__REG(0x40E00050)  /* GPIO Edge Detect Status Register GPIO<80:64> */
-
-#define GAFR0_L		__REG(0x40E00054)  /* GPIO Alternate Function Select Register GPIO<15:0> */
-#define GAFR0_U		__REG(0x40E00058)  /* GPIO Alternate Function Select Register GPIO<31:16> */
-#define GAFR1_L		__REG(0x40E0005C)  /* GPIO Alternate Function Select Register GPIO<47:32> */
-#define GAFR1_U		__REG(0x40E00060)  /* GPIO Alternate Function Select Register GPIO<63:48> */
-#define GAFR2_L		__REG(0x40E00064)  /* GPIO Alternate Function Select Register GPIO<79:64> */
-#define GAFR2_U		__REG(0x40E00068)  /* GPIO Alternate Function Select Register GPIO<95-80> */
-#define GAFR3_L		__REG(0x40E0006C)  /* GPIO Alternate Function Select Register GPIO<111:96> */
-#define GAFR3_U		__REG(0x40E00070)  /* GPIO Alternate Function Select Register GPIO<127:112> */
-
-#define GPLR3		__REG(0x40E00100)  /* GPIO Pin-Level Register GPIO<127:96> */
-#define GPDR3		__REG(0x40E0010C)  /* GPIO Pin Direction Register GPIO<127:96> */
-#define GPSR3		__REG(0x40E00118)  /* GPIO Pin Output Set Register GPIO<127:96> */
-#define GPCR3		__REG(0x40E00124)  /* GPIO Pin Output Clear Register GPIO<127:96> */
-#define GRER3		__REG(0x40E00130)  /* GPIO Rising-Edge Detect Register GPIO<127:96> */
-#define GFER3		__REG(0x40E0013C)  /* GPIO Falling-Edge Detect Register GPIO<127:96> */
-#define GEDR3		__REG(0x40E00148)  /* GPIO Edge Detect Status Register GPIO<127:96> */
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-#define _GPLR(x)	__REG2(0x40E00000, ((x) & 0x60) >> 3)
-#define _GPDR(x)	__REG2(0x40E0000C, ((x) & 0x60) >> 3)
-#define _GPSR(x)	__REG2(0x40E00018, ((x) & 0x60) >> 3)
-#define _GPCR(x)	__REG2(0x40E00024, ((x) & 0x60) >> 3)
-#define _GRER(x)	__REG2(0x40E00030, ((x) & 0x60) >> 3)
-#define _GFER(x)	__REG2(0x40E0003C, ((x) & 0x60) >> 3)
-#define _GEDR(x)	__REG2(0x40E00048, ((x) & 0x60) >> 3)
-#define _GAFR(x)	__REG2(0x40E00054, ((x) & 0x70) >> 2)
-
-#define GPLR(x) 	(*((((x) & 0x7f) < 96) ? &_GPLR(x) : &GPLR3))
-#define GPDR(x)		(*((((x) & 0x7f) < 96) ? &_GPDR(x) : &GPDR3))
-#define GPSR(x)		(*((((x) & 0x7f) < 96) ? &_GPSR(x) : &GPSR3))
-#define GPCR(x)		(*((((x) & 0x7f) < 96) ? &_GPCR(x) : &GPCR3))
-#define GRER(x)		(*((((x) & 0x7f) < 96) ? &_GRER(x) : &GRER3))
-#define GFER(x)		(*((((x) & 0x7f) < 96) ? &_GFER(x) : &GFER3))
-#define GEDR(x)		(*((((x) & 0x7f) < 96) ? &_GEDR(x) : &GEDR3))
-#define GAFR(x)		(*((((x) & 0x7f) < 96) ? &_GAFR(x) : \
-			 ((((x) & 0x7f) < 112) ? &GAFR3_L : &GAFR3_U)))
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/pxa25x.h b/arch/arm/mach-pxa/include/mach/pxa25x.h
new file mode 100644
index 0000000..508c3ba
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa25x.h
@@ -0,0 +1,8 @@
+#ifndef __MACH_PXA25x_H
+#define __MACH_PXA25x_H
+
+#include <mach/hardware.h>
+#include <mach/pxa2xx-regs.h>
+#include <mach/mfp-pxa25x.h>
+
+#endif /* __MACH_PXA25x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h
new file mode 100644
index 0000000..6876e16
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -0,0 +1,19 @@
+#ifndef __MACH_PXA27x_H
+#define __MACH_PXA27x_H
+
+#include <mach/hardware.h>
+#include <mach/pxa2xx-regs.h>
+#include <mach/mfp-pxa27x.h>
+
+#define ARB_CNTRL	__REG(0x48000048)  /* Arbiter Control Register */
+
+#define ARB_DMA_SLV_PARK	(1<<31)	   /* Be parked with DMA slave when idle */
+#define ARB_CI_PARK		(1<<30)	   /* Be parked with Camera Interface when idle */
+#define ARB_EX_MEM_PARK 	(1<<29)	   /* Be parked with external MEMC when idle */
+#define ARB_INT_MEM_PARK	(1<<28)	   /* Be parked with internal MEMC when idle */
+#define ARB_USB_PARK		(1<<27)	   /* Be parked with USB when idle */
+#define ARB_LCD_PARK		(1<<26)	   /* Be parked with LCD when idle */
+#define ARB_DMA_PARK		(1<<25)	   /* Be parked with DMA when idle */
+#define ARB_CORE_PARK		(1<<24)	   /* Be parked with core when idle */
+#define ARB_LOCK_FLAG		(1<<23)	   /* Only Locking masters gain access to the bus */
+#endif /* __MACH_PXA27x_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h b/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h
index d83393e..1209c44 100644
--- a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h
+++ b/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h
@@ -3,6 +3,8 @@
 
 #warning Please use mfp-pxa2[57]x.h instead of pxa2xx-gpio.h
 
+#include <mach/gpio.h>
+
 /* GPIO alternate function assignments */
 
 #define GPIO1_RST		1	/* reset */
diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
index 77102d6..4fcddd9 100644
--- a/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa2xx-regs.h
@@ -14,6 +14,19 @@
 #ifndef __PXA2XX_REGS_H
 #define __PXA2XX_REGS_H
 
+#include <mach/hardware.h>
+
+/*
+ * PXA Chip selects
+ */
+
+#define PXA_CS0_PHYS	0x00000000
+#define PXA_CS1_PHYS	0x04000000
+#define PXA_CS2_PHYS	0x08000000
+#define PXA_CS3_PHYS	0x0C000000
+#define PXA_CS4_PHYS	0x10000000
+#define PXA_CS5_PHYS	0x14000000
+
 /*
  * Memory controller
  */
@@ -69,24 +82,6 @@
 #define MDREFR_K0RUN	(1 << 13)	/* SDCLK0 Run Control/Status */
 #define MDREFR_E0PIN	(1 << 12)	/* SDCKE0 Level Control/Status */
 
-
-#ifdef CONFIG_PXA27x
-
-#define ARB_CNTRL	__REG(0x48000048)  /* Arbiter Control Register */
-
-#define ARB_DMA_SLV_PARK	(1<<31)	   /* Be parked with DMA slave when idle */
-#define ARB_CI_PARK		(1<<30)	   /* Be parked with Camera Interface when idle */
-#define ARB_EX_MEM_PARK 	(1<<29)	   /* Be parked with external MEMC when idle */
-#define ARB_INT_MEM_PARK	(1<<28)	   /* Be parked with internal MEMC when idle */
-#define ARB_USB_PARK		(1<<27)	   /* Be parked with USB when idle */
-#define ARB_LCD_PARK		(1<<26)	   /* Be parked with LCD when idle */
-#define ARB_DMA_PARK		(1<<25)	   /* Be parked with DMA when idle */
-#define ARB_CORE_PARK		(1<<24)	   /* Be parked with core when idle */
-#define ARB_LOCK_FLAG		(1<<23)	   /* Only Locking masters gain access to the bus */
-
-#endif
-
-
 /*
  * Power Manager
  */
diff --git a/arch/arm/mach-pxa/include/mach/pxa300.h b/arch/arm/mach-pxa/include/mach/pxa300.h
new file mode 100644
index 0000000..2f33076
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa300.h
@@ -0,0 +1,8 @@
+#ifndef __MACH_PXA300_H
+#define __MACH_PXA300_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa300.h>
+
+#endif /* __MACH_PXA300_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa320.h b/arch/arm/mach-pxa/include/mach/pxa320.h
new file mode 100644
index 0000000..cab78e9
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa320.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_PXA320_H
+#define __MACH_PXA320_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa320.h>
+
+#endif /* __MACH_PXA320_H */
+
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
index bcf3fb2..7d1a059 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
@@ -13,6 +13,17 @@
 #ifndef __ASM_ARCH_PXA3XX_REGS_H
 #define __ASM_ARCH_PXA3XX_REGS_H
 
+#include <mach/hardware.h>
+
+/*
+ * Static Chip Selects
+ */
+
+#define PXA300_CS0_PHYS		(0x00000000)	/* PXA300/PXA310 _only_ */
+#define PXA300_CS1_PHYS		(0x30000000)	/* PXA300/PXA310 _only_ */
+#define PXA3xx_CS2_PHYS		(0x10000000)
+#define PXA3xx_CS3_PHYS		(0x14000000)
+
 /*
  * Oscillator Configuration Register (OSCC)
  */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930.h b/arch/arm/mach-pxa/include/mach/pxa930.h
new file mode 100644
index 0000000..d45f76a
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa930.h
@@ -0,0 +1,8 @@
+#ifndef __MACH_PXA930_H
+#define __MACH_PXA930_H
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa930.h>
+
+#endif /* __MACH_PXA930_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h b/arch/arm/mach-pxa/include/mach/regs-intc.h
new file mode 100644
index 0000000..ad23e74
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/regs-intc.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_MACH_REGS_INTC_H
+#define __ASM_MACH_REGS_INTC_H
+
+#include <mach/hardware.h>
+
+/*
+ * Interrupt Controller
+ */
+
+#define ICIP		__REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
+#define ICMR		__REG(0x40D00004)  /* Interrupt Controller Mask Register */
+#define ICLR		__REG(0x40D00008)  /* Interrupt Controller Level Register */
+#define ICFP		__REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
+#define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
+#define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
+
+#define ICIP2		__REG(0x40D0009C)  /* Interrupt Controller IRQ Pending Register 2 */
+#define ICMR2		__REG(0x40D000A0)  /* Interrupt Controller Mask Register 2 */
+#define ICLR2		__REG(0x40D000A4)  /* Interrupt Controller Level Register 2 */
+#define ICFP2		__REG(0x40D000A8)  /* Interrupt Controller FIQ Pending Register 2 */
+#define ICPR2		__REG(0x40D000AC)  /* Interrupt Controller Pending Register 2 */
+
+#endif /* __ASM_MACH_REGS_INTC_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-ost.h b/arch/arm/mach-pxa/include/mach/regs-ost.h
new file mode 100644
index 0000000..a3e5f86
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/regs-ost.h
@@ -0,0 +1,34 @@
+#ifndef __ASM_MACH_REGS_OST_H
+#define __ASM_MACH_REGS_OST_H
+
+#include <mach/hardware.h>
+
+/*
+ * OS Timer & Match Registers
+ */
+
+#define OSMR0		__REG(0x40A00000)  /* */
+#define OSMR1		__REG(0x40A00004)  /* */
+#define OSMR2		__REG(0x40A00008)  /* */
+#define OSMR3		__REG(0x40A0000C)  /* */
+#define OSMR4		__REG(0x40A00080)  /* */
+#define OSCR		__REG(0x40A00010)  /* OS Timer Counter Register */
+#define OSCR4		__REG(0x40A00040)  /* OS Timer Counter Register */
+#define OMCR4		__REG(0x40A000C0)  /* */
+#define OSSR		__REG(0x40A00014)  /* OS Timer Status Register */
+#define OWER		__REG(0x40A00018)  /* OS Timer Watchdog Enable Register */
+#define OIER		__REG(0x40A0001C)  /* OS Timer Interrupt Enable Register */
+
+#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
+#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
+#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
+#define OSSR_M0		(1 << 0)	/* Match status channel 0 */
+
+#define OWER_WME	(1 << 0)	/* Watchdog Match Enable */
+
+#define OIER_E3		(1 << 3)	/* Interrupt enable channel 3 */
+#define OIER_E2		(1 << 2)	/* Interrupt enable channel 2 */
+#define OIER_E1		(1 << 1)	/* Interrupt enable channel 1 */
+#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */
+
+#endif /* __ASM_MACH_REGS_OST_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-rtc.h b/arch/arm/mach-pxa/include/mach/regs-rtc.h
new file mode 100644
index 0000000..f0e4a58
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/regs-rtc.h
@@ -0,0 +1,23 @@
+#ifndef __ASM_MACH_REGS_RTC_H
+#define __ASM_MACH_REGS_RTC_H
+
+#include <mach/hardware.h>
+
+/*
+ * Real Time Clock
+ */
+
+#define RCNR		__REG(0x40900000)  /* RTC Count Register */
+#define RTAR		__REG(0x40900004)  /* RTC Alarm Register */
+#define RTSR		__REG(0x40900008)  /* RTC Status Register */
+#define RTTR		__REG(0x4090000C)  /* RTC Timer Trim Register */
+#define PIAR		__REG(0x40900038)  /* Periodic Interrupt Alarm Register */
+
+#define RTSR_PICE	(1 << 15)	/* Periodic interrupt count enable */
+#define RTSR_PIALE	(1 << 14)	/* Periodic interrupt Alarm enable */
+#define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
+#define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
+#define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
+#define RTSR_AL		(1 << 0)	/* RTC alarm detected */
+
+#endif /* __ASM_MACH_REGS_RTC_H */
diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h b/arch/arm/mach-pxa/include/mach/regs-ssp.h
index 018f6d6..6a2ed35 100644
--- a/arch/arm/mach-pxa/include/mach/regs-ssp.h
+++ b/arch/arm/mach-pxa/include/mach/regs-ssp.h
@@ -37,7 +37,6 @@
 #if defined(CONFIG_PXA25x)
 #define SSCR0_SCR	(0x0000ff00)	/* Serial Clock Rate (mask) */
 #define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
-
 #elif defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define SSCR0_SCR	(0x000fff00)	/* Serial Clock Rate (mask) */
 #define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
diff --git a/arch/arm/mach-pxa/include/mach/system.h b/arch/arm/mach-pxa/include/mach/system.h
index 0f381e6..d1fce8b 100644
--- a/arch/arm/mach-pxa/include/mach/system.h
+++ b/arch/arm/mach-pxa/include/mach/system.h
@@ -13,7 +13,6 @@
 #include <asm/proc-fns.h>
 #include "hardware.h"
 #include "pxa2xx-regs.h"
-#include "pxa-regs.h"
 
 static inline void arch_idle(void)
 {
@@ -21,4 +20,4 @@
 }
 
 
-void arch_reset(char mode);
+void arch_reset(char mode, const char *cmd);
diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h
index f4b029c..5706cea 100644
--- a/arch/arm/mach-pxa/include/mach/uncompress.h
+++ b/arch/arm/mach-pxa/include/mach/uncompress.h
@@ -35,7 +35,8 @@
 
 static inline void arch_decomp_setup(void)
 {
-	if (machine_is_littleton() || machine_is_intelmote2())
+	if (machine_is_littleton() || machine_is_intelmote2()
+			|| machine_is_csb726())
 		UART = STUART;
 }
 
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index fa69c3a..f6e0300 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -20,7 +20,8 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
-#include <mach/pxa-regs.h>
+#include <mach/gpio.h>
+#include <mach/regs-intc.h>
 
 #include "generic.h"
 
@@ -51,6 +52,72 @@
 	.unmask		= pxa_unmask_irq,
 };
 
+/*
+ * GPIO IRQs for GPIO 0 and 1
+ */
+static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type)
+{
+	int gpio = irq - IRQ_GPIO0;
+
+	if (__gpio_is_occupied(gpio)) {
+		pr_err("%s failed: GPIO is configured\n", __func__);
+		return -EINVAL;
+	}
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		GRER0 |= GPIO_bit(gpio);
+	else
+		GRER0 &= ~GPIO_bit(gpio);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		GFER0 |= GPIO_bit(gpio);
+	else
+		GFER0 &= ~GPIO_bit(gpio);
+
+	return 0;
+}
+
+static void pxa_ack_low_gpio(unsigned int irq)
+{
+	GEDR0 = (1 << (irq - IRQ_GPIO0));
+}
+
+static void pxa_mask_low_gpio(unsigned int irq)
+{
+	ICMR &= ~(1 << (irq - PXA_IRQ(0)));
+}
+
+static void pxa_unmask_low_gpio(unsigned int irq)
+{
+	ICMR |= 1 << (irq - PXA_IRQ(0));
+}
+
+static struct irq_chip pxa_low_gpio_chip = {
+	.name		= "GPIO-l",
+	.ack		= pxa_ack_low_gpio,
+	.mask		= pxa_mask_low_gpio,
+	.unmask		= pxa_unmask_low_gpio,
+	.set_type	= pxa_set_low_gpio_type,
+};
+
+static void __init pxa_init_low_gpio_irq(set_wake_t fn)
+{
+	int irq;
+
+	/* clear edge detection on GPIO 0 and 1 */
+	GFER0 &= ~0x3;
+	GRER0 &= ~0x3;
+	GEDR0 = 0x3;
+
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+		set_irq_chip(irq, &pxa_low_gpio_chip);
+		set_irq_handler(irq, handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	pxa_low_gpio_chip.set_wake = fn;
+}
+
 void __init pxa_init_irq(int irq_nr, set_wake_t fn)
 {
 	int irq;
@@ -72,6 +139,7 @@
 	}
 
 	pxa_internal_irq_chip.set_wake = fn;
+	pxa_init_low_gpio_irq(fn);
 }
 
 #ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
index 18b20d4..8b9c171 100644
--- a/arch/arm/mach-pxa/leds-idp.c
+++ b/arch/arm/mach-pxa/leds-idp.c
@@ -18,7 +18,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
-#include <mach/pxa-regs.h>
+#include <mach/pxa25x.h>
 #include <mach/idp.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
index 1a25802..e26d5ef 100644
--- a/arch/arm/mach-pxa/leds-lubbock.c
+++ b/arch/arm/mach-pxa/leds-lubbock.c
@@ -16,7 +16,7 @@
 #include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa25x.h>
 #include <mach/lubbock.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c
index 95e06b8..db4af5e 100644
--- a/arch/arm/mach-pxa/leds-mainstone.c
+++ b/arch/arm/mach-pxa/leds-mainstone.c
@@ -16,7 +16,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
-#include <mach/pxa-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/mainstone.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 31da7f3..e13f6a8 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -39,8 +39,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
 #include <mach/pxafb.h>
 #include <mach/ssp.h>
 #include <mach/pxa2xx_spi.h>
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index de3f67d..d64395f 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -38,9 +38,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
+#include <mach/gpio.h>
 #include <mach/lpd270.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index bff7043..f04c833 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -41,15 +41,15 @@
 
 #include <asm/hardware/sa1111.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
+#include <mach/gpio.h>
 #include <mach/audio.h>
 #include <mach/lubbock.h>
 #include <mach/udc.h>
 #include <mach/irda.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
+#include <mach/pm.h>
 
 #include "generic.h"
 #include "clock.h"
@@ -113,8 +113,14 @@
 	GPIO1_GPIO | WAKEUP_ON_EDGE_RISE,
 };
 
+#define LUB_HEXLED		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x010)
 #define LUB_MISC_WR		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
 
+void lubbock_set_hexled(uint32_t value)
+{
+	LUB_HEXLED = value;
+}
+
 void lubbock_set_misc_wr(unsigned int mask, unsigned int set)
 {
 	unsigned long flags;
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 21b821e..d46b367 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -25,14 +25,14 @@
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
 #include <linux/pwm_backlight.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+
+#include <mach/pxa27x.h>
 #include <mach/magician.h>
-#include <mach/mfp-pxa27x.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
 #include <mach/pxafb.h>
 #include <mach/i2c.h>
 #include <mach/mmc.h>
@@ -66,6 +66,11 @@
 	GPIO31_I2S_SYNC,
 	GPIO113_I2S_SYSCLK,
 
+	/* SSP 1 */
+	GPIO23_SSP1_SCLK,
+	GPIO24_SSP1_SFRM,
+	GPIO25_SSP1_TXD,
+
 	/* SSP 2 */
 	GPIO19_SSP2_SCLK,
 	GPIO14_SSP2_SFRM,
@@ -148,22 +153,31 @@
  * GPIO Keys
  */
 
+#define INIT_KEY(_code, _gpio, _desc)	\
+	{				\
+		.code   = KEY_##_code,	\
+		.gpio   = _gpio,	\
+		.desc   = _desc,	\
+		.type   = EV_KEY,	\
+		.wakeup = 1,		\
+	}
+
 static struct gpio_keys_button magician_button_table[] = {
-	{KEY_POWER,      GPIO0_MAGICIAN_KEY_POWER,      0, "Power button"},
-	{KEY_ESC,        GPIO37_MAGICIAN_KEY_HANGUP,    0, "Hangup button"},
-	{KEY_F10,        GPIO38_MAGICIAN_KEY_CONTACTS,  0, "Contacts button"},
-	{KEY_CALENDAR,   GPIO90_MAGICIAN_KEY_CALENDAR,  0, "Calendar button"},
-	{KEY_CAMERA,     GPIO91_MAGICIAN_KEY_CAMERA,    0, "Camera button"},
-	{KEY_UP,         GPIO93_MAGICIAN_KEY_UP,        0, "Up button"},
-	{KEY_DOWN,       GPIO94_MAGICIAN_KEY_DOWN,      0, "Down button"},
-	{KEY_LEFT,       GPIO95_MAGICIAN_KEY_LEFT,      0, "Left button"},
-	{KEY_RIGHT,      GPIO96_MAGICIAN_KEY_RIGHT,     0, "Right button"},
-	{KEY_KPENTER,    GPIO97_MAGICIAN_KEY_ENTER,     0, "Action button"},
-	{KEY_RECORD,     GPIO98_MAGICIAN_KEY_RECORD,    0, "Record button"},
-	{KEY_VOLUMEUP,   GPIO100_MAGICIAN_KEY_VOL_UP,   0, "Volume up"},
-	{KEY_VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, 0, "Volume down"},
-	{KEY_PHONE,      GPIO102_MAGICIAN_KEY_PHONE,    0, "Phone button"},
-	{KEY_PLAY,       GPIO99_MAGICIAN_HEADPHONE_IN,  0, "Headset button"},
+	INIT_KEY(POWER,      GPIO0_MAGICIAN_KEY_POWER,      "Power button"),
+	INIT_KEY(ESC,        GPIO37_MAGICIAN_KEY_HANGUP,    "Hangup button"),
+	INIT_KEY(F10,        GPIO38_MAGICIAN_KEY_CONTACTS,  "Contacts button"),
+	INIT_KEY(CALENDAR,   GPIO90_MAGICIAN_KEY_CALENDAR,  "Calendar button"),
+	INIT_KEY(CAMERA,     GPIO91_MAGICIAN_KEY_CAMERA,    "Camera button"),
+	INIT_KEY(UP,         GPIO93_MAGICIAN_KEY_UP,        "Up button"),
+	INIT_KEY(DOWN,       GPIO94_MAGICIAN_KEY_DOWN,      "Down button"),
+	INIT_KEY(LEFT,       GPIO95_MAGICIAN_KEY_LEFT,      "Left button"),
+	INIT_KEY(RIGHT,      GPIO96_MAGICIAN_KEY_RIGHT,     "Right button"),
+	INIT_KEY(KPENTER,    GPIO97_MAGICIAN_KEY_ENTER,     "Action button"),
+	INIT_KEY(RECORD,     GPIO98_MAGICIAN_KEY_RECORD,    "Record button"),
+	INIT_KEY(VOLUMEUP,   GPIO100_MAGICIAN_KEY_VOL_UP,   "Volume up"),
+	INIT_KEY(VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, "Volume down"),
+	INIT_KEY(PHONE,      GPIO102_MAGICIAN_KEY_PHONE,    "Phone button"),
+	INIT_KEY(PLAY,       GPIO99_MAGICIAN_HEADPHONE_IN,  "Headset button"),
 };
 
 static struct gpio_keys_platform_data gpio_keys_data = {
@@ -189,7 +203,7 @@
 static struct resource egpio_resources[] = {
 	[0] = {
 		.start = PXA_CS3_PHYS,
-		.end   = PXA_CS3_PHYS + 0x20,
+		.end   = PXA_CS3_PHYS + 0x20 - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -420,7 +434,7 @@
 	},
 	{
 		.name = "magician::phone_bl",
-		.default_trigger = "none",
+		.default_trigger = "backlight",
 		.gpio = GPIO103_MAGICIAN_LED_KP,
 	},
 };
@@ -468,8 +482,6 @@
 	},
 };
 
-static struct platform_device pasic3;
-
 static struct pasic3_leds_machinfo pasic3_leds_info = {
 	.num_leds   = ARRAY_SIZE(pasic3_leds),
 	.power_gpio = EGPIO_MAGICIAN_LED_POWER,
@@ -511,6 +523,31 @@
 };
 
 /*
+ * USB "Transceiver"
+ */
+
+static struct resource gpio_vbus_resource = {
+	.flags = IORESOURCE_IRQ,
+	.start = IRQ_MAGICIAN_VBUS,
+	.end   = IRQ_MAGICIAN_VBUS,
+};
+
+static struct gpio_vbus_mach_info gpio_vbus_info = {
+	.gpio_pullup = GPIO27_MAGICIAN_USBC_PUEN,
+	.gpio_vbus   = EGPIO_MAGICIAN_CABLE_STATE_USB,
+};
+
+static struct platform_device gpio_vbus = {
+	.name          = "gpio-vbus",
+	.id            = -1,
+	.num_resources = 1,
+	.resource      = &gpio_vbus_resource,
+	.dev = {
+		.platform_data = &gpio_vbus_info,
+	},
+};
+
+/*
  * External power
  */
 
@@ -586,15 +623,17 @@
 static struct resource power_supply_resources[] = {
 	[0] = {
 		.name  = "ac",
-		.flags = IORESOURCE_IRQ,
-		.start = IRQ_MAGICIAN_AC,
-		.end   = IRQ_MAGICIAN_AC,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = IRQ_MAGICIAN_VBUS,
+		.end   = IRQ_MAGICIAN_VBUS,
 	},
 	[1] = {
 		.name  = "usb",
-		.flags = IORESOURCE_IRQ,
-		.start = IRQ_MAGICIAN_AC,
-		.end   = IRQ_MAGICIAN_AC,
+		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE |
+		         IORESOURCE_IRQ_LOWEDGE,
+		.start = IRQ_MAGICIAN_VBUS,
+		.end   = IRQ_MAGICIAN_VBUS,
 	},
 };
 
@@ -688,11 +727,9 @@
 	gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);
 }
 
-#define PXA_CS_SIZE		0x04000000
-
 static struct resource strataflash_resource = {
 	.start = PXA_CS0_PHYS,
-	.end   = PXA_CS0_PHYS + PXA_CS_SIZE - 1,
+	.end   = PXA_CS0_PHYS + SZ_64M - 1,
 	.flags = IORESOURCE_MEM,
 };
 
@@ -720,6 +757,7 @@
 	&egpio,
 	&backlight,
 	&pasic3,
+	&gpio_vbus,
 	&power_supply,
 	&strataflash,
 	&leds_gpio,
@@ -743,6 +781,7 @@
 		gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
 		pxa_set_ficp_info(&magician_ficp_info);
 	}
+	pxa27x_set_i2c_power_info(NULL);
 	pxa_set_i2c_info(NULL);
 	pxa_set_mci_info(&magician_mci_info);
 	pxa_set_ohci_info(&magician_ohci_info);
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 5f22496..a6c8429 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -41,9 +41,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
+#include <mach/gpio.h>
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index 33626de..7ffb91d 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -18,15 +18,12 @@
 #include <linux/init.h>
 #include <linux/sysdev.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/gpio.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa2xx.h>
 
 #include "generic.h"
 
-#define gpio_to_bank(gpio)	((gpio) >> 5)
-
 #define PGSR(x)		__REG2(0x40F00020, (x) << 2)
 #define __GAFR(u, x)	__REG2((u) ? 0x40E00058 : 0x40E00054, (x) << 3)
 #define GAFR_L(x)	__GAFR(0, x)
diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c
index eb197a6..7a270ee 100644
--- a/arch/arm/mach-pxa/mfp-pxa3xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa3xx.c
@@ -20,183 +20,9 @@
 #include <linux/sysdev.h>
 
 #include <mach/hardware.h>
-#include <mach/mfp.h>
 #include <mach/mfp-pxa3xx.h>
 #include <mach/pxa3xx-regs.h>
 
-/* mfp_spin_lock is used to ensure that MFP register configuration
- * (most likely a read-modify-write operation) is atomic, and that
- * mfp_table[] is consistent
- */
-static DEFINE_SPINLOCK(mfp_spin_lock);
-
-static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
-
-struct pxa3xx_mfp_pin {
-	unsigned long	config;		/* -1 for not configured */
-	unsigned long	mfpr_off;	/* MFPRxx Register offset */
-	unsigned long	mfpr_run;	/* Run-Mode Register Value */
-	unsigned long	mfpr_lpm;	/* Low Power Mode Register Value */
-};
-
-static struct pxa3xx_mfp_pin mfp_table[MFP_PIN_MAX];
-
-/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
-static const unsigned long mfpr_lpm[] = {
-	MFPR_LPM_INPUT,
-	MFPR_LPM_DRIVE_LOW,
-	MFPR_LPM_DRIVE_HIGH,
-	MFPR_LPM_PULL_LOW,
-	MFPR_LPM_PULL_HIGH,
-	MFPR_LPM_FLOAT,
-};
-
-/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
-static const unsigned long mfpr_pull[] = {
-	MFPR_PULL_NONE,
-	MFPR_PULL_LOW,
-	MFPR_PULL_HIGH,
-	MFPR_PULL_BOTH,
-};
-
-/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
-static const unsigned long mfpr_edge[] = {
-	MFPR_EDGE_NONE,
-	MFPR_EDGE_RISE,
-	MFPR_EDGE_FALL,
-	MFPR_EDGE_BOTH,
-};
-
-#define mfpr_readl(off)			\
-	__raw_readl(mfpr_mmio_base + (off))
-
-#define mfpr_writel(off, val)		\
-	__raw_writel(val, mfpr_mmio_base + (off))
-
-#define mfp_configured(p)	((p)->config != -1)
-
-/*
- * perform a read-back of any MFPR register to make sure the
- * previous writings are finished
- */
-#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)
-
-static inline void __mfp_config_run(struct pxa3xx_mfp_pin *p)
-{
-	if (mfp_configured(p))
-		mfpr_writel(p->mfpr_off, p->mfpr_run);
-}
-
-static inline void __mfp_config_lpm(struct pxa3xx_mfp_pin *p)
-{
-	if (mfp_configured(p)) {
-		unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
-		if (mfpr_clr != p->mfpr_run)
-			mfpr_writel(p->mfpr_off, mfpr_clr);
-		if (p->mfpr_lpm != mfpr_clr)
-			mfpr_writel(p->mfpr_off, p->mfpr_lpm);
-	}
-}
-
-void pxa3xx_mfp_config(unsigned long *mfp_cfgs, int num)
-{
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&mfp_spin_lock, flags);
-
-	for (i = 0; i < num; i++, mfp_cfgs++) {
-		unsigned long tmp, c = *mfp_cfgs;
-		struct pxa3xx_mfp_pin *p;
-		int pin, af, drv, lpm, edge, pull;
-
-		pin = MFP_PIN(c);
-		BUG_ON(pin >= MFP_PIN_MAX);
-		p = &mfp_table[pin];
-
-		af  = MFP_AF(c);
-		drv = MFP_DS(c);
-		lpm = MFP_LPM_STATE(c);
-		edge = MFP_LPM_EDGE(c);
-		pull = MFP_PULL(c);
-
-		/* run-mode pull settings will conflict with MFPR bits of
-		 * low power mode state,  calculate mfpr_run and mfpr_lpm
-		 * individually if pull != MFP_PULL_NONE
-		 */
-		tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
-
-		if (likely(pull == MFP_PULL_NONE)) {
-			p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
-			p->mfpr_lpm = p->mfpr_run;
-		} else {
-			p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
-			p->mfpr_run = tmp | mfpr_pull[pull];
-		}
-
-		p->config = c; __mfp_config_run(p);
-	}
-
-	mfpr_sync();
-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
-}
-
-unsigned long pxa3xx_mfp_read(int mfp)
-{
-	unsigned long val, flags;
-
-	BUG_ON(mfp >= MFP_PIN_MAX);
-
-	spin_lock_irqsave(&mfp_spin_lock, flags);
-	val = mfpr_readl(mfp_table[mfp].mfpr_off);
-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
-
-	return val;
-}
-
-void pxa3xx_mfp_write(int mfp, unsigned long val)
-{
-	unsigned long flags;
-
-	BUG_ON(mfp >= MFP_PIN_MAX);
-
-	spin_lock_irqsave(&mfp_spin_lock, flags);
-	mfpr_writel(mfp_table[mfp].mfpr_off, val);
-	mfpr_sync();
-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
-}
-
-void __init pxa3xx_mfp_init_addr(struct pxa3xx_mfp_addr_map *map)
-{
-	struct pxa3xx_mfp_addr_map *p;
-	unsigned long offset, flags;
-	int i;
-
-	spin_lock_irqsave(&mfp_spin_lock, flags);
-
-	for (p = map; p->start != MFP_PIN_INVALID; p++) {
-		offset = p->offset;
-		i = p->start;
-
-		do {
-			mfp_table[i].mfpr_off = offset;
-			mfp_table[i].mfpr_run = 0;
-			mfp_table[i].mfpr_lpm = 0;
-			offset += 4; i++;
-		} while ((i <= p->end) && (p->end != -1));
-	}
-
-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
-}
-
-void __init pxa3xx_init_mfp(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
-		mfp_table[i].config = -1;
-}
-
 #ifdef CONFIG_PM
 /*
  * Configure the MFPs appropriately for suspend/resume.
@@ -207,23 +33,13 @@
  */
 static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state)
 {
-	int pin;
-
-	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
-		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
-		__mfp_config_lpm(p);
-	}
+	mfp_config_lpm();
 	return 0;
 }
 
 static int pxa3xx_mfp_resume(struct sys_device *d)
 {
-	int pin;
-
-	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
-		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
-		__mfp_config_run(p);
-	}
+	mfp_config_run();
 
 	/* clear RDH bit when MFP settings are restored
 	 *
@@ -231,7 +47,6 @@
 	 * preserve them here in case they will be referenced later
 	 */
 	ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
-
 	return 0;
 }
 #else
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 2b427e0..97c93a7 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -36,13 +36,15 @@
 #include <linux/power_supply.h>
 #include <linux/wm97xx_batt.h>
 #include <linux/mtd/physmap.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/mfp-pxa27x.h>
+
+#include <mach/pxa27x.h>
+#include <mach/regs-rtc.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/pxafb.h>
-#include <mach/pxa2xx-regs.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
@@ -411,21 +413,6 @@
 /*
  * USB UDC
  */
-static void udc_power_command(int cmd)
-{
-	switch (cmd) {
-	case PXA2XX_UDC_CMD_DISCONNECT:
-		gpio_set_value(GPIO22_USB_ENABLE, 0);
-		break;
-	case PXA2XX_UDC_CMD_CONNECT:
-		gpio_set_value(GPIO22_USB_ENABLE, 1);
-		break;
-	default:
-		printk(KERN_INFO "udc_control: unknown command (0x%x)!\n", cmd);
-		break;
-	}
-}
-
 static int is_usb_connected(void)
 {
 	return !gpio_get_value(GPIO13_nUSB_DETECT);
@@ -433,24 +420,15 @@
 
 static struct pxa2xx_udc_mach_info mioa701_udc_info = {
 	.udc_is_connected = is_usb_connected,
-	.udc_command	  = udc_power_command,
+	.gpio_pullup	  = GPIO22_USB_ENABLE,
 };
 
-struct gpio_ress udc_gpios[] = {
-	MIO_GPIO_OUT(GPIO22_USB_ENABLE, 0, "USB Vbus enable")
+struct gpio_vbus_mach_info gpio_vbus_data = {
+	.gpio_vbus = GPIO13_nUSB_DETECT,
+	.gpio_vbus_inverted = 1,
+	.gpio_pullup = -1,
 };
 
-static int __init udc_init(void)
-{
-	pxa_set_udc_info(&mioa701_udc_info);
-	return mio_gpio_request(ARRAY_AND_SIZE(udc_gpios));
-}
-
-static void udc_exit(void)
-{
-	mio_gpio_free(ARRAY_AND_SIZE(udc_gpios));
-}
-
 /*
  * SDIO/MMC Card controller
  */
@@ -789,6 +767,7 @@
 MIO_PARENT_DEV(mio_wm9713_codec,  "wm9713-codec",   &pxa2xx_ac97.dev, NULL)
 MIO_SIMPLE_DEV(mioa701_sound,	  "mioa701-wm9713", NULL)
 MIO_SIMPLE_DEV(mioa701_board,	  "mioa701-board",  NULL)
+MIO_SIMPLE_DEV(gpio_vbus,	  "gpio-vbus",      &gpio_vbus_data);
 
 static struct platform_device *devices[] __initdata = {
 	&mioa701_gpio_keys,
@@ -800,7 +779,8 @@
 	&mioa701_sound,
 	&power_dev,
 	&strataflash,
-	&mioa701_board
+	&gpio_vbus,
+	&mioa701_board,
 };
 
 static void mioa701_machine_exit(void);
@@ -808,13 +788,13 @@
 static void mioa701_poweroff(void)
 {
 	mioa701_machine_exit();
-	arm_machine_restart('s');
+	arm_machine_restart('s', NULL);
 }
 
-static void mioa701_restart(char c)
+static void mioa701_restart(char c, const char *cmd)
 {
 	mioa701_machine_exit();
-	arm_machine_restart('s');
+	arm_machine_restart('s', cmd);
 }
 
 struct gpio_ress global_gpios[] = {
@@ -837,7 +817,7 @@
 	pxa_set_mci_info(&mioa701_mci_info);
 	pxa_set_keypad_info(&mioa701_keypad_info);
 	wm97xx_bat_set_pdata(&mioa701_battery_data);
-	udc_init();
+	pxa_set_udc_info(&mioa701_udc_info);
 	pm_power_off = mioa701_poweroff;
 	arm_pm_restart = mioa701_restart;
 	platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -850,7 +830,6 @@
 
 static void mioa701_machine_exit(void)
 {
-	udc_exit();
 	bootstrap_exit();
 	gsm_exit();
 }
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 8a73814..a65713c 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -19,10 +19,10 @@
 #include <linux/types.h>
 #include <linux/usb/isp116x.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+
+#include <mach/pxa25x.h>
 #include "generic.h"
 
 static void isp116x_pfm_delay(struct device *dev, int delay)
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
new file mode 100644
index 0000000..8587477
--- /dev/null
+++ b/arch/arm/mach-pxa/palmld.c
@@ -0,0 +1,565 @@
+/*
+ * Hardware definitions for Palm LifeDrive
+ *
+ * Author:     Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on work of:
+ *		Alex Osborne <ato@meshy.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.
+ *
+ * (find more info at www.hackndev.com)
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/wm97xx_batt.h>
+#include <linux/power_supply.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/pxa27x.h>
+#include <mach/audio.h>
+#include <mach/palmld.h>
+#include <mach/mmc.h>
+#include <mach/pxafb.h>
+#include <mach/irda.h>
+#include <mach/pxa27x_keypad.h>
+#include <mach/palmasoc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * Pin configuration
+ ******************************************************************************/
+static unsigned long palmld_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO14_GPIO,	/* SD detect */
+	GPIO114_GPIO,	/* SD power */
+	GPIO116_GPIO,	/* SD r/o switch */
+
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
+	/* IrDA */
+	GPIO108_GPIO,	/* ir disable */
+	GPIO46_FICP_RXD,
+	GPIO47_FICP_TXD,
+
+	/* MATRIX KEYPAD */
+	GPIO100_KP_MKIN_0,
+	GPIO101_KP_MKIN_1,
+	GPIO102_KP_MKIN_2,
+	GPIO97_KP_MKIN_3,
+	GPIO103_KP_MKOUT_0,
+	GPIO104_KP_MKOUT_1,
+	GPIO105_KP_MKOUT_2,
+
+	/* LCD */
+	GPIO58_LCD_LDD_0,
+	GPIO59_LCD_LDD_1,
+	GPIO60_LCD_LDD_2,
+	GPIO61_LCD_LDD_3,
+	GPIO62_LCD_LDD_4,
+	GPIO63_LCD_LDD_5,
+	GPIO64_LCD_LDD_6,
+	GPIO65_LCD_LDD_7,
+	GPIO66_LCD_LDD_8,
+	GPIO67_LCD_LDD_9,
+	GPIO68_LCD_LDD_10,
+	GPIO69_LCD_LDD_11,
+	GPIO70_LCD_LDD_12,
+	GPIO71_LCD_LDD_13,
+	GPIO72_LCD_LDD_14,
+	GPIO73_LCD_LDD_15,
+	GPIO74_LCD_FCLK,
+	GPIO75_LCD_LCLK,
+	GPIO76_LCD_PCLK,
+	GPIO77_LCD_BIAS,
+
+	/* PWM */
+	GPIO16_PWM0_OUT,
+
+	/* GPIO KEYS */
+	GPIO10_GPIO,	/* hotsync button */
+	GPIO12_GPIO,	/* power switch */
+	GPIO15_GPIO,	/* lock switch */
+
+	/* LEDs */
+	GPIO52_GPIO,	/* green led */
+	GPIO94_GPIO,	/* orange led */
+
+	/* PCMCIA */
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO79_PSKTSEL,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+	GPIO36_GPIO,	/* wifi power */
+	GPIO38_GPIO,	/* wifi ready */
+	GPIO81_GPIO,	/* wifi reset */
+
+	/* HDD */
+	GPIO95_GPIO,	/* HDD irq */
+	GPIO115_GPIO,	/* HDD power */
+
+	/* MISC */
+	GPIO13_GPIO,	/* earphone detect */
+};
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+static int palmld_mci_init(struct device *dev, irq_handler_t palmld_detect_int,
+				void *data)
+{
+	int err = 0;
+
+	/* Setup an interrupt for detecting card insert/remove events */
+	err = gpio_request(GPIO_NR_PALMLD_SD_DETECT_N, "SD IRQ");
+	if (err)
+		goto err;
+	err = gpio_direction_input(GPIO_NR_PALMLD_SD_DETECT_N);
+	if (err)
+		goto err2;
+	err = request_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N),
+			palmld_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"SD/MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
+				__func__);
+		goto err2;
+	}
+
+	err = gpio_request(GPIO_NR_PALMLD_SD_POWER, "SD_POWER");
+	if (err)
+		goto err3;
+	err = gpio_direction_output(GPIO_NR_PALMLD_SD_POWER, 0);
+	if (err)
+		goto err4;
+
+	err = gpio_request(GPIO_NR_PALMLD_SD_READONLY, "SD_READONLY");
+	if (err)
+		goto err4;
+	err = gpio_direction_input(GPIO_NR_PALMLD_SD_READONLY);
+	if (err)
+		goto err5;
+
+	printk(KERN_DEBUG "%s: irq registered\n", __func__);
+
+	return 0;
+
+err5:
+	gpio_free(GPIO_NR_PALMLD_SD_READONLY);
+err4:
+	gpio_free(GPIO_NR_PALMLD_SD_POWER);
+err3:
+	free_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N), data);
+err2:
+	gpio_free(GPIO_NR_PALMLD_SD_DETECT_N);
+err:
+	return err;
+}
+
+static void palmld_mci_exit(struct device *dev, void *data)
+{
+	gpio_free(GPIO_NR_PALMLD_SD_READONLY);
+	gpio_free(GPIO_NR_PALMLD_SD_POWER);
+	free_irq(gpio_to_irq(GPIO_NR_PALMLD_SD_DETECT_N), data);
+	gpio_free(GPIO_NR_PALMLD_SD_DETECT_N);
+}
+
+static void palmld_mci_power(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data *p_d = dev->platform_data;
+	gpio_set_value(GPIO_NR_PALMLD_SD_POWER, p_d->ocr_mask & (1 << vdd));
+}
+
+static int palmld_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_NR_PALMLD_SD_READONLY);
+}
+
+static struct pxamci_platform_data palmld_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.setpower	= palmld_mci_power,
+	.get_ro		= palmld_mci_get_ro,
+	.init 		= palmld_mci_init,
+	.exit		= palmld_mci_exit,
+};
+
+/******************************************************************************
+ * GPIO keyboard
+ ******************************************************************************/
+static unsigned int palmld_matrix_keys[] = {
+	KEY(0, 1, KEY_F2),
+	KEY(0, 2, KEY_UP),
+
+	KEY(1, 0, KEY_F3),
+	KEY(1, 1, KEY_F4),
+	KEY(1, 2, KEY_RIGHT),
+
+	KEY(2, 0, KEY_F1),
+	KEY(2, 1, KEY_F5),
+	KEY(2, 2, KEY_DOWN),
+
+	KEY(3, 0, KEY_F6),
+	KEY(3, 1, KEY_ENTER),
+	KEY(3, 2, KEY_LEFT),
+};
+
+static struct pxa27x_keypad_platform_data palmld_keypad_platform_data = {
+	.matrix_key_rows	= 4,
+	.matrix_key_cols	= 3,
+	.matrix_key_map		= palmld_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(palmld_matrix_keys),
+
+	.debounce_interval	= 30,
+};
+
+/******************************************************************************
+ * GPIO keys
+ ******************************************************************************/
+static struct gpio_keys_button palmld_pxa_buttons[] = {
+	{KEY_F8, GPIO_NR_PALMLD_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
+	{KEY_F9, GPIO_NR_PALMLD_LOCK_SWITCH, 0, "Lock Switch" },
+	{KEY_POWER, GPIO_NR_PALMLD_POWER_SWITCH, 0, "Power Switch" },
+};
+
+static struct gpio_keys_platform_data palmld_pxa_keys_data = {
+	.buttons	= palmld_pxa_buttons,
+	.nbuttons	= ARRAY_SIZE(palmld_pxa_buttons),
+};
+
+static struct platform_device palmld_pxa_keys = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &palmld_pxa_keys_data,
+	},
+};
+
+/******************************************************************************
+ * Backlight
+ ******************************************************************************/
+static int palmld_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMLD_BL_POWER, "BL POWER");
+	if (ret)
+		goto err;
+	ret = gpio_direction_output(GPIO_NR_PALMLD_BL_POWER, 0);
+	if (ret)
+		goto err2;
+	ret = gpio_request(GPIO_NR_PALMLD_LCD_POWER, "LCD POWER");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_output(GPIO_NR_PALMLD_LCD_POWER, 0);
+	if (ret)
+		goto err3;
+
+	return 0;
+err3:
+	gpio_free(GPIO_NR_PALMLD_LCD_POWER);
+err2:
+	gpio_free(GPIO_NR_PALMLD_BL_POWER);
+err:
+	return ret;
+}
+
+static int palmld_backlight_notify(int brightness)
+{
+	gpio_set_value(GPIO_NR_PALMLD_BL_POWER, brightness);
+	gpio_set_value(GPIO_NR_PALMLD_LCD_POWER, brightness);
+	return brightness;
+}
+
+static void palmld_backlight_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMLD_BL_POWER);
+	gpio_free(GPIO_NR_PALMLD_LCD_POWER);
+}
+
+static struct platform_pwm_backlight_data palmld_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= PALMLD_MAX_INTENSITY,
+	.dft_brightness	= PALMLD_MAX_INTENSITY,
+	.pwm_period_ns	= PALMLD_PERIOD_NS,
+	.init		= palmld_backlight_init,
+	.notify		= palmld_backlight_notify,
+	.exit		= palmld_backlight_exit,
+};
+
+static struct platform_device palmld_backlight = {
+	.name	= "pwm-backlight",
+	.dev	= {
+		.parent		= &pxa27x_device_pwm0.dev,
+		.platform_data	= &palmld_backlight_data,
+	},
+};
+
+/******************************************************************************
+ * IrDA
+ ******************************************************************************/
+static int palmld_irda_startup(struct device *dev)
+{
+	int err;
+	err = gpio_request(GPIO_NR_PALMLD_IR_DISABLE, "IR DISABLE");
+	if (err)
+		goto err;
+	err = gpio_direction_output(GPIO_NR_PALMLD_IR_DISABLE, 1);
+	if (err)
+		gpio_free(GPIO_NR_PALMLD_IR_DISABLE);
+err:
+	return err;
+}
+
+static void palmld_irda_shutdown(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMLD_IR_DISABLE);
+}
+
+static void palmld_irda_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_NR_PALMLD_IR_DISABLE, mode & IR_OFF);
+	pxa2xx_transceiver_mode(dev, mode);
+}
+
+static struct pxaficp_platform_data palmld_ficp_platform_data = {
+	.startup		= palmld_irda_startup,
+	.shutdown		= palmld_irda_shutdown,
+	.transceiver_cap	= IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode	= palmld_irda_transceiver_mode,
+};
+
+/******************************************************************************
+ * LEDs
+ ******************************************************************************/
+struct gpio_led gpio_leds[] = {
+{
+	.name			= "palmld:green:led",
+	.default_trigger	= "none",
+	.gpio			= GPIO_NR_PALMLD_LED_GREEN,
+}, {
+	.name			= "palmld:amber:led",
+	.default_trigger	= "none",
+	.gpio			= GPIO_NR_PALMLD_LED_AMBER,
+},
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device palmld_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_led_info,
+	}
+};
+
+/******************************************************************************
+ * Power supply
+ ******************************************************************************/
+static int power_supply_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMLD_POWER_DETECT, "CABLE_STATE_AC");
+	if (ret)
+		goto err1;
+	ret = gpio_direction_input(GPIO_NR_PALMLD_POWER_DETECT);
+	if (ret)
+		goto err2;
+
+	ret = gpio_request(GPIO_NR_PALMLD_USB_DETECT_N, "CABLE_STATE_USB");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_input(GPIO_NR_PALMLD_USB_DETECT_N);
+	if (ret)
+		goto err3;
+
+	return 0;
+
+err3:
+	gpio_free(GPIO_NR_PALMLD_USB_DETECT_N);
+err2:
+	gpio_free(GPIO_NR_PALMLD_POWER_DETECT);
+err1:
+	return ret;
+}
+
+static int palmld_is_ac_online(void)
+{
+	return gpio_get_value(GPIO_NR_PALMLD_POWER_DETECT);
+}
+
+static int palmld_is_usb_online(void)
+{
+	return !gpio_get_value(GPIO_NR_PALMLD_USB_DETECT_N);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMLD_USB_DETECT_N);
+	gpio_free(GPIO_NR_PALMLD_POWER_DETECT);
+}
+
+static char *palmld_supplicants[] = {
+	"main-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
+	.is_ac_online    = palmld_is_ac_online,
+	.is_usb_online   = palmld_is_usb_online,
+	.exit            = power_supply_exit,
+	.supplied_to     = palmld_supplicants,
+	.num_supplicants = ARRAY_SIZE(palmld_supplicants),
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+};
+
+/******************************************************************************
+ * WM97xx battery
+ ******************************************************************************/
+static struct wm97xx_batt_info wm97xx_batt_pdata = {
+	.batt_aux	= WM97XX_AUX_ID3,
+	.temp_aux	= WM97XX_AUX_ID2,
+	.charge_gpio	= -1,
+	.max_voltage	= PALMLD_BAT_MAX_VOLTAGE,
+	.min_voltage	= PALMLD_BAT_MIN_VOLTAGE,
+	.batt_mult	= 1000,
+	.batt_div	= 414,
+	.temp_mult	= 1,
+	.temp_div	= 1,
+	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.batt_name	= "main-batt",
+};
+
+/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palm27x_asoc_pdata = {
+	.jack_gpio	= GPIO_NR_PALMLD_EARPHONE_DETECT,
+};
+
+/******************************************************************************
+ * Framebuffer
+ ******************************************************************************/
+static struct pxafb_mode_info palmld_lcd_modes[] = {
+{
+	.pixclock	= 57692,
+	.xres		= 320,
+	.yres		= 480,
+	.bpp		= 16,
+
+	.left_margin	= 32,
+	.right_margin	= 1,
+	.upper_margin	= 7,
+	.lower_margin	= 1,
+
+	.hsync_len	= 4,
+	.vsync_len	= 1,
+},
+};
+
+static struct pxafb_mach_info palmld_lcd_screen = {
+	.modes		= palmld_lcd_modes,
+	.num_modes	= ARRAY_SIZE(palmld_lcd_modes),
+	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+/******************************************************************************
+ * Machine init
+ ******************************************************************************/
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+	&palmld_pxa_keys,
+#endif
+	&palmld_backlight,
+	&palmld_leds,
+	&power_supply,
+};
+
+static struct map_desc palmld_io_desc[] __initdata = {
+{
+	.virtual	= PALMLD_IDE_VIRT,
+	.pfn		= __phys_to_pfn(PALMLD_IDE_PHYS),
+	.length		= PALMLD_IDE_SIZE,
+	.type		= MT_DEVICE
+},
+{
+	.virtual	= PALMLD_USB_VIRT,
+	.pfn		= __phys_to_pfn(PALMLD_USB_PHYS),
+	.length		= PALMLD_USB_SIZE,
+	.type		= MT_DEVICE
+},
+};
+
+static void __init palmld_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(palmld_io_desc, ARRAY_SIZE(palmld_io_desc));
+}
+
+static void __init palmld_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config));
+
+	set_pxa_fb_info(&palmld_lcd_screen);
+	pxa_set_mci_info(&palmld_mci_platform_data);
+	pxa_set_ac97_info(NULL);
+	pxa_set_ficp_info(&palmld_ficp_platform_data);
+	pxa_set_keypad_info(&palmld_keypad_platform_data);
+	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
+	palm27x_asoc_set_pdata(&palm27x_asoc_pdata);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(PALMLD, "Palm LifeDrive")
+	.phys_io	= PALMLD_PHYS_IO_START,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= palmld_map_io,
+	.init_irq	= pxa27x_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= palmld_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
new file mode 100644
index 0000000..9521c7b
--- /dev/null
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -0,0 +1,496 @@
+/*
+ * Hardware definitions for Palm Tungsten|T5
+ *
+ * Author:	Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on work of:
+ *		Ales Snuparek <snuparek@atlas.cz>
+ *		Justin Kendrick <twilightsentry@gmail.com>
+ *		RichardT5 <richard_t5@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.
+ *
+ * (find more info at www.hackndev.com)
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/wm97xx_batt.h>
+#include <linux/power_supply.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/pxa27x.h>
+#include <mach/audio.h>
+#include <mach/palmt5.h>
+#include <mach/mmc.h>
+#include <mach/pxafb.h>
+#include <mach/irda.h>
+#include <mach/pxa27x_keypad.h>
+#include <mach/udc.h>
+#include <mach/palmasoc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * Pin configuration
+ ******************************************************************************/
+static unsigned long palmt5_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+	GPIO14_GPIO,	/* SD detect */
+	GPIO114_GPIO,	/* SD power */
+	GPIO115_GPIO,	/* SD r/o switch */
+
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
+	/* IrDA */
+	GPIO40_GPIO,	/* ir disable */
+	GPIO46_FICP_RXD,
+	GPIO47_FICP_TXD,
+
+	/* USB */
+	GPIO15_GPIO,	/* usb detect */
+	GPIO95_GPIO,	/* usb power */
+
+	/* MATRIX KEYPAD */
+	GPIO100_KP_MKIN_0,
+	GPIO101_KP_MKIN_1,
+	GPIO102_KP_MKIN_2,
+	GPIO97_KP_MKIN_3,
+	GPIO103_KP_MKOUT_0,
+	GPIO104_KP_MKOUT_1,
+	GPIO105_KP_MKOUT_2,
+
+	/* LCD */
+	GPIO58_LCD_LDD_0,
+	GPIO59_LCD_LDD_1,
+	GPIO60_LCD_LDD_2,
+	GPIO61_LCD_LDD_3,
+	GPIO62_LCD_LDD_4,
+	GPIO63_LCD_LDD_5,
+	GPIO64_LCD_LDD_6,
+	GPIO65_LCD_LDD_7,
+	GPIO66_LCD_LDD_8,
+	GPIO67_LCD_LDD_9,
+	GPIO68_LCD_LDD_10,
+	GPIO69_LCD_LDD_11,
+	GPIO70_LCD_LDD_12,
+	GPIO71_LCD_LDD_13,
+	GPIO72_LCD_LDD_14,
+	GPIO73_LCD_LDD_15,
+	GPIO74_LCD_FCLK,
+	GPIO75_LCD_LCLK,
+	GPIO76_LCD_PCLK,
+	GPIO77_LCD_BIAS,
+
+	/* PWM */
+	GPIO16_PWM0_OUT,
+
+	/* MISC */
+	GPIO10_GPIO,	/* hotsync button */
+	GPIO90_GPIO,	/* power detect */
+	GPIO107_GPIO,	/* earphone detect */
+};
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+static int palmt5_mci_init(struct device *dev, irq_handler_t palmt5_detect_int,
+				void *data)
+{
+	int err = 0;
+
+	/* Setup an interrupt for detecting card insert/remove events */
+	err = gpio_request(GPIO_NR_PALMT5_SD_DETECT_N, "SD IRQ");
+	if (err)
+		goto err;
+	err = gpio_direction_input(GPIO_NR_PALMT5_SD_DETECT_N);
+	if (err)
+		goto err2;
+	err = request_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N),
+			palmt5_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"SD/MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
+				__func__);
+		goto err2;
+	}
+
+	err = gpio_request(GPIO_NR_PALMT5_SD_POWER, "SD_POWER");
+	if (err)
+		goto err3;
+	err = gpio_direction_output(GPIO_NR_PALMT5_SD_POWER, 0);
+	if (err)
+		goto err4;
+
+	err = gpio_request(GPIO_NR_PALMT5_SD_READONLY, "SD_READONLY");
+	if (err)
+		goto err4;
+	err = gpio_direction_input(GPIO_NR_PALMT5_SD_READONLY);
+	if (err)
+		goto err5;
+
+	printk(KERN_DEBUG "%s: irq registered\n", __func__);
+
+	return 0;
+
+err5:
+	gpio_free(GPIO_NR_PALMT5_SD_READONLY);
+err4:
+	gpio_free(GPIO_NR_PALMT5_SD_POWER);
+err3:
+	free_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N), data);
+err2:
+	gpio_free(GPIO_NR_PALMT5_SD_DETECT_N);
+err:
+	return err;
+}
+
+static void palmt5_mci_exit(struct device *dev, void *data)
+{
+	gpio_free(GPIO_NR_PALMT5_SD_READONLY);
+	gpio_free(GPIO_NR_PALMT5_SD_POWER);
+	free_irq(IRQ_GPIO_PALMT5_SD_DETECT_N, data);
+	gpio_free(GPIO_NR_PALMT5_SD_DETECT_N);
+}
+
+static void palmt5_mci_power(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data *p_d = dev->platform_data;
+	gpio_set_value(GPIO_NR_PALMT5_SD_POWER, p_d->ocr_mask & (1 << vdd));
+}
+
+static int palmt5_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_NR_PALMT5_SD_READONLY);
+}
+
+static struct pxamci_platform_data palmt5_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.setpower	= palmt5_mci_power,
+	.get_ro		= palmt5_mci_get_ro,
+	.init 		= palmt5_mci_init,
+	.exit		= palmt5_mci_exit,
+};
+
+/******************************************************************************
+ * GPIO keyboard
+ ******************************************************************************/
+static unsigned int palmt5_matrix_keys[] = {
+	KEY(0, 0, KEY_POWER),
+	KEY(0, 1, KEY_F1),
+	KEY(0, 2, KEY_ENTER),
+
+	KEY(1, 0, KEY_F2),
+	KEY(1, 1, KEY_F3),
+	KEY(1, 2, KEY_F4),
+
+	KEY(2, 0, KEY_UP),
+	KEY(2, 2, KEY_DOWN),
+
+	KEY(3, 0, KEY_RIGHT),
+	KEY(3, 2, KEY_LEFT),
+};
+
+static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = {
+	.matrix_key_rows	= 4,
+	.matrix_key_cols	= 3,
+	.matrix_key_map		= palmt5_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(palmt5_matrix_keys),
+
+	.debounce_interval	= 30,
+};
+
+/******************************************************************************
+ * GPIO keys
+ ******************************************************************************/
+static struct gpio_keys_button palmt5_pxa_buttons[] = {
+	{KEY_F8, GPIO_NR_PALMT5_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
+};
+
+static struct gpio_keys_platform_data palmt5_pxa_keys_data = {
+	.buttons	= palmt5_pxa_buttons,
+	.nbuttons	= ARRAY_SIZE(palmt5_pxa_buttons),
+};
+
+static struct platform_device palmt5_pxa_keys = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &palmt5_pxa_keys_data,
+	},
+};
+
+/******************************************************************************
+ * Backlight
+ ******************************************************************************/
+static int palmt5_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMT5_BL_POWER, "BL POWER");
+	if (ret)
+		goto err;
+	ret = gpio_direction_output(GPIO_NR_PALMT5_BL_POWER, 0);
+	if (ret)
+		goto err2;
+	ret = gpio_request(GPIO_NR_PALMT5_LCD_POWER, "LCD POWER");
+	if (ret)
+		goto err2;
+	ret = gpio_direction_output(GPIO_NR_PALMT5_LCD_POWER, 0);
+	if (ret)
+		goto err3;
+
+	return 0;
+err3:
+	gpio_free(GPIO_NR_PALMT5_LCD_POWER);
+err2:
+	gpio_free(GPIO_NR_PALMT5_BL_POWER);
+err:
+	return ret;
+}
+
+static int palmt5_backlight_notify(int brightness)
+{
+	gpio_set_value(GPIO_NR_PALMT5_BL_POWER, brightness);
+	gpio_set_value(GPIO_NR_PALMT5_LCD_POWER, brightness);
+	return brightness;
+}
+
+static void palmt5_backlight_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMT5_BL_POWER);
+	gpio_free(GPIO_NR_PALMT5_LCD_POWER);
+}
+
+static struct platform_pwm_backlight_data palmt5_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= PALMT5_MAX_INTENSITY,
+	.dft_brightness	= PALMT5_MAX_INTENSITY,
+	.pwm_period_ns	= PALMT5_PERIOD_NS,
+	.init		= palmt5_backlight_init,
+	.notify		= palmt5_backlight_notify,
+	.exit		= palmt5_backlight_exit,
+};
+
+static struct platform_device palmt5_backlight = {
+	.name	= "pwm-backlight",
+	.dev	= {
+		.parent		= &pxa27x_device_pwm0.dev,
+		.platform_data	= &palmt5_backlight_data,
+	},
+};
+
+/******************************************************************************
+ * IrDA
+ ******************************************************************************/
+static int palmt5_irda_startup(struct device *dev)
+{
+	int err;
+	err = gpio_request(GPIO_NR_PALMT5_IR_DISABLE, "IR DISABLE");
+	if (err)
+		goto err;
+	err = gpio_direction_output(GPIO_NR_PALMT5_IR_DISABLE, 1);
+	if (err)
+		gpio_free(GPIO_NR_PALMT5_IR_DISABLE);
+err:
+	return err;
+}
+
+static void palmt5_irda_shutdown(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMT5_IR_DISABLE);
+}
+
+static void palmt5_irda_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_NR_PALMT5_IR_DISABLE, mode & IR_OFF);
+	pxa2xx_transceiver_mode(dev, mode);
+}
+
+static struct pxaficp_platform_data palmt5_ficp_platform_data = {
+	.startup		= palmt5_irda_startup,
+	.shutdown		= palmt5_irda_shutdown,
+	.transceiver_cap	= IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode	= palmt5_irda_transceiver_mode,
+};
+
+/******************************************************************************
+ * UDC
+ ******************************************************************************/
+static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = {
+	.gpio_vbus		= GPIO_NR_PALMT5_USB_DETECT_N,
+	.gpio_vbus_inverted	= 1,
+	.gpio_pullup		= GPIO_NR_PALMT5_USB_POWER,
+	.gpio_pullup_inverted	= 0,
+};
+
+/******************************************************************************
+ * Power supply
+ ******************************************************************************/
+static int power_supply_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMT5_POWER_DETECT, "CABLE_STATE_AC");
+	if (ret)
+		goto err1;
+	ret = gpio_direction_input(GPIO_NR_PALMT5_POWER_DETECT);
+	if (ret)
+		goto err2;
+
+	return 0;
+err2:
+	gpio_free(GPIO_NR_PALMT5_POWER_DETECT);
+err1:
+	return ret;
+}
+
+static int palmt5_is_ac_online(void)
+{
+	return gpio_get_value(GPIO_NR_PALMT5_POWER_DETECT);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMT5_POWER_DETECT);
+}
+
+static char *palmt5_supplicants[] = {
+	"main-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
+	.is_ac_online    = palmt5_is_ac_online,
+	.exit            = power_supply_exit,
+	.supplied_to     = palmt5_supplicants,
+	.num_supplicants = ARRAY_SIZE(palmt5_supplicants),
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+};
+
+/******************************************************************************
+ * WM97xx battery
+ ******************************************************************************/
+static struct wm97xx_batt_info wm97xx_batt_pdata = {
+	.batt_aux	= WM97XX_AUX_ID3,
+	.temp_aux	= WM97XX_AUX_ID2,
+	.charge_gpio	= -1,
+	.max_voltage	= PALMT5_BAT_MAX_VOLTAGE,
+	.min_voltage	= PALMT5_BAT_MIN_VOLTAGE,
+	.batt_mult	= 1000,
+	.batt_div	= 414,
+	.temp_mult	= 1,
+	.temp_div	= 1,
+	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LIPO,
+	.batt_name	= "main-batt",
+};
+
+/******************************************************************************
+ * aSoC audio
+ ******************************************************************************/
+static struct palm27x_asoc_info palm27x_asoc_pdata = {
+	.jack_gpio	= GPIO_NR_PALMT5_EARPHONE_DETECT,
+};
+
+/******************************************************************************
+ * Framebuffer
+ ******************************************************************************/
+static struct pxafb_mode_info palmt5_lcd_modes[] = {
+{
+	.pixclock	= 57692,
+	.xres		= 320,
+	.yres		= 480,
+	.bpp		= 16,
+
+	.left_margin	= 32,
+	.right_margin	= 1,
+	.upper_margin	= 7,
+	.lower_margin	= 1,
+
+	.hsync_len	= 4,
+	.vsync_len	= 1,
+},
+};
+
+static struct pxafb_mach_info palmt5_lcd_screen = {
+	.modes		= palmt5_lcd_modes,
+	.num_modes	= ARRAY_SIZE(palmt5_lcd_modes),
+	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+/******************************************************************************
+ * Machine init
+ ******************************************************************************/
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+	&palmt5_pxa_keys,
+#endif
+	&palmt5_backlight,
+	&power_supply,
+};
+
+/* setup udc GPIOs initial state */
+static void __init palmt5_udc_init(void)
+{
+	if (!gpio_request(GPIO_NR_PALMT5_USB_POWER, "UDC Vbus")) {
+		gpio_direction_output(GPIO_NR_PALMT5_USB_POWER, 1);
+		gpio_free(GPIO_NR_PALMT5_USB_POWER);
+	}
+}
+
+static void __init palmt5_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config));
+
+	set_pxa_fb_info(&palmt5_lcd_screen);
+	pxa_set_mci_info(&palmt5_mci_platform_data);
+	palmt5_udc_init();
+	pxa_set_udc_info(&palmt5_udc_info);
+	pxa_set_ac97_info(NULL);
+	pxa_set_ficp_info(&palmt5_ficp_platform_data);
+	pxa_set_keypad_info(&palmt5_keypad_platform_data);
+	wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
+	palm27x_asoc_set_pdata(&palm27x_asoc_pdata);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(PALMT5, "Palm Tungsten|T5")
+	.phys_io	= PALMT5_PHYS_IO_START,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= 0xa0000100,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa27x_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= palmt5_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index a9d94f5..b490c09 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -32,12 +32,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/palmtx.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/pxa-regs.h>
-#include <mach/mfp-pxa27x.h>
 #include <mach/irda.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 2f730da..b88eb4d 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -33,13 +33,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/palmz72.h>
 #include <mach/mmc.h>
 #include <mach/pxafb.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
 #include <mach/irda.h>
 #include <mach/pxa27x_keypad.h>
 #include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 36135a0..6abfa29 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -29,10 +29,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/mfp-pxa27x.h>
-#include <mach/pxa2xx-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/pcm027.h>
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 34841c7..6112740 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -31,13 +31,12 @@
 #include <mach/i2c.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pcm990_baseboard.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa27x.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -381,14 +380,49 @@
 	.gpio_base	= NR_BUILTIN_GPIO + 1,
 };
 
-static struct soc_camera_link iclink[] = {
-	{
-		.bus_id	= 0, /* Must match with the camera ID above */
-		.gpio	= NR_BUILTIN_GPIO + 1,
-	}, {
-		.bus_id	= 0, /* Must match with the camera ID above */
-		.gpio	= -ENXIO,
+static int gpio_bus_switch;
+
+static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
+		unsigned long flags)
+{
+	if (gpio_bus_switch <= 0) {
+		if (flags == SOCAM_DATAWIDTH_10)
+			return 0;
+		else
+			return -EINVAL;
 	}
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		gpio_set_value(gpio_bus_switch, 1);
+	else
+		gpio_set_value(gpio_bus_switch, 0);
+
+	return 0;
+}
+
+static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
+{
+	int ret;
+
+	if (!gpio_bus_switch) {
+		ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
+		if (!ret) {
+			gpio_bus_switch = NR_BUILTIN_GPIO + 1;
+			gpio_direction_output(gpio_bus_switch, 0);
+		} else
+			gpio_bus_switch = -EINVAL;
+	}
+
+	if (gpio_bus_switch > 0)
+		return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
+	else
+		return SOCAM_DATAWIDTH_10;
+}
+
+static struct soc_camera_link iclink = {
+	.bus_id	= 0, /* Must match with the camera ID above */
+	.query_bus_param = pcm990_camera_query_bus_param,
+	.set_bus_param = pcm990_camera_set_bus_param,
 };
 
 /* Board I2C devices. */
@@ -399,10 +433,10 @@
 		.platform_data = &pca9536_data,
 	}, {
 		I2C_BOARD_INFO("mt9v022", 0x48),
-		.platform_data = &iclink[0], /* With extender */
+		.platform_data = &iclink, /* With extender */
 	}, {
 		I2C_BOARD_INFO("mt9m001", 0x5d),
-		.platform_data = &iclink[0], /* With extender */
+		.platform_data = &iclink, /* With extender */
 	},
 };
 #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 164eb0b..884b174 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -14,15 +14,8 @@
 #include <linux/module.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
-#include <linux/time.h>
 
-#include <mach/hardware.h>
-#include <asm/memory.h>
-#include <asm/system.h>
 #include <mach/pm.h>
-#include <mach/pxa-regs.h>
-#include <mach/lubbock.h>
-#include <asm/mach/time.h>
 
 struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
 static unsigned long *sleep_save;
@@ -57,9 +50,9 @@
 
 		/* if invalid, display message and wait for a hardware reset */
 		if (checksum != sleep_save_checksum) {
-#ifdef CONFIG_ARCH_LUBBOCK
-			LUB_HEXLED = 0xbadbadc5;
-#endif
+
+			lubbock_set_hexled(0xbadbadc5);
+
 			while (1)
 				pxa_cpu_pm_fns->enter(state);
 		}
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index f9093be..036bbde 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -36,9 +36,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/pxa25x.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/i2c.h>
@@ -503,12 +501,12 @@
 
 static void poodle_poweroff(void)
 {
-	arm_machine_restart('h');
+	arm_machine_restart('h', NULL);
 }
 
-static void poodle_restart(char mode)
+static void poodle_restart(char mode, const char *cmd)
 {
-	arm_machine_restart('h');
+	arm_machine_restart('h', cmd);
 }
 
 static void __init poodle_init(void)
diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/mach-pxa/pwm.c
index 3ca7ffc..fcdd374 100644
--- a/arch/arm/mach-pxa/pwm.c
+++ b/arch/arm/mach-pxa/pwm.c
@@ -20,7 +20,6 @@
 #include <linux/pwm.h>
 
 #include <asm/div64.h>
-#include <mach/pxa-regs.h>
 
 /* PWM registers and bits definitions */
 #define PWMCR		(0x00)
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 6c57522..77c2693 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -25,9 +25,8 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+#include <mach/gpio.h>
+#include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
@@ -310,14 +309,14 @@
 void __init pxa25x_init_irq(void)
 {
 	pxa_init_irq(32, pxa25x_set_wake);
-	pxa_init_gpio(85, pxa25x_set_wake);
+	pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake);
 }
 
 #ifdef CONFIG_CPU_PXA26x
 void __init pxa26x_init_irq(void)
 {
 	pxa_init_irq(32, pxa25x_set_wake);
-	pxa_init_gpio(90, pxa25x_set_wake);
+	pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake);
 }
 #endif
 
@@ -355,7 +354,7 @@
 
 		clks_register(pxa25x_clkregs, ARRAY_SIZE(pxa25x_clkregs));
 
-		if ((ret = pxa_init_dma(16)))
+		if ((ret = pxa_init_dma(IRQ_DMA, 16)))
 			return ret;
 
 		pxa25x_init_pm();
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 411bec5..a425ec7 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -21,9 +21,8 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/gpio.h>
+#include <mach/pxa27x.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
 #include <mach/pm.h>
@@ -332,7 +331,7 @@
 void __init pxa27x_init_irq(void)
 {
 	pxa_init_irq(34, pxa27x_set_wake);
-	pxa_init_gpio(121, pxa27x_set_wake);
+	pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
 /*
@@ -381,7 +380,7 @@
 
 		clks_register(pxa27x_clkregs, ARRAY_SIZE(pxa27x_clkregs));
 
-		if ((ret = pxa_init_dma(32)))
+		if ((ret = pxa_init_dma(IRQ_DMA, 32)))
 			return ret;
 
 		pxa27x_init_pm();
diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
index 73d04d8..2f3394f 100644
--- a/arch/arm/mach-pxa/pxa2xx.c
+++ b/arch/arm/mach-pxa/pxa2xx.c
@@ -16,7 +16,6 @@
 
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa2xx.h>
 #include <mach/mfp-pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
index 83fb609..4ba6d21 100644
--- a/arch/arm/mach-pxa/pxa300.c
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -17,15 +17,13 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
 
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
 
-static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
+static struct mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0,   GPIO2,   0x00b4),
 	MFP_ADDR_X(GPIO3,   GPIO26,  0x027c),
@@ -74,7 +72,7 @@
 };
 
 /* override pxa300 MFP register addresses */
-static struct pxa3xx_mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
+static struct mfp_addr_map pxa310_mfp_addr_map[] __initdata = {
 	MFP_ADDR_X(GPIO30,  GPIO98,   0x0418),
 	MFP_ADDR_X(GPIO7_2, GPIO12_2, 0x052C),
 
@@ -100,13 +98,13 @@
 static int __init pxa300_init(void)
 {
 	if (cpu_is_pxa300() || cpu_is_pxa310()) {
-		pxa3xx_init_mfp();
-		pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
+		mfp_init_base(io_p2v(MFPR_BASE));
+		mfp_init_addr(pxa300_mfp_addr_map);
 		clks_register(ARRAY_AND_SIZE(common_clkregs));
 	}
 
 	if (cpu_is_pxa310()) {
-		pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
+		mfp_init_addr(pxa310_mfp_addr_map);
 		clks_register(ARRAY_AND_SIZE(pxa310_clkregs));
 	}
 
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
index 36f0661..8b3d97e 100644
--- a/arch/arm/mach-pxa/pxa320.c
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -17,16 +17,13 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
-#include <mach/mfp.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa320.h>
+#include <mach/pxa320.h>
 
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
 
-static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
+static struct mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0,  GPIO4,   0x0124),
 	MFP_ADDR_X(GPIO5,  GPIO9,   0x028C),
@@ -89,8 +86,8 @@
 static int __init pxa320_init(void)
 {
 	if (cpu_is_pxa320()) {
-		pxa3xx_init_mfp();
-		pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
+		mfp_init_base(io_p2v(MFPR_BASE));
+		mfp_init_addr(pxa320_mfp_addr_map);
 		clks_register(ARRAY_AND_SIZE(pxa320_clkregs));
 	}
 
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 4908938..b02d454 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -23,6 +23,7 @@
 #include <linux/sysdev.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -538,7 +539,7 @@
 	__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
 
 	pxa_init_irq(56, pxa3xx_set_wake);
-	pxa_init_gpio(128, NULL);
+	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 /*
@@ -594,7 +595,7 @@
 
 		clks_register(pxa3xx_clkregs, ARRAY_SIZE(pxa3xx_clkregs));
 
-		if ((ret = pxa_init_dma(32)))
+		if ((ret = pxa_init_dma(IRQ_DMA, 32)))
 			return ret;
 
 		pxa3xx_init_pm();
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
index 13e6bfd..7113174 100644
--- a/arch/arm/mach-pxa/pxa930.c
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -16,10 +16,9 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 
-#include <mach/hardware.h>
-#include <mach/mfp-pxa930.h>
+#include <mach/pxa930.h>
 
-static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = {
+static struct mfp_addr_map pxa930_mfp_addr_map[] __initdata = {
 
 	MFP_ADDR(GPIO0, 0x02e0),
 	MFP_ADDR(GPIO1, 0x02dc),
@@ -180,8 +179,8 @@
 static int __init pxa930_init(void)
 {
 	if (cpu_is_pxa930()) {
-		pxa3xx_init_mfp();
-		pxa3xx_mfp_init_addr(pxa930_mfp_addr_map);
+		mfp_init_base(io_p2v(MFPR_BASE));
+		mfp_init_addr(pxa930_mfp_addr_map);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
index 00b2dc2..df29d45 100644
--- a/arch/arm/mach-pxa/reset.c
+++ b/arch/arm/mach-pxa/reset.c
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <asm/proc-fns.h>
 
-#include <mach/pxa-regs.h>
+#include <mach/regs-ost.h>
 #include <mach/reset.h>
 
 unsigned int reset_status;
@@ -81,7 +81,7 @@
 	OSMR3 = OSCR + 368640;	/* ... in 100 ms */
 }
 
-void arch_reset(char mode)
+void arch_reset(char mode, const char *cmd)
 {
 	clear_reset_status(RESET_STATUS_ALL);
 
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index 5d02a73..ff82399 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -25,11 +25,9 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa930.h>
+
+#include <mach/pxa930.h>
 #include <mach/i2c.h>
-#include <mach/regs-lcd.h>
 #include <mach/pxafb.h>
 
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index f0845c1..16b4ec6 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -25,7 +25,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/pm.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-gpio.h>
 #include <mach/sharpsl.h>
 #include "sharpsl.h"
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index a62c837..2ed95f3 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -15,7 +15,6 @@
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 
 #define MDREFR_KDIV	0x200a4000	// all banks
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 0d62d31..8c61dda 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -44,9 +44,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/reset.h>
 #include <mach/i2c.h>
@@ -709,10 +707,10 @@
 
 static void spitz_poweroff(void)
 {
-	arm_machine_restart('g');
+	arm_machine_restart('g', NULL);
 }
 
-static void spitz_restart(char mode)
+static void spitz_restart(char mode, const char *cmd)
 {
 	/* Bootloader magic for a reboot */
 	if((MSC0 & 0xffff0000) == 0x7ff00000)
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 072e77c..2e44905 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -24,7 +24,6 @@
 
 #include <mach/sharpsl.h>
 #include <mach/spitz.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/pxa2xx-gpio.h>
 #include "sharpsl.h"
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 6f42004..965e38c 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <mach/ssp.h>
-#include <mach/pxa-regs.h>
 #include <mach/regs-ssp.h>
 
 #define TIMEOUT 100000
diff --git a/arch/arm/mach-pxa/standby.S b/arch/arm/mach-pxa/standby.S
index f3821cf..29f5f5c 100644
--- a/arch/arm/mach-pxa/standby.S
+++ b/arch/arm/mach-pxa/standby.S
@@ -13,7 +13,6 @@
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 
 		.text
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 58ef08a..b75353a 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -22,9 +22,8 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <mach/hardware.h>
-#include <mach/pxa3xx-regs.h>
-#include <mach/mfp-pxa930.h>
+
+#include <mach/pxa930.h>
 #include <mach/pxafb.h>
 #include <mach/pxa27x_keypad.h>
 
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 95656a7..8eb3830 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -22,8 +22,7 @@
 #include <asm/div64.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/regs-ost.h>
 
 /*
  * This is PXA's sched_clock implementation. This has a resolution
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 3332e5d..6e8ade6 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -36,8 +36,8 @@
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa25x.h>
+
+#include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
 #include <mach/i2c.h>
@@ -876,10 +876,10 @@
 
 static void tosa_poweroff(void)
 {
-	arm_machine_restart('g');
+	arm_machine_restart('g', NULL);
 }
 
-static void tosa_restart(char mode)
+static void tosa_restart(char mode, const char *cmd)
 {
 	/* Bootloader magic for a reboot */
 	if((MSC0 & 0xffff0000) == 0x7ff00000)
@@ -919,7 +919,7 @@
 	pxa2xx_set_spi_info(2, &pxa_ssp_master_info);
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
-	clk_add_alias("CLK_CK3P6MI", &tc6393xb_device.dev, "GPIO11_CLK", NULL);
+	clk_add_alias("CLK_CK3P6MI", tc6393xb_device.name, "GPIO11_CLK", NULL);
 
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index a72e3ad..f79c9cb 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -39,10 +39,7 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/flash.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/mfp-pxa27x.h>
+#include <mach/pxa27x.h>
 #include <mach/pxa2xx_spi.h>
 #include <mach/trizeps4.h>
 #include <mach/audio.h>
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 4b3120d..0e65344 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -42,12 +42,9 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 
-#include <mach/pxa-regs.h>
-#include <mach/pxa2xx-regs.h>
-#include <mach/bitfield.h>
+#include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <mach/mfp-pxa25x.h>
 #include <mach/i2c.h>
 #include <mach/viper.h>
 
@@ -956,7 +953,7 @@
 	},
 	{
 		.virtual = VIPER_PC104IO_BASE,
-		.pfn     = __phys_to_pfn(_PCMCIA1IO),
+		.pfn     = __phys_to_pfn(0x30000000),
 		.length  = 0x00800000,
 		.type    = MT_DEVICE,
 	},
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index 4653888..c1f7320 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -18,9 +18,9 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/gpio.h>
 
-#include <asm/gpio.h>
-#include <mach/mfp-pxa300.h>
+#include <mach/pxa300.h>
 #include <mach/i2c.h>
 #include <mach/zylonite.h>
 
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
index 28e4e62..4e1c488 100644
--- a/arch/arm/mach-pxa/zylonite_pxa320.c
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -18,7 +18,7 @@
 #include <linux/init.h>
 #include <linux/gpio.h>
 
-#include <mach/mfp-pxa320.h>
+#include <mach/pxa320.h>
 #include <mach/zylonite.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index ad91185..b6ec106 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -35,6 +35,7 @@
 	bool "Support RealView/PB11MPCore platform"
 	select CPU_V6
 	select ARM_GIC
+	select HAVE_PATA_PLATFORM
 	help
 	  Include support for the ARM(R) RealView MPCore Platform Baseboard.
 	  PB11MPCore is a platform with an on-board ARM11MPCore and has
@@ -51,6 +52,7 @@
 	bool "Support RealView/PB-A8 platform"
 	select CPU_V7
 	select ARM_GIC
+	select HAVE_PATA_PLATFORM
 	help
 	  Include support for the ARM(R) RealView Cortex-A8 Platform Baseboard.
 	  PB-A8 is a platform with an on-board Cortex-A8 and has support for
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index bd2aa4f..d676668 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -29,6 +29,7 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 #include <linux/smc911x.h>
+#include <linux/ata_platform.h>
 
 #include <asm/clkdev.h>
 #include <asm/system.h>
@@ -150,6 +151,44 @@
 	return platform_device_register(&realview_eth_device);
 }
 
+struct platform_device realview_usb_device = {
+	.name			= "isp1760",
+	.num_resources		= 2,
+};
+
+int realview_usb_register(struct resource *res)
+{
+	realview_usb_device.resource = res;
+	return platform_device_register(&realview_usb_device);
+}
+
+static struct pata_platform_info pata_platform_data = {
+	.ioport_shift		= 1,
+};
+
+static struct resource pata_resources[] = {
+	[0] = {
+		.start		= REALVIEW_CF_BASE,
+		.end		= REALVIEW_CF_BASE + 0xff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= REALVIEW_CF_BASE + 0x100,
+		.end		= REALVIEW_CF_BASE + SZ_4K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device realview_cf_device = {
+	.name			= "pata_platform",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(pata_resources),
+	.resource		= pata_resources,
+	.dev			= {
+		.platform_data	= &pata_platform_data,
+	},
+};
+
 static struct resource realview_i2c_resource = {
 	.start		= REALVIEW_I2C_BASE,
 	.end		= REALVIEW_I2C_BASE + SZ_4K - 1,
@@ -158,11 +197,25 @@
 
 struct platform_device realview_i2c_device = {
 	.name		= "versatile-i2c",
-	.id		= -1,
+	.id		= 0,
 	.num_resources	= 1,
 	.resource	= &realview_i2c_resource,
 };
 
+static struct i2c_board_info realview_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
+		.type = "ds1338",
+	},
+};
+
+static int __init realview_i2c_init(void)
+{
+	return i2c_register_board_info(0, realview_i2c_board_info,
+				       ARRAY_SIZE(realview_i2c_board_info));
+}
+arch_initcall(realview_i2c_init);
+
 #define REALVIEW_SYSMCI	(__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
 
 static unsigned int realview_mmc_status(struct device *dev)
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 44269b1..21c0863 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -45,6 +45,7 @@
 }
 
 extern struct platform_device realview_flash_device;
+extern struct platform_device realview_cf_device;
 extern struct platform_device realview_i2c_device;
 extern struct mmc_platform_data realview_mmc0_plat_data;
 extern struct mmc_platform_data realview_mmc1_plat_data;
@@ -62,5 +63,6 @@
 extern void realview_timer_init(unsigned int timer_irq);
 extern int realview_flash_register(struct resource *res, u32 num);
 extern int realview_eth_register(const char *name, struct resource *res);
+extern int realview_usb_register(struct resource *res);
 
 #endif
diff --git a/arch/arm/mach-realview/include/mach/board-pba8.h b/arch/arm/mach-realview/include/mach/board-pba8.h
index c8bed8f..307f97b 100644
--- a/arch/arm/mach-realview/include/mach/board-pba8.h
+++ b/arch/arm/mach-realview/include/mach/board-pba8.h
@@ -45,8 +45,6 @@
 #define REALVIEW_PBA8_DMC_BASE			0x100E0000	/* DMC configuration */
 #define REALVIEW_PBA8_SMC_BASE			0x100E1000	/* SMC configuration */
 #define REALVIEW_PBA8_CAN_BASE			0x100E2000	/* CAN bus */
-#define REALVIEW_PBA8_CF_BASE			0x18000000	/* Compact flash */
-#define REALVIEW_PBA8_CF_MEM_BASE		0x18003000	/* SMC for Compact flash */
 #define REALVIEW_PBA8_GIC_CPU_BASE		0x1E000000	/* Generic interrupt controller CPU interface */
 #define REALVIEW_PBA8_FLASH0_BASE		0x40000000
 #define REALVIEW_PBA8_FLASH0_SIZE		SZ_64M
diff --git a/arch/arm/mach-realview/include/mach/platform.h b/arch/arm/mach-realview/include/mach/platform.h
index 793a3a3..c8f5083 100644
--- a/arch/arm/mach-realview/include/mach/platform.h
+++ b/arch/arm/mach-realview/include/mach/platform.h
@@ -204,6 +204,12 @@
 #define REALVIEW_LT_BASE              0x80000000	/* Logic Tile expansion */
 
 /*
+ * CompactFlash
+ */
+#define REALVIEW_CF_BASE		0x18000000	/* CompactFlash */
+#define REALVIEW_CF_MEM_BASE		0x18003000	/* SMC for CompactFlash */
+
+/*
  * Disk on Chip
  */
 #define REALVIEW_DOC_BASE             0x2C000000
diff --git a/arch/arm/mach-realview/include/mach/system.h b/arch/arm/mach-realview/include/mach/system.h
index a2f61c7..1a15a44 100644
--- a/arch/arm/mach-realview/include/mach/system.h
+++ b/arch/arm/mach-realview/include/mach/system.h
@@ -34,7 +34,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	void __iomem *hdr_ctrl = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_RESETCTL_OFFSET;
 	unsigned int val;
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index bed39ed..c20fbef 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -264,6 +264,19 @@
 	return realview_eth_register(name, realview_eb_eth_resources);
 }
 
+static struct resource realview_eb_isp1761_resources[] = {
+	[0] = {
+		.start		= REALVIEW_EB_USB_BASE,
+		.end		= REALVIEW_EB_USB_BASE + SZ_128K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IRQ_EB_USB,
+		.end		= IRQ_EB_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
 static void __init gic_init_irq(void)
 {
 	if (core_tile_eb11mp() || core_tile_a9mp()) {
@@ -323,6 +336,8 @@
 	/* platform devices */
 	realview_eb_eth_resources[1].start	= IRQ_EB11MP_ETH;
 	realview_eb_eth_resources[1].end	= IRQ_EB11MP_ETH;
+	realview_eb_isp1761_resources[1].start	= IRQ_EB11MP_USB;
+	realview_eb_isp1761_resources[1].end	= IRQ_EB11MP_USB;
 }
 
 static void __init realview_eb_timer_init(void)
@@ -366,6 +381,7 @@
 	realview_flash_register(&realview_eb_flash_resource, 1);
 	platform_device_register(&realview_i2c_device);
 	eth_device_register();
+	realview_usb_register(realview_eb_isp1761_resources);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index 8f0683c..a64b84a 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -222,6 +222,19 @@
 	},
 };
 
+static struct resource realview_pb1176_isp1761_resources[] = {
+	[0] = {
+		.start		= REALVIEW_PB1176_USB_BASE,
+		.end		= REALVIEW_PB1176_USB_BASE + SZ_128K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IRQ_PB1176_USB,
+		.end		= IRQ_PB1176_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
 static void __init gic_init_irq(void)
 {
 	/* ARM1176 DevChip GIC, primary */
@@ -260,6 +273,8 @@
 
 	realview_flash_register(&realview_pb1176_flash_resource, 1);
 	realview_eth_register(NULL, realview_pb1176_smsc911x_resources);
+	platform_device_register(&realview_i2c_device);
+	realview_usb_register(realview_pb1176_isp1761_resources);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 3ebdb2d..ea1e60e 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -230,31 +230,19 @@
 	},
 };
 
-struct resource realview_pb11mp_cf_resources[] = {
+static struct resource realview_pb11mp_isp1761_resources[] = {
 	[0] = {
-		.start		= REALVIEW_PB11MP_CF_BASE,
-		.end		= REALVIEW_PB11MP_CF_BASE + SZ_4K - 1,
+		.start		= REALVIEW_PB11MP_USB_BASE,
+		.end		= REALVIEW_PB11MP_USB_BASE + SZ_128K - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start		= REALVIEW_PB11MP_CF_MEM_BASE,
-		.end		= REALVIEW_PB11MP_CF_MEM_BASE + SZ_4K - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start		= -1,		/* FIXME: Find correct irq */
-		.end		= -1,
+		.start		= IRQ_TC11MP_USB,
+		.end		= IRQ_TC11MP_USB,
 		.flags		= IORESOURCE_IRQ,
 	},
 };
 
-struct platform_device realview_pb11mp_cf_device = {
-	.name		= "compactflash",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(realview_pb11mp_cf_resources),
-	.resource	= realview_pb11mp_cf_resources,
-};
-
 static void __init gic_init_irq(void)
 {
 	unsigned int pldctrl;
@@ -308,7 +296,8 @@
 				ARRAY_SIZE(realview_pb11mp_flash_resource));
 	realview_eth_register(NULL, realview_pb11mp_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
-	platform_device_register(&realview_pb11mp_cf_device);
+	platform_device_register(&realview_cf_device);
+	realview_usb_register(realview_pb11mp_isp1761_resources);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 34c9443..d6ac1eb 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -221,31 +221,19 @@
 	},
 };
 
-struct resource realview_pba8_cf_resources[] = {
+static struct resource realview_pba8_isp1761_resources[] = {
 	[0] = {
-		.start		= REALVIEW_PBA8_CF_BASE,
-		.end		= REALVIEW_PBA8_CF_BASE + SZ_4K - 1,
+		.start		= REALVIEW_PBA8_USB_BASE,
+		.end		= REALVIEW_PBA8_USB_BASE + SZ_128K - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start		= REALVIEW_PBA8_CF_MEM_BASE,
-		.end		= REALVIEW_PBA8_CF_MEM_BASE + SZ_4K - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	[2] = {
-		.start		= -1,		/* FIXME: Find correct irq */
-		.end		= -1,
+		.start		= IRQ_PBA8_USB,
+		.end		= IRQ_PBA8_USB,
 		.flags		= IORESOURCE_IRQ,
 	},
 };
 
-struct platform_device realview_pba8_cf_device = {
-	.name		= "compactflash",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(realview_pba8_cf_resources),
-	.resource	= realview_pba8_cf_resources,
-};
-
 static void __init gic_init_irq(void)
 {
 	/* ARM PB-A8 on-board GIC */
@@ -276,7 +264,8 @@
 				ARRAY_SIZE(realview_pba8_flash_resource));
 	realview_eth_register(NULL, realview_pba8_smsc911x_resources);
 	platform_device_register(&realview_i2c_device);
-	platform_device_register(&realview_pba8_cf_device);
+	platform_device_register(&realview_cf_device);
+	realview_usb_register(realview_pba8_isp1761_resources);
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index 7958a30..c47d974 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -26,6 +26,16 @@
 #include <asm/mach/dma.h>
 #include <asm/hardware/iomd.h>
 
+struct iomd_dma {
+	struct dma_struct	dma;
+	unsigned int		state;
+	unsigned long		base;		/* Controller base address */
+	int			irq;		/* Controller IRQ */
+	struct scatterlist	cur_sg;		/* Current controller buffer */
+	dma_addr_t		dma_addr;
+	unsigned int		dma_len;
+};
+
 #if 0
 typedef enum {
 	dma_size_8	= 1,
@@ -44,15 +54,15 @@
 #define CR	(IOMD_IO0CR - IOMD_IO0CURA)
 #define ST	(IOMD_IO0ST - IOMD_IO0CURA)
 
-static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
+static void iomd_get_next_sg(struct scatterlist *sg, struct iomd_dma *idma)
 {
 	unsigned long end, offset, flags = 0;
 
-	if (dma->sg) {
-		sg->dma_address = dma->sg->dma_address;
+	if (idma->dma.sg) {
+		sg->dma_address = idma->dma_addr;
 		offset = sg->dma_address & ~PAGE_MASK;
 
-		end = offset + dma->sg->length;
+		end = offset + idma->dma_len;
 
 		if (end > PAGE_SIZE)
 			end = PAGE_SIZE;
@@ -62,15 +72,17 @@
 
 		sg->length = end - TRANSFER_SIZE;
 
-		dma->sg->length -= end - offset;
-		dma->sg->dma_address += end - offset;
+		idma->dma_len -= end - offset;
+		idma->dma_addr += end - offset;
 
-		if (dma->sg->length == 0) {
-			if (dma->sgcount > 1) {
-				dma->sg++;
-				dma->sgcount--;
+		if (idma->dma_len == 0) {
+			if (idma->dma.sgcount > 1) {
+				idma->dma.sg = sg_next(idma->dma.sg);
+				idma->dma_addr = idma->dma.sg->dma_address;
+				idma->dma_len = idma->dma.sg->length;
+				idma->dma.sgcount--;
 			} else {
-				dma->sg = NULL;
+				idma->dma.sg = NULL;
 				flags |= DMA_END_S;
 			}
 		}
@@ -85,8 +97,8 @@
 
 static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
 {
-	dma_t *dma = (dma_t *)dev_id;
-	unsigned long base = dma->dma_base;
+	struct iomd_dma *idma = dev_id;
+	unsigned long base = idma->base;
 
 	do {
 		unsigned int status;
@@ -95,93 +107,99 @@
 		if (!(status & DMA_ST_INT))
 			return IRQ_HANDLED;
 
-		if ((dma->state ^ status) & DMA_ST_AB)
-			iomd_get_next_sg(&dma->cur_sg, dma);
+		if ((idma->state ^ status) & DMA_ST_AB)
+			iomd_get_next_sg(&idma->cur_sg, idma);
 
 		switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
 		case DMA_ST_OFL:			/* OIA */
 		case DMA_ST_AB:				/* .IB */
-			iomd_writel(dma->cur_sg.dma_address, base + CURA);
-			iomd_writel(dma->cur_sg.length, base + ENDA);
-			dma->state = DMA_ST_AB;
+			iomd_writel(idma->cur_sg.dma_address, base + CURA);
+			iomd_writel(idma->cur_sg.length, base + ENDA);
+			idma->state = DMA_ST_AB;
 			break;
 
 		case DMA_ST_OFL | DMA_ST_AB:		/* OIB */
 		case 0:					/* .IA */
-			iomd_writel(dma->cur_sg.dma_address, base + CURB);
-			iomd_writel(dma->cur_sg.length, base + ENDB);
-			dma->state = 0;
+			iomd_writel(idma->cur_sg.dma_address, base + CURB);
+			iomd_writel(idma->cur_sg.length, base + ENDB);
+			idma->state = 0;
 			break;
 		}
 
 		if (status & DMA_ST_OFL &&
-		    dma->cur_sg.length == (DMA_END_S|DMA_END_L))
+		    idma->cur_sg.length == (DMA_END_S|DMA_END_L))
 			break;
 	} while (1);
 
-	dma->state = ~DMA_ST_AB;
+	idma->state = ~DMA_ST_AB;
 	disable_irq(irq);
 
 	return IRQ_HANDLED;
 }
 
-static int iomd_request_dma(dmach_t channel, dma_t *dma)
+static int iomd_request_dma(unsigned int chan, dma_t *dma)
 {
-	return request_irq(dma->dma_irq, iomd_dma_handle,
-			   IRQF_DISABLED, dma->device_id, dma);
+	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
+
+	return request_irq(idma->irq, iomd_dma_handle,
+			   IRQF_DISABLED, idma->dma.device_id, idma);
 }
 
-static void iomd_free_dma(dmach_t channel, dma_t *dma)
+static void iomd_free_dma(unsigned int chan, dma_t *dma)
 {
-	free_irq(dma->dma_irq, dma);
+	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
+
+	free_irq(idma->irq, idma);
 }
 
-static void iomd_enable_dma(dmach_t channel, dma_t *dma)
+static void iomd_enable_dma(unsigned int chan, dma_t *dma)
 {
-	unsigned long dma_base = dma->dma_base;
+	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
+	unsigned long dma_base = idma->base;
 	unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
 
-	if (dma->invalid) {
-		dma->invalid = 0;
+	if (idma->dma.invalid) {
+		idma->dma.invalid = 0;
 
 		/*
 		 * Cope with ISA-style drivers which expect cache
 		 * coherence.
 		 */
-		if (!dma->sg) {
-			dma->sg = &dma->buf;
-			dma->sgcount = 1;
-			dma->buf.length = dma->count;
-			dma->buf.dma_address = dma_map_single(NULL,
-				dma->addr, dma->count,
-				dma->dma_mode == DMA_MODE_READ ?
+		if (!idma->dma.sg) {
+			idma->dma.sg = &idma->dma.buf;
+			idma->dma.sgcount = 1;
+			idma->dma.buf.length = idma->dma.count;
+			idma->dma.buf.dma_address = dma_map_single(NULL,
+				idma->dma.addr, idma->dma.count,
+				idma->dma.dma_mode == DMA_MODE_READ ?
 				DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		}
 
 		iomd_writeb(DMA_CR_C, dma_base + CR);
-		dma->state = DMA_ST_AB;
+		idma->state = DMA_ST_AB;
 	}
-		
-	if (dma->dma_mode == DMA_MODE_READ)
+
+	if (idma->dma.dma_mode == DMA_MODE_READ)
 		ctrl |= DMA_CR_D;
 
 	iomd_writeb(ctrl, dma_base + CR);
-	enable_irq(dma->dma_irq);
+	enable_irq(idma->irq);
 }
 
-static void iomd_disable_dma(dmach_t channel, dma_t *dma)
+static void iomd_disable_dma(unsigned int chan, dma_t *dma)
 {
-	unsigned long dma_base = dma->dma_base;
+	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);
+	unsigned long dma_base = idma->base;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	if (dma->state != ~DMA_ST_AB)
-		disable_irq(dma->dma_irq);
+	if (idma->state != ~DMA_ST_AB)
+		disable_irq(idma->irq);
 	iomd_writeb(0, dma_base + CR);
 	local_irq_restore(flags);
 }
 
-static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
+static int iomd_set_dma_speed(unsigned int chan, dma_t *dma, int cycle)
 {
 	int tcr, speed;
 
@@ -197,7 +215,7 @@
 	tcr = iomd_readb(IOMD_DMATCR);
 	speed &= 3;
 
-	switch (channel) {
+	switch (chan) {
 	case DMA_0:
 		tcr = (tcr & ~0x03) | speed;
 		break;
@@ -236,16 +254,22 @@
 	.name	= "floppydma"
 };
 
-static void floppy_enable_dma(dmach_t channel, dma_t *dma)
+struct floppy_dma {
+	struct dma_struct	dma;
+	unsigned int		fiq;
+};
+
+static void floppy_enable_dma(unsigned int chan, dma_t *dma)
 {
+	struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma);
 	void *fiqhandler_start;
 	unsigned int fiqhandler_length;
 	struct pt_regs regs;
 
-	if (dma->sg)
+	if (fdma->dma.sg)
 		BUG();
 
-	if (dma->dma_mode == DMA_MODE_READ) {
+	if (fdma->dma.dma_mode == DMA_MODE_READ) {
 		extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
 		fiqhandler_start = &floppy_fiqin_start;
 		fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
@@ -255,8 +279,8 @@
 		fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
 	}
 
-	regs.ARM_r9  = dma->count;
-	regs.ARM_r10 = (unsigned long)dma->addr;
+	regs.ARM_r9  = fdma->dma.count;
+	regs.ARM_r10 = (unsigned long)fdma->dma.addr;
 	regs.ARM_fp  = (unsigned long)FLOPPYDMA_BASE;
 
 	if (claim_fiq(&fh)) {
@@ -266,16 +290,17 @@
 
 	set_fiq_handler(fiqhandler_start, fiqhandler_length);
 	set_fiq_regs(&regs);
-	enable_fiq(dma->dma_irq);
+	enable_fiq(fdma->fiq);
 }
 
-static void floppy_disable_dma(dmach_t channel, dma_t *dma)
+static void floppy_disable_dma(unsigned int chan, dma_t *dma)
 {
-	disable_fiq(dma->dma_irq);
+	struct floppy_dma *fdma = container_of(dma, struct floppy_dma, dma);
+	disable_fiq(fdma->fiq);
 	release_fiq(&fh);
 }
 
-static int floppy_get_residue(dmach_t channel, dma_t *dma)
+static int floppy_get_residue(unsigned int chan, dma_t *dma)
 {
 	struct pt_regs regs;
 	get_fiq_regs(&regs);
@@ -292,7 +317,7 @@
 /*
  * This is virtual DMA - we don't need anything here.
  */
-static void sound_enable_disable_dma(dmach_t channel, dma_t *dma)
+static void sound_enable_disable_dma(unsigned int chan, dma_t *dma)
 {
 }
 
@@ -302,8 +327,24 @@
 	.disable	= sound_enable_disable_dma,
 };
 
-void __init arch_dma_init(dma_t *dma)
+static struct iomd_dma iomd_dma[6];
+
+static struct floppy_dma floppy_dma = {
+	.dma		= {
+		.d_ops	= &floppy_dma_ops,
+	},
+	.fiq		= FIQ_FLOPPYDATA,
+};
+
+static dma_t sound_dma = {
+	.d_ops		= &sound_dma_ops,
+};
+
+static int __init rpc_dma_init(void)
 {
+	unsigned int i;
+	int ret;
+
 	iomd_writeb(0, IOMD_IO0CR);
 	iomd_writeb(0, IOMD_IO1CR);
 	iomd_writeb(0, IOMD_IO2CR);
@@ -311,31 +352,39 @@
 
 	iomd_writeb(0xa0, IOMD_DMATCR);
 
-	dma[DMA_0].dma_base		= IOMD_IO0CURA;
-	dma[DMA_0].dma_irq		= IRQ_DMA0;
-	dma[DMA_0].d_ops		= &iomd_dma_ops;
-	dma[DMA_1].dma_base		= IOMD_IO1CURA;
-	dma[DMA_1].dma_irq		= IRQ_DMA1;
-	dma[DMA_1].d_ops		= &iomd_dma_ops;
-	dma[DMA_2].dma_base		= IOMD_IO2CURA;
-	dma[DMA_2].dma_irq		= IRQ_DMA2;
-	dma[DMA_2].d_ops		= &iomd_dma_ops;
-	dma[DMA_3].dma_base		= IOMD_IO3CURA;
-	dma[DMA_3].dma_irq		= IRQ_DMA3;
-	dma[DMA_3].d_ops		= &iomd_dma_ops;
-	dma[DMA_S0].dma_base		= IOMD_SD0CURA;
-	dma[DMA_S0].dma_irq		= IRQ_DMAS0;
-	dma[DMA_S0].d_ops		= &iomd_dma_ops;
-	dma[DMA_S1].dma_base		= IOMD_SD1CURA;
-	dma[DMA_S1].dma_irq		= IRQ_DMAS1;
-	dma[DMA_S1].d_ops		= &iomd_dma_ops;
-	dma[DMA_VIRTUAL_FLOPPY].dma_irq	= FIQ_FLOPPYDATA;
-	dma[DMA_VIRTUAL_FLOPPY].d_ops	= &floppy_dma_ops;
-	dma[DMA_VIRTUAL_SOUND].d_ops	= &sound_dma_ops;
-
 	/*
 	 * Setup DMA channels 2,3 to be for podules
 	 * and channels 0,1 for internal devices
 	 */
 	iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
+
+	iomd_dma[DMA_0].base	= IOMD_IO0CURA;
+	iomd_dma[DMA_0].irq	= IRQ_DMA0;
+	iomd_dma[DMA_1].base	= IOMD_IO1CURA;
+	iomd_dma[DMA_1].irq	= IRQ_DMA1;
+	iomd_dma[DMA_2].base	= IOMD_IO2CURA;
+	iomd_dma[DMA_2].irq	= IRQ_DMA2;
+	iomd_dma[DMA_3].base	= IOMD_IO3CURA;
+	iomd_dma[DMA_3].irq	= IRQ_DMA3;
+	iomd_dma[DMA_S0].base	= IOMD_SD0CURA;
+	iomd_dma[DMA_S0].irq	= IRQ_DMAS0;
+	iomd_dma[DMA_S1].base	= IOMD_SD1CURA;
+	iomd_dma[DMA_S1].irq	= IRQ_DMAS1;
+
+	for (i = DMA_0; i <= DMA_S1; i++) {
+		iomd_dma[i].dma.d_ops = &iomd_dma_ops;
+
+		ret = isa_dma_add(i, &iomd_dma[i].dma);
+		if (ret)
+			printk("IOMDDMA%u: unable to register: %d\n", i, ret);
+	}
+
+	ret = isa_dma_add(DMA_VIRTUAL_FLOPPY, &floppy_dma.dma);
+	if (ret)
+		printk("IOMDFLOPPY: unable to register: %d\n", ret);
+	ret = isa_dma_add(DMA_VIRTUAL_SOUND, &sound_dma);
+	if (ret)
+		printk("IOMDSOUND: unable to register: %d\n", ret);
+	return 0;
 }
+core_initcall(rpc_dma_init);
diff --git a/arch/arm/mach-rpc/include/mach/isa-dma.h b/arch/arm/mach-rpc/include/mach/isa-dma.h
index bad7205..67bfc67 100644
--- a/arch/arm/mach-rpc/include/mach/isa-dma.h
+++ b/arch/arm/mach-rpc/include/mach/isa-dma.h
@@ -23,5 +23,7 @@
 
 #define DMA_FLOPPY		DMA_VIRTUAL_FLOPPY
 
+#define IOMD_DMA_BOUNDARY	(PAGE_SIZE - 1)
+
 #endif /* _ASM_ARCH_DMA_H */
 
diff --git a/arch/arm/mach-rpc/include/mach/system.h b/arch/arm/mach-rpc/include/mach/system.h
index bd7268b..45c7b93 100644
--- a/arch/arm/mach-rpc/include/mach/system.h
+++ b/arch/arm/mach-rpc/include/mach/system.h
@@ -16,7 +16,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	iomd_writeb(0, IOMD_ROMCR0);
 
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
new file mode 100644
index 0000000..ce1ec69
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - GPIO bank numbering
+ *
+ * This program is free software; you can 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 S3C2410_GPIONO(bank,offset) ((bank) + (offset))
+
+#define S3C2410_GPIO_BANKA   (32*0)
+#define S3C2410_GPIO_BANKB   (32*1)
+#define S3C2410_GPIO_BANKC   (32*2)
+#define S3C2410_GPIO_BANKD   (32*3)
+#define S3C2410_GPIO_BANKE   (32*4)
+#define S3C2410_GPIO_BANKF   (32*5)
+#define S3C2410_GPIO_BANKG   (32*6)
+#define S3C2410_GPIO_BANKH   (32*7)
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h
index 00476a5..51a88cf 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio.h
@@ -23,3 +23,6 @@
 #define ARCH_NR_GPIOS	(256 + CONFIG_S3C24XX_GPIO_EXTRA)
 
 #include <asm-generic/gpio.h>
+#include <mach/gpio-nrs.h>
+
+#define S3C_GPIO_END	(S3C2410_GPIO_BANKH + 32)
diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h
index 49efce8..2a2384f 100644
--- a/arch/arm/mach-s3c2410/include/mach/irqs.h
+++ b/arch/arm/mach-s3c2410/include/mach/irqs.h
@@ -80,7 +80,7 @@
 #define IRQ_EINT22     S3C2410_IRQ(50)
 #define IRQ_EINT23     S3C2410_IRQ(51)
 
-
+#define IRQ_EINT_BIT(x)	((x) - IRQ_EINT4 + 4)
 #define IRQ_EINT(x)    (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
 
 #define IRQ_LCD_FIFO   S3C2410_IRQ(52)
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
index 3210776..35a03df 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
@@ -14,16 +14,7 @@
 #ifndef __ASM_ARCH_REGS_GPIO_H
 #define __ASM_ARCH_REGS_GPIO_H
 
-#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
-
-#define S3C2410_GPIO_BANKA   (32*0)
-#define S3C2410_GPIO_BANKB   (32*1)
-#define S3C2410_GPIO_BANKC   (32*2)
-#define S3C2410_GPIO_BANKD   (32*3)
-#define S3C2410_GPIO_BANKE   (32*4)
-#define S3C2410_GPIO_BANKF   (32*5)
-#define S3C2410_GPIO_BANKG   (32*6)
-#define S3C2410_GPIO_BANKH   (32*7)
+#include <mach/gpio-nrs.h>
 
 #ifdef CONFIG_CPU_S3C2400
 #define S3C24XX_GPIO_BASE(x)  S3C2400_GPIO_BASE(x)
diff --git a/arch/arm/mach-s3c2410/include/mach/system-reset.h b/arch/arm/mach-s3c2410/include/mach/system-reset.h
index 7613d0a..b8687f7 100644
--- a/arch/arm/mach-s3c2410/include/mach/system-reset.h
+++ b/arch/arm/mach-s3c2410/include/mach/system-reset.h
@@ -22,7 +22,7 @@
 extern void (*s3c24xx_reset_hook)(void);
 
 static void
-arch_reset(char mode)
+arch_reset(char mode, const char *cmd)
 {
 	struct clk *wdtclk;
 
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 821a166..7a7c4da 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -203,7 +203,7 @@
 #ifdef CONFIG_PM_H1940
 	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
 #endif
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 static void __init h1940_init_irq(void)
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index 9678a53..9f1ba9b 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -355,7 +355,7 @@
 	s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
 
 	platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
 
 MACHINE_START(QT2410, "QT2410")
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index a6970f6..87fc481 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -37,21 +37,14 @@
 #include <plat/cpu.h>
 #include <plat/pm.h>
 
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
 static void s3c2410_pm_prepare(void)
 {
 	/* ensure at least GSTATUS3 has the resume address */
 
-	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S3C2410_GSTATUS3);
 
-	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
+	S3C_PMDBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+	S3C_PMDBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
 	if (machine_is_h1940()) {
 		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index ecddbbb..72c266a 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -494,7 +494,7 @@
 	 * correct address to resume from. */
 
 	__raw_writel(0x2BED, S3C2412_INFORM0);
-	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2412_INFORM1);
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1);
 
 	return 0;
 }
@@ -630,7 +630,7 @@
 
 	/* initialise the power management now we've setup everything. */
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 
 	s3c_device_nand.dev.platform_data = &jive_nand_info;
 
diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c
index 217e9e4..c9cfe40 100644
--- a/arch/arm/mach-s3c2412/pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -85,7 +85,7 @@
 
 static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
 {
-	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
 	return 0;
 }
 
@@ -98,7 +98,7 @@
 	tmp |=  S3C2412_PWRCFG_STANDBYWFI_IDLE;
 	__raw_writel(tmp, S3C2412_PWRCFG);
 
-	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
 	return 0;
 }
 
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 12d378f..bc8d8d1 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -203,7 +203,7 @@
 #ifdef CONFIG_PM_H1940
 	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
 #endif
-	s3c2410_pm_init();
+	s3c_pm_init();
 
 	s3c24xx_fb_set_platdata(&rx3715_fb_info);
 	platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
diff --git a/arch/arm/mach-s3c24a0/include/mach/irqs.h b/arch/arm/mach-s3c24a0/include/mach/irqs.h
index ae8c0e3..83ce2a7 100644
--- a/arch/arm/mach-s3c24a0/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24a0/include/mach/irqs.h
@@ -70,6 +70,8 @@
 #define IRQ_EINT17	S3C2410_IRQ(49)
 #define IRQ_EINT18	S3C2410_IRQ(50)
 
+#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT00)
+
 /* SUB IRQS */
 #define IRQ_S3CUART_RX0		S3C2410_IRQ(51)	/* 67 */
 #define IRQ_S3CUART_TX0		S3C2410_IRQ(52)
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
index cff27d8..baf1c0f 100644
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ b/arch/arm/mach-s3c6400/include/mach/map.h
@@ -52,6 +52,9 @@
 #define S3C64XX_PA_VIC0		(0x71200000)
 #define S3C64XX_PA_VIC1		(0x71300000)
 
+#define S3C64XX_PA_MODEM	(0x74108000)
+#define S3C64XX_VA_MODEM	S3C_ADDR(0x00600000)
+
 /* place VICs close together */
 #define S3C_VA_VIC0		(S3C_VA_IRQ + 0x00)
 #define S3C_VA_VIC1		(S3C_VA_IRQ + 0x10000)
diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c6400/include/mach/system.h
index 652bbc4..090cfd9 100644
--- a/arch/arm/mach-s3c6400/include/mach/system.h
+++ b/arch/arm/mach-s3c6400/include/mach/system.h
@@ -16,7 +16,7 @@
 	/* nothing here yet */
 }
 
-static void arch_reset(char mode)
+static void arch_reset(char mode, const char *cmd)
 {
 	/* nothing here yet */
 }
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index f99d901..81ffff7 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -71,19 +71,9 @@
 	  <http://www.handhelds.org/Compaq/index.html#iPAQ_H3600>
 	  <http://www.compaq.com/products/handhelds/pocketpc/>
 
-config SA1100_H3800
-	bool "Compaq iPAQ H3800"
-	help
-	  Say Y here if you intend to run this kernel on the Compaq iPAQ H3800
-	  series handheld computer.  Information about this machine and the
-	  Linux port to this machine can be found at:
-
-	  <http://www.handhelds.org/Compaq/index.html#iPAQ_H3800>
-	  <http://www.compaq.com/products/handhelds/pocketpc/>
-
 config SA1100_H3XXX
 	bool
-	depends on SA1100_H3100 || SA1100_H3600 || SA1100_H3800
+	depends on SA1100_H3100 || SA1100_H3600
 	default y
 
 config SA1100_BADGE4
@@ -157,15 +147,6 @@
 	  This isn't for audio support, but for attached sensors and
 	  other devices, eg for BadgePAD 4 sensor support.
 
-config H3600_SLEEVE
-	tristate "Compaq iPAQ Handheld sleeve support"
-	depends on SA1100_H3100 || SA1100_H3600
-	help
-	  Choose this option to enable support for extension packs (sleeves)
-	  for the Compaq iPAQ H3XXX series of handheld computers.  This option
-	  is required for the CF, PCMCIA, Bluetooth and GSM/GPRS extension
-	  packs.
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 2052eb8..bbf2ebc 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -25,6 +25,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/timer.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -145,7 +146,8 @@
 	.remove	= collie_uart_remove,
 };
 
-static int __init collie_uart_init(void) {
+static int __init collie_uart_init(void)
+{
 	return locomo_driver_register(&collie_uart_driver);
 }
 device_initcall(collie_uart_init);
@@ -195,18 +197,34 @@
 	}
 };
 
+static int collie_flash_init(void)
+{
+	int rc = gpio_request(COLLIE_GPIO_VPEN, "flash Vpp enable");
+	if (rc)
+		return rc;
+
+	rc = gpio_direction_output(COLLIE_GPIO_VPEN, 1);
+	if (rc)
+		gpio_free(COLLIE_GPIO_VPEN);
+
+	return rc;
+}
+
 static void collie_set_vpp(int vpp)
 {
-	write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR) | COLLIE_SCP_VPEN);
-	if (vpp)
-		write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) | COLLIE_SCP_VPEN);
-	else
-		write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
+	gpio_set_value(COLLIE_GPIO_VPEN, vpp);
+}
+
+static void collie_flash_exit(void)
+{
+	gpio_free(COLLIE_GPIO_VPEN);
 }
 
 static struct flash_platform_data collie_flash_data = {
 	.map_name	= "cfi_probe",
+	.init		= collie_flash_init,
 	.set_vpp	= collie_set_vpp,
+	.exit		= collie_flash_exit,
 	.parts		= collie_partitions,
 	.nr_parts	= ARRAY_SIZE(collie_partitions),
 };
diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c
index b39307f..444f266 100644
--- a/arch/arm/mach-sa1100/collie_pm.c
+++ b/arch/arm/mach-sa1100/collie_pm.c
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -58,6 +59,9 @@
 		return;
 	}
 
+	gpio_request(COLLIE_GPIO_CHARGE_ON, "charge on");
+	gpio_direction_output(COLLIE_GPIO_CHARGE_ON, 1);
+
 	ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON |
 			           COLLIE_TC35143_GPIO_BBAT_ON);
 	return;
@@ -73,17 +77,11 @@
 
 static void collie_charge(int on)
 {
-	extern struct platform_device colliescoop_device;
-
 	/* Zaurus seems to contain LTC1731; it should know when to
 	 * stop charging itself, so setting charge on should be
 	 * relatively harmless (as long as it is not done too often).
 	 */
-	if (on) {
-		set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
-	} else {
-		reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
-	}
+	gpio_set_value(COLLIE_GPIO_CHARGE_ON, on);
 }
 
 static void collie_discharge(int on)
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index af25a78..0eb2f15 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -42,19 +42,12 @@
 #include <asm/mach/serial_sa1100.h>
 
 #include <mach/h3600.h>
-
-#if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100)
 #include <mach/h3600_gpio.h>
-#endif
-
-#ifdef CONFIG_SA1100_H3800
-#include <mach/h3600_asic.h>
-#endif
 
 #include "generic.h"
 
-struct ipaq_model_ops ipaq_model_ops;
-EXPORT_SYMBOL(ipaq_model_ops);
+void (*assign_h3600_egpio)(enum ipaq_egpio_type x, int level);
+EXPORT_SYMBOL(assign_h3600_egpio);
 
 static struct mtd_partition h3xxx_partitions[] = {
 	{
@@ -63,41 +56,9 @@
 		.offset		= 0,
 		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
 	}, {
-#ifdef CONFIG_MTD_2PARTS_IPAQ
-		.name		= "H3XXX root jffs2",
+		.name		= "H3XXX rootfs",
 		.size		= MTDPART_SIZ_FULL,
 		.offset		= 0x00040000,
-#else
-		.name		= "H3XXX kernel",
-		.size		= 0x00080000,
-		.offset		= 0x00040000,
-	}, {
-		.name		= "H3XXX params",
-		.size		= 0x00040000,
-		.offset		= 0x000C0000,
-	}, {
-#ifdef CONFIG_JFFS2_FS
-		.name		= "H3XXX root jffs2",
-		.size		= MTDPART_SIZ_FULL,
-		.offset		= 0x00100000,
-#else
-		.name		= "H3XXX initrd",
-		.size		= 0x00100000,
-		.offset		= 0x00100000,
-	}, {
-		.name		= "H3XXX root cramfs",
-		.size		= 0x00300000,
-		.offset		= 0x00200000,
-	}, {
-		.name		= "H3XXX usr cramfs",
-		.size		= 0x00800000,
-		.offset		= 0x00500000,
-	}, {
-		.name		= "H3XXX usr local",
-		.size		= MTDPART_SIZ_FULL,
-		.offset		= 0x00d00000,
-#endif
-#endif
 	}
 };
 
@@ -131,11 +92,7 @@
 
 static void h3600_irda_set_speed(struct device *dev, unsigned int speed)
 {
-	if (speed < 4000000) {
-		clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
-	} else {
-		set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
-	}
+	assign_h3600_egpio(IPAQ_EGPIO_IR_FSEL, !(speed < 4000000));
 }
 
 static struct irda_platform_data h3600_irda_data = {
@@ -266,12 +223,6 @@
 	sa1100fb_lcd_power = h3xxx_lcd_power;
 }
 
-static __inline__ void do_blank(int setp)
-{
-	if (ipaq_model_ops.blank_callback)
-		ipaq_model_ops.blank_callback(1-setp);
-}
-
 /************************* H3100 *************************/
 
 #ifdef CONFIG_SA1100_H3100
@@ -289,7 +240,6 @@
 	case IPAQ_EGPIO_LCD_POWER:
 		egpio |= EGPIO_H3600_LCD_ON;
 		gpio  |= GPIO_H3100_LCD_3V_ON;
-		do_blank(setp);
 		break;
 	case IPAQ_EGPIO_LCD_ENABLE:
 		break;
@@ -343,25 +293,6 @@
 	}
 }
 
-static unsigned long h3100_read_egpio(void)
-{
-	return h3100_egpio;
-}
-
-static int h3100_pm_callback(int req)
-{
-	if (ipaq_model_ops.pm_callback_aux)
-		return ipaq_model_ops.pm_callback_aux(req);
-	return 0;
-}
-
-static struct ipaq_model_ops h3100_model_ops __initdata = {
-	.generic_name	= "3100",
-	.control	= h3100_control_egpio,
-	.read		= h3100_read_egpio,
-	.pm_callback	= h3100_pm_callback
-};
-
 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON	  \
 			  | GPIO_H3100_GPIO3	  \
 			  | GPIO_H3100_QMUTE	  \
@@ -387,7 +318,7 @@
 	GAFR &= ~H3100_DIRECT_EGPIO;
 
 	H3100_EGPIO = h3100_egpio;
-	ipaq_model_ops = h3100_model_ops;
+	assign_h3600_egpio = h3100_control_egpio;
 }
 
 MACHINE_START(H3100, "Compaq iPAQ H3100")
@@ -420,7 +351,6 @@
 			 EGPIO_H3600_LCD_PCI |
 			 EGPIO_H3600_LCD_5V_ON |
 			 EGPIO_H3600_LVDD_ON;
-		do_blank(setp);
 		break;
 	case IPAQ_EGPIO_LCD_ENABLE:
 		break;
@@ -471,25 +401,6 @@
 	}
 }
 
-static unsigned long h3600_read_egpio(void)
-{
-	return h3600_egpio;
-}
-
-static int h3600_pm_callback(int req)
-{
-	if (ipaq_model_ops.pm_callback_aux)
-		return ipaq_model_ops.pm_callback_aux(req);
-	return 0;
-}
-
-static struct ipaq_model_ops h3600_model_ops __initdata = {
-	.generic_name	= "3600",
-	.control	= h3600_control_egpio,
-	.read		= h3600_read_egpio,
-	.pm_callback	= h3600_pm_callback
-};
-
 static void __init h3600_map_io(void)
 {
 	h3xxx_map_io();
@@ -504,7 +415,7 @@
 	       GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
 
 	H3600_EGPIO = h3600_egpio;	   /* Maintains across sleep? */
-	ipaq_model_ops = h3600_model_ops;
+	assign_h3600_egpio = h3600_control_egpio;
 }
 
 MACHINE_START(H3600, "Compaq iPAQ H3600")
@@ -519,388 +430,3 @@
 
 #endif /* CONFIG_SA1100_H3600 */
 
-#ifdef CONFIG_SA1100_H3800
-
-#define SET_ASIC1(x) \
-   do {if (setp) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
-
-#define SET_ASIC2(x) \
-   do {if (setp) { H3800_ASIC2_GPIOPIOD |= (x); } else { H3800_ASIC2_GPIOPIOD &= ~(x); }} while(0)
-
-#define CLEAR_ASIC1(x) \
-   do {if (setp) { H3800_ASIC1_GPIO_OUT &= ~(x); } else { H3800_ASIC1_GPIO_OUT |= (x); }} while(0)
-
-#define CLEAR_ASIC2(x) \
-   do {if (setp) { H3800_ASIC2_GPIOPIOD &= ~(x); } else { H3800_ASIC2_GPIOPIOD |= (x); }} while(0)
-
-
-/*
-  On screen enable, we get
-
-     h3800_video_power_on(1)
-     LCD controller starts
-     h3800_video_lcd_enable(1)
-
-  On screen disable, we get
-
-     h3800_video_lcd_enable(0)
-     LCD controller stops
-     h3800_video_power_on(0)
-*/
-
-
-static void h3800_video_power_on(int setp)
-{
-	if (setp) {
-		H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_ON;
-		msleep(30);
-		H3800_ASIC1_GPIO_OUT |= GPIO1_VGL_ON;
-		msleep(5);
-		H3800_ASIC1_GPIO_OUT |= GPIO1_VGH_ON;
-		msleep(50);
-		H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_5V_ON;
-		msleep(5);
-	} else {
-		msleep(5);
-		H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_5V_ON;
-		msleep(50);
-		H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGL_ON;
-		msleep(5);
-		H3800_ASIC1_GPIO_OUT &= ~GPIO1_VGH_ON;
-		msleep(100);
-		H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_ON;
-	}
-}
-
-static void h3800_video_lcd_enable(int setp)
-{
-	if (setp) {
-		msleep(17);	// Wait one from before turning on
-		H3800_ASIC1_GPIO_OUT |= GPIO1_LCD_PCI;
-	} else {
-		H3800_ASIC1_GPIO_OUT &= ~GPIO1_LCD_PCI;
-		msleep(30);	// Wait before turning off
-	}
-}
-
-
-static void h3800_control_egpio(enum ipaq_egpio_type x, int setp)
-{
-	switch (x) {
-	case IPAQ_EGPIO_LCD_POWER:
-		h3800_video_power_on(setp);
-		break;
-	case IPAQ_EGPIO_LCD_ENABLE:
-		h3800_video_lcd_enable(setp);
-		break;
-	case IPAQ_EGPIO_CODEC_NRESET:
-	case IPAQ_EGPIO_AUDIO_ON:
-	case IPAQ_EGPIO_QMUTE:
-		printk("%s: error - should not be called\n", __func__);
-		break;
-	case IPAQ_EGPIO_OPT_NVRAM_ON:
-		SET_ASIC2(GPIO2_OPT_ON_NVRAM);
-		break;
-	case IPAQ_EGPIO_OPT_ON:
-		SET_ASIC2(GPIO2_OPT_ON);
-		break;
-	case IPAQ_EGPIO_CARD_RESET:
-		SET_ASIC2(GPIO2_OPT_PCM_RESET);
-		break;
-	case IPAQ_EGPIO_OPT_RESET:
-		SET_ASIC2(GPIO2_OPT_RESET);
-		break;
-	case IPAQ_EGPIO_IR_ON:
-		CLEAR_ASIC1(GPIO1_IR_ON_N);
-		break;
-	case IPAQ_EGPIO_IR_FSEL:
-		break;
-	case IPAQ_EGPIO_RS232_ON:
-		SET_ASIC1(GPIO1_RS232_ON);
-		break;
-	case IPAQ_EGPIO_VPP_ON:
-		H3800_ASIC2_FlashWP_VPP_ON = setp;
-		break;
-	}
-}
-
-static unsigned long h3800_read_egpio(void)
-{
-	return H3800_ASIC1_GPIO_OUT | (H3800_ASIC2_GPIOPIOD << 16);
-}
-
-/* We need to fix ASIC2 GPIO over suspend/resume.  At the moment,
-   it doesn't appear that ASIC1 GPIO has the same problem */
-
-static int h3800_pm_callback(int req)
-{
-	static u16 asic1_data;
-	static u16 asic2_data;
-	int result = 0;
-
-	printk("%s %d\n", __func__, req);
-
-	switch (req) {
-	case PM_RESUME:
-		MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000;  /* Set MSC2 correctly */
-
-		H3800_ASIC2_GPIOPIOD = asic2_data;
-		H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ
-			| GPIO2_SD_DETECT
-			| GPIO2_EAR_IN_N
-			| GPIO2_USB_DETECT_N
-			| GPIO2_SD_CON_SLT;
-
-		H3800_ASIC1_GPIO_OUT = asic1_data;
-
-		if (ipaq_model_ops.pm_callback_aux)
-			result = ipaq_model_ops.pm_callback_aux(req);
-		break;
-
-	case PM_SUSPEND:
-		if (ipaq_model_ops.pm_callback_aux &&
-		     ((result = ipaq_model_ops.pm_callback_aux(req)) != 0))
-			return result;
-
-		asic1_data = H3800_ASIC1_GPIO_OUT;
-		asic2_data = H3800_ASIC2_GPIOPIOD;
-		break;
-	default:
-		printk("%s: unrecognized PM callback\n", __func__);
-		break;
-	}
-	return result;
-}
-
-static struct ipaq_model_ops h3800_model_ops __initdata = {
-	.generic_name	= "3800",
-	.control	= h3800_control_egpio,
-	.read		= h3800_read_egpio,
-	.pm_callback	= h3800_pm_callback
-};
-
-#define MAX_ASIC_ISR_LOOPS    20
-
-/* The order of these is important - see #include <mach/irqs.h> */
-static u32 kpio_irq_mask[] = {
-	KPIO_KEY_ALL,
-	KPIO_SPI_INT,
-	KPIO_OWM_INT,
-	KPIO_ADC_INT,
-	KPIO_UART_0_INT,
-	KPIO_UART_1_INT,
-	KPIO_TIMER_0_INT,
-	KPIO_TIMER_1_INT,
-	KPIO_TIMER_2_INT
-};
-
-static u32 gpio_irq_mask[] = {
-	GPIO2_PEN_IRQ,
-	GPIO2_SD_DETECT,
-	GPIO2_EAR_IN_N,
-	GPIO2_USB_DETECT_N,
-	GPIO2_SD_CON_SLT,
-};
-
-static void h3800_IRQ_demux(unsigned int irq, struct irq_desc *desc)
-{
-	int i;
-
-	if (0) printk("%s: interrupt received\n", __func__);
-
-	desc->chip->ack(irq);
-
-	for (i = 0; i < MAX_ASIC_ISR_LOOPS && (GPLR & GPIO_H3800_ASIC); i++) {
-		u32 irq;
-		int j;
-
-		/* KPIO */
-		irq = H3800_ASIC2_KPIINTFLAG;
-		if (0) printk("%s KPIO 0x%08X\n", __func__, irq);
-		for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++)
-			if (irq & kpio_irq_mask[j])
-				handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j);
-
-		/* GPIO2 */
-		irq = H3800_ASIC2_GPIINTFLAG;
-		if (0) printk("%s GPIO 0x%08X\n", __func__, irq);
-		for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++)
-			if (irq & gpio_irq_mask[j])
-				handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j);
-	}
-
-	if (i >= MAX_ASIC_ISR_LOOPS)
-		printk("%s: interrupt processing overrun\n", __func__);
-
-	/* For level-based interrupts */
-	desc->chip->unmask(irq);
-
-}
-
-static struct irqaction h3800_irq = {
-	.name		= "h3800_asic",
-	.handler	= h3800_IRQ_demux,
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-};
-
-u32 kpio_int_shadow = 0;
-
-
-/* mask_ack <- IRQ is first serviced.
-       mask <- IRQ is disabled.
-     unmask <- IRQ is enabled
-
-     The INTCLR registers are poorly documented.  I believe that writing
-     a "1" to the register clears the specific interrupt, but the documentation
-     indicates writing a "0" clears the interrupt.  In any case, they shouldn't
-     be read (that's the INTFLAG register)
- */
-
-static void h3800_mask_ack_kpio_irq(unsigned int irq)
-{
-	u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
-	kpio_int_shadow &= ~mask;
-	H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
-	H3800_ASIC2_KPIINTCLR  = mask;
-}
-
-static void h3800_mask_kpio_irq(unsigned int irq)
-{
-	u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
-	kpio_int_shadow &= ~mask;
-	H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
-}
-
-static void h3800_unmask_kpio_irq(unsigned int irq)
-{
-	u32 mask = kpio_irq_mask[irq - H3800_KPIO_IRQ_START];
-	kpio_int_shadow |= mask;
-	H3800_ASIC2_KPIINTSTAT = kpio_int_shadow;
-}
-
-static void h3800_mask_ack_gpio_irq(unsigned int irq)
-{
-	u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
-	H3800_ASIC2_GPIINTSTAT &= ~mask;
-	H3800_ASIC2_GPIINTCLR	= mask;
-}
-
-static void h3800_mask_gpio_irq(unsigned int irq)
-{
-	u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
-	H3800_ASIC2_GPIINTSTAT &= ~mask;
-	}
-
-static void h3800_unmask_gpio_irq(unsigned int irq)
-{
-	u32 mask = gpio_irq_mask[irq - H3800_GPIO_IRQ_START];
-	H3800_ASIC2_GPIINTSTAT |= mask;
-}
-
-static void __init h3800_init_irq(void)
-{
-	int i;
-
-	/* Initialize standard IRQs */
-	sa1100_init_irq();
-
-	/* Disable all IRQs and set up clock */
-	H3800_ASIC2_KPIINTSTAT	   =  0;     /* Disable all interrupts */
-	H3800_ASIC2_GPIINTSTAT	   =  0;
-
-	H3800_ASIC2_KPIINTCLR	   =  0;     /* Clear all KPIO interrupts */
-	H3800_ASIC2_GPIINTCLR	   =  0;     /* Clear all GPIO interrupts */
-
-//	H3800_ASIC2_KPIINTCLR	   =  0xffff;	  /* Clear all KPIO interrupts */
-//	H3800_ASIC2_GPIINTCLR	   =  0xffff;	  /* Clear all GPIO interrupts */
-
-	H3800_ASIC2_CLOCK_Enable       |= ASIC2_CLOCK_EX0;   /* 32 kHZ crystal on */
-	H3800_ASIC2_INTR_ClockPrescale |= ASIC2_INTCPS_SET;
-	H3800_ASIC2_INTR_ClockPrescale	= ASIC2_INTCPS_CPS(0x0e) | ASIC2_INTCPS_SET;
-	H3800_ASIC2_INTR_TimerSet	= 1;
-
-#if 0
-	for (i = 0; i < H3800_KPIO_IRQ_COUNT; i++) {
-		int irq = i + H3800_KPIO_IRQ_START;
-		irq_desc[irq].valid    = 1;
-		irq_desc[irq].probe_ok = 1;
-		set_irq_chip(irq, &h3800_kpio_irqchip);
-	}
-
-	for (i = 0; i < H3800_GPIO_IRQ_COUNT; i++) {
-		int irq = i + H3800_GPIO_IRQ_START;
-		irq_desc[irq].valid    = 1;
-		irq_desc[irq].probe_ok = 1;
-		set_irq_chip(irq, &h3800_gpio_irqchip);
-	}
-#endif
-	set_irq_type(IRQ_GPIO_H3800_ASIC, IRQ_TYPE_EDGE_RISING);
-	set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux);
-}
-
-
-#define ASIC1_OUTPUTS	 0x7fff   /* First 15 bits are used */
-
-static void __init h3800_map_io(void)
-{
-	h3xxx_map_io();
-
-	/* Add wakeup on AC plug/unplug */
-	PWER  |= PWER_GPIO12;
-
-	/* Initialize h3800-specific values here */
-	GPCR = 0x0fffffff;	 /* All outputs are set low by default */
-	GAFR =	GPIO_H3800_CLK_OUT |
-		GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
-		GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
-	GPDR =	GPIO_H3800_CLK_OUT |
-		GPIO_H3600_COM_RTS  | GPIO_H3600_L3_CLOCK |
-		GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
-		GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
-		GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
-	TUCR =	TUCR_3_6864MHz;   /* Seems to be used only for the Bluetooth UART */
-
-	/* Fix the memory bus */
-	MSC2 = (MSC2 & 0x0000ffff) | 0xE4510000;
-
-	/* Set up ASIC #1 */
-	H3800_ASIC1_GPIO_DIR		= ASIC1_OUTPUTS;	    /* All outputs */
-	H3800_ASIC1_GPIO_MASK		= ASIC1_OUTPUTS;	    /* No interrupts */
-	H3800_ASIC1_GPIO_SLEEP_MASK	= ASIC1_OUTPUTS;
-	H3800_ASIC1_GPIO_SLEEP_DIR	= ASIC1_OUTPUTS;
-	H3800_ASIC1_GPIO_SLEEP_OUT	= GPIO1_EAR_ON_N;
-	H3800_ASIC1_GPIO_BATT_FAULT_DIR = ASIC1_OUTPUTS;
-	H3800_ASIC1_GPIO_BATT_FAULT_OUT = GPIO1_EAR_ON_N;
-
-	H3800_ASIC1_GPIO_OUT = GPIO1_IR_ON_N
-				      | GPIO1_RS232_ON
-				      | GPIO1_EAR_ON_N;
-
-	/* Set up ASIC #2 */
-	H3800_ASIC2_GPIOPIOD	= GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
-	H3800_ASIC2_GPOBFSTAT	= GPIO2_IN_Y1_N | GPIO2_IN_X1_N;
-
-	H3800_ASIC2_GPIODIR	= GPIO2_PEN_IRQ
-				      | GPIO2_SD_DETECT
-				      | GPIO2_EAR_IN_N
-				      | GPIO2_USB_DETECT_N
-				      | GPIO2_SD_CON_SLT;
-
-	/* TODO : Set sleep states & battery fault states */
-
-	/* Clear VPP Enable */
-	H3800_ASIC2_FlashWP_VPP_ON = 0;
-	ipaq_model_ops = h3800_model_ops;
-}
-
-MACHINE_START(H3800, "Compaq iPAQ H3800")
-	.phys_io	= 0x80000000,
-	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
-	.boot_params	= 0xc0000100,
-	.map_io		= h3800_map_io,
-	.init_irq	= h3800_init_irq,
-	.timer		= &sa1100_timer,
-	.init_machine	= h3xxx_mach_init,
-MACHINE_END
-
-#endif /* CONFIG_SA1100_H3800 */
diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h
index 69e9624..9efb569 100644
--- a/arch/arm/mach-sa1100/include/mach/collie.h
+++ b/arch/arm/mach-sa1100/include/mach/collie.h
@@ -14,21 +14,21 @@
 #define __ASM_ARCH_COLLIE_H
 
 
-#define COLLIE_SCP_CHARGE_ON	SCOOP_GPCR_PA11
+#define COLLIE_SCOOP_GPIO_BASE	(GPIO_MAX + 1)
+#define COLLIE_GPIO_CHARGE_ON	(COLLIE_SCOOP_GPIO_BASE + 0)
 #define COLLIE_SCP_DIAG_BOOT1	SCOOP_GPCR_PA12
 #define COLLIE_SCP_DIAG_BOOT2	SCOOP_GPCR_PA13
 #define COLLIE_SCP_MUTE_L	SCOOP_GPCR_PA14
 #define COLLIE_SCP_MUTE_R	SCOOP_GPCR_PA15
 #define COLLIE_SCP_5VON		SCOOP_GPCR_PA16
 #define COLLIE_SCP_AMP_ON	SCOOP_GPCR_PA17
-#define COLLIE_SCP_VPEN		SCOOP_GPCR_PA18
+#define COLLIE_GPIO_VPEN	(COLLIE_SCOOP_GPIO_BASE + 7)
 #define COLLIE_SCP_LB_VOL_CHG	SCOOP_GPCR_PA19
 
-#define COLLIE_SCOOP_IO_DIR	( COLLIE_SCP_CHARGE_ON | COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \
-				COLLIE_SCP_5VON | COLLIE_SCP_AMP_ON | COLLIE_SCP_VPEN | \
+#define COLLIE_SCOOP_IO_DIR	( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | \
+				COLLIE_SCP_5VON | COLLIE_SCP_AMP_ON | \
 				COLLIE_SCP_LB_VOL_CHG )
-#define COLLIE_SCOOP_IO_OUT	( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R | COLLIE_SCP_VPEN | \
-				COLLIE_SCP_CHARGE_ON )
+#define COLLIE_SCOOP_IO_OUT	( COLLIE_SCP_MUTE_L | COLLIE_SCP_MUTE_R )
 
 /* GPIOs for which the generic definition doesn't say much */
 
diff --git a/arch/arm/mach-sa1100/include/mach/h3600.h b/arch/arm/mach-sa1100/include/mach/h3600.h
index 9cc47fd..2827faa 100644
--- a/arch/arm/mach-sa1100/include/mach/h3600.h
+++ b/arch/arm/mach-sa1100/include/mach/h3600.h
@@ -29,7 +29,7 @@
 #define PM_RESUME	((__force pm_request_t) 2)	/* enter D0 */
 
 /* generalized support for H3xxx series Compaq Pocket PC's */
-#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
+#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600())
 
 /* Physical memory regions corresponding to chip selects */
 #define H3600_EGPIO_PHYS	(SA1100_CS5_PHYS + 0x01000000)
@@ -93,76 +93,7 @@
 	IPAQ_EGPIO_LCD_ENABLE,	  /* Enable/disable LCD controller */
 };
 
-struct ipaq_model_ops {
-	const char     *generic_name;
-	void	      (*control)(enum ipaq_egpio_type, int);
-	unsigned long (*read)(void);
-	void	      (*blank_callback)(int blank);
-	int	      (*pm_callback)(int req);	    /* Primary model callback */
-	int	      (*pm_callback_aux)(int req);  /* Secondary callback (used by HAL modules) */
-};
-
-extern struct ipaq_model_ops ipaq_model_ops;
-
-static __inline__ const char * h3600_generic_name(void)
-{
-	return ipaq_model_ops.generic_name;
-}
-
-static __inline__ void assign_h3600_egpio(enum ipaq_egpio_type x, int level)
-{
-	if (ipaq_model_ops.control)
-		ipaq_model_ops.control(x,level);
-}
-
-static __inline__ void clr_h3600_egpio(enum ipaq_egpio_type x)
-{
-	if (ipaq_model_ops.control)
-		ipaq_model_ops.control(x,0);
-}
-
-static __inline__ void set_h3600_egpio(enum ipaq_egpio_type x)
-{
-	if (ipaq_model_ops.control)
-		ipaq_model_ops.control(x,1);
-}
-
-static __inline__ unsigned long read_h3600_egpio(void)
-{
-	if (ipaq_model_ops.read)
-		return ipaq_model_ops.read();
-	return 0;
-}
-
-static __inline__ int  h3600_register_blank_callback(void (*f)(int))
-{
-	ipaq_model_ops.blank_callback = f;
-	return 0;
-}
-
-static __inline__ void h3600_unregister_blank_callback(void (*f)(int))
-{
-	ipaq_model_ops.blank_callback = NULL;
-}
-
-
-static __inline__ int  h3600_register_pm_callback(int (*f)(int))
-{
-	ipaq_model_ops.pm_callback_aux = f;
-	return 0;
-}
-
-static __inline__ void h3600_unregister_pm_callback(int (*f)(int))
-{
-	ipaq_model_ops.pm_callback_aux = NULL;
-}
-
-static __inline__ int h3600_power_management(int req)
-{
-	if (ipaq_model_ops.pm_callback)
-		return ipaq_model_ops.pm_callback(req);
-	return 0;
-}
+extern void (*assign_h3600_egpio)(enum ipaq_egpio_type x, int level);
 
 #endif /* ASSEMBLY */
 
diff --git a/arch/arm/mach-sa1100/include/mach/h3600_gpio.h b/arch/arm/mach-sa1100/include/mach/h3600_gpio.h
index 62b0b78..a36ca76 100644
--- a/arch/arm/mach-sa1100/include/mach/h3600_gpio.h
+++ b/arch/arm/mach-sa1100/include/mach/h3600_gpio.h
@@ -48,22 +48,11 @@
 #define GPIO_H3600_OPT_LOCK		GPIO_GPIO (22)
 #define GPIO_H3600_OPT_DET		GPIO_GPIO (27)
 
-/* H3800 specific pins */
-#define GPIO_H3800_AC_IN                GPIO_GPIO (12)
-#define GPIO_H3800_COM_DSR              GPIO_GPIO (13)
-#define GPIO_H3800_MMC_INT              GPIO_GPIO (18)
-#define GPIO_H3800_NOPT_IND             GPIO_GPIO (20)   /* Almost exactly the same as GPIO_H3600_OPT_DET */
-#define GPIO_H3800_OPT_BAT_FAULT        GPIO_GPIO (22)
-#define GPIO_H3800_CLK_OUT              GPIO_GPIO (27)
-
 /****************************************************/
 
 #define IRQ_GPIO_H3600_ACTION_BUTTON    IRQ_GPIO18
 #define IRQ_GPIO_H3600_OPT_DET		IRQ_GPIO27
 
-#define IRQ_GPIO_H3800_MMC_INT          IRQ_GPIO18
-#define IRQ_GPIO_H3800_NOPT_IND         IRQ_GPIO20 /* almost same as OPT_DET */
-
 /* H3100 / 3600 EGPIO pins */
 #define EGPIO_H3600_VPP_ON		(1 << 0)
 #define EGPIO_H3600_CARD_RESET		(1 << 1)   /* reset the attached pcmcia/compactflash card.  active high. */
@@ -84,457 +73,5 @@
 #define EGPIO_H3600_LCD_5V_ON		(1 << 14)  /* enable 5V to LCD. active high. */
 #define EGPIO_H3600_LVDD_ON		(1 << 15)  /* enable 9V and -6.5V to LCD. */
 
-/********************* H3800, ASIC #2 ********************/
-
-#define _H3800_ASIC2_Base            (H3600_EGPIO_VIRT)
-#define H3800_ASIC2_OFFSET(s,x,y)    \
-    (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
-#define H3800_ASIC2_NOFFSET(s,x,n,y) \
-    (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _ ## n ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
-
-#define _H3800_ASIC2_GPIO_Base                 0x0000
-#define _H3800_ASIC2_GPIO_Direction            0x0000    /* R/W, 16 bits 1:input, 0:output */
-#define _H3800_ASIC2_GPIO_InterruptType        0x0004    /* R/W, 12 bits 1:edge, 0:level          */
-#define _H3800_ASIC2_GPIO_InterruptEdgeType    0x0008    /* R/W, 12 bits 1:rising, 0:falling */
-#define _H3800_ASIC2_GPIO_InterruptLevelType   0x000C    /* R/W, 12 bits 1:high, 0:low  */
-#define _H3800_ASIC2_GPIO_InterruptClear       0x0010    /* W,   12 bits */
-#define _H3800_ASIC2_GPIO_InterruptFlag        0x0010    /* R,   12 bits - reads int status */
-#define _H3800_ASIC2_GPIO_Data                 0x0014    /* R/W, 16 bits */
-#define _H3800_ASIC2_GPIO_BattFaultOut         0x0018    /* R/W, 16 bit - sets level on batt fault */
-#define _H3800_ASIC2_GPIO_InterruptEnable      0x001c    /* R/W, 12 bits 1:enable interrupt */
-#define _H3800_ASIC2_GPIO_Alternate            0x003c    /* R/W, 12+1 bits - set alternate functions */
-
-#define H3800_ASIC2_GPIO_Direction          H3800_ASIC2_OFFSET( u16, GPIO, Direction )
-#define H3800_ASIC2_GPIO_InterruptType      H3800_ASIC2_OFFSET( u16, GPIO, InterruptType )
-#define H3800_ASIC2_GPIO_InterruptEdgeType  H3800_ASIC2_OFFSET( u16, GPIO, InterruptEdgeType )
-#define H3800_ASIC2_GPIO_InterruptLevelType H3800_ASIC2_OFFSET( u16, GPIO, InterruptLevelType )
-#define H3800_ASIC2_GPIO_InterruptClear     H3800_ASIC2_OFFSET( u16, GPIO, InterruptClear )
-#define H3800_ASIC2_GPIO_InterruptFlag      H3800_ASIC2_OFFSET( u16, GPIO, InterruptFlag )
-#define H3800_ASIC2_GPIO_Data               H3800_ASIC2_OFFSET( u16, GPIO, Data )
-#define H3800_ASIC2_GPIO_BattFaultOut       H3800_ASIC2_OFFSET( u16, GPIO, BattFaultOut )
-#define H3800_ASIC2_GPIO_InterruptEnable    H3800_ASIC2_OFFSET( u16, GPIO, InterruptEnable )
-#define H3800_ASIC2_GPIO_Alternate          H3800_ASIC2_OFFSET( u16, GPIO, Alternate )
-
-#define GPIO_H3800_ASIC2_IN_Y1_N          (1 << 0)   /* Output: Touchscreen Y1 */
-#define GPIO_H3800_ASIC2_IN_X0            (1 << 1)   /* Output: Touchscreen X0 */
-#define GPIO_H3800_ASIC2_IN_Y0            (1 << 2)   /* Output: Touchscreen Y0 */
-#define GPIO_H3800_ASIC2_IN_X1_N          (1 << 3)   /* Output: Touchscreen X1 */
-#define GPIO_H3800_ASIC2_BT_RST           (1 << 4)   /* Output: Bluetooth reset */
-#define GPIO_H3800_ASIC2_PEN_IRQ          (1 << 5)   /* Input : Pen down        */
-#define GPIO_H3800_ASIC2_SD_DETECT        (1 << 6)   /* Input : SD detect */
-#define GPIO_H3800_ASIC2_EAR_IN_N         (1 << 7)   /* Input : Audio jack plug inserted */
-#define GPIO_H3800_ASIC2_OPT_PCM_RESET    (1 << 8)   /* Output: */
-#define GPIO_H3800_ASIC2_OPT_RESET        (1 << 9)   /* Output: */
-#define GPIO_H3800_ASIC2_USB_DETECT_N     (1 << 10)  /* Input : */
-#define GPIO_H3800_ASIC2_SD_CON_SLT       (1 << 11)  /* Input : */
-
-#define _H3800_ASIC2_KPIO_Base                 0x0200
-#define _H3800_ASIC2_KPIO_Direction            0x0000    /* R/W, 12 bits 1:input, 0:output */
-#define _H3800_ASIC2_KPIO_InterruptType        0x0004    /* R/W, 12 bits 1:edge, 0:level          */
-#define _H3800_ASIC2_KPIO_InterruptEdgeType    0x0008    /* R/W, 12 bits 1:rising, 0:falling */
-#define _H3800_ASIC2_KPIO_InterruptLevelType   0x000C    /* R/W, 12 bits 1:high, 0:low  */
-#define _H3800_ASIC2_KPIO_InterruptClear       0x0010    /* W,   20 bits - 8 special */
-#define _H3800_ASIC2_KPIO_InterruptFlag        0x0010    /* R,   20 bits - 8 special - reads int status */
-#define _H3800_ASIC2_KPIO_Data                 0x0014    /* R/W, 16 bits */
-#define _H3800_ASIC2_KPIO_BattFaultOut         0x0018    /* R/W, 16 bit - sets level on batt fault */
-#define _H3800_ASIC2_KPIO_InterruptEnable      0x001c    /* R/W, 20 bits - 8 special */
-#define _H3800_ASIC2_KPIO_Alternate            0x003c    /* R/W, 6 bits */
-
-#define H3800_ASIC2_KPIO_Direction          H3800_ASIC2_OFFSET( u16, KPIO, Direction )
-#define H3800_ASIC2_KPIO_InterruptType      H3800_ASIC2_OFFSET( u16, KPIO, InterruptType )
-#define H3800_ASIC2_KPIO_InterruptEdgeType  H3800_ASIC2_OFFSET( u16, KPIO, InterruptEdgeType )
-#define H3800_ASIC2_KPIO_InterruptLevelType H3800_ASIC2_OFFSET( u16, KPIO, InterruptLevelType )
-#define H3800_ASIC2_KPIO_InterruptClear     H3800_ASIC2_OFFSET( u32, KPIO, InterruptClear )
-#define H3800_ASIC2_KPIO_InterruptFlag      H3800_ASIC2_OFFSET( u32, KPIO, InterruptFlag )
-#define H3800_ASIC2_KPIO_Data               H3800_ASIC2_OFFSET( u16, KPIO, Data )
-#define H3800_ASIC2_KPIO_BattFaultOut       H3800_ASIC2_OFFSET( u16, KPIO, BattFaultOut )
-#define H3800_ASIC2_KPIO_InterruptEnable    H3800_ASIC2_OFFSET( u32, KPIO, InterruptEnable )
-#define H3800_ASIC2_KPIO_Alternate          H3800_ASIC2_OFFSET( u16, KPIO, Alternate )
-
-#define H3800_ASIC2_KPIO_SPI_INT        ( 1 << 16 )
-#define H3800_ASIC2_KPIO_OWM_INT        ( 1 << 17 )
-#define H3800_ASIC2_KPIO_ADC_INT        ( 1 << 18 )
-#define H3800_ASIC2_KPIO_UART_0_INT     ( 1 << 19 )
-#define H3800_ASIC2_KPIO_UART_1_INT     ( 1 << 20 )
-#define H3800_ASIC2_KPIO_TIMER_0_INT    ( 1 << 21 )
-#define H3800_ASIC2_KPIO_TIMER_1_INT    ( 1 << 22 )
-#define H3800_ASIC2_KPIO_TIMER_2_INT    ( 1 << 23 )
-
-#define KPIO_H3800_ASIC2_RECORD_BTN_N     (1 << 0)   /* Record button */
-#define KPIO_H3800_ASIC2_KEY_5W1_N        (1 << 1)   /* Keypad */
-#define KPIO_H3800_ASIC2_KEY_5W2_N        (1 << 2)   /* */
-#define KPIO_H3800_ASIC2_KEY_5W3_N        (1 << 3)   /* */
-#define KPIO_H3800_ASIC2_KEY_5W4_N        (1 << 4)   /* */
-#define KPIO_H3800_ASIC2_KEY_5W5_N        (1 << 5)   /* */
-#define KPIO_H3800_ASIC2_KEY_LEFT_N       (1 << 6)   /* */
-#define KPIO_H3800_ASIC2_KEY_RIGHT_N      (1 << 7)   /* */
-#define KPIO_H3800_ASIC2_KEY_AP1_N        (1 << 8)   /* Old "Calendar" */
-#define KPIO_H3800_ASIC2_KEY_AP2_N        (1 << 9)   /* Old "Schedule" */
-#define KPIO_H3800_ASIC2_KEY_AP3_N        (1 << 10)  /* Old "Q"        */
-#define KPIO_H3800_ASIC2_KEY_AP4_N        (1 << 11)  /* Old "Undo"     */
-
-/* Alternate KPIO functions (set by default) */
-#define KPIO_ALT_H3800_ASIC2_KEY_5W1_N        (1 << 1)   /* Action key */
-#define KPIO_ALT_H3800_ASIC2_KEY_5W2_N        (1 << 2)   /* J1 of keypad input */
-#define KPIO_ALT_H3800_ASIC2_KEY_5W3_N        (1 << 3)   /* J2 of keypad input */
-#define KPIO_ALT_H3800_ASIC2_KEY_5W4_N        (1 << 4)   /* J3 of keypad input */
-#define KPIO_ALT_H3800_ASIC2_KEY_5W5_N        (1 << 5)   /* J4 of keypad input */
-
-#define _H3800_ASIC2_SPI_Base                  0x0400
-#define _H3800_ASIC2_SPI_Control               0x0000    /* R/W 8 bits */
-#define _H3800_ASIC2_SPI_Data                  0x0004    /* R/W 8 bits */
-#define _H3800_ASIC2_SPI_ChipSelectDisabled    0x0008    /* W   8 bits */
-
-#define H3800_ASIC2_SPI_Control             H3800_ASIC2_OFFSET( u8, SPI, Control )
-#define H3800_ASIC2_SPI_Data                H3800_ASIC2_OFFSET( u8, SPI, Data )
-#define H3800_ASIC2_SPI_ChipSelectDisabled  H3800_ASIC2_OFFSET( u8, SPI, ChipSelectDisabled )
-
-#define _H3800_ASIC2_PWM_0_Base                0x0600
-#define _H3800_ASIC2_PWM_1_Base                0x0700
-#define _H3800_ASIC2_PWM_TimeBase              0x0000    /* R/W 6 bits */
-#define _H3800_ASIC2_PWM_PeriodTime            0x0004    /* R/W 12 bits */
-#define _H3800_ASIC2_PWM_DutyTime              0x0008    /* R/W 12 bits */
-
-#define H3800_ASIC2_PWM_0_TimeBase          H3800_ASIC2_NOFFSET(  u8, PWM, 0, TimeBase )
-#define H3800_ASIC2_PWM_0_PeriodTime        H3800_ASIC2_NOFFSET( u16, PWM, 0, PeriodTime )
-#define H3800_ASIC2_PWM_0_DutyTime          H3800_ASIC2_NOFFSET( u16, PWM, 0, DutyTime )
-
-#define H3800_ASIC2_PWM_1_TimeBase          H3800_ASIC2_NOFFSET(  u8, PWM, 1, TimeBase )
-#define H3800_ASIC2_PWM_1_PeriodTime        H3800_ASIC2_NOFFSET( u16, PWM, 1, PeriodTime )
-#define H3800_ASIC2_PWM_1_DutyTime          H3800_ASIC2_NOFFSET( u16, PWM, 1, DutyTime )
-
-#define H3800_ASIC2_PWM_TIMEBASE_MASK             0xf    /* Low 4 bits sets time base, max = 8 */
-#define H3800_ASIC2_PWM_TIMEBASE_ENABLE    ( 1 << 4 )    /* Enable clock */
-#define H3800_ASIC2_PWM_TIMEBASE_CLEAR     ( 1 << 5 )    /* Clear the PWM */
-
-#define _H3800_ASIC2_LED_0_Base                0x0800
-#define _H3800_ASIC2_LED_1_Base                0x0880
-#define _H3800_ASIC2_LED_2_Base                0x0900
-#define _H3800_ASIC2_LED_TimeBase              0x0000    /* R/W  7 bits */
-#define _H3800_ASIC2_LED_PeriodTime            0x0004    /* R/W 12 bits */
-#define _H3800_ASIC2_LED_DutyTime              0x0008    /* R/W 12 bits */
-#define _H3800_ASIC2_LED_AutoStopCount         0x000c    /* R/W 16 bits */
-
-#define H3800_ASIC2_LED_0_TimeBase          H3800_ASIC2_NOFFSET(  u8, LED, 0, TimeBase )
-#define H3800_ASIC2_LED_0_PeriodTime        H3800_ASIC2_NOFFSET( u16, LED, 0, PeriodTime )
-#define H3800_ASIC2_LED_0_DutyTime          H3800_ASIC2_NOFFSET( u16, LED, 0, DutyTime )
-#define H3800_ASIC2_LED_0_AutoStopClock     H3800_ASIC2_NOFFSET( u16, LED, 0, AutoStopClock )
-
-#define H3800_ASIC2_LED_1_TimeBase          H3800_ASIC2_NOFFSET(  u8, LED, 1, TimeBase )
-#define H3800_ASIC2_LED_1_PeriodTime        H3800_ASIC2_NOFFSET( u16, LED, 1, PeriodTime )
-#define H3800_ASIC2_LED_1_DutyTime          H3800_ASIC2_NOFFSET( u16, LED, 1, DutyTime )
-#define H3800_ASIC2_LED_1_AutoStopClock     H3800_ASIC2_NOFFSET( u16, LED, 1, AutoStopClock )
-
-#define H3800_ASIC2_LED_2_TimeBase          H3800_ASIC2_NOFFSET(  u8, LED, 2, TimeBase )
-#define H3800_ASIC2_LED_2_PeriodTime        H3800_ASIC2_NOFFSET( u16, LED, 2, PeriodTime )
-#define H3800_ASIC2_LED_2_DutyTime          H3800_ASIC2_NOFFSET( u16, LED, 2, DutyTime )
-#define H3800_ASIC2_LED_2_AutoStopClock     H3800_ASIC2_NOFFSET( u16, LED, 2, AutoStopClock )
-
-#define H3800_ASIC2_LED_TIMEBASE_MASK            0x0f    /* Low 4 bits sets time base, max = 13 */
-#define H3800_ASIC2_LED_TIMEBASE_BLINK     ( 1 << 4 )    /* Enable blinking */
-#define H3800_ASIC2_LED_TIMEBASE_AUTOSTOP  ( 1 << 5 )
-#define H3800_ASIC2_LED_TIMEBASE_ALWAYS    ( 1 << 6 )    /* Enable blink always */
-
-#define _H3800_ASIC2_UART_0_Base               0x0A00
-#define _H3800_ASIC2_UART_1_Base               0x0C00
-#define _H3800_ASIC2_UART_Receive              0x0000    /* R    8 bits */
-#define _H3800_ASIC2_UART_Transmit             0x0000    /*   W  8 bits */
-#define _H3800_ASIC2_UART_IntEnable            0x0004    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_IntVerify            0x0008    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_FIFOControl          0x000c    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_LineControl          0x0010    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_ModemStatus          0x0014    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_LineStatus           0x0018    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_ScratchPad           0x001c    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_DivisorLatchL        0x0020    /* R/W  8 bits */
-#define _H3800_ASIC2_UART_DivisorLatchH        0x0024    /* R/W  8 bits */
-
-#define H3800_ASIC2_UART_0_Receive          H3800_ASIC2_NOFFSET(  u8, UART, 0, Receive )
-#define H3800_ASIC2_UART_0_Transmit         H3800_ASIC2_NOFFSET(  u8, UART, 0, Transmit )
-#define H3800_ASIC2_UART_0_IntEnable        H3800_ASIC2_NOFFSET(  u8, UART, 0, IntEnable )
-#define H3800_ASIC2_UART_0_IntVerify        H3800_ASIC2_NOFFSET(  u8, UART, 0, IntVerify )
-#define H3800_ASIC2_UART_0_FIFOControl      H3800_ASIC2_NOFFSET(  u8, UART, 0, FIFOControl )
-#define H3800_ASIC2_UART_0_LineControl      H3800_ASIC2_NOFFSET(  u8, UART, 0, LineControl )
-#define H3800_ASIC2_UART_0_ModemStatus      H3800_ASIC2_NOFFSET(  u8, UART, 0, ModemStatus )
-#define H3800_ASIC2_UART_0_LineStatus       H3800_ASIC2_NOFFSET(  u8, UART, 0, LineStatus )
-#define H3800_ASIC2_UART_0_ScratchPad       H3800_ASIC2_NOFFSET(  u8, UART, 0, ScratchPad )
-#define H3800_ASIC2_UART_0_DivisorLatchL    H3800_ASIC2_NOFFSET(  u8, UART, 0, DivisorLatchL )
-#define H3800_ASIC2_UART_0_DivisorLatchH    H3800_ASIC2_NOFFSET(  u8, UART, 0, DivisorLatchH )
-
-#define H3800_ASIC2_UART_1_Receive          H3800_ASIC2_NOFFSET(  u8, UART, 1, Receive )
-#define H3800_ASIC2_UART_1_Transmit         H3800_ASIC2_NOFFSET(  u8, UART, 1, Transmit )
-#define H3800_ASIC2_UART_1_IntEnable        H3800_ASIC2_NOFFSET(  u8, UART, 1, IntEnable )
-#define H3800_ASIC2_UART_1_IntVerify        H3800_ASIC2_NOFFSET(  u8, UART, 1, IntVerify )
-#define H3800_ASIC2_UART_1_FIFOControl      H3800_ASIC2_NOFFSET(  u8, UART, 1, FIFOControl )
-#define H3800_ASIC2_UART_1_LineControl      H3800_ASIC2_NOFFSET(  u8, UART, 1, LineControl )
-#define H3800_ASIC2_UART_1_ModemStatus      H3800_ASIC2_NOFFSET(  u8, UART, 1, ModemStatus )
-#define H3800_ASIC2_UART_1_LineStatus       H3800_ASIC2_NOFFSET(  u8, UART, 1, LineStatus )
-#define H3800_ASIC2_UART_1_ScratchPad       H3800_ASIC2_NOFFSET(  u8, UART, 1, ScratchPad )
-#define H3800_ASIC2_UART_1_DivisorLatchL    H3800_ASIC2_NOFFSET(  u8, UART, 1, DivisorLatchL )
-#define H3800_ASIC2_UART_1_DivisorLatchH    H3800_ASIC2_NOFFSET(  u8, UART, 1, DivisorLatchH )
-
-#define _H3800_ASIC2_TIMER_Base                0x0E00
-#define _H3800_ASIC2_TIMER_Command             0x0000    /* R/W  8 bits */
-
-#define H3800_ASIC2_TIMER_Command           H3800_ASIC2_OFFSET( u8, Timer, Command )
-
-#define H3800_ASIC2_TIMER_GAT_0            ( 1 << 0 )    /* Gate enable, counter 0 */
-#define H3800_ASIC2_TIMER_GAT_1            ( 1 << 1 )    /* Gate enable, counter 1 */
-#define H3800_ASIC2_TIMER_GAT_2            ( 1 << 2 )    /* Gate enable, counter 2 */
-#define H3800_ASIC2_TIMER_CLK_0            ( 1 << 3 )    /* Clock enable, counter 0 */
-#define H3800_ASIC2_TIMER_CLK_1            ( 1 << 4 )    /* Clock enable, counter 1 */
-#define H3800_ASIC2_TIMER_CLK_2            ( 1 << 5 )    /* Clock enable, counter 2 */
-#define H3800_ASIC2_TIMER_MODE_0           ( 1 << 6 )    /* Mode 0 enable, counter 0 */
-#define H3800_ASIC2_TIMER_MODE_1           ( 1 << 7 )    /* Mode 0 enable, counter 1 */
-
-#define _H3800_ASIC2_CLOCK_Base                0x1000
-#define _H3800_ASIC2_CLOCK_Enable              0x0000    /* R/W  18 bits */
-
-#define H3800_ASIC2_CLOCK_Enable            H3800_ASIC2_OFFSET( u32, CLOCK, Enable )
-
-#define H3800_ASIC2_CLOCK_AUDIO_1              0x0001    /* Enable 4.1 MHz clock for 8Khz and 4khz sample rate */
-#define H3800_ASIC2_CLOCK_AUDIO_2              0x0002    /* Enable 12.3 MHz clock for 48Khz and 32khz sample rate */
-#define H3800_ASIC2_CLOCK_AUDIO_3              0x0004    /* Enable 5.6 MHz clock for 11 kHZ sample rate */
-#define H3800_ASIC2_CLOCK_AUDIO_4              0x0008    /* Enable 11.289 MHz clock for 44 and 22 kHz sample rate */
-#define H3800_ASIC2_CLOCK_ADC              ( 1 << 4 )    /* 1.024 MHz clock to ADC */
-#define H3800_ASIC2_CLOCK_SPI              ( 1 << 5 )    /* 4.096 MHz clock to SPI */
-#define H3800_ASIC2_CLOCK_OWM              ( 1 << 6 )    /* 4.096 MHz clock to OWM */
-#define H3800_ASIC2_CLOCK_PWM              ( 1 << 7 )    /* 2.048 MHz clock to PWM */
-#define H3800_ASIC2_CLOCK_UART_1           ( 1 << 8 )    /* 24.576 MHz clock to UART1 (turn off bit 16) */
-#define H3800_ASIC2_CLOCK_UART_0           ( 1 << 9 )    /* 24.576 MHz clock to UART0 (turn off bit 17) */
-#define H3800_ASIC2_CLOCK_SD_1             ( 1 << 10 )   /* 16.934 MHz to SD */
-#define H3800_ASIC2_CLOCK_SD_2             ( 2 << 10 )   /* 24.576 MHz to SD */
-#define H3800_ASIC2_CLOCK_SD_3             ( 3 << 10 )   /* 33.869 MHz to SD */
-#define H3800_ASIC2_CLOCK_SD_4             ( 4 << 10 )   /* 49.152 MHz to SD */
-#define H3800_ASIC2_CLOCK_EX0              ( 1 << 13 )   /* Enable 32.768 kHz crystal */
-#define H3800_ASIC2_CLOCK_EX1              ( 1 << 14 )   /* Enable 24.576 MHz crystal */
-#define H3800_ASIC2_CLOCK_EX2              ( 1 << 15 )   /* Enable 33.869 MHz crystal */
-#define H3800_ASIC2_CLOCK_SLOW_UART_1      ( 1 << 16 )   /* Enable 3.686 MHz to UART1 (turn off bit 8) */
-#define H3800_ASIC2_CLOCK_SLOW_UART_0      ( 1 << 17 )   /* Enable 3.686 MHz to UART0 (turn off bit 9) */
-
-#define _H3800_ASIC2_ADC_Base                  0x1200
-#define _H3800_ASIC2_ADC_Multiplexer           0x0000    /* R/W 4 bits - low 3 bits set channel */
-#define _H3800_ASIC2_ADC_ControlStatus         0x0004    /* R/W 8 bits */
-#define _H3800_ASIC2_ADC_Data                  0x0008    /* R   10 bits */
-
-#define H3800_ASIC2_ADC_Multiplexer       H3800_ASIC2_OFFSET(  u8, ADC, Multiplexer )
-#define H3800_ASIC2_ADC_ControlStatus     H3800_ASIC2_OFFSET(  u8, ADC, ControlStatus )
-#define H3800_ASIC2_ADC_Data              H3800_ASIC2_OFFSET( u16, ADC, Data )
-
-#define H3600_ASIC2_ADC_MUX_CHANNEL_MASK         0x07    /* Low 3 bits sets channel.  max = 4 */
-#define H3600_ASIC2_ADC_MUX_CLKEN          ( 1 << 3 )    /* Enable clock */
-
-#define H3600_ASIC2_ADC_CSR_ADPS_MASK            0x0f    /* Low 4 bits sets prescale, max = 8 */
-#define H3600_ASIC2_ADC_CSR_FREE_RUN       ( 1 << 4 )
-#define H3600_ASIC2_ADC_CSR_INT_ENABLE     ( 1 << 5 )
-#define H3600_ASIC2_ADC_CSR_START          ( 1 << 6 )    /* Set to start conversion.  Goes to 0 when done */
-#define H3600_ASIC2_ADC_CSR_ENABLE         ( 1 << 7 )    /* 1:power up ADC, 0:power down */
-
-
-#define _H3800_ASIC2_INTR_Base                 0x1600
-#define _H3800_ASIC2_INTR_MaskAndFlag          0x0000    /* R/(W) 8bits */
-#define _H3800_ASIC2_INTR_ClockPrescale        0x0004    /* R/(W) 5bits */
-#define _H3800_ASIC2_INTR_TimerSet             0x0008    /* R/(W) 8bits */
-
-#define H3800_ASIC2_INTR_MaskAndFlag      H3800_ASIC2_OFFSET( u8, INTR, MaskAndFlag )
-#define H3800_ASIC2_INTR_ClockPrescale    H3800_ASIC2_OFFSET( u8, INTR, ClockPrescale )
-#define H3800_ASIC2_INTR_TimerSet         H3800_ASIC2_OFFSET( u8, INTR, TimerSet )
-
-#define H3800_ASIC2_INTR_GLOBAL_MASK       ( 1 << 0 )    /* Global interrupt mask */
-#define H3800_ASIC2_INTR_POWER_ON_RESET    ( 1 << 1 )    /* 01: Power on reset (bits 1 & 2 ) */
-#define H3800_ASIC2_INTR_EXTERNAL_RESET    ( 2 << 1 )    /* 10: External reset (bits 1 & 2 ) */
-#define H3800_ASIC2_INTR_MASK_UART_0       ( 1 << 4 )
-#define H3800_ASIC2_INTR_MASK_UART_1       ( 1 << 5 )
-#define H3800_ASIC2_INTR_MASK_TIMER        ( 1 << 6 )
-#define H3800_ASIC2_INTR_MASK_OWM          ( 1 << 7 )
-
-#define H3800_ASIC2_INTR_CLOCK_PRESCALE          0x0f    /* 4 bits, max 14 */
-#define H3800_ASIC2_INTR_SET               ( 1 << 4 )    /* Time base enable */
-
-
-#define _H3800_ASIC2_OWM_Base                  0x1800
-#define _H3800_ASIC2_OWM_Command               0x0000    /* R/W 4 bits command register */
-#define _H3800_ASIC2_OWM_Data                  0x0004    /* R/W 8 bits, transmit / receive buffer */
-#define _H3800_ASIC2_OWM_Interrupt             0x0008    /* R/W Command register */
-#define _H3800_ASIC2_OWM_InterruptEnable       0x000c    /* R/W Command register */
-#define _H3800_ASIC2_OWM_ClockDivisor          0x0010    /* R/W 5 bits of divisor and pre-scale */
-
-#define H3800_ASIC2_OWM_Command            H3800_ASIC2_OFFSET( u8, OWM, Command )
-#define H3800_ASIC2_OWM_Data               H3800_ASIC2_OFFSET( u8, OWM, Data )
-#define H3800_ASIC2_OWM_Interrupt          H3800_ASIC2_OFFSET( u8, OWM, Interrupt )
-#define H3800_ASIC2_OWM_InterruptEnable    H3800_ASIC2_OFFSET( u8, OWM, InterruptEnable )
-#define H3800_ASIC2_OWM_ClockDivisor       H3800_ASIC2_OFFSET( u8, OWM, ClockDivisor )
-
-#define H3800_ASIC2_OWM_CMD_ONE_WIRE_RESET ( 1 << 0 )    /* Set to force reset on 1-wire bus */
-#define H3800_ASIC2_OWM_CMD_SRA            ( 1 << 1 )    /* Set to switch to Search ROM accelerator mode */
-#define H3800_ASIC2_OWM_CMD_DQ_OUTPUT      ( 1 << 2 )    /* Write only - forces bus low */
-#define H3800_ASIC2_OWM_CMD_DQ_INPUT       ( 1 << 3 )    /* Read only - reflects state of bus */
-
-#define H3800_ASIC2_OWM_INT_PD             ( 1 << 0 )    /* Presence detect */
-#define H3800_ASIC2_OWM_INT_PDR            ( 1 << 1 )    /* Presence detect result */
-#define H3800_ASIC2_OWM_INT_TBE            ( 1 << 2 )    /* Transmit buffer empty */
-#define H3800_ASIC2_OWM_INT_TEMT           ( 1 << 3 )    /* Transmit shift register empty */
-#define H3800_ASIC2_OWM_INT_RBF            ( 1 << 4 )    /* Receive buffer full */
-
-#define H3800_ASIC2_OWM_INTEN_EPD          ( 1 << 0 )    /* Enable receive buffer full interrupt */
-#define H3800_ASIC2_OWM_INTEN_IAS          ( 1 << 1 )    /* Enable transmit shift register empty interrupt */
-#define H3800_ASIC2_OWM_INTEN_ETBE         ( 1 << 2 )    /* Enable transmit buffer empty interrupt */
-#define H3800_ASIC2_OWM_INTEN_ETMT         ( 1 << 3 )    /* INTR active state */
-#define H3800_ASIC2_OWM_INTEN_ERBF         ( 1 << 4 )    /* Enable presence detect interrupt */
-
-#define _H3800_ASIC2_FlashCtl_Base             0x1A00
-
-/****************************************************/
-/* H3800, ASIC #1
- * This ASIC is accesed through ASIC #2, and
- * mapped into the 1c00 - 1f00 region
- */
-
-#define H3800_ASIC1_OFFSET(s,x,y)   \
-     (*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC1_ ## x ## _Base + (_H3800_ASIC1_ ## x ## _ ## y << 1))))
-
-#define _H3800_ASIC1_MMC_Base             0x1c00
-
-#define _H3800_ASIC1_MMC_StartStopClock     0x00    /* R/W 8bit                                  */
-#define _H3800_ASIC1_MMC_Status             0x02    /* R   See below, default 0x0040             */
-#define _H3800_ASIC1_MMC_ClockRate          0x04    /* R/W 8bit, low 3 bits are clock divisor    */
-#define _H3800_ASIC1_MMC_SPIRegister        0x08    /* R/W 8bit, see below                       */
-#define _H3800_ASIC1_MMC_CmdDataCont        0x0a    /* R/W 8bit, write to start MMC adapter      */
-#define _H3800_ASIC1_MMC_ResponseTimeout    0x0c    /* R/W 8bit, clocks before response timeout  */
-#define _H3800_ASIC1_MMC_ReadTimeout        0x0e    /* R/W 16bit, clocks before received data timeout */
-#define _H3800_ASIC1_MMC_BlockLength        0x10    /* R/W 10bit */
-#define _H3800_ASIC1_MMC_NumOfBlocks        0x12    /* R/W 16bit, in block mode, number of blocks  */
-#define _H3800_ASIC1_MMC_InterruptMask      0x1a    /* R/W 8bit */
-#define _H3800_ASIC1_MMC_CommandNumber      0x1c    /* R/W 6 bits */
-#define _H3800_ASIC1_MMC_ArgumentH          0x1e    /* R/W 16 bits  */
-#define _H3800_ASIC1_MMC_ArgumentL          0x20    /* R/W 16 bits */
-#define _H3800_ASIC1_MMC_ResFifo            0x22    /* R   8 x 16 bits - contains response FIFO */
-#define _H3800_ASIC1_MMC_BufferPartFull     0x28    /* R/W 8 bits */
-
-#define H3800_ASIC1_MMC_StartStopClock    H3800_ASIC1_OFFSET(  u8, MMC, StartStopClock )
-#define H3800_ASIC1_MMC_Status            H3800_ASIC1_OFFSET( u16, MMC, Status )
-#define H3800_ASIC1_MMC_ClockRate         H3800_ASIC1_OFFSET(  u8, MMC, ClockRate )
-#define H3800_ASIC1_MMC_SPIRegister       H3800_ASIC1_OFFSET(  u8, MMC, SPIRegister )
-#define H3800_ASIC1_MMC_CmdDataCont       H3800_ASIC1_OFFSET(  u8, MMC, CmdDataCont )
-#define H3800_ASIC1_MMC_ResponseTimeout   H3800_ASIC1_OFFSET(  u8, MMC, ResponseTimeout )
-#define H3800_ASIC1_MMC_ReadTimeout       H3800_ASIC1_OFFSET( u16, MMC, ReadTimeout )
-#define H3800_ASIC1_MMC_BlockLength       H3800_ASIC1_OFFSET( u16, MMC, BlockLength )
-#define H3800_ASIC1_MMC_NumOfBlocks       H3800_ASIC1_OFFSET( u16, MMC, NumOfBlocks )
-#define H3800_ASIC1_MMC_InterruptMask     H3800_ASIC1_OFFSET(  u8, MMC, InterruptMask )
-#define H3800_ASIC1_MMC_CommandNumber     H3800_ASIC1_OFFSET(  u8, MMC, CommandNumber )
-#define H3800_ASIC1_MMC_ArgumentH         H3800_ASIC1_OFFSET( u16, MMC, ArgumentH )
-#define H3800_ASIC1_MMC_ArgumentL         H3800_ASIC1_OFFSET( u16, MMC, ArgumentL )
-#define H3800_ASIC1_MMC_ResFifo           H3800_ASIC1_OFFSET( u16, MMC, ResFifo )
-#define H3800_ASIC1_MMC_BufferPartFull    H3800_ASIC1_OFFSET(  u8, MMC, BufferPartFull )
-
-#define H3800_ASIC1_MMC_STOP_CLOCK                   (1 << 0)   /* Write to "StartStopClock" register */
-#define H3800_ASIC1_MMC_START_CLOCK                  (1 << 1)
-
-#define H3800_ASIC1_MMC_STATUS_READ_TIMEOUT          (1 << 0)
-#define H3800_ASIC1_MMC_STATUS_RESPONSE_TIMEOUT      (1 << 1)
-#define H3800_ASIC1_MMC_STATUS_CRC_WRITE_ERROR       (1 << 2)
-#define H3800_ASIC1_MMC_STATUS_CRC_READ_ERROR        (1 << 3)
-#define H3800_ASIC1_MMC_STATUS_SPI_READ_ERROR        (1 << 4)  /* SPI data token error received */
-#define H3800_ASIC1_MMC_STATUS_CRC_RESPONSE_ERROR    (1 << 5)
-#define H3800_ASIC1_MMC_STATUS_FIFO_EMPTY            (1 << 6)
-#define H3800_ASIC1_MMC_STATUS_FIFO_FULL             (1 << 7)
-#define H3800_ASIC1_MMC_STATUS_CLOCK_ENABLE          (1 << 8)  /* MultiMediaCard clock stopped */
-#define H3800_ASIC1_MMC_STATUS_DATA_TRANSFER_DONE    (1 << 11) /* Write operation, indicates transfer finished */
-#define H3800_ASIC1_MMC_STATUS_END_PROGRAM           (1 << 12) /* End write and read operations */
-#define H3800_ASIC1_MMC_STATUS_END_COMMAND_RESPONSE  (1 << 13) /* End command response */
-
-#define H3800_ASIC1_MMC_SPI_REG_SPI_ENABLE           (1 << 0)  /* Enables SPI mode */
-#define H3800_ASIC1_MMC_SPI_REG_CRC_ON               (1 << 1)  /* 1:turn on CRC    */
-#define H3800_ASIC1_MMC_SPI_REG_SPI_CS_ENABLE        (1 << 2)  /* 1:turn on SPI CS */
-#define H3800_ASIC1_MMC_SPI_REG_CS_ADDRESS_MASK      0x38      /* Bits 3,4,5 are the SPI CS relative address */
-
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_NO_RESPONSE  0x00
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R1           0x01
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R2           0x02
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R3           0x03
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_DATA_ENABLE         (1 << 2)  /* This command contains a data transfer */
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_WRITE               (1 << 3)  /* This data transfer is a write */
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_STREAM_MODE         (1 << 4)  /* This data transfer is in stream mode */
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_BUSY_BIT            (1 << 5)  /* Busy signal expected after current cmd */
-#define H3800_ASIC1_MMC_CMD_DATA_CONT_INITIALIZE          (1 << 6)  /* Enables the 80 bits for initializing card */
-
-#define H3800_ASIC1_MMC_INT_MASK_DATA_TRANSFER_DONE       (1 << 0)
-#define H3800_ASIC1_MMC_INT_MASK_PROGRAM_DONE             (1 << 1)
-#define H3800_ASIC1_MMC_INT_MASK_END_COMMAND_RESPONSE     (1 << 2)
-#define H3800_ASIC1_MMC_INT_MASK_BUFFER_READY             (1 << 3)
-
-#define H3800_ASIC1_MMC_BUFFER_PART_FULL                  (1 << 0)
-
-/********* GPIO **********/
-
-#define _H3800_ASIC1_GPIO_Base        0x1e00
-
-#define _H3800_ASIC1_GPIO_Mask          0x30    /* R/W 0:don't mask, 1:mask interrupt */
-#define _H3800_ASIC1_GPIO_Direction     0x32    /* R/W 0:input, 1:output              */
-#define _H3800_ASIC1_GPIO_Out           0x34    /* R/W 0:output low, 1:output high    */
-#define _H3800_ASIC1_GPIO_TriggerType   0x36    /* R/W 0:level, 1:edge                */
-#define _H3800_ASIC1_GPIO_EdgeTrigger   0x38    /* R/W 0:falling, 1:rising            */
-#define _H3800_ASIC1_GPIO_LevelTrigger  0x3A    /* R/W 0:low, 1:high level detect     */
-#define _H3800_ASIC1_GPIO_LevelStatus   0x3C    /* R/W 0:none, 1:detect               */
-#define _H3800_ASIC1_GPIO_EdgeStatus    0x3E    /* R/W 0:none, 1:detect               */
-#define _H3800_ASIC1_GPIO_State         0x40    /* R   See masks below  (default 0)         */
-#define _H3800_ASIC1_GPIO_Reset         0x42    /* R/W See masks below  (default 0x04)      */
-#define _H3800_ASIC1_GPIO_SleepMask     0x44    /* R/W 0:don't mask, 1:mask trigger in sleep mode  */
-#define _H3800_ASIC1_GPIO_SleepDir      0x46    /* R/W direction 0:input, 1:output in sleep mode    */
-#define _H3800_ASIC1_GPIO_SleepOut      0x48    /* R/W level 0:low, 1:high in sleep mode           */
-#define _H3800_ASIC1_GPIO_Status        0x4A    /* R   Pin status                                  */
-#define _H3800_ASIC1_GPIO_BattFaultDir  0x4C    /* R/W direction 0:input, 1:output in batt_fault   */
-#define _H3800_ASIC1_GPIO_BattFaultOut  0x4E    /* R/W level 0:low, 1:high in batt_fault           */
-
-#define H3800_ASIC1_GPIO_Mask         H3800_ASIC1_OFFSET( u16, GPIO, Mask )
-#define H3800_ASIC1_GPIO_Direction    H3800_ASIC1_OFFSET( u16, GPIO, Direction )
-#define H3800_ASIC1_GPIO_Out          H3800_ASIC1_OFFSET( u16, GPIO, Out )
-#define H3800_ASIC1_GPIO_TriggerType  H3800_ASIC1_OFFSET( u16, GPIO, TriggerType )
-#define H3800_ASIC1_GPIO_EdgeTrigger  H3800_ASIC1_OFFSET( u16, GPIO, EdgeTrigger )
-#define H3800_ASIC1_GPIO_LevelTrigger H3800_ASIC1_OFFSET( u16, GPIO, LevelTrigger )
-#define H3800_ASIC1_GPIO_LevelStatus  H3800_ASIC1_OFFSET( u16, GPIO, LevelStatus )
-#define H3800_ASIC1_GPIO_EdgeStatus   H3800_ASIC1_OFFSET( u16, GPIO, EdgeStatus )
-#define H3800_ASIC1_GPIO_State        H3800_ASIC1_OFFSET(  u8, GPIO, State )
-#define H3800_ASIC1_GPIO_Reset        H3800_ASIC1_OFFSET(  u8, GPIO, Reset )
-#define H3800_ASIC1_GPIO_SleepMask    H3800_ASIC1_OFFSET( u16, GPIO, SleepMask )
-#define H3800_ASIC1_GPIO_SleepDir     H3800_ASIC1_OFFSET( u16, GPIO, SleepDir )
-#define H3800_ASIC1_GPIO_SleepOut     H3800_ASIC1_OFFSET( u16, GPIO, SleepOut )
-#define H3800_ASIC1_GPIO_Status       H3800_ASIC1_OFFSET( u16, GPIO, Status )
-#define H3800_ASIC1_GPIO_BattFaultDir H3800_ASIC1_OFFSET( u16, GPIO, BattFaultDir )
-#define H3800_ASIC1_GPIO_BattFaultOut H3800_ASIC1_OFFSET( u16, GPIO, BattFaultOut )
-
-#define H3800_ASIC1_GPIO_STATE_MASK            (1 << 0)
-#define H3800_ASIC1_GPIO_STATE_DIRECTION       (1 << 1)
-#define H3800_ASIC1_GPIO_STATE_OUT             (1 << 2)
-#define H3800_ASIC1_GPIO_STATE_TRIGGER_TYPE    (1 << 3)
-#define H3800_ASIC1_GPIO_STATE_EDGE_TRIGGER    (1 << 4)
-#define H3800_ASIC1_GPIO_STATE_LEVEL_TRIGGER   (1 << 5)
-
-#define H3800_ASIC1_GPIO_RESET_SOFTWARE        (1 << 0)
-#define H3800_ASIC1_GPIO_RESET_AUTO_SLEEP      (1 << 1)
-#define H3800_ASIC1_GPIO_RESET_FIRST_PWR_ON    (1 << 2)
-
-/* These are all outputs */
-#define GPIO_H3800_ASIC1_IR_ON_N          (1 << 0)   /* Apply power to the IR Module */
-#define GPIO_H3800_ASIC1_SD_PWR_ON        (1 << 1)   /* Secure Digital power on */
-#define GPIO_H3800_ASIC1_RS232_ON         (1 << 2)   /* Turn on power to the RS232 chip ? */
-#define GPIO_H3800_ASIC1_PULSE_GEN        (1 << 3)   /* Goes to speaker / earphone */
-#define GPIO_H3800_ASIC1_CH_TIMER         (1 << 4)   /* */
-#define GPIO_H3800_ASIC1_LCD_5V_ON        (1 << 5)   /* Enables LCD_5V */
-#define GPIO_H3800_ASIC1_LCD_ON           (1 << 6)   /* Enables LCD_3V */
-#define GPIO_H3800_ASIC1_LCD_PCI          (1 << 7)   /* Connects to PDWN on LCD controller */
-#define GPIO_H3800_ASIC1_VGH_ON           (1 << 8)   /* Drives VGH on the LCD (+9??) */
-#define GPIO_H3800_ASIC1_VGL_ON           (1 << 9)   /* Drivers VGL on the LCD (-6??) */
-#define GPIO_H3800_ASIC1_FL_PWR_ON        (1 << 10)  /* Frontlight power on */
-#define GPIO_H3800_ASIC1_BT_PWR_ON        (1 << 11)  /* Bluetooth power on */
-#define GPIO_H3800_ASIC1_SPK_ON           (1 << 12)  /* */
-#define GPIO_H3800_ASIC1_EAR_ON_N         (1 << 13)  /* */
-#define GPIO_H3800_ASIC1_AUD_PWR_ON       (1 << 14)  /* */
-
-/* Write enable for the flash */
-
-#define _H3800_ASIC1_FlashWP_Base         0x1F00
-#define _H3800_ASIC1_FlashWP_VPP_ON         0x00    /* R   1: write, 0: protect */
-#define H3800_ASIC1_FlashWP_VPP_ON       H3800_ASIC1_OFFSET( u8, FlashWP, VPP_ON )
 
 #endif /* _INCLUDE_H3600_GPIO_H_ */
diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h
index 0cb3660..ae81f80 100644
--- a/arch/arm/mach-sa1100/include/mach/irqs.h
+++ b/arch/arm/mach-sa1100/include/mach/irqs.h
@@ -153,8 +153,6 @@
  */
 #ifdef CONFIG_SA1111
 #define NR_IRQS			(IRQ_S1_BVD1_STSCHG + 1)
-#elif defined(CONFIG_SA1100_H3800)
-#define NR_IRQS			(IRQ_BOARD_END)
 #elif defined(CONFIG_SHARP_LOCOMO)
 #define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
 #else
@@ -175,23 +173,3 @@
 #define IRQ_LOCOMO_LT_BASE	(IRQ_BOARD_START + 2)
 #define IRQ_LOCOMO_SPI_BASE	(IRQ_BOARD_START + 3)
 
-/* H3800-specific IRQs (CONFIG_SA1100_H3800) */
-#define H3800_KPIO_IRQ_START    (IRQ_BOARD_START)
-#define IRQ_H3800_KEY           (IRQ_BOARD_START + 0)
-#define IRQ_H3800_SPI           (IRQ_BOARD_START + 1)
-#define IRQ_H3800_OWM           (IRQ_BOARD_START + 2)
-#define IRQ_H3800_ADC           (IRQ_BOARD_START + 3)
-#define IRQ_H3800_UART_0        (IRQ_BOARD_START + 4)
-#define IRQ_H3800_UART_1        (IRQ_BOARD_START + 5)
-#define IRQ_H3800_TIMER_0       (IRQ_BOARD_START + 6)
-#define IRQ_H3800_TIMER_1       (IRQ_BOARD_START + 7)
-#define IRQ_H3800_TIMER_2       (IRQ_BOARD_START + 8)
-#define H3800_KPIO_IRQ_COUNT    9
-
-#define H3800_GPIO_IRQ_START    (IRQ_BOARD_START + 9)
-#define IRQ_H3800_PEN           (IRQ_BOARD_START + 9)
-#define IRQ_H3800_SD_DETECT     (IRQ_BOARD_START + 10)
-#define IRQ_H3800_EAR_IN        (IRQ_BOARD_START + 11)
-#define IRQ_H3800_USB_DETECT    (IRQ_BOARD_START + 12)
-#define IRQ_H3800_SD_CON_SLT    (IRQ_BOARD_START + 13)
-#define H3800_GPIO_IRQ_COUNT    5
diff --git a/arch/arm/mach-sa1100/include/mach/system.h b/arch/arm/mach-sa1100/include/mach/system.h
index 63755ca..942b153 100644
--- a/arch/arm/mach-sa1100/include/mach/system.h
+++ b/arch/arm/mach-sa1100/include/mach/system.h
@@ -10,7 +10,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	if (mode == 's') {
 		/* Jump into ROM at address 0 */
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 81848aa..fd776bb 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -226,12 +226,22 @@
 	.id             = -1,
 };
 
+static struct platform_device jornada_kbd_device = {
+	.name		= "jornada720_kbd",
+	.id		= -1,
+};
+
+static struct platform_device jornada_ts_device = {
+	.name		= "jornada_ts",
+	.id		= -1,
+};
+
 static struct platform_device *devices[] __initdata = {
 	&sa1111_device,
-#ifdef CONFIG_SA1100_JORNADA720_SSP
 	&jornada_ssp_device,
-#endif
 	&s1d13xxxfb_device,
+	&jornada_kbd_device,
+	&jornada_ts_device,
 };
 
 static int __init jornada720_init(void)
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index a23fd3d..358d875 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -16,12 +16,28 @@
 #include <asm/leds.h>
 #include <asm/param.h>
 
-#include <mach/hardware.h>
-
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
+#define IO_BASE                 0xe0000000
+#define IO_SIZE                 0x08000000
+#define IO_START                0x40000000
+#define ROMCARD_SIZE            0x08000000
+#define ROMCARD_START           0x10000000
+
+void arch_reset(char mode, const char *cmd)
+{
+        short temp;
+        local_irq_disable();
+        /* Reset the Machine via pc[3] of the sequoia chipset */
+        outw(0x09,0x24);
+        temp=inw(0x26);
+        temp = temp | (1<<3) | (1<<10);
+        outw(0x09,0x24);
+        outw(temp,0x26);
+}
+
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.iobase		= 0x3f8,
@@ -50,14 +66,38 @@
 	},
 };
 
+static struct resource rtc_resources[] = {
+	[0] = {
+		.start	= 0x70,
+		.end	= 0x73,
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		.start	= IRQ_ISA_RTC_ALARM,
+		.end	= IRQ_ISA_RTC_ALARM,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device rtc_device = {
+	.name		= "rtc_cmos",
+	.id		= -1,
+	.resource	= rtc_resources,
+	.num_resources	= ARRAY_SIZE(rtc_resources),
+};
+
 static int __init shark_init(void)
 {
 	int ret;
 
 	if (machine_is_shark())
+	{
+	        ret = platform_device_register(&rtc_device);
+		if (ret) printk(KERN_ERR "Unable to register RTC device: %d\n", ret);
 		ret = platform_device_register(&serial_device);
-
-	return ret;
+		if (ret) printk(KERN_ERR "Unable to register Serial device: %d\n", ret);
+	}
+	return 0;
 }
 
 arch_initcall(shark_init);
diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c
index 6774b8d..10b5b8b 100644
--- a/arch/arm/mach-shark/dma.c
+++ b/arch/arm/mach-shark/dma.c
@@ -13,9 +13,11 @@
 #include <asm/dma.h>
 #include <asm/mach/dma.h>
 
-void __init arch_dma_init(dma_t *dma)
+static int __init shark_dma_init(void)
 {
 #ifdef CONFIG_ISA_DMA
-	isa_init_dma(dma);
+	isa_init_dma();
 #endif
+	return 0;
 }
+core_initcall(shark_dma_init);
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
index 0836cb7..f97a762 100644
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ b/arch/arm/mach-shark/include/mach/debug-macro.S
@@ -27,5 +27,3 @@
 		bne	1001b
 		.endm
 
-		.macro	waituart,rd,rx
-		.endm
diff --git a/arch/arm/mach-shark/include/mach/framebuffer.h b/arch/arm/mach-shark/include/mach/framebuffer.h
new file mode 100644
index 0000000..84a5bf6
--- /dev/null
+++ b/arch/arm/mach-shark/include/mach/framebuffer.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-shark/include/mach/framebuffer.h
+ *
+ * by Alexander Schulz
+ *
+ */
+
+#ifndef __ASM_ARCH_FRAMEBUFFER_H
+#define __ASM_ARCH_FRAMEBUFFER_H
+
+/* defines for the Framebuffer */
+#define FB_START		0x06000000
+#define FB_SIZE			0x01000000
+
+#endif
+
diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h
index 01bf760..94d84b2 100644
--- a/arch/arm/mach-shark/include/mach/hardware.h
+++ b/arch/arm/mach-shark/include/mach/hardware.h
@@ -10,35 +10,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#ifndef __ASSEMBLY__
-
-/*
- * Mapping areas
- */
-#define IO_BASE			0xe0000000
-
-#else
-
-#define IO_BASE			0
-
-#endif
-
-#define IO_SIZE			0x08000000
-#define IO_START		0x40000000
-#define ROMCARD_SIZE		0x08000000
-#define ROMCARD_START		0x10000000
-
-
-/* defines for the Framebuffer */
-#define FB_START		0x06000000
-#define FB_SIZE			0x01000000
-
 #define UNCACHEABLE_ADDR        0xdf010000
 
-#define SEQUOIA_LED_GREEN       (1<<6)
-#define SEQUOIA_LED_AMBER       (1<<5)
-#define SEQUOIA_LED_BACK        (1<<7)
-
 #define pcibios_assign_all_busses()     1
 
 #define PCIBIOS_MIN_IO          0x6000
diff --git a/arch/arm/mach-shark/include/mach/io.h b/arch/arm/mach-shark/include/mach/io.h
index c5cee82..9ccbcec 100644
--- a/arch/arm/mach-shark/include/mach/io.h
+++ b/arch/arm/mach-shark/include/mach/io.h
@@ -11,10 +11,10 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define PCIO_BASE	0xe0000000
-#define IO_SPACE_LIMIT	0xffffffff
+#define IO_SPACE_LIMIT 0xffffffff
 
-#define __io(a)		((void __iomem *)(PCIO_BASE + (a)))
-#define __mem_pci(addr)	(addr)
+#define __io(a)                 ((void __iomem *)(0xe0000000 + (a)))
+
+#define __mem_pci(addr) (addr)
 
 #endif
diff --git a/arch/arm/mach-shark/include/mach/irqs.h b/arch/arm/mach-shark/include/mach/irqs.h
index 0586acd..c8e8a4e 100644
--- a/arch/arm/mach-shark/include/mach/irqs.h
+++ b/arch/arm/mach-shark/include/mach/irqs.h
@@ -7,7 +7,7 @@
 #define NR_IRQS			16
 
 #define IRQ_ISA_KEYBOARD	 1
-#define RTC_IRQ			 8
+#define IRQ_ISA_RTC_ALARM	 8
 #define I8042_KBD_IRQ		 1
 #define I8042_AUX_IRQ		12
 #define IRQ_HARDDISK            14
diff --git a/arch/arm/mach-shark/include/mach/isa-dma.h b/arch/arm/mach-shark/include/mach/isa-dma.h
index 864298ff..96c43b8 100644
--- a/arch/arm/mach-shark/include/mach/isa-dma.h
+++ b/arch/arm/mach-shark/include/mach/isa-dma.h
@@ -6,10 +6,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/* Use only the lowest 4MB, nothing else works.
- * The rest is not DMAable. See dev /  .properties
- * in OpenFirmware.
- */
 #define MAX_DMA_CHANNELS	8
 #define DMA_ISA_CASCADE         4
 
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
index c5ab038..3053e5b 100644
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ b/arch/arm/mach-shark/include/mach/memory.h
@@ -23,6 +23,7 @@
 {
   if (node != 0) return;
   /* Only the first 4 MB (=1024 Pages) are usable for DMA */
+  /* See dev / -> .properties in OpenFirmware. */
   zone_size[1] = zone_size[0] - 1024;
   zone_size[0] = 1024;
   zhole_size[1] = zhole_size[0];
diff --git a/arch/arm/mach-shark/include/mach/system.h b/arch/arm/mach-shark/include/mach/system.h
index e45bd73..21c373b 100644
--- a/arch/arm/mach-shark/include/mach/system.h
+++ b/arch/arm/mach-shark/include/mach/system.h
@@ -6,20 +6,8 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
-#include <linux/io.h>
-
-static void arch_reset(char mode)
-{
-	short temp;
-	local_irq_disable();
-	/* Reset the Machine via pc[3] of the sequoia chipset */
-	outw(0x09,0x24);
-	temp=inw(0x26);
-	temp = temp | (1<<3) | (1<<10);
-	outw(0x09,0x24);
-	outw(temp,0x26);
-
-}
+/* Found in arch/mach-shark/core.c */
+extern void arch_reset(char mode, const char *cmd);
 
 static inline void arch_idle(void)
 {
diff --git a/arch/arm/mach-shark/include/mach/uncompress.h b/arch/arm/mach-shark/include/mach/uncompress.h
index 3725e16..22ccab4 100644
--- a/arch/arm/mach-shark/include/mach/uncompress.h
+++ b/arch/arm/mach-shark/include/mach/uncompress.h
@@ -11,7 +11,7 @@
 
 static inline void putc(int c)
 {
-	int t;
+	volatile int t;
 
 	SERIAL_BASE[0] = c;
 	t=0x10000;
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
index 8bd8d6b..c9e32de 100644
--- a/arch/arm/mach-shark/leds.c
+++ b/arch/arm/mach-shark/leds.c
@@ -22,12 +22,16 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
 
 #define LED_STATE_ENABLED	1
 #define LED_STATE_CLAIMED	2
+
+#define SEQUOIA_LED_GREEN       (1<<6)
+#define SEQUOIA_LED_AMBER       (1<<5)
+#define SEQUOIA_LED_BACK        (1<<7)
+
 static char led_state;
 static short hw_led_state;
 static short saved_state;
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 1c43494..5657766 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -335,11 +335,25 @@
 
 static struct platform_device versatile_i2c_device = {
 	.name			= "versatile-i2c",
-	.id			= -1,
+	.id			= 0,
 	.num_resources		= 1,
 	.resource		= &versatile_i2c_resource,
 };
 
+static struct i2c_board_info versatile_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
+		.type = "ds1338",
+	},
+};
+
+static int __init versatile_i2c_init(void)
+{
+	return i2c_register_board_info(0, versatile_i2c_board_info,
+				       ARRAY_SIZE(versatile_i2c_board_info));
+}
+arch_initcall(versatile_i2c_init);
+
 #define VERSATILE_SYSMCI	(__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
 
 unsigned int mmc_status(struct device *dev)
diff --git a/arch/arm/mach-versatile/include/mach/system.h b/arch/arm/mach-versatile/include/mach/system.h
index c59e610..8ffc12a 100644
--- a/arch/arm/mach-versatile/include/mach/system.h
+++ b/arch/arm/mach-versatile/include/mach/system.h
@@ -34,7 +34,7 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	u32 val;
 
diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h
index 40ff408..de29ddc 100644
--- a/arch/arm/mach-w90x900/cpu.h
+++ b/arch/arm/mach-w90x900/cpu.h
@@ -43,35 +43,16 @@
 extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no);
 extern void w90p910_init_clocks(int xtal);
 extern void w90p910_map_io(struct map_desc *mach_desc, int size);
+extern struct platform_device w90p910_serial_device;
 extern struct sys_timer w90x900_timer;
 
-#define W90X900_RES(name)				\
-struct resource w90x900_##name##_resource[] = {		\
-	[0] = {						\
-		.start = name##_PA,			\
-		.end   = name##_PA + 0x0ff,		\
-		.flags = IORESOURCE_MEM,		\
-	},						\
-	[1] = {						\
-		.start = IRQ_##name,			\
-		.end   = IRQ_##name,			\
-		.flags = IORESOURCE_IRQ,		\
-	}						\
-}
-
-#define W90X900_DEVICE(devname, regname, devid, platdevname)		\
-struct platform_device w90x900_##devname = {				\
-	.name		= platdevname,					\
-	.id		= devid,					\
-	.num_resources 	= ARRAY_SIZE(w90x900_##regname##_resource),	\
-	.resource 	= w90x900_##regname##_resource,			\
-}
-
-#define W90X900_UARTCFG(port, flag, uc, ulc, ufc)	\
-{							\
-		.hwport	= port,				\
-		.flags	= flag,				\
-		.ucon	= uc,				\
-		.ulcon	= ulc,				\
-		.ufcon	= ufc,				\
+#define W90X900_8250PORT(name)					\
+{								\
+	.membase	= name##_BA,				\
+	.mapbase	= name##_PA,				\
+	.irq		= IRQ_##name,				\
+	.uartclk	= 11313600,				\
+	.regshift	= 2,					\
+	.iotype		= UPIO_MEM,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
 }
diff --git a/arch/arm/mach-w90x900/include/mach/system.h b/arch/arm/mach-w90x900/include/mach/system.h
index 93753f9..9406400 100644
--- a/arch/arm/mach-w90x900/include/mach/system.h
+++ b/arch/arm/mach-w90x900/include/mach/system.h
@@ -21,7 +21,7 @@
 {
 }
 
-static void arch_reset(char mode)
+static void arch_reset(char mode, const char *cmd)
 {
 	cpu_reset(0);
 }
diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c
index 9ebc93f..726ff67 100644
--- a/arch/arm/mach-w90x900/mach-w90p910evb.c
+++ b/arch/arm/mach-w90x900/mach-w90p910evb.c
@@ -22,6 +22,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -32,28 +33,67 @@
 #include <mach/map.h>
 
 #include "cpu.h"
+/*w90p910 evb norflash driver data */
 
-static struct map_desc w90p910_iodesc[] __initdata = {
+#define W90P910_FLASH_BASE	0xA0000000
+#define W90P910_FLASH_SIZE	0x400000
+
+static struct mtd_partition w90p910_flash_partitions[] = {
+	{
+		.name	=	"NOR Partition 1 for kernel (960K)",
+		.size	=	0xF0000,
+		.offset	=	0x10000,
+	},
+	{
+		.name	=	"NOR Partition 2 for image (1M)",
+		.size	=	0x100000,
+		.offset	=	0x100000,
+	},
+	{
+		.name	=	"NOR Partition 3 for user (2M)",
+		.size	=	0x200000,
+		.offset	=	0x00200000,
+	}
 };
 
-static struct w90x900_uartcfg w90p910_uartcfgs[] = {
-	W90X900_UARTCFG(0, 0, 0, 0, 0),
-	W90X900_UARTCFG(1, 0, 0, 0, 0),
-	W90X900_UARTCFG(2, 0, 0, 0, 0),
-	W90X900_UARTCFG(3, 0, 0, 0, 0),
-	W90X900_UARTCFG(4, 0, 0, 0, 0),
+static struct physmap_flash_data w90p910_flash_data = {
+	.width		=	2,
+	.parts		=	w90p910_flash_partitions,
+	.nr_parts	=	ARRAY_SIZE(w90p910_flash_partitions),
+};
+
+static struct resource w90p910_flash_resources[] = {
+	{
+		.start	=	W90P910_FLASH_BASE,
+		.end	=	W90P910_FLASH_BASE + W90P910_FLASH_SIZE - 1,
+		.flags	=	IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device w90p910_flash_device = {
+	.name		=	"physmap-flash",
+	.id		=	0,
+	.dev		= {
+				.platform_data = &w90p910_flash_data,
+			},
+	.resource	=	w90p910_flash_resources,
+	.num_resources	=	ARRAY_SIZE(w90p910_flash_resources),
+};
+
+static struct map_desc w90p910_iodesc[] __initdata = {
 };
 
 /*Here should be your evb resourse,such as LCD*/
 
 static struct platform_device *w90p910evb_dev[] __initdata = {
+	&w90p910_serial_device,
+	&w90p910_flash_device,
 };
 
 static void __init w90p910evb_map_io(void)
 {
 	w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc));
 	w90p910_init_clocks(0);
-	w90p910_init_uarts(w90p910_uartcfgs, ARRAY_SIZE(w90p910_uartcfgs));
 }
 
 static void __init w90p910evb_init(void)
diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c
index aa783bc..2bcbaa6 100644
--- a/arch/arm/mach-w90x900/w90p910.c
+++ b/arch/arm/mach-w90x900/w90p910.c
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/serial_8250.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -36,12 +37,6 @@
 
 #include "cpu.h"
 
-/*W90P910 has five uarts*/
-
-#define MAX_UART_COUNT 5
-static int uart_count;
-static struct platform_device *uart_devs[MAX_UART_COUNT-1];
-
 /* Initial IO mappings */
 
 static struct map_desc w90p910_iodesc[] __initdata = {
@@ -53,48 +48,19 @@
 	/*IODESC_ENT(LCD),*/
 };
 
-/*Init the dev resource*/
+/* Initial serial platform data */
 
-static W90X900_RES(UART0);
-static W90X900_RES(UART1);
-static W90X900_RES(UART2);
-static W90X900_RES(UART3);
-static W90X900_RES(UART4);
-static W90X900_DEVICE(uart0, UART0, 0, "w90x900-uart");
-static W90X900_DEVICE(uart1, UART1, 1, "w90x900-uart");
-static W90X900_DEVICE(uart2, UART2, 2, "w90x900-uart");
-static W90X900_DEVICE(uart3, UART3, 3, "w90x900-uart");
-static W90X900_DEVICE(uart4, UART4, 4, "w90x900-uart");
-
-static struct platform_device *uart_devices[] __initdata = {
-	&w90x900_uart0,
-	&w90x900_uart1,
-	&w90x900_uart2,
-	&w90x900_uart3,
-	&w90x900_uart4
+struct plat_serial8250_port w90p910_uart_data[] = {
+	W90X900_8250PORT(UART0),
 };
 
-/*Init W90P910 uart device*/
-
-void __init w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no)
-{
-	struct platform_device *platdev;
-	int uart, uartdev;
-
-	/*By min() to judge count of uart be used indeed*/
-
-	uartdev = ARRAY_SIZE(uart_devices);
-	no = min(uartdev, no);
-
-	for (uart = 0; uart < no; uart++, cfg++) {
-		if (cfg->hwport != uart)
-			printk(KERN_ERR "w90x900_uartcfg[%d] error\n", uart);
-		platdev = uart_devices[cfg->hwport];
-		uart_devs[uart] = platdev;
-		platdev->dev.platform_data = cfg;
-	}
-	uart_count = uart;
-}
+struct platform_device w90p910_serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= w90p910_uart_data,
+	},
+};
 
 /*Init W90P910 evb io*/
 
@@ -122,13 +88,6 @@
 
 static int __init w90x900_arch_init(void)
 {
-	int ret;
-
-	ret = w90p910_init_cpu();
-	if (ret != 0)
-		return ret;
-
-	return platform_add_devices(uart_devs, uart_count);
-
+	return w90p910_init_cpu();
 }
 arch_initcall(w90x900_arch_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index d490f37..2097956 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -186,6 +186,24 @@
 	  Say Y if you want support for the ARM926T processor.
 	  Otherwise, say N.
 
+# FA526
+config CPU_FA526
+	bool
+	select CPU_32v4
+	select CPU_ABRT_EV4
+	select CPU_PABRT_NOIFAR
+	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
+	select CPU_CACHE_FA
+	select CPU_COPY_FA if MMU
+	select CPU_TLB_FA if MMU
+	help
+	  The FA526 is a version of the ARMv4 compatible processor with
+	  Branch Target Buffer, Unified TLB and cache line size 16.
+
+	  Say Y if you want support for the FA526 processor.
+	  Otherwise, say N.
+
 # ARM940T
 config CPU_ARM940T
 	bool "Support ARM940T processor" if ARCH_INTEGRATOR
@@ -340,6 +358,17 @@
 	select CPU_TLB_V4WBI if MMU
 	select IO_36
 
+# Marvell PJ1 (Mohawk)
+config CPU_MOHAWK
+	bool
+	select CPU_32v5
+	select CPU_ABRT_EV5T
+	select CPU_PABRT_NOIFAR
+	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
+	select CPU_TLB_V4WBI if MMU
+	select CPU_COPY_V4WB if MMU
+
 # Feroceon
 config CPU_FEROCEON
 	bool
@@ -484,6 +513,9 @@
 config CPU_CACHE_VIPT
 	bool
 
+config CPU_CACHE_FA
+	bool
+
 if MMU
 # The copy-page model
 config CPU_COPY_V3
@@ -498,6 +530,9 @@
 config CPU_COPY_FEROCEON
 	bool
 
+config CPU_COPY_FA
+	bool
+
 config CPU_COPY_V6
 	bool
 
@@ -528,6 +563,13 @@
 	help
 	  Feroceon TLB (v4wbi with non-outer-cachable page table walks).
 
+config CPU_TLB_FA
+	bool
+	help
+	  Faraday ARM FA526 architecture, unified TLB with writeback cache
+	  and invalidate instruction cache entry. Branch target buffer is
+	  also supported.
+
 config CPU_TLB_V6
 	bool
 
@@ -569,7 +611,7 @@
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 || CPU_FEROCEON
+	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V7 || CPU_FEROCEON
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
@@ -638,7 +680,7 @@
 
 config CPU_DCACHE_WRITETHROUGH
 	bool "Force write through D-cache"
-	depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
+	depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE
 	default y if CPU_ARM925T
 	help
 	  Say Y here to use the data cache in writethrough mode. Unless you
@@ -653,7 +695,7 @@
 
 config CPU_BPREDICT_DISABLE
 	bool "Disable branch prediction"
-	depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7
+	depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526
 	help
 	  Say Y here to disable branch prediction.  If unsure, say N.
 
@@ -704,7 +746,8 @@
 
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
-	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP
+	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
+		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31
 	default y
 	select OUTER_CACHE
 	help
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 480f78a..63e3f6d 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -16,6 +16,7 @@
 
 obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
 obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
+obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
 obj-$(CONFIG_CPU_ABRT_NOMMU)	+= abort-nommu.o
 obj-$(CONFIG_CPU_ABRT_EV4)	+= abort-ev4.o
@@ -32,6 +33,7 @@
 obj-$(CONFIG_CPU_CACHE_V4WB)	+= cache-v4wb.o
 obj-$(CONFIG_CPU_CACHE_V6)	+= cache-v6.o
 obj-$(CONFIG_CPU_CACHE_V7)	+= cache-v7.o
+obj-$(CONFIG_CPU_CACHE_FA)	+= cache-fa.o
 
 obj-$(CONFIG_CPU_COPY_V3)	+= copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)	+= copypage-v4wt.o
@@ -41,6 +43,7 @@
 obj-$(CONFIG_CPU_SA1100)	+= copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)	+= copypage-xscale.o
 obj-$(CONFIG_CPU_XSC3)		+= copypage-xsc3.o
+obj-$(CONFIG_CPU_COPY_FA)	+= copypage-fa.o
 
 obj-$(CONFIG_CPU_TLB_V3)	+= tlb-v3.o
 obj-$(CONFIG_CPU_TLB_V4WT)	+= tlb-v4.o
@@ -49,6 +52,7 @@
 obj-$(CONFIG_CPU_TLB_FEROCEON)	+= tlb-v4wbi.o	# reuse v4wbi TLB functions
 obj-$(CONFIG_CPU_TLB_V6)	+= tlb-v6.o
 obj-$(CONFIG_CPU_TLB_V7)	+= tlb-v7.o
+obj-$(CONFIG_CPU_TLB_FA)	+= tlb-fa.o
 
 obj-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o
@@ -62,6 +66,7 @@
 obj-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o
 obj-$(CONFIG_CPU_ARM940T)	+= proc-arm940.o
 obj-$(CONFIG_CPU_ARM946E)	+= proc-arm946.o
+obj-$(CONFIG_CPU_FA526)		+= proc-fa526.o
 obj-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o
 obj-$(CONFIG_CPU_ARM1020E)	+= proc-arm1020e.o
 obj-$(CONFIG_CPU_ARM1022)	+= proc-arm1022.o
@@ -70,6 +75,7 @@
 obj-$(CONFIG_CPU_SA1100)	+= proc-sa1100.o
 obj-$(CONFIG_CPU_XSCALE)	+= proc-xscale.o
 obj-$(CONFIG_CPU_XSC3)		+= proc-xsc3.o
+obj-$(CONFIG_CPU_MOHAWK)	+= proc-mohawk.o
 obj-$(CONFIG_CPU_FEROCEON)	+= proc-feroceon.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
 obj-$(CONFIG_CPU_V7)		+= proc-v7.o
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
new file mode 100644
index 0000000..b63a8f7
--- /dev/null
+++ b/arch/arm/mm/cache-fa.S
@@ -0,0 +1,220 @@
+/*
+ *  linux/arch/arm/mm/cache-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on cache-v4wb.S:
+ *  Copyright (C) 1997-2002 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.
+ *
+ *  Processors: FA520 FA526 FA626	
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+#include "proc-macros.S"
+
+/*
+ * The size of one data cache line.
+ */
+#define CACHE_DLINESIZE	16
+
+/*
+ * The total size of the data cache.
+ */
+#ifdef CONFIG_ARCH_GEMINI
+#define CACHE_DSIZE	8192
+#else
+#define CACHE_DSIZE	16384 
+#endif 
+
+/* FIXME: put optimal value here. Current one is just estimation */
+#define CACHE_DLIMIT	(CACHE_DSIZE * 2)
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Clean and invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(fa_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(fa_flush_kern_cache_all)
+	mov	ip, #0
+	mov	r2, #VM_EXEC
+__flush_whole_cache:
+	mcr	p15, 0, ip, c7, c14, 0		@ clean/invalidate D cache
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain write buffer
+	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	Invalidate a range of cache entries in the specified
+ *	address space.
+ *
+ *	- start - start address (inclusive, page aligned)
+ *	- end	- end address (exclusive, page aligned)
+ *	- flags	- vma_area_struct flags describing address space
+ */
+ENTRY(fa_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT		@ total size >= limit?
+	bhs	__flush_whole_cache		@ flush whole D cache
+
+1:	tst	r2, #VM_EXEC
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I line
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	mcrne	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcrne	p15, 0, ip, c7, c5, 4		@ prefetch flush
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_coherent_kern_range)
+	/* fall through */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_coherent_user_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(kaddr)
+ *
+ *	Ensure that the data held in the page kaddr is written back
+ *	to the page in question.
+ *
+ *	- kaddr   - kernel address (guaranteed to be page aligned)
+ */
+ENTRY(fa_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_dma_inv_range)
+	tst	r0, #CACHE_DLINESIZE - 1
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	bic	r1, r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c14, 1		@ clean & invalidate D entry
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean (write back) the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_dma_clean_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0	
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start,end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(fa_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0	
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mov	pc, lr
+
+	__INITDATA
+
+	.type	fa_cache_fns, #object
+ENTRY(fa_cache_fns)
+	.long	fa_flush_kern_cache_all
+	.long	fa_flush_user_cache_all
+	.long	fa_flush_user_cache_range
+	.long	fa_coherent_kern_range
+	.long	fa_coherent_user_range
+	.long	fa_flush_kern_dcache_page
+	.long	fa_dma_inv_range
+	.long	fa_dma_clean_range
+	.long	fa_dma_flush_range
+	.size	fa_cache_fns, . - fa_cache_fns
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index 80cd207..d6dd838 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -14,8 +14,12 @@
 
 #include <linux/init.h>
 #include <asm/cacheflush.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 #include <plat/cache-feroceon-l2.h>
-
+#include "mm.h"
 
 /*
  * Low-level cache maintenance operations.
@@ -34,14 +38,36 @@
  * The range operations require two successive cp15 writes, in
  * between which we don't want to be preempted.
  */
+
+static inline unsigned long l2_start_va(unsigned long paddr)
+{
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * Let's do our own fixmap stuff in a minimal way here.
+	 * Because range ops can't be done on physical addresses,
+	 * we simply install a virtual mapping for it only for the
+	 * TLB lookup to occur, hence no need to flush the untouched
+	 * memory mapping.  This is protected with the disabling of
+	 * interrupts by the caller.
+	 */
+	unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
+	unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
+	local_flush_tlb_kernel_page(vaddr);
+	return vaddr + (paddr & ~PAGE_MASK);
+#else
+	return __phys_to_virt(paddr);
+#endif
+}
+
 static inline void l2_clean_pa(unsigned long addr)
 {
 	__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
 }
 
-static inline void l2_clean_mva_range(unsigned long start, unsigned long end)
+static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
 {
-	unsigned long flags;
+	unsigned long va_start, va_end, flags;
 
 	/*
 	 * Make sure 'start' and 'end' reference the same page, as
@@ -51,17 +77,14 @@
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
 	raw_local_irq_save(flags);
+	va_start = l2_start_va(start);
+	va_end = va_start + (end - start);
 	__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
 		"mcr p15, 1, %1, c15, c9, 5"
-		: : "r" (start), "r" (end));
+		: : "r" (va_start), "r" (va_end));
 	raw_local_irq_restore(flags);
 }
 
-static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
-{
-	l2_clean_mva_range(__phys_to_virt(start), __phys_to_virt(end));
-}
-
 static inline void l2_clean_inv_pa(unsigned long addr)
 {
 	__asm__("mcr p15, 1, %0, c15, c10, 3" : : "r" (addr));
@@ -72,9 +95,9 @@
 	__asm__("mcr p15, 1, %0, c15, c11, 3" : : "r" (addr));
 }
 
-static inline void l2_inv_mva_range(unsigned long start, unsigned long end)
+static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
 {
-	unsigned long flags;
+	unsigned long va_start, va_end, flags;
 
 	/*
 	 * Make sure 'start' and 'end' reference the same page, as
@@ -84,17 +107,14 @@
 	BUG_ON((start ^ end) >> PAGE_SHIFT);
 
 	raw_local_irq_save(flags);
+	va_start = l2_start_va(start);
+	va_end = va_start + (end - start);
 	__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
 		"mcr p15, 1, %1, c15, c11, 5"
-		: : "r" (start), "r" (end));
+		: : "r" (va_start), "r" (va_end));
 	raw_local_irq_restore(flags);
 }
 
-static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
-{
-	l2_inv_mva_range(__phys_to_virt(start), __phys_to_virt(end));
-}
-
 
 /*
  * Linux primitives.
diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c
index 464de89..5d180cb 100644
--- a/arch/arm/mm/cache-xsc3l2.c
+++ b/arch/arm/mm/cache-xsc3l2.c
@@ -17,12 +17,14 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-
 #include <asm/system.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include "mm.h"
 
 #define CR_L2	(1 << 26)
 
@@ -47,21 +49,11 @@
 	__asm__("mcr p15, 1, %0, c7, c11, 1" : : "r" (addr));
 }
 
-static inline void xsc3_l2_clean_pa(unsigned long addr)
-{
-	xsc3_l2_clean_mva(__phys_to_virt(addr));
-}
-
 static inline void xsc3_l2_inv_mva(unsigned long addr)
 {
 	__asm__("mcr p15, 1, %0, c7, c7, 1" : : "r" (addr));
 }
 
-static inline void xsc3_l2_inv_pa(unsigned long addr)
-{
-	xsc3_l2_inv_mva(__phys_to_virt(addr));
-}
-
 static inline void xsc3_l2_inv_all(void)
 {
 	unsigned long l2ctype, set_way;
@@ -79,50 +71,103 @@
 	dsb();
 }
 
+#ifdef CONFIG_HIGHMEM
+#define l2_map_save_flags(x)		raw_local_save_flags(x)
+#define l2_map_restore_flags(x)		raw_local_irq_restore(x)
+#else
+#define l2_map_save_flags(x)		((x) = 0)
+#define l2_map_restore_flags(x)		((void)(x))
+#endif
+
+static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
+				      unsigned long flags)
+{
+#ifdef CONFIG_HIGHMEM
+	unsigned long va = prev_va & PAGE_MASK;
+	unsigned long pa_offset = pa << (32 - PAGE_SHIFT);
+	if (unlikely(pa_offset < (prev_va << (32 - PAGE_SHIFT)))) {
+		/*
+		 * Switching to a new page.  Because cache ops are
+		 * using virtual addresses only, we must put a mapping
+		 * in place for it.  We also enable interrupts for a
+		 * short while and disable them again to protect this
+		 * mapping.
+		 */
+		unsigned long idx;
+		raw_local_irq_restore(flags);
+		idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
+		va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+		raw_local_irq_restore(flags | PSR_I_BIT);
+		set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
+		local_flush_tlb_kernel_page(va);
+	}
+	return va + (pa_offset >> (32 - PAGE_SHIFT));
+#else
+	return __phys_to_virt(pa);
+#endif
+}
+
 static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
 {
+	unsigned long vaddr, flags;
+
 	if (start == 0 && end == -1ul) {
 		xsc3_l2_inv_all();
 		return;
 	}
 
+	vaddr = -1;  /* to force the first mapping */
+	l2_map_save_flags(flags);
+
 	/*
 	 * Clean and invalidate partial first cache line.
 	 */
 	if (start & (CACHE_LINE_SIZE - 1)) {
-		xsc3_l2_clean_pa(start & ~(CACHE_LINE_SIZE - 1));
-		xsc3_l2_inv_pa(start & ~(CACHE_LINE_SIZE - 1));
+		vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags);
+		xsc3_l2_clean_mva(vaddr);
+		xsc3_l2_inv_mva(vaddr);
 		start = (start | (CACHE_LINE_SIZE - 1)) + 1;
 	}
 
 	/*
-	 * Clean and invalidate partial last cache line.
-	 */
-	if (start < end && (end & (CACHE_LINE_SIZE - 1))) {
-		xsc3_l2_clean_pa(end & ~(CACHE_LINE_SIZE - 1));
-		xsc3_l2_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
-		end &= ~(CACHE_LINE_SIZE - 1);
-	}
-
-	/*
 	 * Invalidate all full cache lines between 'start' and 'end'.
 	 */
-	while (start < end) {
-		xsc3_l2_inv_pa(start);
+	while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
+		vaddr = l2_map_va(start, vaddr, flags);
+		xsc3_l2_inv_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
 
+	/*
+	 * Clean and invalidate partial last cache line.
+	 */
+	if (start < end) {
+		vaddr = l2_map_va(start, vaddr, flags);
+		xsc3_l2_clean_mva(vaddr);
+		xsc3_l2_inv_mva(vaddr);
+	}
+
+	l2_map_restore_flags(flags);
+
 	dsb();
 }
 
 static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
 {
+	unsigned long vaddr, flags;
+
+	vaddr = -1;  /* to force the first mapping */
+	l2_map_save_flags(flags);
+
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
-		xsc3_l2_clean_pa(start);
+		vaddr = l2_map_va(start, vaddr, flags);
+		xsc3_l2_clean_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
 
+	l2_map_restore_flags(flags);
+
 	dsb();
 }
 
@@ -148,18 +193,26 @@
 
 static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
 {
+	unsigned long vaddr, flags;
+
 	if (start == 0 && end == -1ul) {
 		xsc3_l2_flush_all();
 		return;
 	}
 
+	vaddr = -1;  /* to force the first mapping */
+	l2_map_save_flags(flags);
+
 	start &= ~(CACHE_LINE_SIZE - 1);
 	while (start < end) {
-		xsc3_l2_clean_pa(start);
-		xsc3_l2_inv_pa(start);
+		vaddr = l2_map_va(start, vaddr, flags);
+		xsc3_l2_clean_mva(vaddr);
+		xsc3_l2_inv_mva(vaddr);
 		start += CACHE_LINE_SIZE;
 	}
 
+	l2_map_restore_flags(flags);
+
 	dsb();
 }
 
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c
new file mode 100644
index 0000000..b2a6008
--- /dev/null
+++ b/arch/arm/mm/copypage-fa.c
@@ -0,0 +1,86 @@
+/*
+ *  linux/arch/arm/lib/copypage-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on copypage-v4wb.S:
+ *  Copyright (C) 1995-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.
+ */
+#include <linux/init.h>
+#include <linux/highmem.h>
+
+/*
+ * Faraday optimised copy_user_page
+ */
+static void __naked
+fa_copy_user_page(void *kto, const void *kfrom)
+{
+	asm("\
+	stmfd	sp!, {r4, lr}			@ 2\n\
+	mov	r2, %0				@ 1\n\
+1:	ldmia	r1!, {r3, r4, ip, lr}		@ 4\n\
+	stmia	r0, {r3, r4, ip, lr}		@ 4\n\
+	mcr	p15, 0, r0, c7, c14, 1		@ 1   clean and invalidate D line\n\
+	add	r0, r0, #16			@ 1\n\
+	ldmia	r1!, {r3, r4, ip, lr}		@ 4\n\
+	stmia	r0, {r3, r4, ip, lr}		@ 4\n\
+	mcr	p15, 0, r0, c7, c14, 1		@ 1   clean and invalidate D line\n\
+	add	r0, r0, #16			@ 1\n\
+	subs	r2, r2, #1			@ 1\n\
+	bne	1b				@ 1\n\
+	mcr	p15, 0, r2, c7, c10, 4		@ 1   drain WB\n\
+	ldmfd	sp!, {r4, pc}			@ 3"
+	:
+	: "I" (PAGE_SIZE / 32));
+}
+
+void fa_copy_user_highpage(struct page *to, struct page *from,
+	unsigned long vaddr)
+{
+	void *kto, *kfrom;
+
+	kto = kmap_atomic(to, KM_USER0);
+	kfrom = kmap_atomic(from, KM_USER1);
+	fa_copy_user_page(kto, kfrom);
+	kunmap_atomic(kfrom, KM_USER1);
+	kunmap_atomic(kto, KM_USER0);
+}
+
+/*
+ * Faraday optimised clear_user_page
+ *
+ * Same story as above.
+ */
+void fa_clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	asm volatile("\
+	mov	r1, %2				@ 1\n\
+	mov	r2, #0				@ 1\n\
+	mov	r3, #0				@ 1\n\
+	mov	ip, #0				@ 1\n\
+	mov	lr, #0				@ 1\n\
+1:	stmia	%0, {r2, r3, ip, lr}		@ 4\n\
+	mcr	p15, 0, %0, c7, c14, 1		@ 1   clean and invalidate D line\n\
+	add	%0, %0, #16			@ 1\n\
+	stmia	%0, {r2, r3, ip, lr}		@ 4\n\
+	mcr	p15, 0, %0, c7, c14, 1		@ 1   clean and invalidate D line\n\
+	add	%0, %0, #16			@ 1\n\
+	subs	r1, r1, #1			@ 1\n\
+	bne	1b				@ 1\n\
+	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB"
+	: "=r" (ptr)
+	: "0" (kaddr), "I" (PAGE_SIZE / 32)
+	: "r1", "r2", "r3", "ip", "lr");
+	kunmap_atomic(kaddr, KM_USER0);
+}
+
+struct cpu_user_fns fa_user_fns __initdata = {
+	.cpu_clear_user_highpage = fa_clear_user_highpage,
+	.cpu_copy_user_highpage	= fa_copy_user_highpage,
+};
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f1ef561..510c179 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/memory.h>
+#include <asm/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
@@ -517,6 +518,74 @@
 }
 EXPORT_SYMBOL(dma_cache_maint);
 
+static void dma_cache_maint_contiguous(struct page *page, unsigned long offset,
+				       size_t size, int direction)
+{
+	void *vaddr;
+	unsigned long paddr;
+	void (*inner_op)(const void *, const void *);
+	void (*outer_op)(unsigned long, unsigned long);
+
+	switch (direction) {
+	case DMA_FROM_DEVICE:		/* invalidate only */
+		inner_op = dmac_inv_range;
+		outer_op = outer_inv_range;
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		inner_op = dmac_clean_range;
+		outer_op = outer_clean_range;
+		break;
+	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
+		inner_op = dmac_flush_range;
+		outer_op = outer_flush_range;
+		break;
+	default:
+		BUG();
+	}
+
+	if (!PageHighMem(page)) {
+		vaddr = page_address(page) + offset;
+		inner_op(vaddr, vaddr + size);
+	} else {
+		vaddr = kmap_high_get(page);
+		if (vaddr) {
+			vaddr += offset;
+			inner_op(vaddr, vaddr + size);
+			kunmap_high(page);
+		}
+	}
+
+	paddr = page_to_phys(page) + offset;
+	outer_op(paddr, paddr + size);
+}
+
+void dma_cache_maint_page(struct page *page, unsigned long offset,
+			  size_t size, int dir)
+{
+	/*
+	 * A single sg entry may refer to multiple physically contiguous
+	 * pages.  But we still need to process highmem pages individually.
+	 * If highmem is not configured then the bulk of this loop gets
+	 * optimized out.
+	 */
+	size_t left = size;
+	do {
+		size_t len = left;
+		if (PageHighMem(page) && len + offset > PAGE_SIZE) {
+			if (offset >= PAGE_SIZE) {
+				page += offset / PAGE_SIZE;
+				offset %= PAGE_SIZE;
+			}
+			len = PAGE_SIZE - offset;
+		}
+		dma_cache_maint_contiguous(page, offset, len, dir);
+		offset = 0;
+		page++;
+		left -= len;
+	} while (left);
+}
+EXPORT_SYMBOL(dma_cache_maint_page);
+
 /**
  * dma_map_sg - map a set of SG buffers for streaming mode DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -614,7 +683,8 @@
 			continue;
 
 		if (!arch_is_coherent())
-			dma_cache_maint(sg_virt(s), s->length, dir);
+			dma_cache_maint_page(sg_page(s), s->offset,
+					     s->length, dir);
 	}
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 0fa9bf3..4e28348 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -192,7 +192,7 @@
 	struct address_space *mapping = page_mapping(page);
 
 #ifndef CONFIG_SMP
-	if (mapping && !mapping_mapped(mapping))
+	if (!PageHighMem(page) && mapping && !mapping_mapped(mapping))
 		set_bit(PG_dcache_dirty, &page->flags);
 	else
 #endif
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
new file mode 100644
index 0000000..a34954d
--- /dev/null
+++ b/arch/arm/mm/highmem.c
@@ -0,0 +1,116 @@
+/*
+ * arch/arm/mm/highmem.c -- ARM highmem support
+ *
+ * Author:	Nicolas Pitre
+ * Created:	september 8, 2008
+ * Copyright:	Marvell Semiconductors 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/module.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <asm/fixmap.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include "mm.h"
+
+void *kmap(struct page *page)
+{
+	might_sleep();
+	if (!PageHighMem(page))
+		return page_address(page);
+	return kmap_high(page);
+}
+EXPORT_SYMBOL(kmap);
+
+void kunmap(struct page *page)
+{
+	BUG_ON(in_interrupt());
+	if (!PageHighMem(page))
+		return;
+	kunmap_high(page);
+}
+EXPORT_SYMBOL(kunmap);
+
+void *kmap_atomic(struct page *page, enum km_type type)
+{
+	unsigned int idx;
+	unsigned long vaddr;
+
+	pagefault_disable();
+	if (!PageHighMem(page))
+		return page_address(page);
+
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	/*
+	 * With debugging enabled, kunmap_atomic forces that entry to 0.
+	 * Make sure it was indeed properly unmapped.
+	 */
+	BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+#endif
+	set_pte_ext(TOP_PTE(vaddr), mk_pte(page, kmap_prot), 0);
+	/*
+	 * When debugging is off, kunmap_atomic leaves the previous mapping
+	 * in place, so this TLB flush ensures the TLB is updated with the
+	 * new mapping.
+	 */
+	local_flush_tlb_kernel_page(vaddr);
+
+	return (void *)vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
+
+	if (kvaddr >= (void *)FIXADDR_START) {
+		__cpuc_flush_dcache_page((void *)vaddr);
+#ifdef CONFIG_DEBUG_HIGHMEM
+		BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+		set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
+		local_flush_tlb_kernel_page(vaddr);
+#else
+		(void) idx;  /* to kill a warning */
+#endif
+	}
+	pagefault_enable();
+}
+EXPORT_SYMBOL(kunmap_atomic);
+
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+	unsigned int idx;
+	unsigned long vaddr;
+
+	pagefault_disable();
+
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+#endif
+	set_pte_ext(TOP_PTE(vaddr), pfn_pte(pfn, kmap_prot), 0);
+	local_flush_tlb_kernel_page(vaddr);
+
+	return (void *)vaddr;
+}
+
+struct page *kmap_atomic_to_page(const void *ptr)
+{
+	unsigned long vaddr = (unsigned long)ptr;
+	pte_t *pte;
+
+	if (vaddr < FIXADDR_START)
+		return virt_to_page(ptr);
+
+	pte = TOP_PTE(vaddr);
+	return pte_page(*pte);
+}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 80fd3b6..8277802 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -15,6 +15,7 @@
 #include <linux/mman.h>
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
+#include <linux/highmem.h>
 
 #include <asm/mach-types.h>
 #include <asm/sections.h>
@@ -485,7 +486,7 @@
 	int i, node;
 
 #ifndef CONFIG_DISCONTIGMEM
-	max_mapnr   = virt_to_page(high_memory) - mem_map;
+	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 #endif
 
 	/* this will put all unused low memory onto the freelists */
@@ -504,6 +505,19 @@
 				    __phys_to_pfn(__pa(swapper_pg_dir)), NULL);
 #endif
 
+#ifdef CONFIG_HIGHMEM
+	/* set highmem page free */
+	for_each_online_node(node) {
+		for_each_nodebank (i, &meminfo, node) {
+			unsigned long start = bank_pfn_start(&meminfo.bank[i]);
+			unsigned long end = bank_pfn_end(&meminfo.bank[i]);
+			if (start >= max_low_pfn + PHYS_PFN_OFFSET)
+				totalhigh_pages += free_area(start, end, NULL);
+		}
+	}
+	totalram_pages += totalhigh_pages;
+#endif
+
 	/*
 	 * Since our memory may not be contiguous, calculate the
 	 * real number of pages we have in this system
@@ -521,9 +535,10 @@
 	initsize = __init_end - __init_begin;
 
 	printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
-		"%dK data, %dK init)\n",
+		"%dK data, %dK init, %luK highmem)\n",
 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-		codesize >> 10, datasize >> 10, initsize >> 10);
+		codesize >> 10, datasize >> 10, initsize >> 10,
+		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
 
 	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
 		extern int sysctl_overcommit_memory;
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 95bbe11..c4f6f05 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -1,7 +1,6 @@
-/* the upper-most page table pointer */
-
 #ifdef CONFIG_MMU
 
+/* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 
 #define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index d4d082c..b438fc4 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -18,9 +18,11 @@
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
 #include <asm/sections.h>
+#include <asm/cachetype.h>
 #include <asm/setup.h>
 #include <asm/sizes.h>
 #include <asm/tlb.h>
+#include <asm/highmem.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -243,6 +245,10 @@
 		.prot_sect = PMD_TYPE_SECT,
 		.domain    = DOMAIN_KERNEL,
 	},
+	[MT_MEMORY_NONCACHED] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
+		.domain    = DOMAIN_KERNEL,
+	},
 };
 
 const struct mem_type *get_mem_type(unsigned int type)
@@ -406,9 +412,28 @@
 		kern_pgprot |= L_PTE_SHARED;
 		vecs_pgprot |= L_PTE_SHARED;
 		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+		mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
 #endif
 	}
 
+	/*
+	 * Non-cacheable Normal - intended for memory areas that must
+	 * not cause dirty cache line writebacks when used
+	 */
+	if (cpu_arch >= CPU_ARCH_ARMv6) {
+		if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
+			/* Non-cacheable Normal is XCB = 001 */
+			mem_types[MT_MEMORY_NONCACHED].prot_sect |=
+				PMD_SECT_BUFFERED;
+		} else {
+			/* For both ARMv6 and non-TEX-remapping ARMv7 */
+			mem_types[MT_MEMORY_NONCACHED].prot_sect |=
+				PMD_SECT_TEX(1);
+		}
+	} else {
+		mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
+	}
+
 	for (i = 0; i < 16; i++) {
 		unsigned long v = pgprot_val(protection_map[i]);
 		protection_map[i] = __pgprot(v | user_pgprot);
@@ -677,6 +702,10 @@
 			if (meminfo.nr_banks >= NR_BANKS) {
 				printk(KERN_CRIT "NR_BANKS too low, "
 						 "ignoring high memory\n");
+			} else if (cache_is_vipt_aliasing()) {
+				printk(KERN_CRIT "HIGHMEM is not yet supported "
+						 "with VIPT aliasing cache, "
+						 "ignoring high memory\n");
 			} else {
 				memmove(bank + 1, bank,
 					(meminfo.nr_banks - i) * sizeof(*bank));
@@ -694,7 +723,7 @@
 		 * the vmalloc area.
 		 */
 		if (__va(bank->start) >= VMALLOC_MIN ||
-		    __va(bank->start) < PAGE_OFFSET) {
+		    __va(bank->start) < (void *)PAGE_OFFSET) {
 			printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
 			       "(vmalloc region overlap).\n",
 			       bank->start, bank->start + bank->size - 1);
@@ -895,6 +924,17 @@
 	flush_cache_all();
 }
 
+static void __init kmap_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+	pmd_t *pmd = pmd_off_k(PKMAP_BASE);
+	pte_t *pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t));
+	BUG_ON(!pmd_none(*pmd) || !pte);
+	__pmd_populate(pmd, __pa(pte) | _PAGE_KERNEL_TABLE);
+	pkmap_page_table = pte + PTRS_PER_PTE;
+#endif
+}
+
 /*
  * paging_init() sets up the page tables, initialises the zone memory
  * maps, and sets up the zero page, bad page and bad page tables.
@@ -908,6 +948,7 @@
 	prepare_page_table();
 	bootmem_init();
 	devicemaps_init(mdesc);
+	kmap_init();
 
 	top_pmd = pmd_off_k(0xffff0000);
 
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
new file mode 100644
index 0000000..08b8a95
--- /dev/null
+++ b/arch/arm/mm/proc-fa526.S
@@ -0,0 +1,248 @@
+/*
+ *  linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
+ *
+ *  Written by : Luke Lee
+ *  Copyright (C) 2005 Faraday Corp.
+ *  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.
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the fa526.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/hwcap.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#include "proc-macros.S"
+
+#define CACHE_DLINESIZE	16
+
+	.text
+/*
+ * cpu_fa526_proc_init()
+ */
+ENTRY(cpu_fa526_proc_init)
+	mov	pc, lr
+
+/*
+ * cpu_fa526_proc_fin()
+ */
+ENTRY(cpu_fa526_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	bl	fa_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1000			@ ...i............
+	bic	r0, r0, #0x000e			@ ............wca.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	nop
+	nop
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_fa526_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+	.align	4
+ENTRY(cpu_fa526_reset)
+/* TODO: Use CP8 if possible... */
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+#ifdef CONFIG_MMU
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+#endif
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x000f			@ ............wcam
+	bic	ip, ip, #0x1100			@ ...i...s........
+	bic	ip, ip, #0x0800			@ BTB off
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	nop
+	nop
+	mov	pc, r0
+
+/*
+ * cpu_fa526_do_idle()
+ */
+	.align	4
+ENTRY(cpu_fa526_do_idle)
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
+	mov	pc, lr
+
+
+ENTRY(cpu_fa526_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_fa526_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	4
+ENTRY(cpu_fa526_switch_mm)
+#ifdef CONFIG_MMU
+	mov	ip, #0
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+	mcr	p15, 0, ip, c7, c14, 0		@ clean and invalidate whole D cache
+#endif
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c5, 6		@ invalidate BTB since mm changed
+	mcr	p15, 0, ip, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, ip, c7, c5, 4		@ prefetch flush
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate UTLB
+#endif
+	mov	pc, lr
+
+/*
+ * cpu_fa526_set_pte_ext(ptep, pte, ext)
+ *
+ * Set a PTE and flush it out
+ */
+	.align	4
+ENTRY(cpu_fa526_set_pte_ext)
+#ifdef CONFIG_MMU
+	armv3_set_pte_ext
+	mov	r0, r0
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+#endif
+	mov	pc, lr
+
+	__INIT
+
+	.type	__fa526_setup, #function
+__fa526_setup:
+	/* On return of this routine, r0 must carry correct flags for CFG register */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches on v4
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
+#ifdef CONFIG_MMU
+	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs on v4
+#endif
+	mcr	p15, 0, r0, c7, c5, 5		@ invalidate IScratchpad RAM
+
+	mov	r0, #1
+	mcr	p15, 0, r0, c1, c1, 0		@ turn-on ECR
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB All
+	mcr	p15, 0, r0, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, r0, c7, c5, 4		@ prefetch flush
+
+	mov	r0, #0x1f			@ Domains 0, 1 = manager, 2 = client
+	mcr	p15, 0, r0, c3, c0		@ load domain access register
+
+	mrc	p15, 0, r0, c1, c0		@ get control register v4
+	ldr	r5, fa526_cr1_clear
+	bic	r0, r0, r5
+	ldr	r5, fa526_cr1_set
+	orr	r0, r0, r5
+	mov	pc, lr
+	.size	__fa526_setup, . - __fa526_setup
+
+	/*
+	 * .RVI ZFRS BLDP WCAM
+	 * ..11 1001 .111 1101
+	 *
+	 */
+	.type	fa526_cr1_clear, #object
+	.type	fa526_cr1_set, #object
+fa526_cr1_clear:
+	.word	0x3f3f
+fa526_cr1_set:
+	.word	0x397D
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	fa526_processor_functions, #object
+fa526_processor_functions:
+	.word	v4_early_abort
+	.word	pabort_noifar
+	.word	cpu_fa526_proc_init
+	.word	cpu_fa526_proc_fin
+	.word	cpu_fa526_reset
+	.word   cpu_fa526_do_idle
+	.word	cpu_fa526_dcache_clean_area
+	.word	cpu_fa526_switch_mm
+	.word	cpu_fa526_set_pte_ext
+	.size	fa526_processor_functions, . - fa526_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_fa526_name, #object
+cpu_fa526_name:
+	.asciz	"FA526"
+	.size	cpu_fa526_name, . - cpu_fa526_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	.type	__fa526_proc_info,#object
+__fa526_proc_info:
+	.long	0x66015261
+	.long	0xff01fff1
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_BUFFERABLE | \
+		PMD_SECT_CACHEABLE | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	.long   PMD_TYPE_SECT | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__fa526_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF
+	.long	cpu_fa526_name
+	.long	fa526_processor_functions
+	.long	fa_tlb_fns
+	.long	fa_user_fns
+	.long	fa_cache_fns
+	.size	__fa526_proc_info, . - __fa526_proc_info
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
new file mode 100644
index 0000000..540f507
--- /dev/null
+++ b/arch/arm/mm/proc-mohawk.S
@@ -0,0 +1,416 @@
+/*
+ *  linux/arch/arm/mm/proc-mohawk.S: MMU functions for Marvell PJ1 core
+ *
+ *  PJ1 (codename Mohawk) is a hybrid of the xscale3 and Marvell's own core.
+ *
+ *  Heavily based on proc-arm926.S and proc-xsc3.S
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/hwcap.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include "proc-macros.S"
+
+/*
+ * This is the maximum size of an area which will be flushed.  If the
+ * area is larger than this, then we flush the whole cache.
+ */
+#define CACHE_DLIMIT	32768
+
+/*
+ * The cache line size of the L1 D cache.
+ */
+#define CACHE_DLINESIZE	32
+
+/*
+ * cpu_mohawk_proc_init()
+ */
+ENTRY(cpu_mohawk_proc_init)
+	mov	pc, lr
+
+/*
+ * cpu_mohawk_proc_fin()
+ */
+ENTRY(cpu_mohawk_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+	bl	mohawk_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1800			@ ...iz...........
+	bic	r0, r0, #0x0006			@ .............ca.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_mohawk_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ *
+ * (same as arm926)
+ */
+	.align	5
+ENTRY(cpu_mohawk_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x0007			@ .............cam
+	bic	ip, ip, #0x1100			@ ...i...s........
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	mov	pc, r0
+
+/*
+ * cpu_mohawk_do_idle()
+ *
+ * Called with IRQs disabled
+ */
+	.align	5
+ENTRY(cpu_mohawk_do_idle)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mcr	p15, 0, r0, c7, c0, 4		@ wait for interrupt
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Clean and invalidate all cache entries in a particular
+ *	address space.
+ */
+ENTRY(mohawk_flush_user_cache_all)
+	/* FALLTHROUGH */
+
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(mohawk_flush_kern_cache_all)
+	mov	r2, #VM_EXEC
+	mov	ip, #0
+__flush_whole_cache:
+	mcr	p15, 0, ip, c7, c14, 0		@ clean & invalidate all D cache
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcrne	p15, 0, ip, c7, c10, 0		@ drain write buffer
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	Clean and invalidate a range of cache entries in the
+ *	specified address range.
+ *
+ *	- start	- start address (inclusive)
+ *	- end	- end address (exclusive)
+ *	- flags	- vm_flags describing address space
+ *
+ * (same as arm926)
+ */
+ENTRY(mohawk_flush_user_cache_range)
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+	cmp	r3, #CACHE_DLIMIT
+	bgt	__flush_whole_cache
+1:	tst	r2, #VM_EXEC
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	tst	r2, #VM_EXEC
+	mcrne	p15, 0, ip, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(mohawk_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as arm926)
+ */
+ENTRY(mohawk_coherent_user_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(mohawk_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
+ */
+ENTRY(mohawk_dma_inv_range)
+	tst	r0, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
+	tst	r1, #CACHE_DLINESIZE - 1
+	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ *
+ * (same as v4wb)
+ */
+ENTRY(mohawk_dma_clean_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(mohawk_dma_flush_range)
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+1:
+	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+ENTRY(mohawk_cache_fns)
+	.long	mohawk_flush_kern_cache_all
+	.long	mohawk_flush_user_cache_all
+	.long	mohawk_flush_user_cache_range
+	.long	mohawk_coherent_kern_range
+	.long	mohawk_coherent_user_range
+	.long	mohawk_flush_kern_dcache_page
+	.long	mohawk_dma_inv_range
+	.long	mohawk_dma_clean_range
+	.long	mohawk_dma_flush_range
+
+ENTRY(cpu_mohawk_dcache_clean_area)
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+/*
+ * cpu_mohawk_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	5
+ENTRY(cpu_mohawk_switch_mm)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0		@ clean & invalidate all D cache
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+	orr	r0, r0, #0x18			@ cache the page table in L2
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mov	pc, lr
+
+/*
+ * cpu_mohawk_set_pte_ext(ptep, pte, ext)
+ *
+ * Set a PTE and flush it out
+ */
+	.align	5
+ENTRY(cpu_mohawk_set_pte_ext)
+	armv3_set_pte_ext
+	mov	r0, r0
+	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+	mov	pc, lr
+
+	__INIT
+
+	.type	__mohawk_setup, #function
+__mohawk_setup:
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs
+	orr	r4, r4, #0x18			@ cache the page table in L2
+	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
+
+	mov	r0, #0				@ don't allow CP access
+	mcr	p15, 0, r0, c15, c1, 0		@ write CP access register
+
+	adr	r5, mohawk_crval
+	ldmia	r5, {r5, r6}
+	mrc	p15, 0, r0, c1, c0		@ get control register
+	bic	r0, r0, r5
+	orr	r0, r0, r6
+	mov	pc, lr
+
+	.size	__mohawk_setup, . - __mohawk_setup
+
+	/*
+	 *  R
+	 * .RVI ZFRS BLDP WCAM
+	 * .011 1001 ..00 0101
+	 *
+	 */
+	.type	mohawk_crval, #object
+mohawk_crval:
+	crval	clear=0x00007f3f, mmuset=0x00003905, ucset=0x00001134
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	mohawk_processor_functions, #object
+mohawk_processor_functions:
+	.word	v5t_early_abort
+	.word	pabort_noifar
+	.word	cpu_mohawk_proc_init
+	.word	cpu_mohawk_proc_fin
+	.word	cpu_mohawk_reset
+	.word	cpu_mohawk_do_idle
+	.word	cpu_mohawk_dcache_clean_area
+	.word	cpu_mohawk_switch_mm
+	.word	cpu_mohawk_set_pte_ext
+	.size	mohawk_processor_functions, . - mohawk_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv5te"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v5"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_mohawk_name, #object
+cpu_mohawk_name:
+	.asciz	"Marvell 88SV331x"
+	.size	cpu_mohawk_name, . - cpu_mohawk_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	.type	__88sv331x_proc_info,#object
+__88sv331x_proc_info:
+	.long	0x56158000			@ Marvell 88SV331x (MOHAWK)
+	.long	0xfffff000
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_BUFFERABLE | \
+		PMD_SECT_CACHEABLE | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	.long   PMD_TYPE_SECT | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__mohawk_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_mohawk_name
+	.long	mohawk_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	v4wb_user_fns
+	.long	mohawk_cache_fns
+	.size	__88sv331x_proc_info, . - __88sv331x_proc_info
diff --git a/arch/arm/mm/tlb-fa.S b/arch/arm/mm/tlb-fa.S
new file mode 100644
index 0000000..9694f1f
--- /dev/null
+++ b/arch/arm/mm/tlb-fa.S
@@ -0,0 +1,75 @@
+/*
+ *  linux/arch/arm/mm/tlb-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on tlb-v4wbi.S:
+ *  Copyright (C) 1997-2002 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.
+ *
+ *  ARM architecture version 4, Faraday variation.
+ *  This assume an unified TLBs, with a write buffer, and branch target buffer (BTB)
+ *
+ *  Processors: FA520 FA526 FA626
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+
+/*
+ *	flush_user_tlb_range(start, end, mm)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - range start address
+ *	- end   - range end address
+ *	- mm    - mm_struct describing address space
+ */
+	.align	4
+ENTRY(fa_flush_user_tlb_range)
+	vma_vm_mm ip, r2
+	act_mm	r3				@ get current->active_mm
+	eors	r3, ip, r3			@ == mm ?
+	movne	pc, lr				@ no, we dont do anything
+	mov	r3, #0
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+1:	mcr	p15, 0, r0, c8, c7, 1		@ invalidate UTLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
+	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
+	mov	pc, lr
+
+
+ENTRY(fa_flush_kern_tlb_range)
+	mov	r3, #0
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+1:	mcr	p15, 0, r0, c8, c7, 1		@ invalidate UTLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	blo	1b
+	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
+	mcr	p15, 0, r3, c7, c10, 4		@ data write barrier
+	mcr	p15, 0, r3, c7, c5, 4		@ prefetch flush
+	mov	pc, lr
+
+	__INITDATA
+
+	.type	fa_tlb_fns, #object
+ENTRY(fa_tlb_fns)
+	.long	fa_flush_user_tlb_range
+	.long	fa_flush_kern_tlb_range
+	.long	fa_tlb_flags
+	.size	fa_tlb_fns, . - fa_tlb_fns
diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c
index cefc21c..d805a52 100644
--- a/arch/arm/oprofile/backtrace.c
+++ b/arch/arm/oprofile/backtrace.c
@@ -18,15 +18,14 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 #include <asm/ptrace.h>
-
-#include "../kernel/stacktrace.h"
+#include <asm/stacktrace.h>
 
 static int report_trace(struct stackframe *frame, void *d)
 {
 	unsigned int *depth = d;
 
 	if (*depth) {
-		oprofile_add_trace(frame->lr);
+		oprofile_add_trace(frame->pc);
 		(*depth)--;
 	}
 
@@ -70,9 +69,12 @@
 	struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;
 
 	if (!user_mode(regs)) {
-		unsigned long base = ((unsigned long)regs) & ~(THREAD_SIZE - 1);
-		walk_stackframe(regs->ARM_fp, base, base + THREAD_SIZE,
-				report_trace, &depth);
+		struct stackframe frame;
+		frame.fp = regs->ARM_fp;
+		frame.sp = regs->ARM_sp;
+		frame.lr = regs->ARM_lr;
+		frame.pc = regs->ARM_pc;
+		walk_stackframe(&frame, report_trace, &depth);
 		return;
 	}
 
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 9cc2b16..17d0e99 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -3,7 +3,7 @@
 menu "Freescale MXC Implementations"
 
 choice
-	prompt "MXC/iMX Base Type"
+	prompt "Freescale CPU family:"
 	default ARCH_MX3
 
 config ARCH_MX1
@@ -15,12 +15,14 @@
 config ARCH_MX2
 	bool "MX2-based"
 	select CPU_ARM926T
+	select COMMON_CLKDEV
 	help
 	  This enables support for systems based on the Freescale i.MX2 family
 
 config ARCH_MX3
 	bool "MX3-based"
 	select CPU_V6
+	select COMMON_CLKDEV
 	help
 	  This enables support for systems based on the Freescale i.MX3 family
 
@@ -43,4 +45,10 @@
 	  requirements for timing.
 	  Say N here, unless you have a specialized requirement.
 
+config MXC_PWM
+	tristate "Enable PWM driver"
+	depends on ARCH_MXC
+	help
+	  Enable support for the i.MX PWM controller(s).
+
 endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index db74a92..0554063 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,8 @@
 #
 
 # Common support
-obj-y := irq.o clock.o gpio.o time.o devices.o
+obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
 
 obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
 obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
+obj-$(CONFIG_MXC_PWM)  += pwm.o
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 0a38f0b..92e1356 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -48,6 +48,11 @@
  *-------------------------------------------------------------------------*/
 
 /*
+ * All the code inside #ifndef CONFIG_COMMON_CLKDEV can be removed once all
+ * MXC architectures have switched to using clkdev.
+ */
+#ifndef CONFIG_COMMON_CLKDEV
+/*
  * Retrieve a clock by name.
  *
  * Note that we first try to use device id on the bus
@@ -110,6 +115,7 @@
 	return clk;
 }
 EXPORT_SYMBOL(clk_get);
+#endif
 
 static void __clk_disable(struct clk *clk)
 {
@@ -187,6 +193,7 @@
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+#ifndef CONFIG_COMMON_CLKDEV
 /* Decrement the clock's module reference count */
 void clk_put(struct clk *clk)
 {
@@ -194,6 +201,7 @@
 		module_put(clk->owner);
 }
 EXPORT_SYMBOL(clk_put);
+#endif
 
 /* Round the requested clock rate to the nearest supported
  * rate that is less than or equal to the requested rate.
@@ -257,6 +265,7 @@
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#ifndef CONFIG_COMMON_CLKDEV
 /*
  * Add a new clock to the clock tree.
  */
@@ -327,4 +336,49 @@
 }
 
 late_initcall(mxc_setup_proc_entry);
+#endif /* CONFIG_PROC_FS */
 #endif
+
+/*
+ * Get the resulting clock rate from a PLL register value and the input
+ * frequency. PLLs with this register layout can at least be found on
+ * MX1, MX21, MX27 and MX31
+ *
+ *                  mfi + mfn / (mfd + 1)
+ *  f = 2 * f_ref * --------------------
+ *                        pd + 1
+ */
+unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq)
+{
+	long long ll;
+	int mfn_abs;
+	unsigned int mfi, mfn, mfd, pd;
+
+	mfi = (reg_val >> 10) & 0xf;
+	mfn = reg_val & 0x3ff;
+	mfd = (reg_val >> 16) & 0x3ff;
+	pd =  (reg_val >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	mfn_abs = mfn;
+
+#if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21
+	if (mfn >= 0x200) {
+		mfn |= 0xFFFFFE00;
+		mfn_abs = -mfn;
+	}
+#endif
+
+	freq *= 2;
+	freq /= pd + 1;
+
+	ll = (unsigned long long)freq * mfn_abs;
+
+	do_div(ll, mfd + 1);
+	if (mfn < 0)
+		ll = -ll;
+	ll = (freq * mfi) + ll;
+
+	return ll;
+}
diff --git a/arch/arm/plat-mxc/cpu.c b/arch/arm/plat-mxc/cpu.c
new file mode 100644
index 0000000..386e0d5
--- /dev/null
+++ b/arch/arm/plat-mxc/cpu.c
@@ -0,0 +1,11 @@
+
+#include <linux/module.h>
+
+unsigned int __mxc_cpu_type;
+EXPORT_SYMBOL(__mxc_cpu_type);
+
+void mxc_set_cpu_type(unsigned int type)
+{
+	__mxc_cpu_type = type;
+}
+
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index c667482..56f2fb5 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <mach/common.h>
 
 int __init mxc_register_device(struct platform_device *pdev, void *data)
 {
diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c
index 2905ec7..e364a5e 100644
--- a/arch/arm/plat-mxc/dma-mx1-mx2.c
+++ b/arch/arm/plat-mxc/dma-mx1-mx2.c
@@ -113,7 +113,7 @@
 	void (*err_handler) (int, void *, int errcode);
 	void (*prog_handler) (int, void *, struct scatterlist *);
 	void *data;
-	unsigned int  dma_mode;
+	unsigned int dma_mode;
 	struct scatterlist *sg;
 	unsigned int resbytes;
 	int dma_num;
@@ -802,7 +802,7 @@
 	int ret = 0;
 	int i;
 
-	dma_clk = clk_get(NULL, "dma_clk");
+	dma_clk = clk_get(NULL, "dma");
 	clk_enable(dma_clk);
 
 	/* reset DMA module */
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index ccbd94a..c6483ba 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -200,8 +200,8 @@
 static int mxc_gpio_direction_output(struct gpio_chip *chip,
 				     unsigned offset, int value)
 {
-	_set_gpio_direction(chip, offset, 1);
 	mxc_gpio_set(chip, offset, value);
+	_set_gpio_direction(chip, offset, 1);
 	return 0;
 }
 
diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h
index 8f34a05..1cac9d1 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h
@@ -48,7 +48,8 @@
  * Base address of PBC controller, CS4
  */
 #define PBC_BASE_ADDRESS        0xEB000000
-#define PBC_REG_ADDR(offset)    (PBC_BASE_ADDRESS + (offset))
+#define PBC_REG_ADDR(offset)    (void __force __iomem *) \
+		(PBC_BASE_ADDRESS + (offset))
 
 /*
  * PBC Interupt name definitions
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
index 451d510..318c72a 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx31ads.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_MXC_BOARD_MX31ADS_H__
 #define __ASM_ARCH_MXC_BOARD_MX31ADS_H__
 
+#include <mach/hardware.h>
+
 /* Base address of PBC controller */
 #define PBC_BASE_ADDRESS        IO_ADDRESS(CS4_BASE_ADDR)
 /* Offsets for the PBC Controller register */
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
new file mode 100644
index 0000000..f8aef1b
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
+#define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__
+
+/* mandatory for CONFIG_LL_DEBUG */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	(AIPI_BASE_ADDR_VIRT + 0x0A000)
+
+#ifndef __ASSEMBLY__
+
+enum mx31moboard_boards {
+	MX31NOBOARD	= 0,
+	MX31DEVBOARD	= 1,
+	MX31MARXBOT	= 2,
+};
+
+/*
+ * This CPU module needs a baseboard to work. After basic initializing
+ * its own devices, it calls baseboard's init function.
+ */
+
+extern void mx31moboard_devboard_init(void);
+extern void mx31moboard_marxbot_init(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/board-qong.h b/arch/arm/plat-mxc/include/mach/board-qong.h
new file mode 100644
index 0000000..4ff762d
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/board-qong.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.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 __ASM_ARCH_MXC_BOARD_QONG_H__
+#define __ASM_ARCH_MXC_BOARD_QONG_H__
+
+/* mandatory for CONFIG_LL_DEBUG */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+
+/* NOR FLASH */
+#define QONG_NOR_SIZE		(128*1024*1024)
+
+#endif /* __ASM_ARCH_MXC_BOARD_QONG_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
new file mode 100644
index 0000000..04b37a8
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index d21f78e..43a82d0 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -26,9 +26,13 @@
 struct module;
 
 struct clk {
+#ifndef CONFIG_COMMON_CLKDEV
+	/* As soon as i.MX1 and i.MX31 switched to clkdev, this
+	 * block can go away */
 	struct list_head node;
 	struct module *owner;
 	const char *name;
+#endif
 	int id;
 	/* Source clock this clk depends on */
 	struct clk *parent;
@@ -63,5 +67,7 @@
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
 
+unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_ARCH_MXC_CLOCK_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 6350287..b2f9b72 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -12,12 +12,18 @@
 #define __ASM_ARCH_MXC_COMMON_H__
 
 struct platform_device;
+struct clk;
 
 extern void mxc_map_io(void);
 extern void mxc_init_irq(void);
-extern void mxc_timer_init(const char *clk_timer);
-extern int mxc_clocks_init(unsigned long fref);
+extern void mxc_timer_init(struct clk *timer_clk);
+extern int mx1_clocks_init(unsigned long fref);
+extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
+extern int mx27_clocks_init(unsigned long fref);
+extern int mx31_clocks_init(unsigned long fref);
+extern int mx35_clocks_init(void);
 extern int mxc_register_gpios(void);
 extern int mxc_register_device(struct platform_device *pdev, void *data);
+extern void mxc_set_cpu_type(unsigned int type);
 
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 602768b..4f77314 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -31,6 +31,9 @@
 #ifdef CONFIG_MACH_MX31_3DS
 #include <mach/board-mx31pdk.h>
 #endif
+#ifdef CONFIG_MACH_QONG
+#include <mach/board-qong.h>
+#endif
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index a612d8b..42e4ee3 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -23,10 +23,16 @@
 #include <asm/sizes.h>
 
 #ifdef CONFIG_ARCH_MX3
-# include <mach/mx31.h>
+#include <mach/mx3x.h>
+#include <mach/mx31.h>
+#include <mach/mx35.h>
 #endif
 
 #ifdef CONFIG_ARCH_MX2
+# include <mach/mx2x.h>
+# ifdef CONFIG_MACH_MX21
+#  include <mach/mx21.h>
+# endif
 # ifdef CONFIG_MACH_MX27
 #  include <mach/mx27.h>
 # endif
diff --git a/arch/arm/mach-imx/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h
similarity index 95%
rename from arch/arm/mach-imx/include/mach/imxfb.h
rename to arch/arm/plat-mxc/include/mach/imxfb.h
index 870d0d9..762a7b0 100644
--- a/arch/arm/mach-imx/include/mach/imxfb.h
+++ b/arch/arm/plat-mxc/include/mach/imxfb.h
@@ -76,6 +76,9 @@
 	u_char * fixed_screen_cpu;
 	dma_addr_t fixed_screen_dma;
 
+	int (*init)(struct platform_device*);
+	int (*exit)(struct platform_device*);
+
 	void (*lcd_power)(int);
 	void (*backlight_power)(int);
 };
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h
deleted file mode 100644
index 95a383b..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx1-mx2.h
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.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
- * 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 _MXC_GPIO_MX1_MX2_H
-#define _MXC_GPIO_MX1_MX2_H
-
-#include <linux/io.h>
-
-/*
- *  GPIO Module and I/O Multiplexer
- *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
- */
-#define VA_GPIO_BASE	IO_ADDRESS(GPIO_BASE_ADDR)
-#define MXC_DDIR(x)    (0x00 + ((x) << 8))
-#define MXC_OCR1(x)    (0x04 + ((x) << 8))
-#define MXC_OCR2(x)    (0x08 + ((x) << 8))
-#define MXC_ICONFA1(x) (0x0c + ((x) << 8))
-#define MXC_ICONFA2(x) (0x10 + ((x) << 8))
-#define MXC_ICONFB1(x) (0x14 + ((x) << 8))
-#define MXC_ICONFB2(x) (0x18 + ((x) << 8))
-#define MXC_DR(x)      (0x1c + ((x) << 8))
-#define MXC_GIUS(x)    (0x20 + ((x) << 8))
-#define MXC_SSR(x)     (0x24 + ((x) << 8))
-#define MXC_ICR1(x)    (0x28 + ((x) << 8))
-#define MXC_ICR2(x)    (0x2c + ((x) << 8))
-#define MXC_IMR(x)     (0x30 + ((x) << 8))
-#define MXC_ISR(x)     (0x34 + ((x) << 8))
-#define MXC_GPR(x)     (0x38 + ((x) << 8))
-#define MXC_SWR(x)     (0x3c + ((x) << 8))
-#define MXC_PUEN(x)    (0x40 + ((x) << 8))
-
-#ifdef CONFIG_ARCH_MX1
-# define GPIO_PORT_MAX  3
-#endif
-#ifdef CONFIG_ARCH_MX2
-# define GPIO_PORT_MAX  5
-#endif
-
-#ifndef GPIO_PORT_MAX
-# error "GPIO config port count unknown!"
-#endif
-
-#define GPIO_PIN_MASK 0x1f
-
-#define GPIO_PORT_SHIFT 5
-#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
-
-#define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
-#define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
-#define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
-#define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
-#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
-#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
-
-#define GPIO_OUT   (1 << 8)
-#define GPIO_IN    (0 << 8)
-#define GPIO_PUEN  (1 << 9)
-
-#define GPIO_PF    (1 << 10)
-#define GPIO_AF    (1 << 11)
-
-#define GPIO_OCR_SHIFT 12
-#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT)
-#define GPIO_AIN   (0 << GPIO_OCR_SHIFT)
-#define GPIO_BIN   (1 << GPIO_OCR_SHIFT)
-#define GPIO_CIN   (2 << GPIO_OCR_SHIFT)
-#define GPIO_GPIO  (3 << GPIO_OCR_SHIFT)
-
-#define GPIO_AOUT_SHIFT 14
-#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT     (0 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_0   (2 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_1   (3 << GPIO_AOUT_SHIFT)
-
-#define GPIO_BOUT_SHIFT 16
-#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT      (0 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_ISR  (1 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_0    (2 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_1    (3 << GPIO_BOUT_SHIFT)
-
-extern void mxc_gpio_mode(int gpio_mode);
-extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-					const char *label);
-extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
-
-/*-------------------------------------------------------------------------*/
-
-/* assignements for GPIO alternate/primary functions */
-
-/* FIXME: This list is not completed. The correct directions are
- * missing on some (many) pins
- */
-#ifdef CONFIG_ARCH_MX1
-#define PA0_AIN_SPI2_CLK     (GPIO_PORTA | GPIO_OUT | 0)
-#define PA0_AF_ETMTRACESYNC  (GPIO_PORTA | GPIO_AF | 0)
-#define PA1_AOUT_SPI2_RXD    (GPIO_PORTA | GPIO_IN | 1)
-#define PA1_PF_TIN           (GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_PWM0          (GPIO_PORTA | GPIO_OUT | GPIO_PF | 2)
-#define PA3_PF_CSI_MCLK      (GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_CSI_D0        (GPIO_PORTA | GPIO_PF | 4)
-#define PA5_PF_CSI_D1        (GPIO_PORTA | GPIO_PF | 5)
-#define PA6_PF_CSI_D2        (GPIO_PORTA | GPIO_PF | 6)
-#define PA7_PF_CSI_D3        (GPIO_PORTA | GPIO_PF | 7)
-#define PA8_PF_CSI_D4        (GPIO_PORTA | GPIO_PF | 8)
-#define PA9_PF_CSI_D5        (GPIO_PORTA | GPIO_PF | 9)
-#define PA10_PF_CSI_D6       (GPIO_PORTA | GPIO_PF | 10)
-#define PA11_PF_CSI_D7       (GPIO_PORTA | GPIO_PF | 11)
-#define PA12_PF_CSI_VSYNC    (GPIO_PORTA | GPIO_PF | 12)
-#define PA13_PF_CSI_HSYNC    (GPIO_PORTA | GPIO_PF | 13)
-#define PA14_PF_CSI_PIXCLK   (GPIO_PORTA | GPIO_PF | 14)
-#define PA15_PF_I2C_SDA      (GPIO_PORTA | GPIO_OUT | GPIO_PF | 15)
-#define PA16_PF_I2C_SCL      (GPIO_PORTA | GPIO_OUT | GPIO_PF | 16)
-#define PA17_AF_ETMTRACEPKT4 (GPIO_PORTA | GPIO_AF | 17)
-#define PA17_AIN_SPI2_SS     (GPIO_PORTA | GPIO_OUT | 17)
-#define PA18_AF_ETMTRACEPKT5 (GPIO_PORTA | GPIO_AF | 18)
-#define PA19_AF_ETMTRACEPKT6 (GPIO_PORTA | GPIO_AF | 19)
-#define PA20_AF_ETMTRACEPKT7 (GPIO_PORTA | GPIO_AF | 20)
-#define PA21_PF_A0           (GPIO_PORTA | GPIO_PF | 21)
-#define PA22_PF_CS4          (GPIO_PORTA | GPIO_PF | 22)
-#define PA23_PF_CS5          (GPIO_PORTA | GPIO_PF | 23)
-#define PA24_PF_A16          (GPIO_PORTA | GPIO_PF | 24)
-#define PA24_AF_ETMTRACEPKT0 (GPIO_PORTA | GPIO_AF | 24)
-#define PA25_PF_A17          (GPIO_PORTA | GPIO_PF | 25)
-#define PA25_AF_ETMTRACEPKT1 (GPIO_PORTA | GPIO_AF | 25)
-#define PA26_PF_A18          (GPIO_PORTA | GPIO_PF | 26)
-#define PA26_AF_ETMTRACEPKT2 (GPIO_PORTA | GPIO_AF | 26)
-#define PA27_PF_A19          (GPIO_PORTA | GPIO_PF | 27)
-#define PA27_AF_ETMTRACEPKT3 (GPIO_PORTA | GPIO_AF | 27)
-#define PA28_PF_A20          (GPIO_PORTA | GPIO_PF | 28)
-#define PA28_AF_ETMPIPESTAT0 (GPIO_PORTA | GPIO_AF | 28)
-#define PA29_PF_A21          (GPIO_PORTA | GPIO_PF | 29)
-#define PA29_AF_ETMPIPESTAT1 (GPIO_PORTA | GPIO_AF | 29)
-#define PA30_PF_A22          (GPIO_PORTA | GPIO_PF | 30)
-#define PA30_AF_ETMPIPESTAT2 (GPIO_PORTA | GPIO_AF | 30)
-#define PA31_PF_A23          (GPIO_PORTA | GPIO_PF | 31)
-#define PA31_AF_ETMTRACECLK  (GPIO_PORTA | GPIO_AF | 31)
-#define PB8_PF_SD_DAT0       (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
-#define PB8_AF_MS_PIO        (GPIO_PORTB | GPIO_AF | 8)
-#define PB9_PF_SD_DAT1       (GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 9)
-#define PB9_AF_MS_PI1        (GPIO_PORTB | GPIO_AF | 9)
-#define PB10_PF_SD_DAT2      (GPIO_PORTB | GPIO_PF | GPIO_PUEN  | 10)
-#define PB10_AF_MS_SCLKI     (GPIO_PORTB | GPIO_AF | 10)
-#define PB11_PF_SD_DAT3      (GPIO_PORTB | GPIO_PF | 11)
-#define PB11_AF_MS_SDIO      (GPIO_PORTB | GPIO_AF | 11)
-#define PB12_PF_SD_CLK       (GPIO_PORTB | GPIO_PF | 12)
-#define PB12_AF_MS_SCLK0     (GPIO_PORTB | GPIO_AF | 12)
-#define PB13_PF_SD_CMD       (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
-#define PB13_AF_MS_BS        (GPIO_PORTB | GPIO_AF | 13)
-#define PB14_AF_SSI_RXFS     (GPIO_PORTB | GPIO_AF | 14)
-#define PB15_AF_SSI_RXCLK    (GPIO_PORTB | GPIO_AF | 15)
-#define PB16_AF_SSI_RXDAT    (GPIO_PORTB | GPIO_IN | GPIO_AF | 16)
-#define PB17_AF_SSI_TXDAT    (GPIO_PORTB | GPIO_OUT | GPIO_AF | 17)
-#define PB18_AF_SSI_TXFS     (GPIO_PORTB | GPIO_AF | 18)
-#define PB19_AF_SSI_TXCLK    (GPIO_PORTB | GPIO_AF | 19)
-#define PB20_PF_USBD_AFE     (GPIO_PORTB | GPIO_PF | 20)
-#define PB21_PF_USBD_OE      (GPIO_PORTB | GPIO_PF | 21)
-#define PB22_PFUSBD_RCV      (GPIO_PORTB | GPIO_PF | 22)
-#define PB23_PF_USBD_SUSPND  (GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USBD_VP      (GPIO_PORTB | GPIO_PF | 24)
-#define PB25_PF_USBD_VM      (GPIO_PORTB | GPIO_PF | 25)
-#define PB26_PF_USBD_VPO     (GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBD_VMO     (GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_UART2_CTS    (GPIO_PORTB | GPIO_OUT | GPIO_PF | 28)
-#define PB29_PF_UART2_RTS    (GPIO_PORTB | GPIO_IN | GPIO_PF | 29)
-#define PB30_PF_UART2_TXD    (GPIO_PORTB | GPIO_OUT | GPIO_PF | 30)
-#define PB31_PF_UART2_RXD    (GPIO_PORTB | GPIO_IN | GPIO_PF | 31)
-#define PC3_PF_SSI_RXFS      (GPIO_PORTC | GPIO_PF | 3)
-#define PC4_PF_SSI_RXCLK     (GPIO_PORTC | GPIO_PF | 4)
-#define PC5_PF_SSI_RXDAT     (GPIO_PORTC | GPIO_IN | GPIO_PF | 5)
-#define PC6_PF_SSI_TXDAT     (GPIO_PORTC | GPIO_OUT | GPIO_PF | 6)
-#define PC7_PF_SSI_TXFS      (GPIO_PORTC | GPIO_PF | 7)
-#define PC8_PF_SSI_TXCLK     (GPIO_PORTC | GPIO_PF | 8)
-#define PC9_PF_UART1_CTS     (GPIO_PORTC | GPIO_OUT | GPIO_PF | 9)
-#define PC10_PF_UART1_RTS    (GPIO_PORTC | GPIO_IN | GPIO_PF | 10)
-#define PC11_PF_UART1_TXD    (GPIO_PORTC | GPIO_OUT | GPIO_PF | 11)
-#define PC12_PF_UART1_RXD    (GPIO_PORTC | GPIO_IN | GPIO_PF | 12)
-#define PC13_PF_SPI1_SPI_RDY (GPIO_PORTC | GPIO_PF | 13)
-#define PC14_PF_SPI1_SCLK    (GPIO_PORTC | GPIO_PF | 14)
-#define PC15_PF_SPI1_SS      (GPIO_PORTC | GPIO_PF | 15)
-#define PC16_PF_SPI1_MISO    (GPIO_PORTC | GPIO_PF | 16)
-#define PC17_PF_SPI1_MOSI    (GPIO_PORTC | GPIO_PF | 17)
-#define PC24_BIN_UART3_RI    (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 24)
-#define PC25_BIN_UART3_DSR   (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 25)
-#define PC26_AOUT_UART3_DTR  (GPIO_PORTC | GPIO_IN | 26)
-#define PC27_BIN_UART3_DCD   (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 27)
-#define PC28_BIN_UART3_CTS   (GPIO_PORTC | GPIO_OUT | GPIO_BIN | 28)
-#define PC29_AOUT_UART3_RTS  (GPIO_PORTC | GPIO_IN | 29)
-#define PC30_BIN_UART3_TX    (GPIO_PORTC | GPIO_BIN | 30)
-#define PC31_AOUT_UART3_RX   (GPIO_PORTC | GPIO_IN | 31)
-#define PD6_PF_LSCLK         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 6)
-#define PD7_PF_REV           (GPIO_PORTD | GPIO_PF | 7)
-#define PD7_AF_UART2_DTR     (GPIO_PORTD | GPIO_IN | GPIO_AF | 7)
-#define PD7_AIN_SPI2_SCLK    (GPIO_PORTD | GPIO_AIN | 7)
-#define PD8_PF_CLS           (GPIO_PORTD | GPIO_PF | 8)
-#define PD8_AF_UART2_DCD     (GPIO_PORTD | GPIO_OUT | GPIO_AF | 8)
-#define PD8_AIN_SPI2_SS      (GPIO_PORTD | GPIO_AIN | 8)
-#define PD9_PF_PS            (GPIO_PORTD | GPIO_PF | 9)
-#define PD9_AF_UART2_RI      (GPIO_PORTD | GPIO_OUT | GPIO_AF | 9)
-#define PD9_AOUT_SPI2_RXD    (GPIO_PORTD | GPIO_IN | 9)
-#define PD10_PF_SPL_SPR      (GPIO_PORTD | GPIO_OUT | GPIO_PF | 10)
-#define PD10_AF_UART2_DSR    (GPIO_PORTD | GPIO_OUT | GPIO_AF | 10)
-#define PD10_AIN_SPI2_TXD    (GPIO_PORTD | GPIO_OUT | 10)
-#define PD11_PF_CONTRAST     (GPIO_PORTD | GPIO_OUT | GPIO_PF | 11)
-#define PD12_PF_ACD_OE       (GPIO_PORTD | GPIO_OUT | GPIO_PF | 12)
-#define PD13_PF_LP_HSYNC     (GPIO_PORTD | GPIO_OUT | GPIO_PF | 13)
-#define PD14_PF_FLM_VSYNC    (GPIO_PORTD | GPIO_OUT | GPIO_PF | 14)
-#define PD15_PF_LD0          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 15)
-#define PD16_PF_LD1          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 16)
-#define PD17_PF_LD2          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 17)
-#define PD18_PF_LD3          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 18)
-#define PD19_PF_LD4          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 19)
-#define PD20_PF_LD5          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 20)
-#define PD21_PF_LD6          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 21)
-#define PD22_PF_LD7          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 22)
-#define PD23_PF_LD8          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 23)
-#define PD24_PF_LD9          (GPIO_PORTD | GPIO_OUT | GPIO_PF | 24)
-#define PD25_PF_LD10         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 25)
-#define PD26_PF_LD11         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 26)
-#define PD27_PF_LD12         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 27)
-#define PD28_PF_LD13         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 28)
-#define PD29_PF_LD14         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 29)
-#define PD30_PF_LD15         (GPIO_PORTD | GPIO_OUT | GPIO_PF | 30)
-#define PD31_PF_TMR2OUT      (GPIO_PORTD | GPIO_PF | 31)
-#define PD31_BIN_SPI2_TXD    (GPIO_PORTD | GPIO_BIN | 31)
-#endif
-
-#ifdef CONFIG_ARCH_MX2
-#define PA0_PF_USBH2_CLK	(GPIO_PORTA | GPIO_PF | 0)
-#define PA1_PF_USBH2_DIR	(GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_USBH2_DATA7	(GPIO_PORTA | GPIO_PF | 2)
-#define PA3_PF_USBH2_NXT	(GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_USBH2_STP	(GPIO_PORTA | GPIO_PF | 4)
-#define PA5_PF_LSCLK		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 5)
-#define PA6_PF_LD0		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 6)
-#define PA7_PF_LD1		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 7)
-#define PA8_PF_LD2		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 8)
-#define PA9_PF_LD3		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 9)
-#define PA10_PF_LD4		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 10)
-#define PA11_PF_LD5		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 11)
-#define PA12_PF_LD6		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 12)
-#define PA13_PF_LD7		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 13)
-#define PA14_PF_LD8		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 14)
-#define PA15_PF_LD9		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 15)
-#define PA16_PF_LD10		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 16)
-#define PA17_PF_LD11		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 17)
-#define PA18_PF_LD12		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 18)
-#define PA19_PF_LD13		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 19)
-#define PA20_PF_LD14		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 20)
-#define PA21_PF_LD15		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 21)
-#define PA22_PF_LD16		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 22)
-#define PA23_PF_LD17		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 23)
-#define PA24_PF_REV		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 24)
-#define PA25_PF_CLS		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 25)
-#define PA26_PF_PS		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 26)
-#define PA27_PF_SPL_SPR		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 27)
-#define PA28_PF_HSYNC		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 28)
-#define PA29_PF_VSYNC		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 29)
-#define PA30_PF_CONTRAST	(GPIO_PORTA | GPIO_OUT | GPIO_PF | 30)
-#define PA31_PF_OE_ACD		(GPIO_PORTA | GPIO_OUT | GPIO_PF | 31)
-#define PB4_PF_SD2_D0		(GPIO_PORTB | GPIO_PF |  4)
-#define PB5_PF_SD2_D1		(GPIO_PORTB | GPIO_PF |  5)
-#define PB6_PF_SD2_D2		(GPIO_PORTB | GPIO_PF |  6)
-#define PB7_PF_SD2_D3		(GPIO_PORTB | GPIO_PF |  7)
-#define PB8_PF_SD2_CMD		(GPIO_PORTB | GPIO_PF |  8)
-#define PB9_PF_SD2_CLK		(GPIO_PORTB | GPIO_PF |  9)
-#define PB10_PF_CSI_D0		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 10)
-#define PB10_AF_UART6_TXD	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 10)
-#define PB11_PF_CSI_D1		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 11)
-#define PB11_AF_UART6_RXD	(GPIO_PORTB | GPIO_IN  | GPIO_AF | 11)
-#define PB12_PF_CSI_D2		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 12)
-#define PB12_AF_UART6_CTS	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 12)
-#define PB13_PF_CSI_D3		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 13)
-#define PB13_AF_UART6_RTS	(GPIO_PORTB | GPIO_IN  | GPIO_AF | 13)
-#define PB14_PF_CSI_D4		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 14)
-#define PB15_PF_CSI_MCLK	(GPIO_PORTB | GPIO_OUT | GPIO_PF | 15)
-#define PB16_PF_CSI_PIXCLK	(GPIO_PORTB | GPIO_OUT | GPIO_PF | 16)
-#define PB17_PF_CSI_D5		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 17)
-#define PB18_PF_CSI_D6		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 18)
-#define PB18_AF_UART5_TXD	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 18)
-#define PB19_PF_CSI_D7		(GPIO_PORTB | GPIO_OUT | GPIO_PF | 19)
-#define PB19_AF_UART5_RXD	(GPIO_PORTB | GPIO_IN  | GPIO_AF | 19)
-#define PB20_PF_CSI_VSYNC	(GPIO_PORTB | GPIO_OUT | GPIO_PF | 20)
-#define PB20_AF_UART5_CTS	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 20)
-#define PB21_PF_CSI_HSYNC	(GPIO_PORTB | GPIO_OUT | GPIO_PF | 21)
-#define PB21_AF_UART5_RTS	(GPIO_PORTB | GPIO_IN  | GPIO_AF | 21)
-#define PB22_PF_USBH1_SUSP	(GPIO_PORTB | GPIO_PF | 22)
-#define PB23_PF_USB_PWR		(GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USB_OC_B	(GPIO_PORTB | GPIO_PF | 24)
-#define PB25_PF_USBH1_RCV	(GPIO_PORTB | GPIO_PF | 25)
-#define PB26_PF_USBH1_FS	(GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBH1_OE_B	(GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_USBH1_TXDM	(GPIO_PORTB | GPIO_PF | 28)
-#define PB29_PF_USBH1_TXDP	(GPIO_PORTB | GPIO_PF | 29)
-#define PB30_PF_USBH1_RXDM	(GPIO_PORTB | GPIO_PF | 30)
-#define PB31_PF_USBH1_RXDP	(GPIO_PORTB | GPIO_PF | 31)
-#define PB26_AF_UART4_RTS	(GPIO_PORTB | GPIO_IN  | GPIO_PF | 26)
-#define PB28_AF_UART4_TXD	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 28)
-#define PB29_AF_UART4_CTS	(GPIO_PORTB | GPIO_OUT | GPIO_AF | 29)
-#define PB31_AF_UART4_RXD	(GPIO_PORTB | GPIO_IN  | GPIO_AF | 31)
-#define PC5_PF_I2C2_SDA		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 5)
-#define PC6_PF_I2C2_SCL		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 6)
-#define PC7_PF_USBOTG_DATA5	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 7)
-#define PC8_PF_USBOTG_DATA6	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 8)
-#define PC9_PF_USBOTG_DATA0	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 9)
-#define PC10_PF_USBOTG_DATA2	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 10)
-#define PC11_PF_USBOTG_DATA1	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 11)
-#define PC12_PF_USBOTG_DATA4	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 12)
-#define PC13_PF_USBOTG_DATA3	(GPIO_PORTC | GPIO_OUT | GPIO_PF | 13)
-#define PC16_PF_SSI4_FS		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 16)
-#define PC17_PF_SSI4_RXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 17)
-#define PC18_PF_SSI4_TXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 18)
-#define PC19_PF_SSI4_CLK	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 19)
-#define PC20_PF_SSI1_FS		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 20)
-#define PC21_PF_SSI1_RXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 21)
-#define PC22_PF_SSI1_TXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 22)
-#define PC23_PF_SSI1_CLK	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 23)
-#define PC24_PF_SSI2_FS		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 24)
-#define PC25_PF_SSI2_RXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 25)
-#define PC26_PF_SSI2_TXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 26)
-#define PC27_PF_SSI2_CLK	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 27)
-#define PC28_PF_SSI3_FS		(GPIO_PORTC | GPIO_IN  | GPIO_PF | 28)
-#define PC29_PF_SSI3_RXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 29)
-#define PC30_PF_SSI3_TXD	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 30)
-#define PC31_PF_SSI3_CLK	(GPIO_PORTC | GPIO_IN  | GPIO_PF | 31)
-#define PD0_AIN_FEC_TXD0	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 0)
-#define PD1_AIN_FEC_TXD1	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 1)
-#define PD2_AIN_FEC_TXD2	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 2)
-#define PD3_AIN_FEC_TXD3	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 3)
-#define PD4_AOUT_FEC_RX_ER	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 4)
-#define PD5_AOUT_FEC_RXD1	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 5)
-#define PD6_AOUT_FEC_RXD2	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 6)
-#define PD7_AOUT_FEC_RXD3	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 7)
-#define PD8_AF_FEC_MDIO		(GPIO_PORTD | GPIO_IN | GPIO_AF | 8)
-#define PD9_AIN_FEC_MDC		(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 9)
-#define PD10_AOUT_FEC_CRS	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 10)
-#define PD11_AOUT_FEC_TX_CLK	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 11)
-#define PD12_AOUT_FEC_RXD0	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 12)
-#define PD13_AOUT_FEC_RX_DV	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 13)
-#define PD14_AOUT_FEC_CLR	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 14)
-#define PD15_AOUT_FEC_COL	(GPIO_PORTD | GPIO_IN | GPIO_AOUT | 15)
-#define PD16_AIN_FEC_TX_ER	(GPIO_PORTD | GPIO_OUT | GPIO_AIN | 16)
-#define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_OUT | GPIO_PF | 17)
-#define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_OUT | GPIO_PF | 18)
-#define PD19_AF_USBH2_DATA4	(GPIO_PORTD | GPIO_AF | 19)
-#define PD20_AF_USBH2_DATA3	(GPIO_PORTD | GPIO_AF | 20)
-#define PD21_AF_USBH2_DATA6	(GPIO_PORTD | GPIO_AF | 21)
-#define PD22_AF_USBH2_DATA0	(GPIO_PORTD | GPIO_AF | 22)
-#define PD23_AF_USBH2_DATA2	(GPIO_PORTD | GPIO_AF | 23)
-#define PD24_AF_USBH2_DATA1	(GPIO_PORTD | GPIO_AF | 24)
-#define PD25_PF_CSPI1_RDY	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 25)
-#define PD26_PF_CSPI1_SS2	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 26)
-#define PD26_AF_USBH2_DATA5     (GPIO_PORTD | GPIO_AF | 26)
-#define PD27_PF_CSPI1_SS1	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 27)
-#define PD28_PF_CSPI1_SS0	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 28)
-#define PD29_PF_CSPI1_SCLK	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 29)
-#define PD30_PF_CSPI1_MISO	(GPIO_PORTD | GPIO_IN | GPIO_PF  | 30)
-#define PD31_PF_CSPI1_MOSI	(GPIO_PORTD | GPIO_OUT | GPIO_PF  | 31)
-#define PF23_AIN_FEC_TX_EN	(GPIO_PORTF | GPIO_OUT | GPIO_AIN | 23)
-#define PE0_PF_USBOTG_NXT	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 0)
-#define PE1_PF_USBOTG_STP	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 1)
-#define PE2_PF_USBOTG_DIR	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 2)
-#define PE3_PF_UART2_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 3)
-#define PE4_PF_UART2_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 4)
-#define PE6_PF_UART2_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 6)
-#define PE7_PF_UART2_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 7)
-#define PE8_PF_UART3_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 8)
-#define PE9_PF_UART3_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 9)
-#define PE10_PF_UART3_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 10)
-#define PE11_PF_UART3_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 11)
-#define PE12_PF_UART1_TXD	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 12)
-#define PE13_PF_UART1_RXD	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 13)
-#define PE14_PF_UART1_CTS	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 14)
-#define PE15_PF_UART1_RTS	(GPIO_PORTE | GPIO_IN  | GPIO_PF | 15)
-#define PE16_AF_RTCK		(GPIO_PORTE | GPIO_OUT | GPIO_AF | 16)
-#define PE16_PF_RTCK		(GPIO_PORTE | GPIO_OUT | GPIO_PF | 16)
-#define PE18_PF_SDHC1_D0	(GPIO_PORTE | GPIO_PF | 18)
-#define PE18_AF_CSPI3_MISO	(GPIO_PORTE | GPIO_IN  | GPIO_AF | 18)
-#define PE19_PF_SDHC1_D1	(GPIO_PORTE | GPIO_PF | 19)
-#define PE20_PF_SDHC1_D2	(GPIO_PORTE | GPIO_PF | 20)
-#define PE21_PF_SDHC1_D3	(GPIO_PORTE | GPIO_PF | 21)
-#define PE21_AF_CSPI3_SS	(GPIO_PORTE | GPIO_OUT | GPIO_AF | 21)
-#define PE22_PF_SDHC1_CMD	(GPIO_PORTE | GPIO_PF | 22)
-#define PE22_AF_CSPI3_MOSI	(GPIO_PORTE | GPIO_OUT | GPIO_AF | 22)
-#define PE22_PF_SDHC1_CLK	(GPIO_PORTE | GPIO_PF | 23)
-#define PE23_AF_CSPI3_SCLK	(GPIO_PORTE | GPIO_OUT | GPIO_AF | 23)
-#define PE24_PF_USBOTG_CLK	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 24)
-#define PE25_PF_USBOTG_DATA7	(GPIO_PORTE | GPIO_OUT | GPIO_PF | 25)
-#endif
-
-/* decode irq number to use with IMR(x), ISR(x) and friends */
-#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
-
-#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
-#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
-#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
-#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
-#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
-
-#endif /* _MXC_GPIO_MX1_MX2_H */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1.h b/arch/arm/plat-mxc/include/mach/iomux-mx1.h
new file mode 100644
index 0000000..bf23305
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx1.h
@@ -0,0 +1,166 @@
+/*
+* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.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
+* 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 _MXC_IOMUX_MX1_H
+#define _MXC_IOMUX_MX1_H
+
+#ifndef GPIO_PORTA
+#error Please include mach/iomux.h
+#endif
+
+/* FIXME: This list is not completed. The correct directions are
+* missing on some (many) pins
+*/
+
+
+/* Primary GPIO pin functions */
+
+#define PA0_AIN_SPI2_CLK        (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA0_AF_ETMTRACESYNC     (GPIO_PORTA | GPIO_AF | 0)
+#define PA1_AOUT_SPI2_RXD       (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1)
+#define PA1_PF_TIN              (GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_PWM0             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 2)
+#define PA3_PF_CSI_MCLK         (GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_CSI_D0           (GPIO_PORTA | GPIO_PF | 4)
+#define PA5_PF_CSI_D1           (GPIO_PORTA | GPIO_PF | 5)
+#define PA6_PF_CSI_D2           (GPIO_PORTA | GPIO_PF | 6)
+#define PA7_PF_CSI_D3           (GPIO_PORTA | GPIO_PF | 7)
+#define PA8_PF_CSI_D4           (GPIO_PORTA | GPIO_PF | 8)
+#define PA9_PF_CSI_D5           (GPIO_PORTA | GPIO_PF | 9)
+#define PA10_PF_CSI_D6          (GPIO_PORTA | GPIO_PF | 10)
+#define PA11_PF_CSI_D7          (GPIO_PORTA | GPIO_PF | 11)
+#define PA12_PF_CSI_VSYNC       (GPIO_PORTA | GPIO_PF | 12)
+#define PA13_PF_CSI_HSYNC       (GPIO_PORTA | GPIO_PF | 13)
+#define PA14_PF_CSI_PIXCLK      (GPIO_PORTA | GPIO_PF | 14)
+#define PA15_PF_I2C_SDA         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_I2C_SCL         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_AF_ETMTRACEPKT4    (GPIO_PORTA | GPIO_AF | 17)
+#define PA17_AIN_SPI2_SS        (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA18_AF_ETMTRACEPKT5    (GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_ETMTRACEPKT6    (GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_ETMTRACEPKT7    (GPIO_PORTA | GPIO_AF | 20)
+#define PA21_PF_A0              (GPIO_PORTA | GPIO_PF | 21)
+#define PA22_PF_CS4             (GPIO_PORTA | GPIO_PF | 22)
+#define PA23_PF_CS5             (GPIO_PORTA | GPIO_PF | 23)
+#define PA24_PF_A16             (GPIO_PORTA | GPIO_PF | 24)
+#define PA24_AF_ETMTRACEPKT0    (GPIO_PORTA | GPIO_AF | 24)
+#define PA25_PF_A17             (GPIO_PORTA | GPIO_PF | 25)
+#define PA25_AF_ETMTRACEPKT1    (GPIO_PORTA | GPIO_AF | 25)
+#define PA26_PF_A18             (GPIO_PORTA | GPIO_PF | 26)
+#define PA26_AF_ETMTRACEPKT2    (GPIO_PORTA | GPIO_AF | 26)
+#define PA27_PF_A19             (GPIO_PORTA | GPIO_PF | 27)
+#define PA27_AF_ETMTRACEPKT3    (GPIO_PORTA | GPIO_AF | 27)
+#define PA28_PF_A20             (GPIO_PORTA | GPIO_PF | 28)
+#define PA28_AF_ETMPIPESTAT0    (GPIO_PORTA | GPIO_AF | 28)
+#define PA29_PF_A21             (GPIO_PORTA | GPIO_PF | 29)
+#define PA29_AF_ETMPIPESTAT1    (GPIO_PORTA | GPIO_AF | 29)
+#define PA30_PF_A22             (GPIO_PORTA | GPIO_PF | 30)
+#define PA30_AF_ETMPIPESTAT2    (GPIO_PORTA | GPIO_AF | 30)
+#define PA31_PF_A23             (GPIO_PORTA | GPIO_PF | 31)
+#define PA31_AF_ETMTRACECLK     (GPIO_PORTA | GPIO_AF | 31)
+#define PB8_PF_SD_DAT0          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
+#define PB8_AF_MS_PIO           (GPIO_PORTB | GPIO_AF | 8)
+#define PB9_PF_SD_DAT1          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9)
+#define PB9_AF_MS_PI1           (GPIO_PORTB | GPIO_AF | 9)
+#define PB10_PF_SD_DAT2         (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10)
+#define PB10_AF_MS_SCLKI        (GPIO_PORTB | GPIO_AF | 10)
+#define PB11_PF_SD_DAT3         (GPIO_PORTB | GPIO_PF | 11)
+#define PB11_AF_MS_SDIO         (GPIO_PORTB | GPIO_AF | 11)
+#define PB12_PF_SD_CLK          (GPIO_PORTB | GPIO_PF | 12)
+#define PB12_AF_MS_SCLK0        (GPIO_PORTB | GPIO_AF | 12)
+#define PB13_PF_SD_CMD          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
+#define PB13_AF_MS_BS           (GPIO_PORTB | GPIO_AF | 13)
+#define PB14_AF_SSI_RXFS        (GPIO_PORTB | GPIO_AF | 14)
+#define PB15_AF_SSI_RXCLK       (GPIO_PORTB | GPIO_AF | 15)
+#define PB16_AF_SSI_RXDAT       (GPIO_PORTB | GPIO_AF | GPIO_IN | 16)
+#define PB17_AF_SSI_TXDAT       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 17)
+#define PB18_AF_SSI_TXFS        (GPIO_PORTB | GPIO_AF | 18)
+#define PB19_AF_SSI_TXCLK       (GPIO_PORTB | GPIO_AF | 19)
+#define PB20_PF_USBD_AFE        (GPIO_PORTB | GPIO_PF | 20)
+#define PB21_PF_USBD_OE         (GPIO_PORTB | GPIO_PF | 21)
+#define PB22_PF_USBD_RCV        (GPIO_PORTB | GPIO_PF | 22)
+#define PB23_PF_USBD_SUSPND     (GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USBD_VP         (GPIO_PORTB | GPIO_PF | 24)
+#define PB25_PF_USBD_VM         (GPIO_PORTB | GPIO_PF | 25)
+#define PB26_PF_USBD_VPO        (GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBD_VMO        (GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_UART2_CTS       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 28)
+#define PB29_PF_UART2_RTS       (GPIO_PORTB | GPIO_PF | GPIO_IN | 29)
+#define PB30_PF_UART2_TXD       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 30)
+#define PB31_PF_UART2_RXD       (GPIO_PORTB | GPIO_PF | GPIO_IN | 31)
+#define PC3_PF_SSI_RXFS         (GPIO_PORTC | GPIO_PF | 3)
+#define PC4_PF_SSI_RXCLK        (GPIO_PORTC | GPIO_PF | 4)
+#define PC5_PF_SSI_RXDAT        (GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_SSI_TXDAT        (GPIO_PORTC | GPIO_PF | GPIO_OUT | 6)
+#define PC7_PF_SSI_TXFS         (GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_SSI_TXCLK        (GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_UART1_CTS        (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_UART1_RTS       (GPIO_PORTC | GPIO_PF | GPIO_IN | 10)
+#define PC11_PF_UART1_TXD       (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_UART1_RXD       (GPIO_PORTC | GPIO_PF | GPIO_IN | 12)
+#define PC13_PF_SPI1_SPI_RDY    (GPIO_PORTC | GPIO_PF | 13)
+#define PC14_PF_SPI1_SCLK       (GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_SPI1_SS         (GPIO_PORTC | GPIO_PF | 15)
+#define PC16_PF_SPI1_MISO       (GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SPI1_MOSI       (GPIO_PORTC | GPIO_PF | 17)
+#define PC24_BIN_UART3_RI       (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24)
+#define PC25_BIN_UART3_DSR      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25)
+#define PC26_AOUT_UART3_DTR     (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26)
+#define PC27_BIN_UART3_DCD      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27)
+#define PC28_BIN_UART3_CTS      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28)
+#define PC29_AOUT_UART3_RTS     (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29)
+#define PC30_BIN_UART3_TX       (GPIO_PORTC | GPIO_BIN | 30)
+#define PC31_AOUT_UART3_RX      (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31)
+#define PD6_PF_LSCLK            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 6)
+#define PD7_PF_REV              (GPIO_PORTD | GPIO_PF | 7)
+#define PD7_AF_UART2_DTR        (GPIO_PORTD | GPIO_AF | GPIO_IN | 7)
+#define PD7_AIN_SPI2_SCLK       (GPIO_PORTD | GPIO_AIN | 7)
+#define PD8_PF_CLS              (GPIO_PORTD | GPIO_PF | 8)
+#define PD8_AF_UART2_DCD        (GPIO_PORTD | GPIO_AF | GPIO_OUT | 8)
+#define PD8_AIN_SPI2_SS         (GPIO_PORTD | GPIO_AIN | 8)
+#define PD9_PF_PS               (GPIO_PORTD | GPIO_PF | 9)
+#define PD9_AF_UART2_RI         (GPIO_PORTD | GPIO_AF | GPIO_OUT | 9)
+#define PD9_AOUT_SPI2_RXD       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9)
+#define PD10_PF_SPL_SPR         (GPIO_PORTD | GPIO_PF | GPIO_OUT | 10)
+#define PD10_AF_UART2_DSR       (GPIO_PORTD | GPIO_AF | GPIO_OUT | 10)
+#define PD10_AIN_SPI2_TXD       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10)
+#define PD11_PF_CONTRAST        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 11)
+#define PD12_PF_ACD_OE          (GPIO_PORTD | GPIO_PF | GPIO_OUT | 12)
+#define PD13_PF_LP_HSYNC        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 13)
+#define PD14_PF_FLM_VSYNC       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 14)
+#define PD15_PF_LD0             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 15)
+#define PD16_PF_LD1             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 16)
+#define PD17_PF_LD2             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_LD3             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_LD4             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
+#define PD20_PF_LD5             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
+#define PD21_PF_LD6             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
+#define PD22_PF_LD7             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
+#define PD23_PF_LD8             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 23)
+#define PD24_PF_LD9             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
+#define PD25_PF_LD10            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_LD11            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_LD12            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_LD13            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_LD14            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_LD15            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 30)
+#define PD31_PF_TMR2OUT         (GPIO_PORTD | GPIO_PF | 31)
+#define PD31_BIN_SPI2_TXD       (GPIO_PORTD | GPIO_BIN | 31)
+
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx21.h b/arch/arm/plat-mxc/include/mach/iomux-mx21.h
new file mode 100644
index 0000000..63aaa97
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx21.h
@@ -0,0 +1,126 @@
+/*
+* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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
+* 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 _MXC_IOMUX_MX21_H
+#define _MXC_IOMUX_MX21_H
+
+#ifndef GPIO_PORTA
+#error Please include mach/iomux.h
+#endif
+
+
+/* Primary GPIO pin functions */
+
+#define PB22_PF_USBH1_BYP       (GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_ON        (GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_USBOTG_SDA       (GPIO_PORTC | GPIO_PF | 5)
+#define PC6_PF_USBOTG_SCL       (GPIO_PORTC | GPIO_PF | 6)
+#define PC7_PF_USBOTG_ON        (GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_USBOTG_FS        (GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_USBOTG_OE        (GPIO_PORTC | GPIO_PF | 9)
+#define PC10_PF_USBOTG_TXDM     (GPIO_PORTC | GPIO_PF | 10)
+#define PC11_PF_USBOTG_TXDP     (GPIO_PORTC | GPIO_PF | 11)
+#define PC12_PF_USBOTG_RXDM     (GPIO_PORTC | GPIO_PF | 12)
+#define PC13_PF_USBOTG_RXDP     (GPIO_PORTC | GPIO_PF | 13)
+#define PC16_PF_SAP_FS          (GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SAP_RXD         (GPIO_PORTC | GPIO_PF | 17)
+#define PC18_PF_SAP_TXD         (GPIO_PORTC | GPIO_PF | 18)
+#define PC19_PF_SAP_CLK         (GPIO_PORTC | GPIO_PF | 19)
+#define PE0_PF_TEST_WB2         (GPIO_PORTE | GPIO_PF | 0)
+#define PE1_PF_TEST_WB1         (GPIO_PORTE | GPIO_PF | 1)
+#define PE2_PF_TEST_WB0         (GPIO_PORTE | GPIO_PF | 2)
+#define PF1_PF_NFCE             (GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCLE            (GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_NFIO0            (GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_NFIO1            (GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_NFIO2            (GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_NFIO3           (GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_NFIO4           (GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_NFIO5           (GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_NFIO6           (GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_NFIO7           (GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_RES             (GPIO_PORTF | GPIO_PF | 16)
+
+/* Alternate GPIO pin functions */
+
+#define PA5_AF_BMI_CLK_CS       (GPIO_PORTA | GPIO_AF | 5)
+#define PA6_AF_BMI_D0           (GPIO_PORTA | GPIO_AF | 6)
+#define PA7_AF_BMI_D1           (GPIO_PORTA | GPIO_AF | 7)
+#define PA8_AF_BMI_D2           (GPIO_PORTA | GPIO_AF | 8)
+#define PA9_AF_BMI_D3           (GPIO_PORTA | GPIO_AF | 9)
+#define PA10_AF_BMI_D4          (GPIO_PORTA | GPIO_AF | 10)
+#define PA11_AF_BMI_D5          (GPIO_PORTA | GPIO_AF | 11)
+#define PA12_AF_BMI_D6          (GPIO_PORTA | GPIO_AF | 12)
+#define PA13_AF_BMI_D7          (GPIO_PORTA | GPIO_AF | 13)
+#define PA14_AF_BMI_D8          (GPIO_PORTA | GPIO_AF | 14)
+#define PA15_AF_BMI_D9          (GPIO_PORTA | GPIO_AF | 15)
+#define PA16_AF_BMI_D10         (GPIO_PORTA | GPIO_AF | 16)
+#define PA17_AF_BMI_D11         (GPIO_PORTA | GPIO_AF | 17)
+#define PA18_AF_BMI_D12         (GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_BMI_D13         (GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_BMI_D14         (GPIO_PORTA | GPIO_AF | 20)
+#define PA21_AF_BMI_D15         (GPIO_PORTA | GPIO_AF | 21)
+#define PA22_AF_BMI_READ_REQ    (GPIO_PORTA | GPIO_AF | 22)
+#define PA23_AF_BMI_WRITE       (GPIO_PORTA | GPIO_AF | 23)
+#define PA29_AF_BMI_RX_FULL     (GPIO_PORTA | GPIO_AF | 29)
+#define PA30_AF_BMI_READ        (GPIO_PORTA | GPIO_AF | 30)
+
+/* AIN GPIO pin functions */
+
+#define PC14_AIN_SYS_CLK        (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PD21_AIN_USBH2_FS       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21)
+#define PD22_AIN_USBH2_OE       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22)
+#define PD23_AIN_USBH2_TXDM     (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23)
+#define PD24_AIN_USBH2_TXDP     (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24)
+#define PE8_AIN_IR_TXD          (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8)
+#define PF0_AIN_PC_RST          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0)
+#define PF1_AIN_PC_CE1          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1)
+#define PF2_AIN_PC_CE2          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2)
+#define PF3_AIN_PC_POE          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3)
+#define PF4_AIN_PC_OE           (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4)
+#define PF5_AIN_PC_RW           (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5)
+
+/* BIN GPIO pin functions */
+
+#define PC14_BIN_SYS_CLK        (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+#define PD27_BIN_EXT_DMA_GRANT  (GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27)
+
+/* CIN GPIO pin functions */
+
+#define PB26_CIN_USBH1_RXDAT    (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26)
+
+/* AOUT GPIO pin functions */
+
+#define PA29_AOUT_BMI_WAIT      (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29)
+#define PD19_AOUT_USBH2_RXDM    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19)
+#define PD20_AOUT_USBH2_RXDP    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20)
+#define PD25_AOUT_EXT_DMAREQ    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25)
+#define PD26_AOUT_USBOTG_RXDAT  (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26)
+#define PE9_AOUT_IR_RXD         (GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9)
+#define PF6_AOUT_PC_BVD2        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6)
+#define PF7_AOUT_PC_BVD1        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7)
+#define PF8_AOUT_PC_VS2         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8)
+#define PF9_AOUT_PC_VS1         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9)
+#define PF10_AOUT_PC_WP         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10)
+#define PF11_AOUT_PC_READY      (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11)
+#define PF12_AOUT_PC_WAIT       (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12)
+#define PF13_AOUT_PC_CD2        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13)
+#define PF14_AOUT_PC_CD1        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14)
+
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx27.h b/arch/arm/plat-mxc/include/mach/iomux-mx27.h
new file mode 100644
index 0000000..5ac158b
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx27.h
@@ -0,0 +1,207 @@
+/*
+* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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
+* 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 _MXC_IOMUX_MX27_H
+#define _MXC_IOMUX_MX27_H
+
+#ifndef GPIO_PORTA
+#error Please include mach/iomux.h
+#endif
+
+
+/* Primary GPIO pin functions */
+
+#define PA0_PF_USBH2_CLK        (GPIO_PORTA | GPIO_PF | 0)
+#define PA1_PF_USBH2_DIR        (GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_USBH2_DATA7      (GPIO_PORTA | GPIO_PF | 2)
+#define PA3_PF_USBH2_NXT        (GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_USBH2_STP        (GPIO_PORTA | GPIO_PF | 4)
+#define PB22_PF_USBH1_SUSP      (GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_RCV       (GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_I2C2_SDA         (GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_I2C2_SCL         (GPIO_PORTC | GPIO_PF | GPIO_IN | 6)
+#define PC7_PF_USBOTG_DATA5     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
+#define PC8_PF_USBOTG_DATA6     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
+#define PC9_PF_USBOTG_DATA0     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_USBOTG_DATA2    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 10)
+#define PC11_PF_USBOTG_DATA1    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_USBOTG_DATA4    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 12)
+#define PC13_PF_USBOTG_DATA3    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 13)
+#define PC16_PF_SSI4_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 16)
+#define PC17_PF_SSI4_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 17)
+#define PC18_PF_SSI4_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 18)
+#define PC19_PF_SSI4_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 19)
+#define PC25_AF_GPT5_TIN        (GPIO_PORTC | GPIO_AF | 25)
+#define PC27_AF_GPT4_TIN        (GPIO_PORTC | GPIO_AF | 27)
+#define PD0_PF_SD3_CMD          (GPIO_PORTD | GPIO_PF | 0)
+#define PD1_PF_SD3_CLK          (GPIO_PORTD | GPIO_PF | 1)
+#define PD2_PF_ATA_DATA0        (GPIO_PORTD | GPIO_PF | 2)
+#define PD3_PF_ATA_DATA1        (GPIO_PORTD | GPIO_PF | 3)
+#define PD4_PF_ATA_DATA2        (GPIO_PORTD | GPIO_PF | 4)
+#define PD5_PF_ATA_DATA3        (GPIO_PORTD | GPIO_PF | 5)
+#define PD6_PF_ATA_DATA4        (GPIO_PORTD | GPIO_PF | 6)
+#define PD7_PF_ATA_DATA5        (GPIO_PORTD | GPIO_PF | 7)
+#define PD8_PF_ATA_DATA6        (GPIO_PORTD | GPIO_PF | 8)
+#define PD9_PF_ATA_DATA7        (GPIO_PORTD | GPIO_PF | 9)
+#define PD10_PF_ATA_DATA8       (GPIO_PORTD | GPIO_PF | 10)
+#define PD11_PF_ATA_DATA9       (GPIO_PORTD | GPIO_PF | 11)
+#define PD12_PF_ATA_DATA10      (GPIO_PORTD | GPIO_PF | 12)
+#define PD13_PF_ATA_DATA11      (GPIO_PORTD | GPIO_PF | 13)
+#define PD14_PF_ATA_DATA12      (GPIO_PORTD | GPIO_PF | 14)
+#define PD15_PF_ATA_DATA13      (GPIO_PORTD | GPIO_PF | 15)
+#define PD16_PF_ATA_DATA14      (GPIO_PORTD | GPIO_PF | 16)
+#define PE0_PF_USBOTG_NXT       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 0)
+#define PE1_PF_USBOTG_STP       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 1)
+#define PE2_PF_USBOTG_DIR       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 2)
+#define PE24_PF_USBOTG_CLK      (GPIO_PORTE | GPIO_PF | GPIO_OUT | 24)
+#define PE25_PF_USBOTG_DATA7    (GPIO_PORTE | GPIO_PF | GPIO_OUT | 25)
+#define PF1_PF_NFCLE            (GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCE             (GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_PC_POE           (GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_PC_RW            (GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_PC_IOIS16        (GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_PC_RST          (GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_PC_BVD2         (GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_PC_BVD1         (GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_PC_VS2          (GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_PC_VS1          (GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_PC_PWRON        (GPIO_PORTF | GPIO_PF | 16)
+#define PF17_PF_PC_READY        (GPIO_PORTF | GPIO_PF | 17)
+#define PF18_PF_PC_WAIT         (GPIO_PORTF | GPIO_PF | 18)
+#define PF19_PF_PC_CD2          (GPIO_PORTF | GPIO_PF | 19)
+#define PF20_PF_PC_CD1          (GPIO_PORTF | GPIO_PF | 20)
+#define PF23_PF_ATA_DATA15      (GPIO_PORTF | GPIO_PF | 23)
+
+/* Alternate GPIO pin functions */
+
+#define PB4_AF_MSHC_DATA0       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 4)
+#define PB5_AF_MSHC_DATA1       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 5)
+#define PB6_AF_MSHC_DATA2       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 6)
+#define PB7_AF_MSHC_DATA4       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 7)
+#define PB8_AF_MSHC_BS          (GPIO_PORTB | GPIO_AF | GPIO_OUT | 8)
+#define PB9_AF_MSHC_SCLK        (GPIO_PORTB | GPIO_AF | GPIO_OUT | 9)
+#define PB10_AF_UART6_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 10)
+#define PB11_AF_UART6_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 11)
+#define PB12_AF_UART6_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 12)
+#define PB13_AF_UART6_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 13)
+#define PB18_AF_UART5_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 18)
+#define PB19_AF_UART5_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 19)
+#define PB20_AF_UART5_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 20)
+#define PB21_AF_UART5_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 21)
+#define PC8_AF_FEC_MDIO         (GPIO_PORTC | GPIO_AF | GPIO_IN | 8)
+#define PC24_AF_GPT5_TOUT       (GPIO_PORTC | GPIO_AF | 24)
+#define PC26_AF_GPT4_TOUT       (GPIO_PORTC | GPIO_AF | 26)
+#define PD1_AF_ETMTRACE_PKT15   (GPIO_PORTD | GPIO_AF | 1)
+#define PD6_AF_ETMTRACE_PKT14   (GPIO_PORTD | GPIO_AF | 6)
+#define PD7_AF_ETMTRACE_PKT13   (GPIO_PORTD | GPIO_AF | 7)
+#define PD9_AF_ETMTRACE_PKT12   (GPIO_PORTD | GPIO_AF | 9)
+#define PD2_AF_SD3_D0           (GPIO_PORTD | GPIO_AF | 2)
+#define PD3_AF_SD3_D1           (GPIO_PORTD | GPIO_AF | 3)
+#define PD4_AF_SD3_D2           (GPIO_PORTD | GPIO_AF | 4)
+#define PD5_AF_SD3_D3           (GPIO_PORTD | GPIO_AF | 5)
+#define PD8_AF_FEC_MDIO         (GPIO_PORTD | GPIO_AF | GPIO_IN | 8)
+#define PD10_AF_ETMTRACE_PKT11  (GPIO_PORTD | GPIO_AF | 10)
+#define PD11_AF_ETMTRACE_PKT10  (GPIO_PORTD | GPIO_AF | 11)
+#define PD12_AF_ETMTRACE_PKT9   (GPIO_PORTD | GPIO_AF | 12)
+#define PD13_AF_ETMTRACE_PKT8   (GPIO_PORTD | GPIO_AF | 13)
+#define PD14_AF_ETMTRACE_PKT7   (GPIO_PORTD | GPIO_AF | 14)
+#define PD15_AF_ETMTRACE_PKT6   (GPIO_PORTD | GPIO_AF | 15)
+#define PD16_AF_ETMTRACE_PKT5   (GPIO_PORTD | GPIO_AF | 16)
+#define PF1_AF_ETMTRACE_PKT0    (GPIO_PORTF | GPIO_AF | 1)
+#define PF3_AF_ETMTRACE_PKT2    (GPIO_PORTF | GPIO_AF | 3)
+#define PF5_AF_ETMPIPESTAT11    (GPIO_PORTF | GPIO_AF | 5)
+#define PF7_AF_ATA_BUFFER_EN    (GPIO_PORTF | GPIO_AF | 7)
+#define PF8_AF_ATA_IORDY        (GPIO_PORTF | GPIO_AF | 8)
+#define PF9_AF_ATA_INTRQ        (GPIO_PORTF | GPIO_AF | 9)
+#define PF10_AF_ATA_RESET       (GPIO_PORTF | GPIO_AF | 10)
+#define PF11_AF_ATA_DMACK       (GPIO_PORTF | GPIO_AF | 11)
+#define PF12_AF_ATA_DMAREQ      (GPIO_PORTF | GPIO_AF | 12)
+#define PF13_AF_ATA_DA0         (GPIO_PORTF | GPIO_AF | 13)
+#define PF14_AF_ATA_DA1         (GPIO_PORTF | GPIO_AF | 14)
+#define PF15_AF_ETMTRACE_SYNC   (GPIO_PORTF | GPIO_AF | 15)
+#define PF16_AF_ATA_DA2         (GPIO_PORTF | GPIO_AF | 16)
+#define PF17_AF_ATA_CS0         (GPIO_PORTF | GPIO_AF | 17)
+#define PF18_AF_ATA_CS1         (GPIO_PORTF | GPIO_AF | 18)
+#define PF19_AF_ATA_DIOW        (GPIO_PORTF | GPIO_AF | 19)
+#define PF20_AF_ATA_DIOR        (GPIO_PORTF | GPIO_AF | 20)
+#define PF22_AF_ETMTRACE_CLK    (GPIO_PORTF | GPIO_AF | 22)
+#define PF23_AF_ETMTRACE_PKT4   (GPIO_PORTF | GPIO_AF | 23)
+
+/* AIN GPIO pin functions */
+
+#define PC14_AIN_SSI1_MCLK      (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PC15_AIN_GPT6_TOUT      (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15)
+#define PD0_AIN_FEC_TXD0        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0)
+#define PD1_AIN_FEC_TXD1        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1)
+#define PD2_AIN_FEC_TXD2        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2)
+#define PD3_AIN_FEC_TXD3        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3)
+#define PD9_AIN_FEC_MDC         (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9)
+#define PD16_AIN_FEC_TX_ER      (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16)
+#define PD27_AIN_EXT_DMA_GRANT  (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27)
+#define PF23_AIN_FEC_TX_EN      (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23)
+
+/* BIN GPIO pin functions */
+
+#define PC14_BIN_SSI2_MCLK      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+
+/* CIN GPIO pin functions */
+
+#define PD2_CIN_SLCDC1_DAT0     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2)
+#define PD3_CIN_SLCDC1_DAT1     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3)
+#define PD4_CIN_SLCDC1_DAT2     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4)
+#define PD5_CIN_SLCDC1_DAT3     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5)
+#define PD6_CIN_SLCDC1_DAT4     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6)
+#define PD7_CIN_SLCDC1_DAT5     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7)
+#define PD8_CIN_SLCDC1_DAT6     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8)
+#define PD9_CIN_SLCDC1_DAT7     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9)
+#define PD10_CIN_SLCDC1_DAT8    (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10)
+#define PD11_CIN_SLCDC1_DAT9    (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11)
+#define PD12_CIN_SLCDC1_DAT10   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12)
+#define PD13_CIN_SLCDC1_DAT11   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13)
+#define PD14_CIN_SLCDC1_DAT12   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14)
+#define PD15_CIN_SLCDC1_DAT13   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15)
+#define PD16_CIN_SLCDC1_DAT14   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16)
+#define PD23_CIN_SLCDC1_DAT15   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23)
+#define PF27_CIN_EXT_DMA_GRANT  (GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27)
+/* LCDC_TESTx on PBxx omitted, because it's not clear what they do */
+
+/* AOUT GPIO pin functions */
+
+#define PC14_AOUT_GPT6_TIN      (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14)
+#define PD4_AOUT_FEC_RX_ER      (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4)
+#define PD5_AOUT_FEC_RXD1       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5)
+#define PD6_AOUT_FEC_RXD2       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6)
+#define PD7_AOUT_FEC_RXD3       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7)
+#define PD10_AOUT_FEC_CRS       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10)
+#define PD11_AOUT_FEC_TX_CLK    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11)
+#define PD12_AOUT_FEC_RXD0      (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12)
+#define PD13_AOUT_FEC_RX_DV     (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13)
+#define PD14_AOUT_FEC_RX_CLK    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14)
+#define PD15_AOUT_FEC_COL       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15)
+
+#define PC17_BOUT_PC_IOIS16     (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17)
+#define PC18_BOUT_PC_BVD2       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18)
+#define PC19_BOUT_PC_BVD1       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19)
+#define PC28_BOUT_PC_BVD2       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28)
+#define PC29_BOUT_PC_VS1        (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29)
+#define PC30_BOUT_PC_READY      (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30)
+#define PC31_BOUT_PC_WAIT       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31)
+
+
+#endif /* _MXC_GPIO_MX1_MX2_H */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
new file mode 100644
index 0000000..fb5ae63
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
@@ -0,0 +1,237 @@
+/*
+* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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
+* 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 _MXC_IOMUX_MX2x_H
+#define _MXC_IOMUX_MX2x_H
+
+#ifndef GPIO_PORTA
+#error Please include mach/iomux.h
+#endif
+
+
+/* Primary GPIO pin functions */
+
+#define PA5_PF_LSCLK            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 5)
+#define PA6_PF_LD0              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 6)
+#define PA7_PF_LD1              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 7)
+#define PA8_PF_LD2              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 8)
+#define PA9_PF_LD3              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 9)
+#define PA10_PF_LD4             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 10)
+#define PA11_PF_LD5             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 11)
+#define PA12_PF_LD6             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 12)
+#define PA13_PF_LD7             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 13)
+#define PA14_PF_LD8             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 14)
+#define PA15_PF_LD9             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_LD10            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_PF_LD11            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 17)
+#define PA18_PF_LD12            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 18)
+#define PA19_PF_LD13            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 19)
+#define PA20_PF_LD14            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 20)
+#define PA21_PF_LD15            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 21)
+#define PA22_PF_LD16            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 22)
+#define PA23_PF_LD17            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 23)
+#define PA24_PF_REV             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 24)
+#define PA25_PF_CLS             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 25)
+#define PA26_PF_PS              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 26)
+#define PA27_PF_SPL_SPR         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 27)
+#define PA28_PF_HSYNC           (GPIO_PORTA | GPIO_PF | GPIO_OUT | 28)
+#define PA29_PF_VSYNC           (GPIO_PORTA | GPIO_PF | GPIO_OUT | 29)
+#define PA30_PF_CONTRAST        (GPIO_PORTA | GPIO_PF | GPIO_OUT | 30)
+#define PA31_PF_OE_ACD          (GPIO_PORTA | GPIO_PF | GPIO_OUT | 31)
+#define PB4_PF_SD2_D0           (GPIO_PORTB | GPIO_PF | 4)
+#define PB5_PF_SD2_D1           (GPIO_PORTB | GPIO_PF | 5)
+#define PB6_PF_SD2_D2           (GPIO_PORTB | GPIO_PF | 6)
+#define PB7_PF_SD2_D3           (GPIO_PORTB | GPIO_PF | 7)
+#define PB8_PF_SD2_CMD          (GPIO_PORTB | GPIO_PF | 8)
+#define PB9_PF_SD2_CLK          (GPIO_PORTB | GPIO_PF | 9)
+#define PB10_PF_CSI_D0          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 10)
+#define PB11_PF_CSI_D1          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 11)
+#define PB12_PF_CSI_D2          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 12)
+#define PB13_PF_CSI_D3          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 13)
+#define PB14_PF_CSI_D4          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 14)
+#define PB15_PF_CSI_MCLK        (GPIO_PORTB | GPIO_PF | GPIO_OUT | 15)
+#define PB16_PF_CSI_PIXCLK      (GPIO_PORTB | GPIO_PF | GPIO_OUT | 16)
+#define PB17_PF_CSI_D5          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 17)
+#define PB18_PF_CSI_D6          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 18)
+#define PB19_PF_CSI_D7          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 19)
+#define PB20_PF_CSI_VSYNC       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 20)
+#define PB21_PF_CSI_HSYNC       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 21)
+#define PB23_PF_USB_PWR         (GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USB_OC          (GPIO_PORTB | GPIO_PF | 24)
+#define PB26_PF_USBH1_FS        (GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBH1_OE        (GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_USBH1_TXDM      (GPIO_PORTB | GPIO_PF | 28)
+#define PB29_PF_USBH1_TXDP      (GPIO_PORTB | GPIO_PF | 29)
+#define PB30_PF_USBH1_RXDM      (GPIO_PORTB | GPIO_PF | 30)
+#define PB31_PF_USBH1_RXDP      (GPIO_PORTB | GPIO_PF | 31)
+#define PC14_PF_TOUT            (GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_TIN             (GPIO_PORTC | GPIO_PF | 15)
+#define PC20_PF_SSI1_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 20)
+#define PC21_PF_SSI1_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 21)
+#define PC22_PF_SSI1_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 22)
+#define PC23_PF_SSI1_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 23)
+#define PC24_PF_SSI2_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 24)
+#define PC25_PF_SSI2_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 25)
+#define PC26_PF_SSI2_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 26)
+#define PC27_PF_SSI2_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 27)
+#define PC28_PF_SSI3_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 28)
+#define PC29_PF_SSI3_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 29)
+#define PC30_PF_SSI3_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 30)
+#define PC31_PF_SSI3_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
+#define PD17_PF_I2C_DATA        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_I2C_CLK         (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_CSPI2_SS2       (GPIO_PORTD | GPIO_PF | 19)
+#define PD20_PF_CSPI2_SS1       (GPIO_PORTD | GPIO_PF | 20)
+#define PD21_PF_CSPI2_SS0       (GPIO_PORTD | GPIO_PF | 21)
+#define PD22_PF_CSPI2_SCLK      (GPIO_PORTD | GPIO_PF | 22)
+#define PD23_PF_CSPI2_MISO      (GPIO_PORTD | GPIO_PF | 23)
+#define PD24_PF_CSPI2_MOSI      (GPIO_PORTD | GPIO_PF | 24)
+#define PD25_PF_CSPI1_RDY       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_CSPI1_SS2       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_CSPI1_SS1       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_CSPI1_SS0       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_CSPI1_SCLK      (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_CSPI1_MISO      (GPIO_PORTD | GPIO_PF | GPIO_IN | 30)
+#define PD31_PF_CSPI1_MOSI      (GPIO_PORTD | GPIO_PF | GPIO_OUT | 31)
+#define PE3_PF_UART2_CTS        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 3)
+#define PE4_PF_UART2_RTS        (GPIO_PORTE | GPIO_PF | GPIO_IN | 4)
+#define PE5_PF_PWMO             (GPIO_PORTE | GPIO_PF | 5)
+#define PE6_PF_UART2_TXD        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 6)
+#define PE7_PF_UART2_RXD        (GPIO_PORTE | GPIO_PF | GPIO_IN | 7)
+#define PE8_PF_UART3_TXD        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 8)
+#define PE9_PF_UART3_RXD        (GPIO_PORTE | GPIO_PF | GPIO_IN | 9)
+#define PE10_PF_UART3_CTS       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 10)
+#define PE11_PF_UART3_RTS       (GPIO_PORTE | GPIO_PF | GPIO_IN | 11)
+#define PE12_PF_UART1_TXD       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 12)
+#define PE13_PF_UART1_RXD       (GPIO_PORTE | GPIO_PF | GPIO_IN | 13)
+#define PE14_PF_UART1_CTS       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 14)
+#define PE15_PF_UART1_RTS       (GPIO_PORTE | GPIO_PF | GPIO_IN | 15)
+#define PE16_PF_RTCK            (GPIO_PORTE | GPIO_PF | GPIO_OUT | 16)
+#define PE17_PF_RESET_OUT       (GPIO_PORTE | GPIO_PF | 17)
+#define PE18_PF_SD1_D0          (GPIO_PORTE | GPIO_PF | 18)
+#define PE19_PF_SD1_D1          (GPIO_PORTE | GPIO_PF | 19)
+#define PE20_PF_SD1_D2          (GPIO_PORTE | GPIO_PF | 20)
+#define PE21_PF_SD1_D3          (GPIO_PORTE | GPIO_PF | 21)
+#define PE22_PF_SD1_CMD         (GPIO_PORTE | GPIO_PF | 22)
+#define PE23_PF_SD1_CLK         (GPIO_PORTE | GPIO_PF | 23)
+#define PF0_PF_NRFB             (GPIO_PORTF | GPIO_PF | 0)
+#define PF2_PF_NFWP             (GPIO_PORTF | GPIO_PF | 2)
+#define PF4_PF_NFALE            (GPIO_PORTF | GPIO_PF | 4)
+#define PF5_PF_NFRE             (GPIO_PORTF | GPIO_PF | 5)
+#define PF6_PF_NFWE             (GPIO_PORTF | GPIO_PF | 6)
+#define PF15_PF_CLKO            (GPIO_PORTF | GPIO_PF | 15)
+#define PF21_PF_CS4             (GPIO_PORTF | GPIO_PF | 21)
+#define PF22_PF_CS5             (GPIO_PORTF | GPIO_PF | 22)
+
+/* Alternate GPIO pin functions */
+
+#define PB26_AF_UART4_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 26)
+#define PB28_AF_UART4_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 28)
+#define PB29_AF_UART4_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 29)
+#define PB31_AF_UART4_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 31)
+#define PC28_AF_SLCDC2_D0       (GPIO_PORTC | GPIO_AF | 28)
+#define PC29_AF_SLCDC2_RS       (GPIO_PORTC | GPIO_AF | 29)
+#define PC30_AF_SLCDC2_CS       (GPIO_PORTC | GPIO_AF | 30)
+#define PC31_AF_SLCDC2_CLK      (GPIO_PORTC | GPIO_AF | 31)
+#define PD19_AF_USBH2_DATA4     (GPIO_PORTD | GPIO_AF | 19)
+#define PD20_AF_USBH2_DATA3     (GPIO_PORTD | GPIO_AF | 20)
+#define PD21_AF_USBH2_DATA6     (GPIO_PORTD | GPIO_AF | 21)
+#define PD22_AF_USBH2_DATA0     (GPIO_PORTD | GPIO_AF | 22)
+#define PD23_AF_USBH2_DATA2     (GPIO_PORTD | GPIO_AF | 23)
+#define PD24_AF_USBH2_DATA1     (GPIO_PORTD | GPIO_AF | 24)
+#define PD26_AF_USBH2_DATA5     (GPIO_PORTD | GPIO_AF | 26)
+#define PE0_AF_KP_COL6          (GPIO_PORTE | GPIO_AF | 0)
+#define PE1_AF_KP_ROW6          (GPIO_PORTE | GPIO_AF | 1)
+#define PE2_AF_KP_ROW7          (GPIO_PORTE | GPIO_AF | 2)
+#define PE3_AF_KP_COL7          (GPIO_PORTE | GPIO_AF | 3)
+#define PE4_AF_KP_ROW7          (GPIO_PORTE | GPIO_AF | 4)
+#define PE6_AF_KP_COL6          (GPIO_PORTE | GPIO_AF | 6)
+#define PE7_AF_KP_ROW6          (GPIO_PORTE | GPIO_AF | 7)
+#define PE16_AF_OWIRE           (GPIO_PORTE | GPIO_AF | 16)
+#define PE18_AF_CSPI3_MISO      (GPIO_PORTE | GPIO_AF | GPIO_IN | 18)
+#define PE21_AF_CSPI3_SS        (GPIO_PORTE | GPIO_AF | GPIO_OUT | 21)
+#define PE22_AF_CSPI3_MOSI      (GPIO_PORTE | GPIO_AF | GPIO_OUT | 22)
+#define PE23_AF_CSPI3_SCLK      (GPIO_PORTE | GPIO_AF | GPIO_OUT | 23)
+
+/* AIN GPIO pin functions */
+
+#define PA6_AIN_SLCDC1_DAT0     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6)
+#define PA7_AIN_SLCDC1_DAT1     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7)
+#define PA8_AIN_SLCDC1_DAT2     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8)
+#define PA0_AIN_SLCDC1_DAT3     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA11_AIN_SLCDC1_DAT5    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11)
+#define PA13_AIN_SLCDC1_DAT7    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13)
+#define PA15_AIN_SLCDC1_DAT9    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15)
+#define PA17_AIN_SLCDC1_DAT11   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA19_AIN_SLCDC1_DAT13   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19)
+#define PA21_AIN_SLCDC1_DAT15   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21)
+#define PA22_AIN_EXT_DMAGRANT   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22)
+#define PA24_AIN_SLCDC1_D0      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24)
+#define PA25_AIN_SLCDC1_RS      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25)
+#define PA26_AIN_SLCDC1_CS      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26)
+#define PA27_AIN_SLCDC1_CLK     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27)
+#define PB6_AIN_SLCDC1_D0       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6)
+#define PB7_AIN_SLCDC1_RS       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7)
+#define PB8_AIN_SLCDC1_CS       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8)
+#define PB9_AIN_SLCDC1_CLK      (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9)
+#define PB25_AIN_SLCDC1_DAT0    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25)
+#define PB26_AIN_SLCDC1_DAT1    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26)
+#define PB27_AIN_SLCDC1_DAT2    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27)
+#define PB28_AIN_SLCDC1_DAT3    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28)
+#define PB29_AIN_SLCDC1_DAT4    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29)
+#define PB30_AIN_SLCDC1_DAT5    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30)
+#define PB31_AIN_SLCDC1_DAT6    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31)
+#define PC5_AIN_SLCDC1_DAT7     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5)
+#define PC6_AIN_SLCDC1_DAT8     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6)
+#define PC7_AIN_SLCDC1_DAT9     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7)
+#define PC8_AIN_SLCDC1_DAT10    (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8)
+#define PC9_AIN_SLCDC1_DAT11    (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9)
+#define PC10_AIN_SLCDC1_DAT12   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10)
+#define PC11_AIN_SLCDC1_DAT13   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11)
+#define PC12_AIN_SLCDC1_DAT14   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12)
+#define PC13_AIN_SLCDC1_DAT15   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13)
+#define PE5_AIN_PC_SPKOUT       (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5)
+
+/* BIN GPIO pin functions */
+
+#define PE5_BIN_TOUT2           (GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5)
+
+/* CIN GPIO pin functions */
+
+#define PA14_CIN_SLCDC1_DAT0    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14)
+#define PA15_CIN_SLCDC1_DAT1    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15)
+#define PA16_CIN_SLCDC1_DAT2    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16)
+#define PA17_CIN_SLCDC1_DAT3    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17)
+#define PA18_CIN_SLCDC1_DAT4    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18)
+#define PA19_CIN_SLCDC1_DAT5    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19)
+#define PA20_CIN_SLCDC1_DAT6    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20)
+#define PA21_CIN_SLCDC1_DAT7    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21)
+#define PB30_CIN_UART4_CTS      (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30)
+#define PE5_CIN_TOUT3           (GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5)
+
+/* AOUT GPIO pin functions */
+
+#define PB29_AOUT_UART4_RXD     (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29)
+#define PB31_AOUT_UART4_RTS     (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31)
+#define PC8_AOUT_USBOTG_TXR_INT (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 8)
+#define PC15_AOUT_WKGD          (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15)
+#define PF21_AOUT_DTACK         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21)
+
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index c9198c0..ab838cf 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -92,7 +92,7 @@
 	MUX_EXTDMAREQ2_MBX_SEL		= 1 << 15,
 	MUX_TAMPER_DETECT_EN		= 1 << 16,
 	MUX_PGP_USB_4WIRE		= 1 << 17,
-	MUX_PGB_USB_COMMON		= 1 << 18,
+	MUX_PGP_USB_COMMON		= 1 << 18,
 	MUX_SDHC_MEMSTICK1		= 1 << 19,
 	MUX_SDHC_MEMSTICK2		= 1 << 20,
 	MUX_PGP_SPLL_BYP		= 1 << 21,
@@ -109,21 +109,44 @@
 };
 
 /*
- * This function enables/disables the general purpose function for a particular
- * signal.
+ * setups a single pin:
+ * 	- reserves the pin so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ * 	- if the pin is configured as a GPIO, we claim it throug kernel gpiolib
  */
-void iomux_config_gpr(enum iomux_gp_func , bool);
+int mxc_iomux_setup_pin(const unsigned int pin, const char *label);
+/*
+ * setups mutliple pins
+ * convenient way to call the above function with tables
+ */
+int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+		const char *label);
 
 /*
- * set the mode for a IOMUX pin.
+ * releases a single pin:
+ * 	- make it available for a future use by another driver
+ * 	- frees the GPIO if the pin was configured as GPIO
+ * 	- DOES NOT reconfigure the IOMUX in its reset state
  */
-int mxc_iomux_mode(unsigned int);
+void mxc_iomux_release_pin(const unsigned int pin);
+/*
+ * releases multiple pins
+ * convenvient way to call the above function with tables
+ */
+void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count);
 
 /*
  * This function enables/disables the general purpose function for a particular
  * signal.
  */
-void mxc_iomux_set_gpr(enum iomux_gp_func, bool);
+void mxc_iomux_set_gpr(enum iomux_gp_func, bool en);
+
+/*
+ * This function only configures the iomux hardware.
+ * It is called by the setup functions and should not be called directly anymore.
+ * It is here visible for backward compatibility
+ */
+int mxc_iomux_mode(unsigned int pin_mode);
 
 #define IOMUX_PADNUM_MASK	0x1ff
 #define IOMUX_GPIONUM_SHIFT	9
@@ -144,6 +167,11 @@
 	MXC_GPIO_IRQ_START)
 
 /*
+ * The number of gpio devices among the pads
+ */
+#define GPIO_PORT_MAX 3
+
+/*
  * This enumeration is constructed based on the Section
  * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated
  * value is constructed based on the rules described above.
@@ -480,6 +508,9 @@
 	MX31_PIN_CAPTURE	= IOMUX_PIN( 7,   327),
 };
 
+#define PIN_MAX 327
+#define NB_PORTS 12 /* NB_PINS/32, we chose 32 pins per "PORT" */
+
 /*
  * Convenience values for use with mxc_iomux_mode()
  *
@@ -507,7 +538,9 @@
 #define MX31_PIN_CSPI1_SS1__SS1		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSPI1_SS2__SS2		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSPI2_MOSI__MOSI	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_MOSI__SCL	IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CSPI2_MISO__MISO	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI2_MISO__SDA	IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CSPI2_SCLK__SCLK	IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSPI2_SPI_RDY__SPI_RDY	IOMUX_MODE(MX31_PIN_CSPI2_SPI_RDY, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSPI2_SS0__SS0		IOMUX_MODE(MX31_PIN_CSPI2_SS0, IOMUX_CONFIG_FUNC)
@@ -525,6 +558,33 @@
 #define MX31_PIN_SD1_DATA0__SD1_DATA0	IOMUX_MODE(MX31_PIN_SD1_DATA0, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SD1_CLK__SD1_CLK	IOMUX_MODE(MX31_PIN_SD1_CLK, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SD1_CMD__SD1_CMD	IOMUX_MODE(MX31_PIN_SD1_CMD, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD0__LD0		IOMUX_MODE(MX31_PIN_LD0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD1__LD1		IOMUX_MODE(MX31_PIN_LD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD2__LD2		IOMUX_MODE(MX31_PIN_LD2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD3__LD3		IOMUX_MODE(MX31_PIN_LD3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD4__LD4		IOMUX_MODE(MX31_PIN_LD4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD5__LD5		IOMUX_MODE(MX31_PIN_LD5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD6__LD6		IOMUX_MODE(MX31_PIN_LD6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD7__LD7		IOMUX_MODE(MX31_PIN_LD7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD8__LD8		IOMUX_MODE(MX31_PIN_LD8, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD9__LD9		IOMUX_MODE(MX31_PIN_LD9, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD10__LD10		IOMUX_MODE(MX31_PIN_LD10, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD11__LD11		IOMUX_MODE(MX31_PIN_LD11, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD12__LD12		IOMUX_MODE(MX31_PIN_LD12, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD13__LD13		IOMUX_MODE(MX31_PIN_LD13, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD14__LD14		IOMUX_MODE(MX31_PIN_LD14, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD15__LD15		IOMUX_MODE(MX31_PIN_LD15, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD16__LD16		IOMUX_MODE(MX31_PIN_LD16, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LD17__LD17		IOMUX_MODE(MX31_PIN_LD17, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_VSYNC3__VSYNC3		IOMUX_MODE(MX31_PIN_VSYNC3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_HSYNC__HSYNC		IOMUX_MODE(MX31_PIN_HSYNC, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_FPSHIFT__FPSHIFT	IOMUX_MODE(MX31_PIN_FPSHIFT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DRDY0__DRDY0		IOMUX_MODE(MX31_PIN_DRDY0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_REV__D3_REV		IOMUX_MODE(MX31_PIN_D3_REV, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CONTRAST__CONTRAST	IOMUX_MODE(MX31_PIN_CONTRAST, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_SPL__D3_SPL		IOMUX_MODE(MX31_PIN_D3_SPL, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_D3_CLS__D3_CLS		IOMUX_MODE(MX31_PIN_D3_CLS, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_LCS0__GPI03_23		IOMUX_MODE(MX31_PIN_LCS0, IOMUX_CONFIG_GPIO)
 
 /*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0
  * cspi1_ss1*/
diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h
new file mode 100644
index 0000000..171f8ad
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux.h
@@ -0,0 +1,127 @@
+/*
+* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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
+* 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 _MXC_IOMUX_H
+#define _MXC_IOMUX_H
+
+/*
+*  GPIO Module and I/O Multiplexer
+*  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+*/
+#define VA_GPIO_BASE	IO_ADDRESS(GPIO_BASE_ADDR)
+#define MXC_DDIR(x)    (0x00 + ((x) << 8))
+#define MXC_OCR1(x)    (0x04 + ((x) << 8))
+#define MXC_OCR2(x)    (0x08 + ((x) << 8))
+#define MXC_ICONFA1(x) (0x0c + ((x) << 8))
+#define MXC_ICONFA2(x) (0x10 + ((x) << 8))
+#define MXC_ICONFB1(x) (0x14 + ((x) << 8))
+#define MXC_ICONFB2(x) (0x18 + ((x) << 8))
+#define MXC_DR(x)      (0x1c + ((x) << 8))
+#define MXC_GIUS(x)    (0x20 + ((x) << 8))
+#define MXC_SSR(x)     (0x24 + ((x) << 8))
+#define MXC_ICR1(x)    (0x28 + ((x) << 8))
+#define MXC_ICR2(x)    (0x2c + ((x) << 8))
+#define MXC_IMR(x)     (0x30 + ((x) << 8))
+#define MXC_ISR(x)     (0x34 + ((x) << 8))
+#define MXC_GPR(x)     (0x38 + ((x) << 8))
+#define MXC_SWR(x)     (0x3c + ((x) << 8))
+#define MXC_PUEN(x)    (0x40 + ((x) << 8))
+
+#ifdef CONFIG_ARCH_MX1
+# define GPIO_PORT_MAX  3
+#endif
+#ifdef CONFIG_ARCH_MX2
+# define GPIO_PORT_MAX  5
+#endif
+
+#ifndef GPIO_PORT_MAX
+# error "GPIO config port count unknown!"
+#endif
+
+#define GPIO_PIN_MASK 0x1f
+
+#define GPIO_PORT_SHIFT 5
+#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
+#define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
+#define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
+#define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
+#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
+#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
+
+#define GPIO_OUT   (1 << 8)
+#define GPIO_IN    (0 << 8)
+#define GPIO_PUEN  (1 << 9)
+
+#define GPIO_PF    (1 << 10)
+#define GPIO_AF    (1 << 11)
+
+#define GPIO_OCR_SHIFT 12
+#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT)
+#define GPIO_AIN   (0 << GPIO_OCR_SHIFT)
+#define GPIO_BIN   (1 << GPIO_OCR_SHIFT)
+#define GPIO_CIN   (2 << GPIO_OCR_SHIFT)
+#define GPIO_GPIO  (3 << GPIO_OCR_SHIFT)
+
+#define GPIO_AOUT_SHIFT 14
+#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT     (0 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_0   (2 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_1   (3 << GPIO_AOUT_SHIFT)
+
+#define GPIO_BOUT_SHIFT 16
+#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT      (0 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_ISR  (1 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_0    (2 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_1    (3 << GPIO_BOUT_SHIFT)
+
+
+#ifdef CONFIG_ARCH_MX1
+#include <mach/iomux-mx1.h>
+#endif
+#ifdef CONFIG_ARCH_MX2
+#include <mach/iomux-mx2x.h>
+#ifdef CONFIG_MACH_MX21
+#include <mach/iomux-mx21.h>
+#endif
+#ifdef CONFIG_MACH_MX27
+#include <mach/iomux-mx27.h>
+#endif
+#endif
+
+
+/* decode irq number to use with IMR(x), ISR(x) and friends */
+#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
+
+#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
+#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
+#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
+#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
+#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
+
+
+extern void mxc_gpio_mode(int gpio_mode);
+extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+	const char *label);
+extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index 0b80839..e0783e6 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -14,7 +14,12 @@
 #if defined CONFIG_ARCH_MX1
 #define PHYS_OFFSET		UL(0x08000000)
 #elif defined CONFIG_ARCH_MX2
+#ifdef CONFIG_MACH_MX21
+#define PHYS_OFFSET		UL(0xC0000000)
+#endif
+#ifdef CONFIG_MACH_MX27
 #define PHYS_OFFSET		UL(0xA0000000)
+#endif
 #elif defined CONFIG_ARCH_MX3
 #define PHYS_OFFSET		UL(0x80000000)
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
new file mode 100644
index 0000000..e8c4cf5
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Holger Schurig, hs4233@mail.mn-solutions.de
+ *
+ * This contains i.MX21-specific hardware definitions. For those
+ * hardware pieces that are common between i.MX21 and i.MX27, have a
+ * look at mx2x.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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __ASM_ARCH_MXC_MX21_H__
+#define __ASM_ARCH_MXC_MX21_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+
+/* Memory regions and CS */
+#define SDRAM_BASE_ADDR         0xC0000000
+#define CSD1_BASE_ADDR          0xC4000000
+
+#define CS0_BASE_ADDR           0xC8000000
+#define CS1_BASE_ADDR           0xCC000000
+#define CS2_BASE_ADDR           0xD0000000
+#define CS3_BASE_ADDR           0xD1000000
+#define CS4_BASE_ADDR           0xD2000000
+#define CS5_BASE_ADDR           0xDD000000
+#define PCMCIA_MEM_BASE_ADDR    0xD4000000
+
+/* NAND, SDRAM, WEIM etc controllers */
+#define X_MEMC_BASE_ADDR        0xDF000000
+#define X_MEMC_BASE_ADDR_VIRT   0xF4200000
+#define X_MEMC_SIZE             SZ_256K
+
+#define SDRAMC_BASE_ADDR        (X_MEMC_BASE_ADDR + 0x0000)
+#define EIM_BASE_ADDR           (X_MEMC_BASE_ADDR + 0x1000)
+#define PCMCIA_CTL_BASE_ADDR    (X_MEMC_BASE_ADDR + 0x2000)
+#define NFC_BASE_ADDR           (X_MEMC_BASE_ADDR + 0x3000)
+
+#define IRAM_BASE_ADDR          0xFFFFE800	/* internal ram */
+
+/* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */
+#define ARCH_NR_GPIOS		(6*32 + 16)
+
+/* fixed interrupt numbers */
+#define MXC_INT_USBCTRL         58
+#define MXC_INT_USBCTRL         58
+#define MXC_INT_USBMNP          57
+#define MXC_INT_USBFUNC         56
+#define MXC_INT_USBHOST         55
+#define MXC_INT_USBDMA          54
+#define MXC_INT_USBWKUP         53
+#define MXC_INT_EMMADEC         50
+#define MXC_INT_EMMAENC         49
+#define MXC_INT_BMI             30
+#define MXC_INT_FIRI            9
+
+/* fixed DMA request numbers */
+#define DMA_REQ_BMI_RX          29
+#define DMA_REQ_BMI_TX          28
+#define DMA_REQ_FIRI_RX         4
+
+#endif /* __ASM_ARCH_MXC_MX21_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index 0313be7..6e93f2c 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -2,6 +2,10 @@
  * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
  *
+ * This contains i.MX27-specific hardware definitions. For those
+ * hardware pieces that are common between i.MX21 and i.MX27, have a
+ * look at mx2x.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
@@ -27,35 +31,6 @@
 /* IRAM */
 #define IRAM_BASE_ADDR          0xFFFF4C00	/* internal ram */
 
-/* Register offests */
-#define AIPI_BASE_ADDR          0x10000000
-#define AIPI_BASE_ADDR_VIRT     0xF4000000
-#define AIPI_SIZE               SZ_1M
-
-#define DMA_BASE_ADDR           (AIPI_BASE_ADDR + 0x01000)
-#define WDOG_BASE_ADDR          (AIPI_BASE_ADDR + 0x02000)
-#define GPT1_BASE_ADDR          (AIPI_BASE_ADDR + 0x03000)
-#define GPT2_BASE_ADDR          (AIPI_BASE_ADDR + 0x04000)
-#define GPT3_BASE_ADDR          (AIPI_BASE_ADDR + 0x05000)
-#define PWM_BASE_ADDR           (AIPI_BASE_ADDR + 0x06000)
-#define RTC_BASE_ADDR           (AIPI_BASE_ADDR + 0x07000)
-#define KPP_BASE_ADDR           (AIPI_BASE_ADDR + 0x08000)
-#define OWIRE_BASE_ADDR         (AIPI_BASE_ADDR + 0x09000)
-#define UART1_BASE_ADDR         (AIPI_BASE_ADDR + 0x0A000)
-#define UART2_BASE_ADDR         (AIPI_BASE_ADDR + 0x0B000)
-#define UART3_BASE_ADDR         (AIPI_BASE_ADDR + 0x0C000)
-#define UART4_BASE_ADDR         (AIPI_BASE_ADDR + 0x0D000)
-#define CSPI1_BASE_ADDR         (AIPI_BASE_ADDR + 0x0E000)
-#define CSPI2_BASE_ADDR         (AIPI_BASE_ADDR + 0x0F000)
-#define SSI1_BASE_ADDR          (AIPI_BASE_ADDR + 0x10000)
-#define SSI2_BASE_ADDR          (AIPI_BASE_ADDR + 0x11000)
-#define I2C_BASE_ADDR           (AIPI_BASE_ADDR + 0x12000)
-#define SDHC1_BASE_ADDR         (AIPI_BASE_ADDR + 0x13000)
-#define SDHC2_BASE_ADDR         (AIPI_BASE_ADDR + 0x14000)
-#define GPIO_BASE_ADDR          (AIPI_BASE_ADDR + 0x15000)
-#define AUDMUX_BASE_ADDR        (AIPI_BASE_ADDR + 0x16000)
-
-#define CSPI3_BASE_ADDR         (AIPI_BASE_ADDR + 0x17000)
 #define MSHC_BASE_ADDR          (AIPI_BASE_ADDR + 0x18000)
 #define GPT5_BASE_ADDR          (AIPI_BASE_ADDR + 0x19000)
 #define GPT4_BASE_ADDR          (AIPI_BASE_ADDR + 0x1A000)
@@ -64,41 +39,33 @@
 #define I2C2_BASE_ADDR          (AIPI_BASE_ADDR + 0x1D000)
 #define SDHC3_BASE_ADDR         (AIPI_BASE_ADDR + 0x1E000)
 #define GPT6_BASE_ADDR          (AIPI_BASE_ADDR + 0x1F000)
-
-#define LCDC_BASE_ADDR          (AIPI_BASE_ADDR + 0x21000)
-#define SLCDC_BASE_ADDR         (AIPI_BASE_ADDR + 0x22000)
 #define VPU_BASE_ADDR           (AIPI_BASE_ADDR + 0x23000)
-#define USBOTG_BASE_ADDR        (AIPI_BASE_ADDR + 0x24000)
-/* for mx27*/
 #define OTG_BASE_ADDR           USBOTG_BASE_ADDR
 #define SAHARA_BASE_ADDR        (AIPI_BASE_ADDR + 0x25000)
-#define EMMA_PP_BASE_ADDR       (AIPI_BASE_ADDR + 0x26000)
-#define EMMA_PRP_BASE_ADDR      (AIPI_BASE_ADDR + 0x26400)
-#define CCM_BASE_ADDR           (AIPI_BASE_ADDR + 0x27000)
-#define SYSCTRL_BASE_ADDR       (AIPI_BASE_ADDR + 0x27800)
 #define IIM_BASE_ADDR           (AIPI_BASE_ADDR + 0x28000)
-
 #define RTIC_BASE_ADDR          (AIPI_BASE_ADDR + 0x2A000)
 #define FEC_BASE_ADDR           (AIPI_BASE_ADDR + 0x2B000)
 #define SCC_BASE_ADDR           (AIPI_BASE_ADDR + 0x2C000)
 #define ETB_BASE_ADDR           (AIPI_BASE_ADDR + 0x3B000)
 #define ETB_RAM_BASE_ADDR       (AIPI_BASE_ADDR + 0x3C000)
 
-#define JAM_BASE_ADDR           (AIPI_BASE_ADDR + 0x3E000)
-#define MAX_BASE_ADDR           (AIPI_BASE_ADDR + 0x3F000)
-
-/* ROMP and AVIC */
+/* ROM patch */
 #define ROMP_BASE_ADDR          0x10041000
 
-#define AVIC_BASE_ADDR          0x10040000
-
-#define SAHB1_BASE_ADDR         0x80000000
-#define SAHB1_BASE_ADDR_VIRT    0xF4100000
-#define SAHB1_SIZE              SZ_1M
-
-#define CSI_BASE_ADDR           (SAHB1_BASE_ADDR + 0x0000)
 #define ATA_BASE_ADDR           (SAHB1_BASE_ADDR + 0x1000)
 
+/* Memory regions and CS */
+#define SDRAM_BASE_ADDR         0xA0000000
+#define CSD1_BASE_ADDR          0xB0000000
+
+#define CS0_BASE_ADDR           0xC0000000
+#define CS1_BASE_ADDR           0xC8000000
+#define CS2_BASE_ADDR           0xD0000000
+#define CS3_BASE_ADDR           0xD2000000
+#define CS4_BASE_ADDR           0xD4000000
+#define CS5_BASE_ADDR           0xD6000000
+#define PCMCIA_MEM_BASE_ADDR    0xDC000000
+
 /* NAND, SDRAM, WEIM, M3IF, EMI controllers */
 #define X_MEMC_BASE_ADDR        0xD8000000
 #define X_MEMC_BASE_ADDR_VIRT   0xF4200000
@@ -110,56 +77,9 @@
 #define M3IF_BASE_ADDR          (X_MEMC_BASE_ADDR + 0x3000)
 #define PCMCIA_CTL_BASE_ADDR    (X_MEMC_BASE_ADDR + 0x4000)
 
-/* Memory regions and CS */
-#define SDRAM_BASE_ADDR		0xA0000000
-#define CSD1_BASE_ADDR		0xB0000000
-
-#define CS0_BASE_ADDR           0xC0000000
-#define CS1_BASE_ADDR           0xC8000000
-#define CS2_BASE_ADDR           0xD0000000
-#define CS3_BASE_ADDR           0xD2000000
-#define CS4_BASE_ADDR           0xD4000000
-#define CS5_BASE_ADDR           0xD6000000
-#define PCMCIA_MEM_BASE_ADDR    0xDC000000
-
-/*
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-#define IO_ADDRESS(x)   \
-	(void __iomem *) \
-	(((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \
-		AIPI_IO_ADDRESS(x) : \
-	((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \
-		SAHB1_IO_ADDRESS(x) : \
-	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \
-		X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF)
-
-/* define the address mapping macros: in physical address order */
-#define AIPI_IO_ADDRESS(x)  \
-	(((x) - AIPI_BASE_ADDR) + AIPI_BASE_ADDR_VIRT)
-
-#define AVIC_IO_ADDRESS(x)	AIPI_IO_ADDRESS(x)
-
-#define SAHB1_IO_ADDRESS(x)  \
-	(((x) - SAHB1_BASE_ADDR) + SAHB1_BASE_ADDR_VIRT)
-
-#define CS4_IO_ADDRESS(x)  \
-	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
-
-#define X_MEMC_IO_ADDRESS(x)  \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-#define PCMCIA_IO_ADDRESS(x) \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-/* fixed interrput numbers */
+/* fixed interrupt numbers */
 #define MXC_INT_CCM		63
 #define MXC_INT_IIM		62
-#define MXC_INT_LCDC		61
-#define MXC_INT_SLCDC		60
 #define MXC_INT_SAHARA		59
 #define MXC_INT_SCC_SCM		58
 #define MXC_INT_SCC_SMN		57
@@ -167,54 +87,12 @@
 #define MXC_INT_USB2		55
 #define MXC_INT_USB1		54
 #define MXC_INT_VPU		53
-#define MXC_INT_EMMAPP		52
-#define MXC_INT_EMMAPRP		51
 #define MXC_INT_FEC		50
 #define MXC_INT_UART5		49
 #define MXC_INT_UART6		48
-#define MXC_INT_DMACH15		47
-#define MXC_INT_DMACH14		46
-#define MXC_INT_DMACH13		45
-#define MXC_INT_DMACH12		44
-#define MXC_INT_DMACH11		43
-#define MXC_INT_DMACH10		42
-#define MXC_INT_DMACH9		41
-#define MXC_INT_DMACH8		40
-#define MXC_INT_DMACH7		39
-#define MXC_INT_DMACH6		38
-#define MXC_INT_DMACH5		37
-#define MXC_INT_DMACH4		36
-#define MXC_INT_DMACH3		35
-#define MXC_INT_DMACH2		34
-#define MXC_INT_DMACH1		33
-#define MXC_INT_DMACH0		32
-#define MXC_INT_CSI		31
 #define MXC_INT_ATA		30
-#define MXC_INT_NANDFC		29
-#define MXC_INT_PCMCIA		28
-#define MXC_INT_WDOG		27
-#define MXC_INT_GPT1		26
-#define MXC_INT_GPT2		25
-#define MXC_INT_GPT3		24
-#define MXC_INT_GPT		INT_GPT1
-#define MXC_INT_PWM		23
-#define MXC_INT_RTC		22
-#define MXC_INT_KPP		21
-#define MXC_INT_UART1		20
-#define MXC_INT_UART2		19
-#define MXC_INT_UART3		18
-#define MXC_INT_UART4		17
-#define MXC_INT_CSPI1		16
-#define MXC_INT_CSPI2		15
-#define MXC_INT_SSI1		14
-#define MXC_INT_SSI2		13
-#define MXC_INT_I2C		12
-#define MXC_INT_SDHC1		11
-#define MXC_INT_SDHC2		10
 #define MXC_INT_SDHC3		9
-#define MXC_INT_GPIO		8
 #define MXC_INT_SDHC		7
-#define MXC_INT_CSPI3		6
 #define MXC_INT_RTIC		5
 #define MXC_INT_GPT4		4
 #define MXC_INT_GPT5		3
@@ -228,36 +106,9 @@
 #define DMA_REQ_UART6_TX        34
 #define DMA_REQ_UART5_RX        33
 #define DMA_REQ_UART5_TX        32
-#define DMA_REQ_CSI_RX          31
-#define DMA_REQ_CSI_STAT        30
 #define DMA_REQ_ATA_RCV         29
 #define DMA_REQ_ATA_TX          28
-#define DMA_REQ_UART1_TX        27
-#define DMA_REQ_UART1_RX        26
-#define DMA_REQ_UART2_TX        25
-#define DMA_REQ_UART2_RX        24
-#define DMA_REQ_UART3_TX        23
-#define DMA_REQ_UART3_RX        22
-#define DMA_REQ_UART4_TX        21
-#define DMA_REQ_UART4_RX        20
-#define DMA_REQ_CSPI1_TX        19
-#define DMA_REQ_CSPI1_RX        18
-#define DMA_REQ_CSPI2_TX        17
-#define DMA_REQ_CSPI2_RX        16
-#define DMA_REQ_SSI1_TX1        15
-#define DMA_REQ_SSI1_RX1        14
-#define DMA_REQ_SSI1_TX0        13
-#define DMA_REQ_SSI1_RX0        12
-#define DMA_REQ_SSI2_TX1        11
-#define DMA_REQ_SSI2_RX1        10
-#define DMA_REQ_SSI2_TX0        9
-#define DMA_REQ_SSI2_RX0        8
-#define DMA_REQ_SDHC1           7
-#define DMA_REQ_SDHC2           6
 #define DMA_REQ_MSHC            4
-#define DMA_REQ_EXT             3
-#define DMA_REQ_CSPI3_TX        2
-#define DMA_REQ_CSPI3_RX        1
 
 /* silicon revisions specific to i.MX27 */
 #define CHIP_REV_1_0		0x00
@@ -267,25 +118,8 @@
 extern int mx27_revision(void);
 #endif
 
-/* gpio and gpio based interrupt handling */
-#define GPIO_DR		 	0x1C
-#define GPIO_GDIR	 	0x00
-#define GPIO_PSR	 	0x24
-#define GPIO_ICR1	 	0x28
-#define GPIO_ICR2	 	0x2C
-#define GPIO_IMR	 	0x30
-#define GPIO_ISR	 	0x34
-#define GPIO_INT_LOW_LEV	0x3
-#define GPIO_INT_HIGH_LEV	0x2
-#define GPIO_INT_RISE_EDGE 	0x0
-#define GPIO_INT_FALL_EDGE	0x1
-#define GPIO_INT_NONE		0x4
-
 /* Mandatory defines used globally */
 
-/* this is an i.MX27 CPU */
-#define cpu_is_mx27()		(1)
-
 /* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */
 #define ARCH_NR_GPIOS		(192 + 16)
 
diff --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h
new file mode 100644
index 0000000..fc40d3a
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx2x.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This contains hardware definitions that are common between i.MX21 and
+ * i.MX27.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 __ASM_ARCH_MXC_MX2x_H__
+#define __ASM_ARCH_MXC_MX2x_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+/* The following addresses are common between i.MX21 and i.MX27 */
+
+/* Register offests */
+#define AIPI_BASE_ADDR          0x10000000
+#define AIPI_BASE_ADDR_VIRT     0xF4000000
+#define AIPI_SIZE               SZ_1M
+
+#define DMA_BASE_ADDR           (AIPI_BASE_ADDR + 0x01000)
+#define WDOG_BASE_ADDR          (AIPI_BASE_ADDR + 0x02000)
+#define GPT1_BASE_ADDR          (AIPI_BASE_ADDR + 0x03000)
+#define GPT2_BASE_ADDR          (AIPI_BASE_ADDR + 0x04000)
+#define GPT3_BASE_ADDR          (AIPI_BASE_ADDR + 0x05000)
+#define PWM_BASE_ADDR           (AIPI_BASE_ADDR + 0x06000)
+#define RTC_BASE_ADDR           (AIPI_BASE_ADDR + 0x07000)
+#define KPP_BASE_ADDR           (AIPI_BASE_ADDR + 0x08000)
+#define OWIRE_BASE_ADDR         (AIPI_BASE_ADDR + 0x09000)
+#define UART1_BASE_ADDR         (AIPI_BASE_ADDR + 0x0A000)
+#define UART2_BASE_ADDR         (AIPI_BASE_ADDR + 0x0B000)
+#define UART3_BASE_ADDR         (AIPI_BASE_ADDR + 0x0C000)
+#define UART4_BASE_ADDR         (AIPI_BASE_ADDR + 0x0D000)
+#define CSPI1_BASE_ADDR         (AIPI_BASE_ADDR + 0x0E000)
+#define CSPI2_BASE_ADDR         (AIPI_BASE_ADDR + 0x0F000)
+#define SSI1_BASE_ADDR          (AIPI_BASE_ADDR + 0x10000)
+#define SSI2_BASE_ADDR          (AIPI_BASE_ADDR + 0x11000)
+#define I2C_BASE_ADDR           (AIPI_BASE_ADDR + 0x12000)
+#define SDHC1_BASE_ADDR         (AIPI_BASE_ADDR + 0x13000)
+#define SDHC2_BASE_ADDR         (AIPI_BASE_ADDR + 0x14000)
+#define GPIO_BASE_ADDR          (AIPI_BASE_ADDR + 0x15000)
+#define AUDMUX_BASE_ADDR        (AIPI_BASE_ADDR + 0x16000)
+#define CSPI3_BASE_ADDR         (AIPI_BASE_ADDR + 0x17000)
+#define LCDC_BASE_ADDR          (AIPI_BASE_ADDR + 0x21000)
+#define SLCDC_BASE_ADDR         (AIPI_BASE_ADDR + 0x22000)
+#define USBOTG_BASE_ADDR        (AIPI_BASE_ADDR + 0x24000)
+#define EMMA_PP_BASE_ADDR       (AIPI_BASE_ADDR + 0x26000)
+#define EMMA_PRP_BASE_ADDR      (AIPI_BASE_ADDR + 0x26400)
+#define CCM_BASE_ADDR           (AIPI_BASE_ADDR + 0x27000)
+#define SYSCTRL_BASE_ADDR       (AIPI_BASE_ADDR + 0x27800)
+#define JAM_BASE_ADDR           (AIPI_BASE_ADDR + 0x3E000)
+#define MAX_BASE_ADDR           (AIPI_BASE_ADDR + 0x3F000)
+
+#define AVIC_BASE_ADDR          0x10040000
+
+#define SAHB1_BASE_ADDR         0x80000000
+#define SAHB1_BASE_ADDR_VIRT    0xF4100000
+#define SAHB1_SIZE              SZ_1M
+
+#define CSI_BASE_ADDR           (SAHB1_BASE_ADDR + 0x0000)
+
+/*
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0xDEADBEEF
+ */
+#define IO_ADDRESS(x)   \
+	(void __force __iomem *) \
+	(((x >= AIPI_BASE_ADDR) && (x < (AIPI_BASE_ADDR + AIPI_SIZE))) ? \
+		AIPI_IO_ADDRESS(x) : \
+	((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \
+		SAHB1_IO_ADDRESS(x) : \
+	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \
+		X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF)
+
+/* define the address mapping macros: in physical address order */
+#define AIPI_IO_ADDRESS(x)  \
+	(((x) - AIPI_BASE_ADDR) + AIPI_BASE_ADDR_VIRT)
+
+#define AVIC_IO_ADDRESS(x)	AIPI_IO_ADDRESS(x)
+
+#define SAHB1_IO_ADDRESS(x)  \
+	(((x) - SAHB1_BASE_ADDR) + SAHB1_BASE_ADDR_VIRT)
+
+#define CS4_IO_ADDRESS(x)  \
+	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
+
+#define X_MEMC_IO_ADDRESS(x)  \
+	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+#define PCMCIA_IO_ADDRESS(x) \
+	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+/* fixed interrupt numbers */
+#define MXC_INT_LCDC		61
+#define MXC_INT_SLCDC		60
+#define MXC_INT_EMMAPP		52
+#define MXC_INT_EMMAPRP		51
+#define MXC_INT_DMACH15		47
+#define MXC_INT_DMACH14		46
+#define MXC_INT_DMACH13		45
+#define MXC_INT_DMACH12		44
+#define MXC_INT_DMACH11		43
+#define MXC_INT_DMACH10		42
+#define MXC_INT_DMACH9		41
+#define MXC_INT_DMACH8		40
+#define MXC_INT_DMACH7		39
+#define MXC_INT_DMACH6		38
+#define MXC_INT_DMACH5		37
+#define MXC_INT_DMACH4		36
+#define MXC_INT_DMACH3		35
+#define MXC_INT_DMACH2		34
+#define MXC_INT_DMACH1		33
+#define MXC_INT_DMACH0		32
+#define MXC_INT_CSI		31
+#define MXC_INT_NANDFC		29
+#define MXC_INT_PCMCIA		28
+#define MXC_INT_WDOG		27
+#define MXC_INT_GPT1		26
+#define MXC_INT_GPT2		25
+#define MXC_INT_GPT3		24
+#define MXC_INT_GPT		INT_GPT1
+#define MXC_INT_PWM		23
+#define MXC_INT_RTC		22
+#define MXC_INT_KPP		21
+#define MXC_INT_UART1		20
+#define MXC_INT_UART2		19
+#define MXC_INT_UART3		18
+#define MXC_INT_UART4		17
+#define MXC_INT_CSPI1		16
+#define MXC_INT_CSPI2		15
+#define MXC_INT_SSI1		14
+#define MXC_INT_SSI2		13
+#define MXC_INT_I2C		12
+#define MXC_INT_SDHC1		11
+#define MXC_INT_SDHC2		10
+#define MXC_INT_GPIO		8
+#define MXC_INT_CSPI3		6
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR		 	0x1C
+#define GPIO_GDIR	 	0x00
+#define GPIO_PSR	 	0x24
+#define GPIO_ICR1	 	0x28
+#define GPIO_ICR2	 	0x2C
+#define GPIO_IMR	 	0x30
+#define GPIO_ISR	 	0x34
+#define GPIO_INT_LOW_LEV	0x3
+#define GPIO_INT_HIGH_LEV	0x2
+#define GPIO_INT_RISE_EDGE 	0x0
+#define GPIO_INT_FALL_EDGE	0x1
+#define GPIO_INT_NONE		0x4
+
+/* fixed DMA request numbers */
+#define DMA_REQ_CSI_RX          31
+#define DMA_REQ_CSI_STAT        30
+#define DMA_REQ_UART1_TX        27
+#define DMA_REQ_UART1_RX        26
+#define DMA_REQ_UART2_TX        25
+#define DMA_REQ_UART2_RX        24
+#define DMA_REQ_UART3_TX        23
+#define DMA_REQ_UART3_RX        22
+#define DMA_REQ_UART4_TX        21
+#define DMA_REQ_UART4_RX        20
+#define DMA_REQ_CSPI1_TX        19
+#define DMA_REQ_CSPI1_RX        18
+#define DMA_REQ_CSPI2_TX        17
+#define DMA_REQ_CSPI2_RX        16
+#define DMA_REQ_SSI1_TX1        15
+#define DMA_REQ_SSI1_RX1        14
+#define DMA_REQ_SSI1_TX0        13
+#define DMA_REQ_SSI1_RX0        12
+#define DMA_REQ_SSI2_TX1        11
+#define DMA_REQ_SSI2_RX1        10
+#define DMA_REQ_SSI2_TX0        9
+#define DMA_REQ_SSI2_RX0        8
+#define DMA_REQ_SDHC1           7
+#define DMA_REQ_SDHC2           6
+#define DMA_REQ_EXT             3
+#define DMA_REQ_CSPI3_TX        2
+#define DMA_REQ_CSPI3_RX        1
+
+#endif /* __ASM_ARCH_MXC_MX2x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index de02665..0b06941b 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -1,360 +1,45 @@
 /*
- * 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.
- */
-
-#ifndef __ASM_ARCH_MXC_MX31_H__
-#define __ASM_ARCH_MXC_MX31_H__
-
-#ifndef __ASM_ARCH_MXC_HARDWARE_H__
-#error "Do not include directly."
-#endif
-
-/*
- * MX31 memory map:
- *
- * Virt		Phys		Size	What
- * ---------------------------------------------------------------------------
- * F8000000	1FFC0000	16K	IRAM
- * F9000000	30000000	256M	L2CC
- * FC000000	43F00000	1M	AIPS 1
- * FC100000	50000000	1M	SPBA
- * FC200000	53F00000	1M	AIPS 2
- * FC500000	60000000	128M	ROMPATCH
- * FC400000	68000000	128M	AVIC
- *         	70000000	256M	IPU (MAX M2)
- *         	80000000	256M	CSD0 SDRAM/DDR
- *         	90000000	256M	CSD1 SDRAM/DDR
- *         	A0000000	128M	CS0 Flash
- *         	A8000000	128M	CS1 Flash
- *         	B0000000	32M	CS2
- *         	B2000000	32M	CS3
- * F4000000	B4000000	32M	CS4
- *         	B6000000	32M	CS5
- * FC320000	B8000000	64K	NAND, SDRAM, WEIM, M3IF, EMI controllers
- *         	C0000000	64M	PCMCIA/CF
- */
-
-#define CS0_BASE_ADDR		0xA0000000
-#define CS1_BASE_ADDR		0xA8000000
-#define CS2_BASE_ADDR		0xB0000000
-#define CS3_BASE_ADDR		0xB2000000
-
-#define CS4_BASE_ADDR		0xB4000000
-#define CS4_BASE_ADDR_VIRT	0xF4000000
-#define CS4_SIZE		SZ_32M
-
-#define CS5_BASE_ADDR		0xB6000000
-#define PCMCIA_MEM_BASE_ADDR	0xBC000000
-
-/*
  * IRAM
  */
-#define IRAM_BASE_ADDR		0x1FFC0000	/* internal ram */
-#define IRAM_BASE_ADDR_VIRT	0xF8000000
-#define IRAM_SIZE		SZ_16K
+#define MX31_IRAM_BASE_ADDR		0x1FFC0000	/* internal ram */
+#define MX31_IRAM_SIZE			SZ_16K
 
-/*
- * L2CC
- */
-#define L2CC_BASE_ADDR		0x30000000
-#define L2CC_BASE_ADDR_VIRT	0xF9000000
-#define L2CC_SIZE		SZ_1M
-
-/*
- * AIPS 1
- */
-#define AIPS1_BASE_ADDR		0x43F00000
-#define AIPS1_BASE_ADDR_VIRT	0xFC000000
-#define AIPS1_SIZE		SZ_1M
-
-#define MAX_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00004000)
-#define EVTMON_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00008000)
-#define CLKCTL_BASE_ADDR	(AIPS1_BASE_ADDR + 0x0000C000)
-#define ETB_SLOT4_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00010000)
-#define ETB_SLOT5_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00014000)
-#define ECT_CTIO_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00018000)
-#define I2C_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00080000)
-#define I2C3_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00084000)
 #define OTG_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00088000)
 #define ATA_BASE_ADDR		(AIPS1_BASE_ADDR + 0x0008C000)
-#define UART1_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x00090000)
-#define UART2_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x00094000)
-#define I2C2_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00098000)
-#define OWIRE_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x0009C000)
-#define SSI1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A0000)
-#define CSPI1_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x000A4000)
-#define KPP_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A8000)
-#define IOMUXC_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000AC000)
 #define UART4_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x000B0000)
 #define UART5_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x000B4000)
-#define ECT_IP1_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000B8000)
-#define ECT_IP2_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000BC000)
-
-/*
- * SPBA global module enabled #0
- */
-#define SPBA0_BASE_ADDR 	0x50000000
-#define SPBA0_BASE_ADDR_VIRT	0xFC100000
-#define SPBA0_SIZE		SZ_1M
 
 #define MMC_SDHC1_BASE_ADDR	(SPBA0_BASE_ADDR + 0x00004000)
 #define MMC_SDHC2_BASE_ADDR	(SPBA0_BASE_ADDR + 0x00008000)
-#define UART3_BASE_ADDR 	(SPBA0_BASE_ADDR + 0x0000C000)
-#define CSPI2_BASE_ADDR 	(SPBA0_BASE_ADDR + 0x00010000)
-#define SSI2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00014000)
 #define SIM1_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00018000)
 #define IIM_BASE_ADDR		(SPBA0_BASE_ADDR + 0x0001C000)
-#define ATA_DMA_BASE_ADDR	(SPBA0_BASE_ADDR + 0x00020000)
-#define MSHC1_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00024000)
-#define MSHC2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00024000)
-#define SPBA_CTRL_BASE_ADDR	(SPBA0_BASE_ADDR + 0x0003C000)
 
-/*
- * AIPS 2
- */
-#define AIPS2_BASE_ADDR		0x53F00000
-#define AIPS2_BASE_ADDR_VIRT	0xFC200000
-#define AIPS2_SIZE		SZ_1M
-#define CCM_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00080000)
 #define CSPI3_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00084000)
 #define FIRI_BASE_ADDR		(AIPS2_BASE_ADDR + 0x0008C000)
-#define GPT1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00090000)
-#define EPIT1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00094000)
-#define EPIT2_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00098000)
-#define GPIO3_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000A4000)
-#define SCC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000AC000)
 #define SCM_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000AE000)
 #define SMN_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000AF000)
-#define RNGA_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000B0000)
-#define IPU_CTRL_BASE_ADDR	(AIPS2_BASE_ADDR + 0x000C0000)
-#define AUDMUX_BASE_ADDR	(AIPS2_BASE_ADDR + 0x000C4000)
 #define MPEG4_ENC_BASE_ADDR	(AIPS2_BASE_ADDR + 0x000C8000)
-#define GPIO1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000CC000)
-#define GPIO2_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D0000)
-#define SDMA_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D4000)
-#define RTC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D8000)
-#define WDOG_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000DC000)
-#define PWM_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000E0000)
-#define RTIC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000EC000)
 
-/*
- * ROMP and AVIC
- */
-#define ROMP_BASE_ADDR		0x60000000
-#define ROMP_BASE_ADDR_VIRT	0xFC500000
-#define ROMP_SIZE		SZ_1M
+#define MX31_NFC_BASE_ADDR	(X_MEMC_BASE_ADDR + 0x0000)
 
-#define AVIC_BASE_ADDR		0x68000000
-#define AVIC_BASE_ADDR_VIRT	0xFC400000
-#define AVIC_SIZE		SZ_1M
-
-/*
- * NAND, SDRAM, WEIM, M3IF, EMI controllers
- */
-#define X_MEMC_BASE_ADDR	0xB8000000
-#define X_MEMC_BASE_ADDR_VIRT	0xFC320000
-#define X_MEMC_SIZE		SZ_64K
-
-#define NFC_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x0000)
-#define ESDCTL_BASE_ADDR	(X_MEMC_BASE_ADDR + 0x1000)
-#define WEIM_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x2000)
-#define M3IF_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x3000)
-#define EMI_CTL_BASE_ADDR	(X_MEMC_BASE_ADDR + 0x4000)
-#define PCMCIA_CTL_BASE_ADDR	EMI_CTL_BASE_ADDR
-
-/*
- * Memory regions and CS
- */
-#define IPU_MEM_BASE_ADDR	0x70000000
-#define CSD0_BASE_ADDR		0x80000000
-#define CSD1_BASE_ADDR		0x90000000
-#define CS0_BASE_ADDR		0xA0000000
-#define CS1_BASE_ADDR		0xA8000000
-#define CS2_BASE_ADDR		0xB0000000
-#define CS3_BASE_ADDR		0xB2000000
-
-#define CS4_BASE_ADDR		0xB4000000
-#define CS4_BASE_ADDR_VIRT	0xF4000000
-#define CS4_SIZE		SZ_32M
-
-#define CS5_BASE_ADDR		0xB6000000
-#define PCMCIA_MEM_BASE_ADDR	0xBC000000
-
-/*!
- * This macro defines the physical to virtual address mapping for all the
- * peripheral modules. It is used by passing in the physical address as x
- * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
- */
-#define IO_ADDRESS(x)   \
-	(void __iomem *) \
-	(((x >= IRAM_BASE_ADDR) && (x < (IRAM_BASE_ADDR + IRAM_SIZE))) ? IRAM_IO_ADDRESS(x):\
-	((x >= L2CC_BASE_ADDR) && (x < (L2CC_BASE_ADDR + L2CC_SIZE))) ? L2CC_IO_ADDRESS(x):\
-	((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\
-	((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\
-	((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\
-	((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\
-	((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\
-	((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\
-	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\
-	0xDEADBEEF)
-
-/*
- * define the address mapping macros: in physical address order
- */
-
-#define IRAM_IO_ADDRESS(x)  \
-	(((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT)
-
-#define L2CC_IO_ADDRESS(x)  \
-	(((x) - L2CC_BASE_ADDR) + L2CC_BASE_ADDR_VIRT)
-
-#define AIPS1_IO_ADDRESS(x)  \
-	(((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
-
-#define SPBA0_IO_ADDRESS(x)  \
-	(((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
-
-#define AIPS2_IO_ADDRESS(x)  \
-	(((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
-
-#define ROMP_IO_ADDRESS(x)  \
-	(((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT)
-
-#define AVIC_IO_ADDRESS(x)  \
-	(((x) - AVIC_BASE_ADDR) + AVIC_BASE_ADDR_VIRT)
-
-#define CS4_IO_ADDRESS(x)  \
-	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
-
-#define X_MEMC_IO_ADDRESS(x)  \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-#define PCMCIA_IO_ADDRESS(x) \
-	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
-
-/*
- * Interrupt numbers
- */
-#define MXC_INT_PEN_ADS7843	0
-#define MXC_INT_RESV1		1
-#define MXC_INT_CS8900A		2
-#define MXC_INT_I2C3		3
-#define MXC_INT_I2C2		4
 #define MXC_INT_MPEG4_ENCODER	5
-#define MXC_INT_RTIC		6
 #define MXC_INT_FIRI		7
-#define MXC_INT_MMC_SDHC2	8
+#define MX31_INT_MMC_SDHC2	8
 #define MXC_INT_MMC_SDHC1	9
-#define MXC_INT_I2C		10
-#define MXC_INT_SSI2		11
-#define MXC_INT_SSI1		12
-#define MXC_INT_CSPI2		13
-#define MXC_INT_CSPI1		14
-#define MXC_INT_ATA		15
+#define MX31_INT_SSI2		11
+#define MX31_INT_SSI1		12
 #define MXC_INT_MBX		16
 #define MXC_INT_CSPI3		17
-#define MXC_INT_UART3		18
-#define MXC_INT_IIM		19
 #define MXC_INT_SIM2		20
 #define MXC_INT_SIM1		21
-#define MXC_INT_RNGA		22
-#define MXC_INT_EVTMON		23
-#define MXC_INT_KPP		24
-#define MXC_INT_RTC		25
-#define MXC_INT_PWM		26
-#define MXC_INT_EPIT2		27
-#define MXC_INT_EPIT1		28
-#define MXC_INT_GPT		29
-#define MXC_INT_RESV30		30
-#define MXC_INT_RESV31		31
-#define MXC_INT_UART2		32
-#define MXC_INT_NANDFC		33
-#define MXC_INT_SDMA		34
+#define MXC_INT_CCM_DVFS	31
 #define MXC_INT_USB1		35
 #define MXC_INT_USB2		36
 #define MXC_INT_USB3		37
 #define MXC_INT_USB4		38
-#define MXC_INT_MSHC1		39
 #define MXC_INT_MSHC2		40
-#define MXC_INT_IPU_ERR		41
-#define MXC_INT_IPU_SYN		42
-#define MXC_INT_RESV43		43
-#define MXC_INT_RESV44		44
-#define MXC_INT_UART1		45
 #define MXC_INT_UART4		46
 #define MXC_INT_UART5		47
-#define MXC_INT_ECT		48
-#define MXC_INT_SCC_SCM		49
-#define MXC_INT_SCC_SMN		50
-#define MXC_INT_GPIO2		51
-#define MXC_INT_GPIO1		52
 #define MXC_INT_CCM		53
 #define MXC_INT_PCMCIA		54
-#define MXC_INT_WDOG		55
-#define MXC_INT_GPIO3		56
-#define MXC_INT_RESV57		57
-#define MXC_INT_EXT_POWER	58
-#define MXC_INT_EXT_TEMPER	59
-#define MXC_INT_EXT_SENSOR60	60
-#define MXC_INT_EXT_SENSOR61	61
-#define MXC_INT_EXT_WDOG	62
-#define MXC_INT_EXT_TV		63
 
-#define PROD_SIGNATURE		0x1	/* For MX31 */
-
-/* silicon revisions specific to i.MX31 */
-#define CHIP_REV_1_0		0x10
-#define CHIP_REV_1_1		0x11
-#define CHIP_REV_1_2		0x12
-#define CHIP_REV_1_3		0x13
-#define CHIP_REV_2_0		0x20
-#define CHIP_REV_2_1		0x21
-#define CHIP_REV_2_2		0x22
-#define CHIP_REV_2_3		0x23
-#define CHIP_REV_3_0		0x30
-#define CHIP_REV_3_1		0x31
-#define CHIP_REV_3_2		0x32
-
-#define SYSTEM_REV_MIN		CHIP_REV_1_0
-#define SYSTEM_REV_NUM		3
-
-/* gpio and gpio based interrupt handling */
-#define GPIO_DR		 	0x00
-#define GPIO_GDIR	 	0x04
-#define GPIO_PSR	 	0x08
-#define GPIO_ICR1	 	0x0C
-#define GPIO_ICR2	 	0x10
-#define GPIO_IMR	 	0x14
-#define GPIO_ISR	 	0x18
-#define GPIO_INT_LOW_LEV	0x0
-#define GPIO_INT_HIGH_LEV	0x1
-#define GPIO_INT_RISE_EDGE	0x2
-#define GPIO_INT_FALL_EDGE	0x3
-#define GPIO_INT_NONE		0x4
-
-/* Mandatory defines used globally */
-
-/* this CPU supports up to 96 GPIOs */
-#define ARCH_NR_GPIOS		96
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-
-/* this is a i.MX31 CPU */
-#define cpu_is_mx31()		(1)
-
-extern unsigned int system_rev;
-
-static inline int mx31_revision(void)
-{
-	return system_rev;
-}
-#endif
-
-#endif /*  __ASM_ARCH_MXC_MX31_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
new file mode 100644
index 0000000..6465fef
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -0,0 +1,29 @@
+/*
+ * IRAM
+ */
+#define MX35_IRAM_BASE_ADDR		0x10000000	/* internal ram */
+#define MX35_IRAM_SIZE		SZ_128K
+
+#define MXC_FEC_BASE_ADDR	0x50038000
+#define MX35_NFC_BASE_ADDR	0xBB000000
+
+/*
+ * Interrupt numbers
+ */
+#define MXC_INT_OWIRE		2
+#define MX35_INT_MMC_SDHC1	7
+#define MXC_INT_MMC_SDHC2	8
+#define MXC_INT_MMC_SDHC3	9
+#define MX35_INT_SSI1		11
+#define MX35_INT_SSI2		12
+#define MXC_INT_GPU2D		16
+#define MXC_INT_ASRC		17
+#define MXC_INT_USBHS		35
+#define MXC_INT_USBOTG		37
+#define MXC_INT_ESAI		40
+#define MXC_INT_CAN1		43
+#define MXC_INT_CAN2		44
+#define MXC_INT_MLB		46
+#define MXC_INT_SPDIF		47
+#define MXC_INT_FEC		57
+
diff --git a/arch/arm/plat-mxc/include/mach/mx3_camera.h b/arch/arm/plat-mxc/include/mach/mx3_camera.h
new file mode 100644
index 0000000..36d7ff2
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx3_camera.h
@@ -0,0 +1,52 @@
+/*
+ * mx3_camera.h - i.MX3x camera driver header file
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.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 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.
+ */
+
+#ifndef _MX3_CAMERA_H_
+#define _MX3_CAMERA_H_
+
+#include <linux/device.h>
+
+#define MX3_CAMERA_CLK_SRC	1
+#define MX3_CAMERA_EXT_VSYNC	2
+#define MX3_CAMERA_DP		4
+#define MX3_CAMERA_PCP		8
+#define MX3_CAMERA_HSP		0x10
+#define MX3_CAMERA_VSP		0x20
+#define MX3_CAMERA_DATAWIDTH_4	0x40
+#define MX3_CAMERA_DATAWIDTH_8	0x80
+#define MX3_CAMERA_DATAWIDTH_10	0x100
+#define MX3_CAMERA_DATAWIDTH_15	0x200
+
+#define MX3_CAMERA_DATAWIDTH_MASK (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | \
+				   MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15)
+
+/**
+ * struct mx3_camera_pdata - i.MX3x camera platform data
+ * @flags:	MX3_CAMERA_* flags
+ * @mclk_10khz:	master clock frequency in 10kHz units
+ * @dma_dev:	IPU DMA device to match against in channel allocation
+ */
+struct mx3_camera_pdata {
+	unsigned long flags;
+	unsigned long mclk_10khz;
+	struct device *dma_dev;
+};
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx3fb.h b/arch/arm/plat-mxc/include/mach/mx3fb.h
index e391a76..ac24c5c 100644
--- a/arch/arm/plat-mxc/include/mach/mx3fb.h
+++ b/arch/arm/plat-mxc/include/mach/mx3fb.h
@@ -14,25 +14,25 @@
 #include <linux/fb.h>
 
 /* Proprietary FB_SYNC_ flags */
-#define FB_SYNC_OE_ACT_HIGH    0x80000000
-#define FB_SYNC_CLK_INVERT     0x40000000
-#define FB_SYNC_DATA_INVERT    0x20000000
-#define FB_SYNC_CLK_IDLE_EN    0x10000000
-#define FB_SYNC_SHARP_MODE     0x08000000
-#define FB_SYNC_SWAP_RGB       0x04000000
-#define FB_SYNC_CLK_SEL_EN     0x02000000
+#define FB_SYNC_OE_ACT_HIGH	0x80000000
+#define FB_SYNC_CLK_INVERT	0x40000000
+#define FB_SYNC_DATA_INVERT	0x20000000
+#define FB_SYNC_CLK_IDLE_EN	0x10000000
+#define FB_SYNC_SHARP_MODE	0x08000000
+#define FB_SYNC_SWAP_RGB	0x04000000
+#define FB_SYNC_CLK_SEL_EN	0x02000000
 
 /**
  * struct mx3fb_platform_data - mx3fb platform data
  *
- * @dma_dev:   pointer to the dma-device, used for dma-slave connection
- * @mode:      pointer to a platform-provided per mxc_register_fb() videomode
+ * @dma_dev:	pointer to the dma-device, used for dma-slave connection
+ * @mode:	pointer to a platform-provided per mxc_register_fb() videomode
  */
 struct mx3fb_platform_data {
-       struct device                   *dma_dev;
-       const char                      *name;
-       const struct fb_videomode       *mode;
-       int                             num_modes;
+	struct device			*dma_dev;
+	const char			*name;
+	const struct fb_videomode	*mode;
+	int				num_modes;
 };
 
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
new file mode 100644
index 0000000..3878c60
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MXC_MX31_H__
+#define __ASM_ARCH_MXC_MX31_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+/*
+ * MX31 memory map:
+ *
+ * Virt		Phys		Size	What
+ * ---------------------------------------------------------------------------
+ * FC000000	43F00000	1M	AIPS 1
+ * FC100000	50000000	1M	SPBA
+ * FC200000	53F00000	1M	AIPS 2
+ * FC500000	60000000	128M	ROMPATCH
+ * FC400000	68000000	128M	AVIC
+ *         	70000000	256M	IPU (MAX M2)
+ *         	80000000	256M	CSD0 SDRAM/DDR
+ *         	90000000	256M	CSD1 SDRAM/DDR
+ *         	A0000000	128M	CS0 Flash
+ *         	A8000000	128M	CS1 Flash
+ *         	B0000000	32M	CS2
+ *         	B2000000	32M	CS3
+ * F4000000	B4000000	32M	CS4
+ *         	B6000000	32M	CS5
+ * FC320000	B8000000	64K	NAND, SDRAM, WEIM, M3IF, EMI controllers
+ *         	C0000000	64M	PCMCIA/CF
+ */
+
+#define CS0_BASE_ADDR		0xA0000000
+#define CS1_BASE_ADDR		0xA8000000
+#define CS2_BASE_ADDR		0xB0000000
+#define CS3_BASE_ADDR		0xB2000000
+
+#define CS4_BASE_ADDR		0xB4000000
+#define CS4_BASE_ADDR_VIRT	0xF4000000
+#define CS4_SIZE		SZ_32M
+
+#define CS5_BASE_ADDR		0xB6000000
+#define PCMCIA_MEM_BASE_ADDR	0xBC000000
+
+/*
+ * L2CC
+ */
+#define L2CC_BASE_ADDR		0x30000000
+#define L2CC_SIZE		SZ_1M
+
+/*
+ * AIPS 1
+ */
+#define AIPS1_BASE_ADDR		0x43F00000
+#define AIPS1_BASE_ADDR_VIRT	0xFC000000
+#define AIPS1_SIZE		SZ_1M
+
+#define MAX_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00004000)
+#define EVTMON_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00008000)
+#define CLKCTL_BASE_ADDR	(AIPS1_BASE_ADDR + 0x0000C000)
+#define ETB_SLOT4_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00010000)
+#define ETB_SLOT5_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00014000)
+#define ECT_CTIO_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00018000)
+#define I2C_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00080000)
+#define I2C3_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00084000)
+#define UART1_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x00090000)
+#define UART2_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x00094000)
+#define I2C2_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00098000)
+#define OWIRE_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x0009C000)
+#define SSI1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A0000)
+#define CSPI1_BASE_ADDR 	(AIPS1_BASE_ADDR + 0x000A4000)
+#define KPP_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A8000)
+#define IOMUXC_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000AC000)
+#define ECT_IP1_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000B8000)
+#define ECT_IP2_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000BC000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define SPBA0_BASE_ADDR 	0x50000000
+#define SPBA0_BASE_ADDR_VIRT	0xFC100000
+#define SPBA0_SIZE		SZ_1M
+
+#define UART3_BASE_ADDR 	(SPBA0_BASE_ADDR + 0x0000C000)
+#define CSPI2_BASE_ADDR 	(SPBA0_BASE_ADDR + 0x00010000)
+#define SSI2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00014000)
+#define ATA_DMA_BASE_ADDR	(SPBA0_BASE_ADDR + 0x00020000)
+#define MSHC1_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00024000)
+#define SPBA_CTRL_BASE_ADDR	(SPBA0_BASE_ADDR + 0x0003C000)
+
+/*
+ * AIPS 2
+ */
+#define AIPS2_BASE_ADDR		0x53F00000
+#define AIPS2_BASE_ADDR_VIRT	0xFC200000
+#define AIPS2_SIZE		SZ_1M
+#define CCM_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00080000)
+#define GPT1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00090000)
+#define EPIT1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00094000)
+#define EPIT2_BASE_ADDR		(AIPS2_BASE_ADDR + 0x00098000)
+#define GPIO3_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000A4000)
+#define SCC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000AC000)
+#define RNGA_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000B0000)
+#define IPU_CTRL_BASE_ADDR	(AIPS2_BASE_ADDR + 0x000C0000)
+#define AUDMUX_BASE_ADDR	(AIPS2_BASE_ADDR + 0x000C4000)
+#define GPIO1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000CC000)
+#define GPIO2_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D0000)
+#define SDMA_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D4000)
+#define RTC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000D8000)
+#define WDOG_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000DC000)
+#define PWM_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000E0000)
+#define RTIC_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000EC000)
+
+/*
+ * ROMP and AVIC
+ */
+#define ROMP_BASE_ADDR		0x60000000
+#define ROMP_BASE_ADDR_VIRT	0xFC500000
+#define ROMP_SIZE		SZ_1M
+
+#define AVIC_BASE_ADDR		0x68000000
+#define AVIC_BASE_ADDR_VIRT	0xFC400000
+#define AVIC_SIZE		SZ_1M
+
+/*
+ * NAND, SDRAM, WEIM, M3IF, EMI controllers
+ */
+#define X_MEMC_BASE_ADDR	0xB8000000
+#define X_MEMC_BASE_ADDR_VIRT	0xFC320000
+#define X_MEMC_SIZE		SZ_64K
+
+#define ESDCTL_BASE_ADDR	(X_MEMC_BASE_ADDR + 0x1000)
+#define WEIM_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x2000)
+#define M3IF_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x3000)
+#define EMI_CTL_BASE_ADDR	(X_MEMC_BASE_ADDR + 0x4000)
+#define PCMCIA_CTL_BASE_ADDR	EMI_CTL_BASE_ADDR
+
+/*
+ * Memory regions and CS
+ */
+#define IPU_MEM_BASE_ADDR	0x70000000
+#define CSD0_BASE_ADDR		0x80000000
+#define CSD1_BASE_ADDR		0x90000000
+
+/*!
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0xDEADBEEF
+ */
+#define IO_ADDRESS(x)   \
+	(void __force __iomem *) \
+	(((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\
+	((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\
+	((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\
+	((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\
+	((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\
+	((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\
+	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\
+	0xDEADBEEF)
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+#define L2CC_IO_ADDRESS(x)  \
+	(((x) - L2CC_BASE_ADDR) + L2CC_BASE_ADDR_VIRT)
+
+#define AIPS1_IO_ADDRESS(x)  \
+	(((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
+
+#define SPBA0_IO_ADDRESS(x)  \
+	(((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
+
+#define AIPS2_IO_ADDRESS(x)  \
+	(((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
+
+#define ROMP_IO_ADDRESS(x)  \
+	(((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT)
+
+#define AVIC_IO_ADDRESS(x)  \
+	(((x) - AVIC_BASE_ADDR) + AVIC_BASE_ADDR_VIRT)
+
+#define CS4_IO_ADDRESS(x)  \
+	(((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
+
+#define X_MEMC_IO_ADDRESS(x)  \
+	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+#define PCMCIA_IO_ADDRESS(x) \
+	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+/*
+ * Interrupt numbers
+ */
+#define MXC_INT_I2C3		3
+#define MXC_INT_I2C2		4
+#define MXC_INT_RTIC		6
+#define MXC_INT_I2C		10
+#define MXC_INT_CSPI2		13
+#define MXC_INT_CSPI1		14
+#define MXC_INT_ATA		15
+#define MXC_INT_UART3		18
+#define MXC_INT_IIM		19
+#define MXC_INT_RNGA		22
+#define MXC_INT_EVTMON		23
+#define MXC_INT_KPP		24
+#define MXC_INT_RTC		25
+#define MXC_INT_PWM		26
+#define MXC_INT_EPIT2		27
+#define MXC_INT_EPIT1		28
+#define MXC_INT_GPT		29
+#define MXC_INT_POWER_FAIL	30
+#define MXC_INT_UART2		32
+#define MXC_INT_NANDFC		33
+#define MXC_INT_SDMA		34
+#define MXC_INT_MSHC1		39
+#define MXC_INT_IPU_ERR		41
+#define MXC_INT_IPU_SYN		42
+#define MXC_INT_UART1		45
+#define MXC_INT_ECT		48
+#define MXC_INT_SCC_SCM		49
+#define MXC_INT_SCC_SMN		50
+#define MXC_INT_GPIO2		51
+#define MXC_INT_GPIO1		52
+#define MXC_INT_WDOG		55
+#define MXC_INT_GPIO3		56
+#define MXC_INT_EXT_POWER	58
+#define MXC_INT_EXT_TEMPER	59
+#define MXC_INT_EXT_SENSOR60	60
+#define MXC_INT_EXT_SENSOR61	61
+#define MXC_INT_EXT_WDOG	62
+#define MXC_INT_EXT_TV		63
+
+#define PROD_SIGNATURE		0x1	/* For MX31 */
+
+/* silicon revisions specific to i.MX31 */
+#define CHIP_REV_1_0		0x10
+#define CHIP_REV_1_1		0x11
+#define CHIP_REV_1_2		0x12
+#define CHIP_REV_1_3		0x13
+#define CHIP_REV_2_0		0x20
+#define CHIP_REV_2_1		0x21
+#define CHIP_REV_2_2		0x22
+#define CHIP_REV_2_3		0x23
+#define CHIP_REV_3_0		0x30
+#define CHIP_REV_3_1		0x31
+#define CHIP_REV_3_2		0x32
+
+#define SYSTEM_REV_MIN		CHIP_REV_1_0
+#define SYSTEM_REV_NUM		3
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR		 	0x00
+#define GPIO_GDIR	 	0x04
+#define GPIO_PSR	 	0x08
+#define GPIO_ICR1	 	0x0C
+#define GPIO_ICR2	 	0x10
+#define GPIO_IMR	 	0x14
+#define GPIO_ISR	 	0x18
+#define GPIO_INT_LOW_LEV	0x0
+#define GPIO_INT_HIGH_LEV	0x1
+#define GPIO_INT_RISE_EDGE	0x2
+#define GPIO_INT_FALL_EDGE	0x3
+#define GPIO_INT_NONE		0x4
+
+/* Mandatory defines used globally */
+
+/* this CPU supports up to 96 GPIOs */
+#define ARCH_NR_GPIOS		96
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+
+extern unsigned int system_rev;
+
+static inline int mx31_revision(void)
+{
+	return system_rev;
+}
+#endif
+
+#endif /*  __ASM_ARCH_MXC_MX31_H__ */
+
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index f6caab0..5fa2a07 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -24,13 +24,74 @@
 #error "Do not include directly."
 #endif
 
-/* clean up all things that are not used */
-#ifndef CONFIG_ARCH_MX3
-# define cpu_is_mx31() (0)
+#define MXC_CPU_MX1		1
+#define MXC_CPU_MX21		21
+#define MXC_CPU_MX27		27
+#define MXC_CPU_MX31		31
+#define MXC_CPU_MX35		35
+
+#ifndef __ASSEMBLY__
+extern unsigned int __mxc_cpu_type;
 #endif
 
-#ifndef CONFIG_MACH_MX27
-# define cpu_is_mx27() (0)
+#ifdef CONFIG_ARCH_MX1
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX1
+# endif
+# define cpu_is_mx1()		(mxc_cpu_type == MXC_CPU_MX1)
+#else
+# define cpu_is_mx1()		(0)
+#endif
+
+#ifdef CONFIG_MACH_MX21
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX21
+# endif
+# define cpu_is_mx21()		(mxc_cpu_type == MXC_CPU_MX21)
+#else
+# define cpu_is_mx21()		(0)
+#endif
+
+#ifdef CONFIG_MACH_MX27
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX27
+# endif
+# define cpu_is_mx27()		(mxc_cpu_type == MXC_CPU_MX27)
+#else
+# define cpu_is_mx27()		(0)
+#endif
+
+#ifdef CONFIG_ARCH_MX31
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX31
+# endif
+# define cpu_is_mx31()		(mxc_cpu_type == MXC_CPU_MX31)
+#else
+# define cpu_is_mx31()		(0)
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX35
+# endif
+# define cpu_is_mx35()		(mxc_cpu_type == MXC_CPU_MX35)
+#else
+# define cpu_is_mx35()		(0)
 #endif
 
 #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2)
@@ -39,4 +100,7 @@
 #define CSCR_A(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x8)
 #endif
 
+#define cpu_is_mx3()	(cpu_is_mx31() || cpu_is_mx35())
+#define cpu_is_mx2()	(cpu_is_mx21() || cpu_is_mx27())
+
 #endif /*  __ASM_ARCH_MXC_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index bbfc374..e56241a 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -26,9 +26,6 @@
 	cpu_do_idle();
 }
 
-static inline void arch_reset(char mode)
-{
-	cpu_reset(0);
-}
+void arch_reset(char mode, const char *cmd);
 
 #endif /* __ASM_ARCH_MXC_SYSTEM_H__ */
diff --git a/arch/arm/plat-mxc/iomux-mx1-mx2.c b/arch/arm/plat-mxc/iomux-mx1-mx2.c
index df6f183..a37163c 100644
--- a/arch/arm/plat-mxc/iomux-mx1-mx2.c
+++ b/arch/arm/plat-mxc/iomux-mx1-mx2.c
@@ -32,7 +32,7 @@
 
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
-#include <mach/iomux-mx1-mx2.h>
+#include <mach/iomux.h>
 
 void mxc_gpio_mode(int gpio_mode)
 {
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
new file mode 100644
index 0000000..9bffbc5
--- /dev/null
+++ b/arch/arm/plat-mxc/pwm.c
@@ -0,0 +1,300 @@
+/*
+ * simple driver for PWM (Pulse Width Modulator) controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#if defined CONFIG_ARCH_MX1 || defined CONFIG_ARCH_MX21
+#define PWM_VER_1
+
+#define PWMCR	0x00	/* PWM Control Register		*/
+#define PWMSR	0x04	/* PWM Sample Register		*/
+#define PWMPR	0x08	/* PWM Period Register		*/
+#define PWMCNR	0x0C	/* PWM Counter Register		*/
+
+#define PWMCR_HCTR		(1 << 18)		/* Halfword FIFO Data Swapping	*/
+#define PWMCR_BCTR		(1 << 17)		/* Byte FIFO Data Swapping	*/
+#define PWMCR_SWR		(1 << 16)		/* Software Reset		*/
+#define PWMCR_CLKSRC_PERCLK	(0 << 15)		/* PERCLK Clock Source		*/
+#define PWMCR_CLKSRC_CLK32	(1 << 15)		/* 32KHz Clock Source		*/
+#define PWMCR_PRESCALER(x)	(((x - 1) & 0x7F) << 8)	/* PRESCALER			*/
+#define PWMCR_IRQ		(1 << 7)		/* Interrupt Request		*/
+#define PWMCR_IRQEN		(1 << 6)		/* Interrupt Request Enable	*/
+#define PWMCR_FIFOAV		(1 << 5)		/* FIFO Available		*/
+#define PWMCR_EN		(1 << 4)		/* Enables/Disables the PWM	*/
+#define PWMCR_REPEAT(x)		(((x) & 0x03) << 2)	/* Sample Repeats		*/
+#define PWMCR_DIV(x)		(((x) & 0x03) << 0)	/* Clock divider 2/4/8/16	*/
+
+#define MAX_DIV			(128 * 16)
+#endif
+
+#if defined CONFIG_MACH_MX27 || defined CONFIG_ARCH_MX31
+#define PWM_VER_2
+
+#define PWMCR	0x00	/* PWM Control Register		*/
+#define PWMSR	0x04	/* PWM Status Register		*/
+#define PWMIR	0x08	/* PWM Interrupt Register	*/
+#define PWMSAR	0x0C	/* PWM Sample Register		*/
+#define PWMPR	0x10	/* PWM Period Register		*/
+#define PWMCNR	0x14	/* PWM Counter Register		*/
+
+#define PWMCR_EN		(1 << 0)		/* Enables/Disables the PWM	*/
+#define PWMCR_REPEAT(x)		(((x) & 0x03) << 1)	/* Sample Repeats		*/
+#define PWMCR_SWR		(1 << 3)		/* Software Reset		*/
+#define PWMCR_PRESCALER(x)	(((x - 1) & 0xFFF) << 4)/* PRESCALER			*/
+#define PWMCR_CLKSRC(x)		(((x) & 0x3) << 16)
+#define PWMCR_CLKSRC_OFF	(0 << 16)
+#define PWMCR_CLKSRC_IPG	(1 << 16)
+#define PWMCR_CLKSRC_IPG_HIGH	(2 << 16)
+#define PWMCR_CLKSRC_CLK32	(3 << 16)
+#define PWMCR_POUTC
+#define PWMCR_HCTR		(1 << 20)		/* Halfword FIFO Data Swapping	*/
+#define PWMCR_BCTR		(1 << 21)		/* Byte FIFO Data Swapping	*/
+#define PWMCR_DBGEN		(1 << 22)		/* Debug Mode			*/
+#define PWMCR_WAITEN		(1 << 23)		/* Wait Mode			*/
+#define PWMCR_DOZEN		(1 << 24)		/* Doze Mode			*/
+#define PWMCR_STOPEN		(1 << 25)		/* Stop Mode			*/
+#define PWMCR_FWM(x)		(((x) & 0x3) << 26)	/* FIFO Water Mark		*/
+
+#define MAX_DIV 4096
+#endif
+
+#define PWMS_SAMPLE(x)		((x) & 0xFFFF)		/* Contains a two-sample word	*/
+#define PWMP_PERIOD(x)		((x) & 0xFFFF)		/* Represents the PWM's period	*/
+#define PWMC_COUNTER(x)		((x) & 0xFFFF)		/* Represents the current count value	*/
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device *pdev;
+
+	const char	*label;
+	struct clk	*clk;
+
+	int		clk_enabled;
+	void __iomem	*mmio_base;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, duty_cycles, prescale;
+
+	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	c = clk_get_rate(pwm->clk);
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	prescale = period_cycles / 0x10000 + 1;
+
+	period_cycles /= prescale;
+	c = (unsigned long long)period_cycles * duty_ns;
+	do_div(c, period_ns);
+	duty_cycles = c;
+
+#ifdef PWM_VER_2
+	writel(duty_cycles, pwm->mmio_base + PWMSAR);
+	writel(period_cycles, pwm->mmio_base + PWMPR);
+	writel(PWMCR_PRESCALER(prescale - 1) | PWMCR_CLKSRC_IPG_HIGH | PWMCR_EN,
+			pwm->mmio_base + PWMCR);
+#elif defined PWM_VER_1
+#error PWM not yet working on MX1 / MX21
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	int rc = 0;
+
+	if (!pwm->clk_enabled) {
+		rc = clk_enable(pwm->clk);
+		if (!rc)
+			pwm->clk_enabled = 1;
+	}
+	return rc;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	if (pwm->clk_enabled) {
+		clk_disable(pwm->clk);
+		pwm->clk_enabled = 0;
+	}
+}
+EXPORT_SYMBOL(pwm_disable);
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int found = 0;
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		if (pwm->use_count == 0) {
+			pwm->use_count++;
+			pwm->label = label;
+		} else
+			pwm = ERR_PTR(-EBUSY);
+	} else
+		pwm = ERR_PTR(-ENOENT);
+
+	mutex_unlock(&pwm_lock);
+	return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else
+		pr_warning("PWM device already freed\n");
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+static int __devinit mxc_pwm_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct resource *r;
+	int ret = 0;
+
+	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+	if (pwm == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	pwm->clk = clk_get(&pdev->dev, "pwm");
+
+	if (IS_ERR(pwm->clk)) {
+		ret = PTR_ERR(pwm->clk);
+		goto err_free;
+	}
+
+	pwm->clk_enabled = 0;
+
+	pwm->use_count = 0;
+	pwm->pwm_id = pdev->id;
+	pwm->pdev = pdev;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto err_free_clk;
+	}
+
+	r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free_clk;
+	}
+
+	pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
+	if (pwm->mmio_base == NULL) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+
+	platform_set_drvdata(pdev, pwm);
+	return 0;
+
+err_free_mem:
+	release_mem_region(r->start, r->end - r->start + 1);
+err_free_clk:
+	clk_put(pwm->clk);
+err_free:
+	kfree(pwm);
+	return ret;
+}
+
+static int __devexit mxc_pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct resource *r;
+
+	pwm = platform_get_drvdata(pdev);
+	if (pwm == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+	list_del(&pwm->node);
+	mutex_unlock(&pwm_lock);
+
+	iounmap(pwm->mmio_base);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, r->end - r->start + 1);
+
+	clk_put(pwm->clk);
+
+	kfree(pwm);
+	return 0;
+}
+
+static struct platform_driver mxc_pwm_driver = {
+	.driver		= {
+		.name	= "mxc_pwm",
+	},
+	.probe		= mxc_pwm_probe,
+	.remove		= __devexit_p(mxc_pwm_remove),
+};
+
+static int __init mxc_pwm_init(void)
+{
+	return platform_driver_register(&mxc_pwm_driver);
+}
+arch_initcall(mxc_pwm_init);
+
+static void __exit mxc_pwm_exit(void)
+{
+	platform_driver_unregister(&mxc_pwm_driver);
+}
+module_exit(mxc_pwm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+
diff --git a/arch/arm/mach-mx2/system.c b/arch/arm/plat-mxc/system.c
similarity index 60%
rename from arch/arm/mach-mx2/system.c
rename to arch/arm/plat-mxc/system.c
index 7b82697..79c3757 100644
--- a/arch/arm/mach-mx2/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2000 Deep Blue Solutions Ltd
  * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.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
@@ -22,42 +23,45 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
 
 #include <mach/hardware.h>
 #include <asm/proc-fns.h>
 #include <asm/system.h>
 
-/*
- * Put the CPU into idle mode. It is called by default_idle()
- * in process.c file.
- */
-void arch_idle(void)
-{
-	/*
-	 * This should do all the clock switching
-	 * and wait for interrupt tricks.
-	 */
-	cpu_do_idle();
-}
-
-#define WDOG_WCR_REG                    IO_ADDRESS(WDOG_BASE_ADDR)
-#define WDOG_WCR_SRS                    (1 << 4)
+#ifdef CONFIG_ARCH_MX1
+#define WDOG_WCR_REG		IO_ADDRESS(WDT_BASE_ADDR)
+#define WDOG_WCR_ENABLE		(1 << 0)
+#else
+#define WDOG_WCR_REG		IO_ADDRESS(WDOG_BASE_ADDR)
+#define WDOG_WCR_ENABLE		(1 << 2)
+#endif
 
 /*
  * Reset the system. It is called by machine_restart().
  */
-void arch_reset(char mode)
+void arch_reset(char mode, const char *cmd)
 {
-	struct clk *clk;
+	if (!cpu_is_mx1()) {
+		struct clk *clk;
 
-	clk = clk_get(NULL, "wdog_clk");
-	if (!clk) {
-		printk(KERN_ERR"Cannot activate the watchdog. Giving up\n");
-		return;
+		clk = clk_get_sys("imx-wdt.0", NULL);
+		if (!IS_ERR(clk))
+			clk_enable(clk);
 	}
 
-	clk_enable(clk);
-
 	/* Assert SRS signal */
-	__raw_writew(__raw_readw(WDOG_WCR_REG) & ~WDOG_WCR_SRS, WDOG_WCR_REG);
+	__raw_writew(WDOG_WCR_ENABLE, WDOG_WCR_REG);
+
+	/* wait for reset to assert... */
+	mdelay(500);
+
+	printk(KERN_ERR "Watchdog reset failed to assert reset\n");
+
+	/* delay to allow the serial port to show the message */
+	mdelay(50);
+
+	/* we'll take a jump through zero as a poor second */
+	cpu_reset(0);
 }
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index 758a129..ef1b3cd 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -34,9 +34,6 @@
 static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
-/* clock source for the timer */
-static struct clk *timer_clk;
-
 /* clock source */
 
 static cycle_t mxc_get_cycles(void)
@@ -53,13 +50,11 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static int __init mxc_clocksource_init(void)
+static int __init mxc_clocksource_init(struct clk *timer_clk)
 {
-	unsigned int clock;
+	unsigned int c = clk_get_rate(timer_clk);
 
-	clock = clk_get_rate(timer_clk);
-
-	clocksource_mxc.mult = clocksource_hz2mult(clock,
+	clocksource_mxc.mult = clocksource_hz2mult(c,
 					clocksource_mxc.shift);
 	clocksource_register(&clocksource_mxc);
 
@@ -177,13 +172,11 @@
 	.rating		= 200,
 };
 
-static int __init mxc_clockevent_init(void)
+static int __init mxc_clockevent_init(struct clk *timer_clk)
 {
-	unsigned int clock;
+	unsigned int c = clk_get_rate(timer_clk);
 
-	clock = clk_get_rate(timer_clk);
-
-	clockevent_mxc.mult = div_sc(clock, NSEC_PER_SEC,
+	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
 					clockevent_mxc.shift);
 	clockevent_mxc.max_delta_ns =
 			clockevent_delta2ns(0xfffffffe, &clockevent_mxc);
@@ -197,14 +190,8 @@
 	return 0;
 }
 
-void __init mxc_timer_init(const char *clk_timer)
+void __init mxc_timer_init(struct clk *timer_clk)
 {
-	timer_clk = clk_get(NULL, clk_timer);
-	if (!timer_clk) {
-		printk(KERN_ERR"Cannot determine timer clock. Giving up.\n");
-		return;
-	}
-
 	clk_enable(timer_clk);
 
 	/*
@@ -219,10 +206,9 @@
 		     TIMER_BASE + MXC_TCTL);
 
 	/* init and register the timer to the framework */
-	mxc_clocksource_init();
-	mxc_clockevent_init();
+	mxc_clocksource_init(timer_clk);
+	mxc_clockevent_init(timer_clk);
 
 	/* Make irqs happen */
 	setup_irq(TIMER_INTERRUPT, &mxc_timer_irq);
 }
-
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 46d3b0b..9dd68fa 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -11,14 +11,17 @@
 
 config ARCH_OMAP1
 	bool "TI OMAP1"
+	select COMMON_CLKDEV
 
 config ARCH_OMAP2
 	bool "TI OMAP2"
 	select CPU_V6
+	select COMMON_CLKDEV
 
 config ARCH_OMAP3
 	bool "TI OMAP3"
 	select CPU_V7
+	select COMMON_CLKDEV
 
 endchoice
 
@@ -104,6 +107,14 @@
 	  Say Y here if you want support for the OMAP Multichannel
 	  Buffered Serial Port.
 
+config OMAP_MBOX_FWK
+	tristate "Mailbox framework support"
+	depends on ARCH_OMAP
+	default n
+	help
+	  Say Y here if you want to use OMAP Mailbox framework support for
+	  DSP, IVA1.0 and IVA2 in OMAP1/2/3.
+
 choice
         prompt "System timer"
 	default OMAP_MPU_TIMER
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index be6aab9..2e06145 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -36,44 +36,6 @@
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk * clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int idno;
-
-	if (dev == NULL || dev->bus != &platform_bus_type)
-		idno = -1;
-	else
-		idno = to_platform_device(dev)->id;
-
-	mutex_lock(&clocks_mutex);
-
-	list_for_each_entry(p, &clocks, node) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
-			clk = p;
-			goto found;
-		}
-	}
-
-	list_for_each_entry(p, &clocks, node) {
-		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-
-found:
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
@@ -114,22 +76,6 @@
 }
 EXPORT_SYMBOL(clk_disable);
 
-int clk_get_usecount(struct clk *clk)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (clk == NULL || IS_ERR(clk))
-		return 0;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	ret = clk->usecount;
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_get_usecount);
-
 unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
@@ -146,13 +92,6 @@
 }
 EXPORT_SYMBOL(clk_get_rate);
 
-void clk_put(struct clk *clk)
-{
-	if (clk && !IS_ERR(clk))
-		module_put(clk->owner);
-}
-EXPORT_SYMBOL(clk_put);
-
 /*-------------------------------------------------------------------------
  * Optional clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -185,6 +124,11 @@
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_rate)
 		ret = arch_clock->clk_set_rate(clk, rate);
+	if (ret == 0) {
+		if (clk->recalc)
+			clk->rate = clk->recalc(clk);
+		propagate_rate(clk);
+	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -200,8 +144,16 @@
 		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_parent)
-		ret =  arch_clock->clk_set_parent(clk, parent);
+	if (clk->usecount == 0) {
+		if (arch_clock->clk_set_parent)
+			ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0) {
+			if (clk->recalc)
+				clk->rate = clk->recalc(clk);
+			propagate_rate(clk);
+		}
+	} else
+		ret = -EBUSY;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -210,18 +162,7 @@
 
 struct clk *clk_get_parent(struct clk *clk)
 {
-	unsigned long flags;
-	struct clk * ret = NULL;
-
-	if (clk == NULL || IS_ERR(clk))
-		return ret;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_get_parent)
-		ret = arch_clock->clk_get_parent(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-
-	return ret;
+	return clk->parent;
 }
 EXPORT_SYMBOL(clk_get_parent);
 
@@ -250,14 +191,20 @@
 __setup("mpurate=", omap_clk_setup);
 
 /* Used for clocks that always have same value as the parent clock */
-void followparent_recalc(struct clk *clk)
+unsigned long followparent_recalc(struct clk *clk)
 {
-	if (clk == NULL || IS_ERR(clk))
-		return;
+	return clk->parent->rate;
+}
 
-	clk->rate = clk->parent->rate;
-	if (unlikely(clk->flags & RATE_PROPAGATES))
-		propagate_rate(clk);
+void clk_reparent(struct clk *child, struct clk *parent)
+{
+	list_del_init(&child->sibling);
+	if (parent)
+		list_add(&child->sibling, &parent->children);
+	child->parent = parent;
+
+	/* now do the debugfs renaming to reattach the child
+	   to the proper parent */
 }
 
 /* Propagate rate to children */
@@ -265,17 +212,15 @@
 {
 	struct clk *clkp;
 
-	if (tclk == NULL || IS_ERR(tclk))
-		return;
-
-	list_for_each_entry(clkp, &clocks, node) {
-		if (likely(clkp->parent != tclk))
-			continue;
-		if (likely((u32)clkp->recalc))
-			clkp->recalc(clkp);
+	list_for_each_entry(clkp, &tclk->children, sibling) {
+		if (clkp->recalc)
+			clkp->rate = clkp->recalc(clkp);
+		propagate_rate(clkp);
 	}
 }
 
+static LIST_HEAD(root_clks);
+
 /**
  * recalculate_root_clocks - recalculate and propagate all root clocks
  *
@@ -287,18 +232,35 @@
 {
 	struct clk *clkp;
 
-	list_for_each_entry(clkp, &clocks, node) {
-		if (unlikely(!clkp->parent) && likely((u32)clkp->recalc))
-			clkp->recalc(clkp);
+	list_for_each_entry(clkp, &root_clks, sibling) {
+		if (clkp->recalc)
+			clkp->rate = clkp->recalc(clkp);
+		propagate_rate(clkp);
 	}
 }
 
+void clk_init_one(struct clk *clk)
+{
+	INIT_LIST_HEAD(&clk->children);
+}
+
 int clk_register(struct clk *clk)
 {
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
+	/*
+	 * trap out already registered clocks
+	 */
+	if (clk->node.next || clk->node.prev)
+		return 0;
+
 	mutex_lock(&clocks_mutex);
+	if (clk->parent)
+		list_add(&clk->sibling, &clk->parent->children);
+	else
+		list_add(&clk->sibling, &root_clks);
+
 	list_add(&clk->node, &clocks);
 	if (clk->init)
 		clk->init(clk);
@@ -314,39 +276,12 @@
 		return;
 
 	mutex_lock(&clocks_mutex);
+	list_del(&clk->sibling);
 	list_del(&clk->node);
 	mutex_unlock(&clocks_mutex);
 }
 EXPORT_SYMBOL(clk_unregister);
 
-void clk_deny_idle(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_deny_idle)
-		arch_clock->clk_deny_idle(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_deny_idle);
-
-void clk_allow_idle(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_allow_idle)
-		arch_clock->clk_allow_idle(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_allow_idle);
-
 void clk_enable_init_clocks(void)
 {
 	struct clk *clkp;
@@ -358,6 +293,23 @@
 }
 EXPORT_SYMBOL(clk_enable_init_clocks);
 
+/*
+ * Low level helpers
+ */
+static int clkll_enable_null(struct clk *clk)
+{
+	return 0;
+}
+
+static void clkll_disable_null(struct clk *clk)
+{
+}
+
+const struct clkops clkops_null = {
+	.enable		= clkll_enable_null,
+	.disable	= clkll_disable_null,
+};
+
 #ifdef CONFIG_CPU_FREQ
 void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 {
@@ -383,8 +335,10 @@
 	unsigned long flags;
 
 	list_for_each_entry(ck, &clocks, node) {
-		if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
-			ck->enable_reg == 0)
+		if (ck->ops == &clkops_null)
+			continue;
+
+		if (ck->usecount > 0 || ck->enable_reg == 0)
 			continue;
 
 		spin_lock_irqsave(&clockfw_lock, flags);
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 6825fbb..d179714 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -245,7 +245,7 @@
 static void __init __omap2_set_globals(void)
 {
 	omap2_set_globals_tap(omap2_globals);
-	omap2_set_globals_memory(omap2_globals);
+	omap2_set_globals_sdrc(omap2_globals);
 	omap2_set_globals_control(omap2_globals);
 	omap2_set_globals_prcm(omap2_globals);
 }
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index b269024..843e8af 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -23,10 +23,13 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
+#include <mach/clock.h>
 #include <asm/system.h>
 
 #define VERY_HI_RATE	900000000
 
+static struct cpufreq_frequency_table *freq_table;
+
 #ifdef CONFIG_ARCH_OMAP1
 #define MPU_CLK		"mpu"
 #else
@@ -39,6 +42,9 @@
 
 int omap_verify_speed(struct cpufreq_policy *policy)
 {
+	if (freq_table)
+		return cpufreq_frequency_table_verify(policy, freq_table);
+
 	if (policy->cpu)
 		return -EINVAL;
 
@@ -70,12 +76,26 @@
 	struct cpufreq_freqs freqs;
 	int ret = 0;
 
+	/* Ensure desired rate is within allowed range.  Some govenors
+	 * (ondemand) will just pass target_freq=0 to get the minimum. */
+	if (target_freq < policy->cpuinfo.min_freq)
+		target_freq = policy->cpuinfo.min_freq;
+	if (target_freq > policy->cpuinfo.max_freq)
+		target_freq = policy->cpuinfo.max_freq;
+
 	freqs.old = omap_getspeed(0);
 	freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
 	freqs.cpu = 0;
 
+	if (freqs.old == freqs.new)
+		return ret;
+
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	ret = clk_set_rate(mpu_clk, target_freq * 1000);
+#ifdef CONFIG_CPU_FREQ_DEBUG
+	printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
+	       freqs.old, freqs.new);
+#endif
+	ret = clk_set_rate(mpu_clk, freqs.new * 1000);
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return ret;
@@ -83,16 +103,31 @@
 
 static int __init omap_cpu_init(struct cpufreq_policy *policy)
 {
+	int result = 0;
+
 	mpu_clk = clk_get(NULL, MPU_CLK);
 	if (IS_ERR(mpu_clk))
 		return PTR_ERR(mpu_clk);
 
 	if (policy->cpu != 0)
 		return -EINVAL;
+
 	policy->cur = policy->min = policy->max = omap_getspeed(0);
-	policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
-	policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000;
-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+
+	clk_init_cpufreq_table(&freq_table);
+	if (freq_table) {
+		result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+		if (!result)
+			cpufreq_frequency_table_get_attr(freq_table,
+							policy->cpu);
+	} else {
+		policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
+		policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
+							VERY_HI_RATE) / 1000;
+	}
+
+	/* FIXME: what's the actual transition time? */
+	policy->cpuinfo.transition_latency = 10 * 1000 * 1000;
 
 	return 0;
 }
@@ -103,6 +138,11 @@
 	return 0;
 }
 
+static struct freq_attr *omap_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
 static struct cpufreq_driver omap_driver = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= omap_verify_speed,
@@ -111,6 +151,7 @@
 	.init		= omap_cpu_init,
 	.exit		= omap_cpu_exit,
 	.name		= "omap",
+	.attr		= omap_cpufreq_attr,
 };
 
 static int __init omap_cpufreq_init(void)
@@ -119,3 +160,11 @@
 }
 
 arch_initcall(omap_cpufreq_init);
+
+/*
+ * if ever we want to remove this, upon cleanup call:
+ *
+ * cpufreq_unregister_driver()
+ * cpufreq_frequency_table_put_attr()
+ */
+
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 208dbb1..87fb7ff 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -228,6 +228,9 @@
 	ret = platform_device_add(pdev);
 	if (ret)
 		goto fail;
+
+	/* return device handle to board setup code */
+	data->dev = &pdev->dev;
 	return 0;
 
 fail:
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 47ec77a..21cc014 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -123,6 +123,7 @@
 
 static int dma_lch_count;
 static int dma_chan_count;
+static int omap_dma_reserve_channels;
 
 static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
@@ -737,7 +738,7 @@
 		 * id.
 		 */
 		dma_write(dev_id | (1 << 10), CCR(free_ch));
-	} else if (cpu_is_omap730() || cpu_is_omap15xx()) {
+	} else if (cpu_is_omap7xx() || cpu_is_omap15xx()) {
 		dma_write(dev_id, CCR(free_ch));
 	}
 
@@ -1900,7 +1901,7 @@
 /* STATUS register count is from 1-32 while our is 0-31 */
 static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
 {
-	u32 val;
+	u32 val, enable_reg;
 	int i;
 
 	val = dma_read(IRQSTATUS_L0);
@@ -1909,6 +1910,8 @@
 			printk(KERN_WARNING "Spurious DMA IRQ\n");
 		return IRQ_HANDLED;
 	}
+	enable_reg = dma_read(IRQENABLE_L0);
+	val &= enable_reg; /* Dispatch only relevant interrupts */
 	for (i = 0; i < dma_lch_count && val != 0; i++) {
 		if (val & 1)
 			omap2_dma_handle_ch(i);
@@ -2321,6 +2324,10 @@
 		return -ENODEV;
 	}
 
+	if (cpu_class_is_omap2() && omap_dma_reserve_channels
+			&& (omap_dma_reserve_channels <= dma_lch_count))
+		dma_lch_count = omap_dma_reserve_channels;
+
 	dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count,
 				GFP_KERNEL);
 	if (!dma_chan)
@@ -2339,7 +2346,7 @@
 		printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
 		dma_chan_count = 9;
 		enable_1510_mode = 1;
-	} else if (cpu_is_omap16xx() || cpu_is_omap730()) {
+	} else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
 		       dma_read(HW_ID));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -2371,7 +2378,7 @@
 		u8 revision = dma_read(REVISION) & 0xff;
 		printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
 		       revision >> 4, revision & 0xf);
-		dma_chan_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
+		dma_chan_count = dma_lch_count;
 	} else {
 		dma_chan_count = 0;
 		return 0;
@@ -2437,4 +2444,17 @@
 
 arch_initcall(omap_init_dma);
 
+/*
+ * Reserve the omap SDMA channels using cmdline bootarg
+ * "omap_dma_reserve_ch=". The valid range is 1 to 32
+ */
+static int __init omap_dma_cmdline_reserve_ch(char *str)
+{
+	if (get_option(&str, &omap_dma_reserve_channels) != 1)
+		omap_dma_reserve_channels = 0;
+	return 1;
+}
+
+__setup("omap_dma_reserve_ch=", omap_dma_cmdline_reserve_ch);
+
 
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index e4f0ce0..bfd4757 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -33,6 +33,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <mach/hardware.h>
 #include <mach/dmtimer.h>
 #include <mach/irqs.h>
@@ -362,6 +363,7 @@
 
 	return timer;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_request);
 
 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 {
@@ -385,6 +387,7 @@
 
 	return timer;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
 void omap_dm_timer_free(struct omap_dm_timer *timer)
 {
@@ -395,6 +398,7 @@
 	WARN_ON(!timer->reserved);
 	timer->reserved = 0;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 
 void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
@@ -406,6 +410,7 @@
 
 	timer->enabled = 1;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
@@ -417,11 +422,13 @@
 
 	timer->enabled = 0;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 {
 	return timer->irq;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 
 #if defined(CONFIG_ARCH_OMAP1)
 
@@ -452,6 +459,7 @@
 
 	return inputmask;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 #elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3)
 
@@ -459,6 +467,7 @@
 {
 	return timer->fclk;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
 
 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 {
@@ -466,6 +475,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 #endif
 
@@ -473,6 +483,7 @@
 {
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
 
 void omap_dm_timer_start(struct omap_dm_timer *timer)
 {
@@ -484,6 +495,7 @@
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 
 void omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
@@ -495,6 +507,7 @@
 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	}
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 
 #ifdef CONFIG_ARCH_OMAP1
 
@@ -507,6 +520,7 @@
 	l |= source << n;
 	omap_writel(l, MOD_CONF_CTRL_1);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
 #else
 
@@ -523,6 +537,7 @@
 	 * cause an abort. */
 	__delay(150000);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 
 #endif
 
@@ -541,6 +556,7 @@
 
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
 
 /* Optimized set_load which removes costly spin wait in timer_start */
 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
@@ -560,6 +576,7 @@
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 
 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 			     unsigned int match)
@@ -574,6 +591,7 @@
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
 
 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 			   int toggle, int trigger)
@@ -590,6 +608,7 @@
 	l |= trigger << 10;
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 
 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 {
@@ -603,6 +622,7 @@
 	}
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 
 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 				  unsigned int value)
@@ -610,6 +630,7 @@
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 
 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 {
@@ -619,11 +640,13 @@
 
 	return l;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 
 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 {
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 
 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 {
@@ -633,11 +656,13 @@
 
 	return l;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 
 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 {
 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 }
+EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 
 int omap_dm_timers_active(void)
 {
@@ -658,6 +683,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 
 int __init omap_dm_timer_init(void)
 {
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index f856a90..d3fa41e 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -81,6 +81,22 @@
 #define OMAP730_GPIO_INT_STATUS		0x14
 
 /*
+ * OMAP850 specific GPIO registers
+ */
+#define OMAP850_GPIO1_BASE		IO_ADDRESS(0xfffbc000)
+#define OMAP850_GPIO2_BASE		IO_ADDRESS(0xfffbc800)
+#define OMAP850_GPIO3_BASE		IO_ADDRESS(0xfffbd000)
+#define OMAP850_GPIO4_BASE		IO_ADDRESS(0xfffbd800)
+#define OMAP850_GPIO5_BASE		IO_ADDRESS(0xfffbe000)
+#define OMAP850_GPIO6_BASE		IO_ADDRESS(0xfffbe800)
+#define OMAP850_GPIO_DATA_INPUT		0x00
+#define OMAP850_GPIO_DATA_OUTPUT	0x04
+#define OMAP850_GPIO_DIR_CONTROL	0x08
+#define OMAP850_GPIO_INT_CONTROL	0x0c
+#define OMAP850_GPIO_INT_MASK		0x10
+#define OMAP850_GPIO_INT_STATUS		0x14
+
+/*
  * omap24xx specific GPIO registers
  */
 #define OMAP242X_GPIO1_BASE		IO_ADDRESS(0x48018000)
@@ -159,7 +175,8 @@
 #define METHOD_GPIO_1510	1
 #define METHOD_GPIO_1610	2
 #define METHOD_GPIO_730		3
-#define METHOD_GPIO_24XX	4
+#define METHOD_GPIO_850		4
+#define METHOD_GPIO_24XX	5
 
 #ifdef CONFIG_ARCH_OMAP16XX
 static struct gpio_bank gpio_bank_1610[5] = {
@@ -190,6 +207,19 @@
 };
 #endif
 
+#ifdef CONFIG_ARCH_OMAP850
+static struct gpio_bank gpio_bank_850[7] = {
+	{ OMAP_MPUIO_BASE,     INT_850_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },
+	{ OMAP850_GPIO1_BASE,  INT_850_GPIO_BANK1,  IH_GPIO_BASE,	METHOD_GPIO_850 },
+	{ OMAP850_GPIO2_BASE,  INT_850_GPIO_BANK2,  IH_GPIO_BASE + 32,	METHOD_GPIO_850 },
+	{ OMAP850_GPIO3_BASE,  INT_850_GPIO_BANK3,  IH_GPIO_BASE + 64,	METHOD_GPIO_850 },
+	{ OMAP850_GPIO4_BASE,  INT_850_GPIO_BANK4,  IH_GPIO_BASE + 96,	METHOD_GPIO_850 },
+	{ OMAP850_GPIO5_BASE,  INT_850_GPIO_BANK5,  IH_GPIO_BASE + 128, METHOD_GPIO_850 },
+	{ OMAP850_GPIO6_BASE,  INT_850_GPIO_BANK6,  IH_GPIO_BASE + 160, METHOD_GPIO_850 },
+};
+#endif
+
+
 #ifdef CONFIG_ARCH_OMAP24XX
 
 static struct gpio_bank gpio_bank_242x[4] = {
@@ -236,7 +266,7 @@
 			return &gpio_bank[0];
 		return &gpio_bank[1 + (gpio >> 4)];
 	}
-	if (cpu_is_omap730()) {
+	if (cpu_is_omap7xx()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1 + (gpio >> 5)];
@@ -251,7 +281,7 @@
 
 static inline int get_gpio_index(int gpio)
 {
-	if (cpu_is_omap730())
+	if (cpu_is_omap7xx())
 		return gpio & 0x1f;
 	if (cpu_is_omap24xx())
 		return gpio & 0x1f;
@@ -273,7 +303,7 @@
 		return 0;
 	if ((cpu_is_omap16xx()) && gpio < 64)
 		return 0;
-	if (cpu_is_omap730() && gpio < 192)
+	if (cpu_is_omap7xx() && gpio < 192)
 		return 0;
 	if (cpu_is_omap24xx() && gpio < 128)
 		return 0;
@@ -318,6 +348,11 @@
 		reg += OMAP730_GPIO_DIR_CONTROL;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DIR_CONTROL;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_OE;
@@ -380,6 +415,16 @@
 			l &= ~(1 << gpio);
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DATA_OUTPUT;
+		l = __raw_readl(reg);
+		if (enable)
+			l |= 1 << gpio;
+		else
+			l &= ~(1 << gpio);
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		if (enable)
@@ -426,6 +471,11 @@
 		reg += OMAP730_GPIO_DATA_INPUT;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DATA_INPUT;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_DATAIN;
@@ -598,6 +648,18 @@
 			goto bad;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_INT_CONTROL;
+		l = __raw_readl(reg);
+		if (trigger & IRQ_TYPE_EDGE_RISING)
+			l |= 1 << gpio;
+		else if (trigger & IRQ_TYPE_EDGE_FALLING)
+			l &= ~(1 << gpio);
+		else
+			goto bad;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		set_24xx_gpio_triggering(bank, gpio, trigger);
@@ -678,6 +740,11 @@
 		reg += OMAP730_GPIO_INT_STATUS;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_INT_STATUS;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_IRQSTATUS1;
@@ -736,6 +803,13 @@
 		inv = 1;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_INT_MASK;
+		mask = 0xffffffff;
+		inv = 1;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_IRQENABLE1;
@@ -799,6 +873,16 @@
 			l |= gpio_mask;
 		break;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_INT_MASK;
+		l = __raw_readl(reg);
+		if (enable)
+			l &= ~(gpio_mask);
+		else
+			l |= gpio_mask;
+		break;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	case METHOD_GPIO_24XX:
 		if (enable)
@@ -983,6 +1067,10 @@
 	if (bank->method == METHOD_GPIO_730)
 		isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	if (bank->method == METHOD_GPIO_850)
+		isr_reg = bank->base + OMAP850_GPIO_INT_STATUS;
+#endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 	if (bank->method == METHOD_GPIO_24XX)
 		isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
@@ -1372,6 +1460,13 @@
 		gpio_bank = gpio_bank_730;
 	}
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+	if (cpu_is_omap850()) {
+		printk(KERN_INFO "OMAP850 GPIO hardware\n");
+		gpio_bank_count = 7;
+		gpio_bank = gpio_bank_850;
+	}
+#endif
 
 #ifdef CONFIG_ARCH_OMAP24XX
 	if (cpu_is_omap242x()) {
@@ -1420,7 +1515,7 @@
 			__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
 			__raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG);
 		}
-		if (cpu_is_omap730() && bank->method == METHOD_GPIO_730) {
+		if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_730) {
 			__raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK);
 			__raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS);
 
@@ -1743,6 +1838,9 @@
 	case METHOD_GPIO_730:
 		reg += OMAP730_GPIO_DIR_CONTROL;
 		break;
+	case METHOD_GPIO_850:
+		reg += OMAP850_GPIO_DIR_CONTROL;
+		break;
 	case METHOD_GPIO_24XX:
 		reg += OMAP24XX_GPIO_OE;
 		break;
@@ -1762,7 +1860,8 @@
 
 		if (bank_is_mpuio(bank))
 			gpio = OMAP_MPUIO(0);
-		else if (cpu_class_is_omap2() || cpu_is_omap730())
+		else if (cpu_class_is_omap2() || cpu_is_omap730() ||
+				cpu_is_omap850())
 			bankwidth = 32;
 
 		for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 467531e..a303071 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -98,6 +98,8 @@
 static const int omap34xx_pins[][2] = {};
 #endif
 
+#define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
+
 static void __init omap_i2c_mux_pins(int bus)
 {
 	int scl, sda;
@@ -119,14 +121,9 @@
 	omap_cfg_reg(scl);
 }
 
-int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
-			  struct i2c_board_info const *info,
-			  unsigned len)
+static int __init omap_i2c_nr_ports(void)
 {
-	int ports, err;
-	struct platform_device *pdev;
-	struct resource *res;
-	resource_size_t base, irq;
+	int ports = 0;
 
 	if (cpu_class_is_omap1())
 		ports = 1;
@@ -135,17 +132,16 @@
 	else if (cpu_is_omap34xx())
 		ports = 3;
 
-	BUG_ON(bus_id < 1 || bus_id > ports);
+	return ports;
+}
 
-	if (info) {
-		err = i2c_register_board_info(bus_id, info, len);
-		if (err)
-			return err;
-	}
+static int __init omap_i2c_add_bus(int bus_id)
+{
+	struct platform_device *pdev;
+	struct resource *res;
+	resource_size_t base, irq;
 
 	pdev = &omap_i2c_devices[bus_id - 1];
-	*(u32 *)pdev->dev.platform_data = clkrate;
-
 	if (bus_id == 1) {
 		res = pdev->resource;
 		if (cpu_class_is_omap1()) {
@@ -163,3 +159,81 @@
 	omap_i2c_mux_pins(bus_id - 1);
 	return platform_device_register(pdev);
 }
+
+/**
+ * omap_i2c_bus_setup - Process command line options for the I2C bus speed
+ * @str: String of options
+ *
+ * This function allow to override the default I2C bus speed for given I2C
+ * bus with a command line option.
+ *
+ * Format: i2c_bus=bus_id,clkrate (in kHz)
+ *
+ * Returns 1 on success, 0 otherwise.
+ */
+static int __init omap_i2c_bus_setup(char *str)
+{
+	int ports;
+	int ints[3];
+
+	ports = omap_i2c_nr_ports();
+	get_options(str, 3, ints);
+	if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
+		return 0;
+	i2c_rate[ints[1] - 1] = ints[2];
+	i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP;
+
+	return 1;
+}
+__setup("i2c_bus=", omap_i2c_bus_setup);
+
+/*
+ * Register busses defined in command line but that are not registered with
+ * omap_register_i2c_bus from board initialization code.
+ */
+static int __init omap_register_i2c_bus_cmdline(void)
+{
+	int i, err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_rate); i++)
+		if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) {
+			i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP;
+			err = omap_i2c_add_bus(i + 1);
+			if (err)
+				goto out;
+		}
+
+out:
+	return err;
+}
+subsys_initcall(omap_register_i2c_bus_cmdline);
+
+/**
+ * omap_register_i2c_bus - register I2C bus with device descriptors
+ * @bus_id: bus id counting from number 1
+ * @clkrate: clock rate of the bus in kHz
+ * @info: pointer into I2C device descriptor table or NULL
+ * @len: number of descriptors in the table
+ *
+ * Returns 0 on success or an error code.
+ */
+int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
+			  struct i2c_board_info const *info,
+			  unsigned len)
+{
+	int err;
+
+	BUG_ON(bus_id < 1 || bus_id > omap_i2c_nr_ports());
+
+	if (info) {
+		err = i2c_register_board_info(bus_id, info, len);
+		if (err)
+			return err;
+	}
+
+	if (!i2c_rate[bus_id - 1])
+		i2c_rate[bus_id - 1] = clkrate;
+	i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP;
+
+	return omap_i2c_add_bus(bus_id);
+}
diff --git a/arch/arm/plat-omap/include/mach/board-2430sdp.h b/arch/arm/plat-omap/include/mach/board-2430sdp.h
deleted file mode 100644
index 10d449e..0000000
--- a/arch/arm/plat-omap/include/mach/board-2430sdp.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-2430sdp.h
- *
- * Hardware definitions for TI OMAP2430 SDP board.
- *
- * Based on board-h4.h by Dirk Behme <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 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 __ASM_ARCH_OMAP_2430SDP_H
-#define __ASM_ARCH_OMAP_2430SDP_H
-
-/* Placeholder for 2430SDP specific defines */
-#define OMAP24XX_ETHR_START		0x08000300
-#define OMAP24XX_ETHR_GPIO_IRQ		149
-#define SDP2430_CS0_BASE		0x04000000
-
-/* Function prototypes */
-extern void sdp2430_flash_init(void);
-extern void sdp2430_usb_init(void);
-
-#endif /* __ASM_ARCH_OMAP_2430SDP_H */
diff --git a/arch/arm/plat-omap/include/mach/board-apollon.h b/arch/arm/plat-omap/include/mach/board-apollon.h
deleted file mode 100644
index 61bd5e8..0000000
--- a/arch/arm/plat-omap/include/mach/board-apollon.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-apollon.h
- *
- * Hardware definitions for Samsung OMAP24XX Apollon board.
- *
- * Initial creation by Kyungmin Park <kyungmin.park@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.
- *
- * 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 __ASM_ARCH_OMAP_APOLLON_H
-#define __ASM_ARCH_OMAP_APOLLON_H
-
-#include <mach/cpu.h>
-
-extern void apollon_mmc_init(void);
-
-static inline int apollon_plus(void)
-{
-	/* The apollon plus has IDCODE revision 5 */
-	return omap_rev() & 0xc0;
-}
-
-/* Placeholder for APOLLON specific defines */
-#define APOLLON_ETHR_GPIO_IRQ		74
-
-#endif /*  __ASM_ARCH_OMAP_APOLLON_H */
-
diff --git a/arch/arm/plat-omap/include/mach/board-fsample.h b/arch/arm/plat-omap/include/mach/board-fsample.h
deleted file mode 100644
index cb3c5ae..0000000
--- a/arch/arm/plat-omap/include/mach/board-fsample.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-fsample.h
- *
- * Board-specific goodies for TI F-Sample.
- *
- * Copyright (C) 2006 Google, Inc.
- * Author: Brian Swetland <swetland@google.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 __ASM_ARCH_OMAP_FSAMPLE_H
-#define __ASM_ARCH_OMAP_FSAMPLE_H
-
-/* fsample is pretty close to p2-sample */
-#include <mach/board-perseus2.h>
-
-#define fsample_cpld_read(reg) __raw_readb(reg)
-#define fsample_cpld_write(val, reg) __raw_writeb(val, reg)
-
-#define FSAMPLE_CPLD_BASE    0xE8100000
-#define FSAMPLE_CPLD_SIZE    SZ_4K
-#define FSAMPLE_CPLD_START   0x05080000
-
-#define FSAMPLE_CPLD_REG_A   (FSAMPLE_CPLD_BASE + 0x00)
-#define FSAMPLE_CPLD_SWITCH  (FSAMPLE_CPLD_BASE + 0x02)
-#define FSAMPLE_CPLD_UART    (FSAMPLE_CPLD_BASE + 0x02)
-#define FSAMPLE_CPLD_REG_B   (FSAMPLE_CPLD_BASE + 0x04)
-#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06)
-#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06)
-
-#define FSAMPLE_CPLD_BIT_BT_RESET         0
-#define FSAMPLE_CPLD_BIT_LCD_RESET        1
-#define FSAMPLE_CPLD_BIT_CAM_PWDN         2
-#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE   3
-#define FSAMPLE_CPLD_BIT_SD_MMC_EN        4
-#define FSAMPLE_CPLD_BIT_aGPS_PWREN       5
-#define FSAMPLE_CPLD_BIT_BACKLIGHT        6
-#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET    7
-#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N    8
-#define FSAMPLE_CPLD_BIT_OTG_RESET        9
-
-#define fsample_cpld_set(bit) \
-    fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR)
-
-#define fsample_cpld_clear(bit) \
-    fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)
-
-#endif
diff --git a/arch/arm/plat-omap/include/mach/board-h4.h b/arch/arm/plat-omap/include/mach/board-h4.h
deleted file mode 100644
index 7c3fa0f..0000000
--- a/arch/arm/plat-omap/include/mach/board-h4.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-h4.h
- *
- * Hardware definitions for TI OMAP2420 H4 board.
- *
- * Initial creation by Dirk Behme <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 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 __ASM_ARCH_OMAP_H4_H
-#define __ASM_ARCH_OMAP_H4_H
-
-/* MMC Prototypes */
-extern void h4_mmc_init(void);
-
-/* Placeholder for H4 specific defines */
-#define OMAP24XX_ETHR_GPIO_IRQ		92
-#endif /*  __ASM_ARCH_OMAP_H4_H */
-
diff --git a/arch/arm/plat-omap/include/mach/board-innovator.h b/arch/arm/plat-omap/include/mach/board-innovator.h
deleted file mode 100644
index 5ae3e79..0000000
--- a/arch/arm/plat-omap/include/mach/board-innovator.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-innovator.h
- *
- * Copyright (C) 2001 RidgeRun, 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 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 __ASM_ARCH_OMAP_INNOVATOR_H
-#define __ASM_ARCH_OMAP_INNOVATOR_H
-
-#if defined (CONFIG_ARCH_OMAP15XX)
-
-#ifndef OMAP_SDRAM_DEVICE
-#define OMAP_SDRAM_DEVICE			D256M_1X16_4B
-#endif
-
-#define OMAP1510P1_IMIF_PRI_VALUE		0x00
-#define OMAP1510P1_EMIFS_PRI_VALUE		0x00
-#define OMAP1510P1_EMIFF_PRI_VALUE		0x00
-
-#ifndef __ASSEMBLY__
-void fpga_write(unsigned char val, int reg);
-unsigned char fpga_read(int reg);
-#endif
-
-#endif /* CONFIG_ARCH_OMAP15XX */
-
-#if defined (CONFIG_ARCH_OMAP16XX)
-
-/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
-#define INNOVATOR1610_ETHR_START	0x04000300
-
-#endif /* CONFIG_ARCH_OMAP1610 */
-#endif /* __ASM_ARCH_OMAP_INNOVATOR_H */
diff --git a/arch/arm/plat-omap/include/mach/board-ldp.h b/arch/arm/plat-omap/include/mach/board-ldp.h
deleted file mode 100644
index f233996..0000000
--- a/arch/arm/plat-omap/include/mach/board-ldp.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-ldp.h
- *
- * Hardware definitions for TI OMAP3 LDP.
- *
- * Copyright (C) 2008 Texas Instruments 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 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 __ASM_ARCH_OMAP_LDP_H
-#define __ASM_ARCH_OMAP_LDP_H
-
-extern void twl4030_bci_battery_init(void);
-
-#define TWL4030_IRQNUM		INT_34XX_SYS_NIRQ
-#define LDP_SMC911X_CS         1
-#define LDP_SMC911X_GPIO       152
-#define DEBUG_BASE             0x08000000
-#define OMAP34XX_ETHR_START    DEBUG_BASE
-#endif /* __ASM_ARCH_OMAP_LDP_H */
diff --git a/arch/arm/plat-omap/include/mach/board-nokia.h b/arch/arm/plat-omap/include/mach/board-nokia.h
deleted file mode 100644
index 2abbe00..0000000
--- a/arch/arm/plat-omap/include/mach/board-nokia.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/board-nokia.h
- *
- *  Information structures for Nokia-specific board config data
- *
- *  Copyright (C) 2005	Nokia Corporation
- */
-
-#ifndef _OMAP_BOARD_NOKIA_H
-#define _OMAP_BOARD_NOKIA_H
-
-#include <linux/types.h>
-
-#define OMAP_TAG_NOKIA_BT	0x4e01
-#define OMAP_TAG_WLAN_CX3110X	0x4e02
-#define OMAP_TAG_CBUS		0x4e03
-#define OMAP_TAG_EM_ASIC_BB5	0x4e04
-
-
-#define BT_CHIP_CSR		1
-#define BT_CHIP_TI		2
-
-#define BT_SYSCLK_12		1
-#define BT_SYSCLK_38_4		2
-
-struct omap_bluetooth_config {
-	u8    chip_type;
-	u8    bt_wakeup_gpio;
-	u8    host_wakeup_gpio;
-	u8    reset_gpio;
-	u8    bt_uart;
-	u8    bd_addr[6];
-	u8    bt_sysclk;
-};
-
-struct omap_wlan_cx3110x_config {
-	u8  chip_type;
-	s16 power_gpio;
-	s16 irq_gpio;
-	s16 spi_cs_gpio;
-};
-
-struct omap_cbus_config {
-	s16 clk_gpio;
-	s16 dat_gpio;
-	s16 sel_gpio;
-};
-
-struct omap_em_asic_bb5_config {
-	s16 retu_irq_gpio;
-	s16 tahvo_irq_gpio;
-};
-
-#endif
diff --git a/arch/arm/plat-omap/include/mach/board-omap3beagle.h b/arch/arm/plat-omap/include/mach/board-omap3beagle.h
deleted file mode 100644
index 3080d52..0000000
--- a/arch/arm/plat-omap/include/mach/board-omap3beagle.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-omap3beagle.h
- *
- * Hardware definitions for TI OMAP3 BEAGLE.
- *
- * Initial creation by Syed Mohammed Khasim <khasim@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.
- *
- * 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 __ASM_ARCH_OMAP3_BEAGLE_H
-#define __ASM_ARCH_OMAP3_BEAGLE_H
-
-#endif /* __ASM_ARCH_OMAP3_BEAGLE_H */
-
diff --git a/arch/arm/plat-omap/include/mach/board-osk.h b/arch/arm/plat-omap/include/mach/board-osk.h
deleted file mode 100644
index 3850cb1..0000000
--- a/arch/arm/plat-omap/include/mach/board-osk.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-osk.h
- *
- * Hardware definitions for TI OMAP5912 OSK board.
- *
- * Written by Dirk Behme <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 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 __ASM_ARCH_OMAP_OSK_H
-#define __ASM_ARCH_OMAP_OSK_H
-
-/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
-#define OMAP_OSK_ETHR_START		0x04800300
-
-/* TPS65010 has four GPIOs.  nPG and LED2 can be treated like GPIOs with
- * alternate pin configurations for hardware-controlled blinking.
- */
-#define OSK_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
-#	define OSK_TPS_GPIO_USB_PWR_EN	(OSK_TPS_GPIO_BASE + 0)
-#	define OSK_TPS_GPIO_LED_D3	(OSK_TPS_GPIO_BASE + 1)
-#	define OSK_TPS_GPIO_LAN_RESET	(OSK_TPS_GPIO_BASE + 2)
-#	define OSK_TPS_GPIO_DSP_PWR_EN	(OSK_TPS_GPIO_BASE + 3)
-#	define OSK_TPS_GPIO_LED_D9	(OSK_TPS_GPIO_BASE + 4)
-#	define OSK_TPS_GPIO_LED_D2	(OSK_TPS_GPIO_BASE + 5)
-
-#endif /*  __ASM_ARCH_OMAP_OSK_H */
-
diff --git a/arch/arm/plat-omap/include/mach/board-overo.h b/arch/arm/plat-omap/include/mach/board-overo.h
deleted file mode 100644
index 7ecae66..0000000
--- a/arch/arm/plat-omap/include/mach/board-overo.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * board-overo.h (Gumstix Overo)
- *
- * Initial code: 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 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.
- */
-
-#ifndef __ASM_ARCH_OVERO_H
-#define __ASM_ARCH_OVERO_H
-
-#define OVERO_GPIO_BT_XGATE	15
-#define OVERO_GPIO_W2W_NRESET	16
-#define OVERO_GPIO_BT_NRESET	164
-#define OVERO_GPIO_USBH_CPEN	168
-#define OVERO_GPIO_USBH_NRESET	183
-
-#endif /* ____ASM_ARCH_OVERO_H */
-
diff --git a/arch/arm/plat-omap/include/mach/board-palmte.h b/arch/arm/plat-omap/include/mach/board-palmte.h
deleted file mode 100644
index 6906cde..0000000
--- a/arch/arm/plat-omap/include/mach/board-palmte.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-palmte.h
- *
- * Hardware definitions for the Palm Tungsten E device.
- *
- * Maintainters :	http://palmtelinux.sf.net
- *			palmtelinux-developpers@lists.sf.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.
- */
-
-#ifndef __OMAP_BOARD_PALMTE_H
-#define __OMAP_BOARD_PALMTE_H
-
-#define PALMTE_USBDETECT_GPIO	0
-#define PALMTE_USB_OR_DC_GPIO	1
-#define PALMTE_TSC_GPIO		4
-#define PALMTE_PINTDAV_GPIO	6
-#define PALMTE_MMC_WP_GPIO	8
-#define PALMTE_MMC_POWER_GPIO	9
-#define PALMTE_HDQ_GPIO		11
-#define PALMTE_HEADPHONES_GPIO	14
-#define PALMTE_SPEAKER_GPIO	15
-#define PALMTE_DC_GPIO		OMAP_MPUIO(2)
-#define PALMTE_MMC_SWITCH_GPIO	OMAP_MPUIO(4)
-#define PALMTE_MMC1_GPIO	OMAP_MPUIO(6)
-#define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
-#define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
-
-#endif	/* __OMAP_BOARD_PALMTE_H */
diff --git a/arch/arm/plat-omap/include/mach/board-palmtt.h b/arch/arm/plat-omap/include/mach/board-palmtt.h
deleted file mode 100644
index e79f382..0000000
--- a/arch/arm/plat-omap/include/mach/board-palmtt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-palmte.h
- *
- * Hardware definitions for the Palm Tungsten|T device.
- *
- * Maintainters :	Marek Vasut <marek.vasut@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __OMAP_BOARD_PALMTT_H
-#define __OMAP_BOARD_PALMTT_H
-
-#define PALMTT_USBDETECT_GPIO	0
-#define PALMTT_CABLE_GPIO	1
-#define PALMTT_LED_GPIO		3
-#define PALMTT_PENIRQ_GPIO	6
-#define PALMTT_MMC_WP_GPIO	8
-#define PALMTT_HDQ_GPIO		11
-
-#endif	/* __OMAP_BOARD_PALMTT_H */
diff --git a/arch/arm/plat-omap/include/mach/board-palmz71.h b/arch/arm/plat-omap/include/mach/board-palmz71.h
deleted file mode 100644
index b1d7d57..0000000
--- a/arch/arm/plat-omap/include/mach/board-palmz71.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-palmz71.h
- *
- * Hardware definitions for the Palm Zire71 device.
- *
- * Maintainters :	Marek Vasut <marek.vasut@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __OMAP_BOARD_PALMZ71_H
-#define __OMAP_BOARD_PALMZ71_H
-
-#define PALMZ71_USBDETECT_GPIO	0
-#define PALMZ71_PENIRQ_GPIO	6
-#define PALMZ71_MMC_WP_GPIO	8
-#define PALMZ71_HDQ_GPIO 	11
-
-#define PALMZ71_HOTSYNC_GPIO	OMAP_MPUIO(1)
-#define PALMZ71_CABLE_GPIO	OMAP_MPUIO(2)
-#define PALMZ71_SLIDER_GPIO	OMAP_MPUIO(3)
-#define PALMZ71_MMC_IN_GPIO	OMAP_MPUIO(4)
-
-#endif	/* __OMAP_BOARD_PALMZ71_H */
diff --git a/arch/arm/plat-omap/include/mach/board-perseus2.h b/arch/arm/plat-omap/include/mach/board-perseus2.h
deleted file mode 100644
index c06c3d7..0000000
--- a/arch/arm/plat-omap/include/mach/board-perseus2.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/board-perseus2.h
- *
- *  Copyright 2003 by Texas Instruments Incorporated
- *    OMAP730 / Perseus2 support by Jean Pihet
- *
- * Copyright (C) 2001 RidgeRun, Inc. (http://www.ridgerun.com)
- * Author: RidgeRun, 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 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 __ASM_ARCH_OMAP_PERSEUS2_H
-#define __ASM_ARCH_OMAP_PERSEUS2_H
-
-#include <mach/fpga.h>
-
-#ifndef OMAP_SDRAM_DEVICE
-#define OMAP_SDRAM_DEVICE		D256M_1X16_4B
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/mach/board-voiceblue.h b/arch/arm/plat-omap/include/mach/board-voiceblue.h
index ed6d346..27916b2 100644
--- a/arch/arm/plat-omap/include/mach/board-voiceblue.h
+++ b/arch/arm/plat-omap/include/mach/board-voiceblue.h
@@ -14,7 +14,6 @@
 extern void voiceblue_wdt_enable(void);
 extern void voiceblue_wdt_disable(void);
 extern void voiceblue_wdt_ping(void);
-extern void voiceblue_reset(void);
 
 #endif /*  __ASM_ARCH_VOICEBLUE_H */
 
diff --git a/arch/arm/plat-omap/include/mach/board.h b/arch/arm/plat-omap/include/mach/board.h
index 9466772..50ea79a 100644
--- a/arch/arm/plat-omap/include/mach/board.h
+++ b/arch/arm/plat-omap/include/mach/board.h
@@ -17,7 +17,6 @@
 /* Different peripheral ids */
 #define OMAP_TAG_CLOCK		0x4f01
 #define OMAP_TAG_SERIAL_CONSOLE 0x4f03
-#define OMAP_TAG_USB		0x4f04
 #define OMAP_TAG_LCD		0x4f05
 #define OMAP_TAG_GPIO_SWITCH	0x4f06
 #define OMAP_TAG_UART		0x4f07
@@ -133,9 +132,6 @@
 	char version[12];
 };
 
-
-#include <mach/board-nokia.h>
-
 struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
diff --git a/arch/arm/plat-omap/include/mach/clkdev.h b/arch/arm/plat-omap/include/mach/clkdev.h
new file mode 100644
index 0000000..730c49d
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/clkdev.h
@@ -0,0 +1,13 @@
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk)
+{
+	return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h
index 7192985..073a2c5 100644
--- a/arch/arm/plat-omap/include/mach/clock.h
+++ b/arch/arm/plat-omap/include/mach/clock.h
@@ -17,11 +17,16 @@
 struct clk;
 struct clockdomain;
 
+struct clkops {
+	int			(*enable)(struct clk *);
+	void			(*disable)(struct clk *);
+};
+
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 
 struct clksel_rate {
-	u8			div;
 	u32			val;
+	u8			div;
 	u8			flags;
 };
 
@@ -34,24 +39,28 @@
 	void __iomem		*mult_div1_reg;
 	u32			mult_mask;
 	u32			div1_mask;
-	u16			last_rounded_m;
-	u8			last_rounded_n;
-	unsigned long		last_rounded_rate;
-	unsigned int		rate_tolerance;
-	u16			max_multiplier;
-	u8			max_divider;
-	u32			max_tolerance;
-#  if defined(CONFIG_ARCH_OMAP3)
-	u8			modes;
+	struct clk		*clk_bypass;
+	struct clk		*clk_ref;
 	void __iomem		*control_reg;
 	u32			enable_mask;
+	unsigned int		rate_tolerance;
+	unsigned long		last_rounded_rate;
+	u16			last_rounded_m;
+	u8			last_rounded_n;
+	u8			min_divider;
+	u8			max_divider;
+	u32			max_tolerance;
+	u16			max_multiplier;
+#  if defined(CONFIG_ARCH_OMAP3)
+	u8			modes;
+	void __iomem		*autoidle_reg;
+	void __iomem		*idlest_reg;
+	u32			autoidle_mask;
+	u32			freqsel_mask;
+	u32			idlest_mask;
 	u8			auto_recal_bit;
 	u8			recal_en_bit;
 	u8			recal_st_bit;
-	void __iomem		*autoidle_reg;
-	u32			autoidle_mask;
-	void __iomem		*idlest_reg;
-	u8			idlest_bit;
 #  endif
 };
 
@@ -59,21 +68,21 @@
 
 struct clk {
 	struct list_head	node;
-	struct module		*owner;
+	const struct clkops	*ops;
 	const char		*name;
 	int			id;
 	struct clk		*parent;
+	struct list_head	children;
+	struct list_head	sibling;	/* node for children */
 	unsigned long		rate;
 	__u32			flags;
 	void __iomem		*enable_reg;
-	__u8			enable_bit;
-	__s8			usecount;
-	void			(*recalc)(struct clk *);
+	unsigned long		(*recalc)(struct clk *);
 	int			(*set_rate)(struct clk *, unsigned long);
 	long			(*round_rate)(struct clk *, unsigned long);
 	void			(*init)(struct clk *);
-	int			(*enable)(struct clk *);
-	void			(*disable)(struct clk *);
+	__u8			enable_bit;
+	__s8			usecount;
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 	u8			fixed_div;
 	void __iomem		*clksel_reg;
@@ -99,7 +108,6 @@
 	long		(*clk_round_rate)(struct clk *clk, unsigned long rate);
 	int		(*clk_set_rate)(struct clk *clk, unsigned long rate);
 	int		(*clk_set_parent)(struct clk *clk, struct clk *parent);
-	struct clk *	(*clk_get_parent)(struct clk *clk);
 	void		(*clk_allow_idle)(struct clk *clk);
 	void		(*clk_deny_idle)(struct clk *clk);
 	void		(*clk_disable_unused)(struct clk *clk);
@@ -110,42 +118,33 @@
 
 extern unsigned int mpurate;
 
-extern int clk_init(struct clk_functions * custom_clocks);
+extern int clk_init(struct clk_functions *custom_clocks);
+extern void clk_init_one(struct clk *clk);
 extern int clk_register(struct clk *clk);
+extern void clk_reparent(struct clk *child, struct clk *parent);
 extern void clk_unregister(struct clk *clk);
 extern void propagate_rate(struct clk *clk);
 extern void recalculate_root_clocks(void);
-extern void followparent_recalc(struct clk * clk);
-extern void clk_allow_idle(struct clk *clk);
-extern void clk_deny_idle(struct clk *clk);
-extern int clk_get_usecount(struct clk *clk);
+extern unsigned long followparent_recalc(struct clk *clk);
 extern void clk_enable_init_clocks(void);
+#ifdef CONFIG_CPU_FREQ
+extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+#endif
+
+extern const struct clkops clkops_null;
 
 /* Clock flags */
-#define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
+/* bit 0 is free */
 #define RATE_FIXED		(1 << 1)	/* Fixed clock rate */
-#define RATE_PROPAGATES		(1 << 2)	/* Program children too */
-#define VIRTUAL_CLOCK		(1 << 3)	/* Composite clock from table */
-#define ALWAYS_ENABLED		(1 << 4)	/* Clock cannot be disabled */
+/* bits 2-4 are free */
 #define ENABLE_REG_32BIT	(1 << 5)	/* Use 32-bit access */
-#define VIRTUAL_IO_ADDRESS	(1 << 6)	/* Clock in virtual address */
 #define CLOCK_IDLE_CONTROL	(1 << 7)
 #define CLOCK_NO_IDLE_PARENT	(1 << 8)
 #define DELAYED_APP		(1 << 9)	/* Delay application of clock */
 #define CONFIG_PARTICIPANT	(1 << 10)	/* Fundamental clock */
 #define ENABLE_ON_INIT		(1 << 11)	/* Enable upon framework init */
 #define INVERT_ENABLE           (1 << 12)       /* 0 enables, 1 disables */
-/* bits 13-20 are currently free */
-#define CLOCK_IN_OMAP310	(1 << 21)
-#define CLOCK_IN_OMAP730	(1 << 22)
-#define CLOCK_IN_OMAP1510	(1 << 23)
-#define CLOCK_IN_OMAP16XX	(1 << 24)
-#define CLOCK_IN_OMAP242X	(1 << 25)
-#define CLOCK_IN_OMAP243X	(1 << 26)
-#define CLOCK_IN_OMAP343X	(1 << 27)	/* clocks common to all 343X */
-#define PARENT_CONTROLS_CLOCK	(1 << 28)
-#define CLOCK_IN_OMAP3430ES1	(1 << 29)	/* 3430ES1 clocks only */
-#define CLOCK_IN_OMAP3430ES2	(1 << 30)	/* 3430ES2 clocks only */
+/* bits 13-31 are currently free */
 
 /* Clksel_rate flags */
 #define DEFAULT_RATE		(1 << 0)
@@ -157,9 +156,4 @@
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
 
 
-/* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
-#define CORE_CLK_SRC_32K		0
-#define CORE_CLK_SRC_DPLL		1
-#define CORE_CLK_SRC_DPLL_X2		2
-
 #endif
diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h
index 1f51f01..b9d0dd2 100644
--- a/arch/arm/plat-omap/include/mach/clockdomain.h
+++ b/arch/arm/plat-omap/include/mach/clockdomain.h
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-omap/clockdomain.h
+ * arch/arm/plat-omap/include/mach/clockdomain.h
  *
  * OMAP2/3 clockdomain framework functions
  *
@@ -48,11 +48,13 @@
  */
 struct clkdm_pwrdm_autodep {
 
-	/* Name of the powerdomain to add a wkdep/sleepdep on */
-	const char *pwrdm_name;
+	union {
+		/* Name of the powerdomain to add a wkdep/sleepdep on */
+		const char *name;
 
-	/* Powerdomain pointer (looked up at clkdm_init() time) */
-	struct powerdomain *pwrdm;
+		/* Powerdomain pointer (looked up at clkdm_init() time) */
+		struct powerdomain *ptr;
+	} pwrdm;
 
 	/* OMAP chip types that this clockdomain dep is valid on */
 	const struct omap_chip_id omap_chip;
@@ -64,8 +66,13 @@
 	/* Clockdomain name */
 	const char *name;
 
-	/* Powerdomain enclosing this clockdomain */
-	const char *pwrdm_name;
+	union {
+		/* Powerdomain enclosing this clockdomain */
+		const char *name;
+
+		/* Powerdomain pointer assigned at clkdm_register() */
+		struct powerdomain *ptr;
+	} pwrdm;
 
 	/* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
 	const u16 clktrctrl_mask;
@@ -79,9 +86,6 @@
 	/* Usecount tracking */
 	atomic_t usecount;
 
-	/* Powerdomain pointer assigned at clkdm_register() */
-	struct powerdomain *pwrdm;
-
 	struct list_head node;
 
 };
diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h
index e746ec7..0ecf36d 100644
--- a/arch/arm/plat-omap/include/mach/common.h
+++ b/arch/arm/plat-omap/include/mach/common.h
@@ -65,7 +65,7 @@
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
 void omap2_set_globals_tap(struct omap_globals *);
-void omap2_set_globals_memory(struct omap_globals *);
+void omap2_set_globals_sdrc(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 
diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h
index a8e1178..98b1442 100644
--- a/arch/arm/plat-omap/include/mach/cpu.h
+++ b/arch/arm/plat-omap/include/mach/cpu.h
@@ -56,6 +56,14 @@
 #  define OMAP_NAME omap730
 # endif
 #endif
+#ifdef CONFIG_ARCH_OMAP850
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP1
+#  define MULTI_OMAP1
+# else
+#  define OMAP_NAME omap850
+# endif
+#endif
 #ifdef CONFIG_ARCH_OMAP15XX
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP1
@@ -105,7 +113,7 @@
 /*
  * Macros to group OMAP into cpu classes.
  * These can be used in most places.
- * cpu_is_omap7xx():	True for OMAP730
+ * cpu_is_omap7xx():	True for OMAP730, OMAP850
  * cpu_is_omap15xx():	True for OMAP1510, OMAP5910 and OMAP310
  * cpu_is_omap16xx():	True for OMAP1610, OMAP5912 and OMAP1710
  * cpu_is_omap24xx():	True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
@@ -153,6 +161,10 @@
 #  undef  cpu_is_omap7xx
 #  define cpu_is_omap7xx()		is_omap7xx()
 # endif
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		is_omap7xx()
+# endif
 # if defined(CONFIG_ARCH_OMAP15XX)
 #  undef  cpu_is_omap15xx
 #  define cpu_is_omap15xx()		is_omap15xx()
@@ -166,6 +178,10 @@
 #  undef  cpu_is_omap7xx
 #  define cpu_is_omap7xx()		1
 # endif
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap7xx
+#  define cpu_is_omap7xx()		1
+# endif
 # if defined(CONFIG_ARCH_OMAP15XX)
 #  undef  cpu_is_omap15xx
 #  define cpu_is_omap15xx()		1
@@ -219,6 +235,7 @@
  * These are only rarely needed.
  * cpu_is_omap330():	True for OMAP330
  * cpu_is_omap730():	True for OMAP730
+ * cpu_is_omap850():	True for OMAP850
  * cpu_is_omap1510():	True for OMAP1510
  * cpu_is_omap1610():	True for OMAP1610
  * cpu_is_omap1611():	True for OMAP1611
@@ -241,6 +258,7 @@
 
 IS_OMAP_TYPE(310, 0x0310)
 IS_OMAP_TYPE(730, 0x0730)
+IS_OMAP_TYPE(850, 0x0850)
 IS_OMAP_TYPE(1510, 0x1510)
 IS_OMAP_TYPE(1610, 0x1610)
 IS_OMAP_TYPE(1611, 0x1611)
@@ -255,6 +273,7 @@
 
 #define cpu_is_omap310()		0
 #define cpu_is_omap730()		0
+#define cpu_is_omap850()		0
 #define cpu_is_omap1510()		0
 #define cpu_is_omap1610()		0
 #define cpu_is_omap5912()		0
@@ -272,12 +291,22 @@
 #  undef  cpu_is_omap730
 #  define cpu_is_omap730()		is_omap730()
 # endif
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap850
+#  define cpu_is_omap850()		is_omap850()
+# endif
 #else
 # if defined(CONFIG_ARCH_OMAP730)
 #  undef  cpu_is_omap730
 #  define cpu_is_omap730()		1
 # endif
 #endif
+#else
+# if defined(CONFIG_ARCH_OMAP850)
+#  undef  cpu_is_omap850
+#  define cpu_is_omap850()		1
+# endif
+#endif
 
 /*
  * Whether we have MULTI_OMAP1 or not, we still need to distinguish
@@ -320,7 +349,7 @@
 #endif
 
 /* Macros to detect if we have OMAP1 or OMAP2 */
-#define cpu_class_is_omap1()	(cpu_is_omap730() || cpu_is_omap15xx() || \
+#define cpu_class_is_omap1()	(cpu_is_omap7xx() || cpu_is_omap15xx() || \
 				cpu_is_omap16xx())
 #define cpu_class_is_omap2()	(cpu_is_omap24xx() || cpu_is_omap34xx())
 
@@ -355,13 +384,27 @@
  * use omap_chip_is().
  *
  */
-#define CHIP_IS_OMAP2420       (1 << 0)
-#define CHIP_IS_OMAP2430       (1 << 1)
-#define CHIP_IS_OMAP3430       (1 << 2)
-#define CHIP_IS_OMAP3430ES1    (1 << 3)
-#define CHIP_IS_OMAP3430ES2    (1 << 4)
+#define CHIP_IS_OMAP2420		(1 << 0)
+#define CHIP_IS_OMAP2430		(1 << 1)
+#define CHIP_IS_OMAP3430		(1 << 2)
+#define CHIP_IS_OMAP3430ES1		(1 << 3)
+#define CHIP_IS_OMAP3430ES2		(1 << 4)
+#define CHIP_IS_OMAP3430ES3_0		(1 << 5)
+#define CHIP_IS_OMAP3430ES3_1		(1 << 6)
 
-#define CHIP_IS_OMAP24XX       (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
+#define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
+
+/*
+ * "GE" here represents "greater than or equal to" in terms of ES
+ * levels.  So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430
+ * chips at ES2 and beyond, but not, for example, any OMAP lines after
+ * OMAP3.
+ */
+#define CHIP_GE_OMAP3430ES2		(CHIP_IS_OMAP3430ES2 | \
+					 CHIP_IS_OMAP3430ES3_0 | \
+					 CHIP_IS_OMAP3430ES3_1)
+#define CHIP_GE_OMAP3430ES3_1		(CHIP_IS_OMAP3430ES3_1)
+
 
 int omap_chip_is(struct omap_chip_id oci);
 int omap_type(void);
@@ -378,5 +421,3 @@
 void omap2_check_revision(void);
 
 #endif    /* defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) */
-
-#endif
diff --git a/arch/arm/plat-omap/include/mach/gpio.h b/arch/arm/plat-omap/include/mach/gpio.h
index 8d9dfe3..2b22a87 100644
--- a/arch/arm/plat-omap/include/mach/gpio.h
+++ b/arch/arm/plat-omap/include/mach/gpio.h
@@ -31,7 +31,8 @@
 
 #define OMAP_MPUIO_BASE			0xfffb5000
 
-#ifdef CONFIG_ARCH_OMAP730
+#if (defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850))
+
 #define OMAP_MPUIO_INPUT_LATCH		0x00
 #define OMAP_MPUIO_OUTPUT		0x02
 #define OMAP_MPUIO_IO_CNTL		0x04
diff --git a/arch/arm/plat-omap/include/mach/gpmc.h b/arch/arm/plat-omap/include/mach/gpmc.h
index 45b6784..921b165 100644
--- a/arch/arm/plat-omap/include/mach/gpmc.h
+++ b/arch/arm/plat-omap/include/mach/gpmc.h
@@ -103,6 +103,6 @@
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
-extern void gpmc_init(void);
+extern void __init gpmc_init(void);
 
 #endif
diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h
index 6589ddb..3dc423e 100644
--- a/arch/arm/plat-omap/include/mach/hardware.h
+++ b/arch/arm/plat-omap/include/mach/hardware.h
@@ -286,78 +286,4 @@
 #include "omap24xx.h"
 #include "omap34xx.h"
 
-#ifndef __ASSEMBLER__
-
-/*
- * ---------------------------------------------------------------------------
- * Board specific defines
- * ---------------------------------------------------------------------------
- */
-
-#ifdef CONFIG_MACH_OMAP_INNOVATOR
-#include "board-innovator.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_H2
-#include "board-h2.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_PERSEUS2
-#include "board-perseus2.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_FSAMPLE
-#include "board-fsample.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_H3
-#include "board-h3.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_H4
-#include "board-h4.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_2430SDP
-#include "board-2430sdp.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP3_BEAGLE
-#include "board-omap3beagle.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_LDP
-#include "board-ldp.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_APOLLON
-#include "board-apollon.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_OSK
-#include "board-osk.h"
-#endif
-
-#ifdef CONFIG_MACH_VOICEBLUE
-#include "board-voiceblue.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_PALMTE
-#include "board-palmte.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_PALMZ71
-#include "board-palmz71.h"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_PALMTT
-#include "board-palmtt.h"
-#endif
-
-#ifdef CONFIG_MACH_SX1
-#include "board-sx1.h"
-#endif
-
-#endif /* !__ASSEMBLER__ */
-
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h
index d92bf79..0610d7e 100644
--- a/arch/arm/plat-omap/include/mach/io.h
+++ b/arch/arm/plat-omap/include/mach/io.h
@@ -185,11 +185,13 @@
 #define omap_writew(v,a)	__raw_writew(v, IO_ADDRESS(a))
 #define omap_writel(v,a)	__raw_writel(v, IO_ADDRESS(a))
 
+struct omap_sdrc_params;
+
 extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
 
 extern void omap2_map_common_io(void);
-extern void omap2_init_common_hw(void);
+extern void omap2_init_common_hw(struct omap_sdrc_params *sp);
 
 #define __arch_ioremap(p,s,t)	omap_ioremap(p,s,t)
 #define __arch_iounmap(v)	omap_iounmap(v)
diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h
index bed5274..7f57ee6 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -105,6 +105,29 @@
 #define INT_730_SPGIO_WR	29
 
 /*
+ * OMAP-850 specific IRQ numbers for interrupt handler 1
+ */
+#define INT_850_IH2_FIQ		0
+#define INT_850_IH2_IRQ		1
+#define INT_850_USB_NON_ISO	2
+#define INT_850_USB_ISO		3
+#define INT_850_ICR		4
+#define INT_850_EAC		5
+#define INT_850_GPIO_BANK1	6
+#define INT_850_GPIO_BANK2	7
+#define INT_850_GPIO_BANK3	8
+#define INT_850_McBSP2TX	10
+#define INT_850_McBSP2RX	11
+#define INT_850_McBSP2RX_OVF	12
+#define INT_850_LCD_LINE	14
+#define INT_850_GSM_PROTECT	15
+#define INT_850_TIMER3		16
+#define INT_850_GPIO_BANK5	17
+#define INT_850_GPIO_BANK6	18
+#define INT_850_SPGIO_WR	29
+
+
+/*
  * IRQ numbers for interrupt handler 2
  *
  * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
@@ -237,6 +260,64 @@
 #define INT_730_DMA_CH15	(62 + IH2_BASE)
 #define INT_730_NAND		(63 + IH2_BASE)
 
+/*
+ * OMAP-850 specific IRQ numbers for interrupt handler 2
+ */
+#define INT_850_HW_ERRORS	(0 + IH2_BASE)
+#define INT_850_NFIQ_PWR_FAIL	(1 + IH2_BASE)
+#define INT_850_CFCD		(2 + IH2_BASE)
+#define INT_850_CFIREQ		(3 + IH2_BASE)
+#define INT_850_I2C		(4 + IH2_BASE)
+#define INT_850_PCC		(5 + IH2_BASE)
+#define INT_850_MPU_EXT_NIRQ	(6 + IH2_BASE)
+#define INT_850_SPI_100K_1	(7 + IH2_BASE)
+#define INT_850_SYREN_SPI	(8 + IH2_BASE)
+#define INT_850_VLYNQ		(9 + IH2_BASE)
+#define INT_850_GPIO_BANK4	(10 + IH2_BASE)
+#define INT_850_McBSP1TX	(11 + IH2_BASE)
+#define INT_850_McBSP1RX	(12 + IH2_BASE)
+#define INT_850_McBSP1RX_OF	(13 + IH2_BASE)
+#define INT_850_UART_MODEM_IRDA_2 (14 + IH2_BASE)
+#define INT_850_UART_MODEM_1	(15 + IH2_BASE)
+#define INT_850_MCSI		(16 + IH2_BASE)
+#define INT_850_uWireTX		(17 + IH2_BASE)
+#define INT_850_uWireRX		(18 + IH2_BASE)
+#define INT_850_SMC_CD		(19 + IH2_BASE)
+#define INT_850_SMC_IREQ	(20 + IH2_BASE)
+#define INT_850_HDQ_1WIRE	(21 + IH2_BASE)
+#define INT_850_TIMER32K	(22 + IH2_BASE)
+#define INT_850_MMC_SDIO	(23 + IH2_BASE)
+#define INT_850_UPLD		(24 + IH2_BASE)
+#define INT_850_USB_HHC_1	(27 + IH2_BASE)
+#define INT_850_USB_HHC_2	(28 + IH2_BASE)
+#define INT_850_USB_GENI	(29 + IH2_BASE)
+#define INT_850_USB_OTG		(30 + IH2_BASE)
+#define INT_850_CAMERA_IF	(31 + IH2_BASE)
+#define INT_850_RNG		(32 + IH2_BASE)
+#define INT_850_DUAL_MODE_TIMER (33 + IH2_BASE)
+#define INT_850_DBB_RF_EN	(34 + IH2_BASE)
+#define INT_850_MPUIO_KEYPAD	(35 + IH2_BASE)
+#define INT_850_SHA1_MD5	(36 + IH2_BASE)
+#define INT_850_SPI_100K_2	(37 + IH2_BASE)
+#define INT_850_RNG_IDLE	(38 + IH2_BASE)
+#define INT_850_MPUIO		(39 + IH2_BASE)
+#define INT_850_LLPC_LCD_CTRL_CAN_BE_OFF	(40 + IH2_BASE)
+#define INT_850_LLPC_OE_FALLING (41 + IH2_BASE)
+#define INT_850_LLPC_OE_RISING	(42 + IH2_BASE)
+#define INT_850_LLPC_VSYNC	(43 + IH2_BASE)
+#define INT_850_WAKE_UP_REQ	(46 + IH2_BASE)
+#define INT_850_DMA_CH6		(53 + IH2_BASE)
+#define INT_850_DMA_CH7		(54 + IH2_BASE)
+#define INT_850_DMA_CH8		(55 + IH2_BASE)
+#define INT_850_DMA_CH9		(56 + IH2_BASE)
+#define INT_850_DMA_CH10	(57 + IH2_BASE)
+#define INT_850_DMA_CH11	(58 + IH2_BASE)
+#define INT_850_DMA_CH12	(59 + IH2_BASE)
+#define INT_850_DMA_CH13	(60 + IH2_BASE)
+#define INT_850_DMA_CH14	(61 + IH2_BASE)
+#define INT_850_DMA_CH15	(62 + IH2_BASE)
+#define INT_850_NAND		(63 + IH2_BASE)
+
 #define INT_24XX_SYS_NIRQ	7
 #define INT_24XX_SDMA_IRQ0	12
 #define INT_24XX_SDMA_IRQ1	13
@@ -341,7 +422,7 @@
 
 #define	INT_34XX_BENCH_MPU_EMUL	3
 
-/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
+/* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and
  * 16 MPUIO lines */
 #define OMAP_MAX_GPIO_LINES	192
 #define IH_GPIO_BASE		(128 + IH2_BASE)
diff --git a/arch/arm/plat-omap/include/mach/mailbox.h b/arch/arm/plat-omap/include/mach/mailbox.h
index 7cbed93..b7a6991 100644
--- a/arch/arm/plat-omap/include/mach/mailbox.h
+++ b/arch/arm/plat-omap/include/mach/mailbox.h
@@ -33,6 +33,9 @@
 	void		(*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
 	void		(*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
 	int		(*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
+	/* ctx */
+	void		(*save_ctx)(struct omap_mbox *mbox);
+	void		(*restore_ctx)(struct omap_mbox *mbox);
 };
 
 struct omap_mbox_queue {
@@ -53,7 +56,7 @@
 
 	mbox_msg_t		seq_snd, seq_rcv;
 
-	struct device		dev;
+	struct device		*dev;
 
 	struct omap_mbox	*next;
 	void			*priv;
@@ -67,7 +70,27 @@
 struct omap_mbox *omap_mbox_get(const char *);
 void omap_mbox_put(struct omap_mbox *);
 
-int omap_mbox_register(struct omap_mbox *);
+int omap_mbox_register(struct device *parent, struct omap_mbox *);
 int omap_mbox_unregister(struct omap_mbox *);
 
+static inline void omap_mbox_save_ctx(struct omap_mbox *mbox)
+{
+	if (!mbox->ops->save_ctx) {
+		dev_err(mbox->dev, "%s:\tno save\n", __func__);
+		return;
+	}
+
+	mbox->ops->save_ctx(mbox);
+}
+
+static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
+{
+	if (!mbox->ops->restore_ctx) {
+		dev_err(mbox->dev, "%s:\tno restore\n", __func__);
+		return;
+	}
+
+	mbox->ops->restore_ctx(mbox);
+}
+
 #endif /* MAILBOX_H */
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h
index 113c246..bb154ea 100644
--- a/arch/arm/plat-omap/include/mach/mcbsp.h
+++ b/arch/arm/plat-omap/include/mach/mcbsp.h
@@ -344,8 +344,6 @@
 	u8 dma_rx_sync, dma_tx_sync;
 	u16 rx_irq, tx_irq;
 	struct omap_mcbsp_ops *ops;
-	char const **clk_names;
-	int num_clks;
 };
 
 struct omap_mcbsp {
@@ -377,8 +375,8 @@
 	/* Protect the field .free, while checking if the mcbsp is in use */
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
-	struct clk **clks;
-	int num_clks;
+	struct clk *iclk;
+	struct clk *fclk;
 };
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count;
diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h
index d6b5ca6..99ed564 100644
--- a/arch/arm/plat-omap/include/mach/memory.h
+++ b/arch/arm/plat-omap/include/mach/memory.h
@@ -61,9 +61,11 @@
 #define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
 #define is_lbus_device(dev)	(cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
 
-#define __arch_page_to_dma(dev, page)	({is_lbus_device(dev) ? \
-					(dma_addr_t)virt_to_lbus(page_address(page)) : \
-					(dma_addr_t)__virt_to_phys(page_address(page));})
+#define __arch_page_to_dma(dev, page)	\
+	({ dma_addr_t __dma = page_to_phys(page); \
+	   if (is_lbus_device(dev)) \
+		__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
+	   __dma; })
 
 #define __arch_dma_to_virt(dev, addr)	({ (void *) (is_lbus_device(dev) ? \
 						lbus_to_virt(addr) : \
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h
index 73a9e15..4435bd4 100644
--- a/arch/arm/plat-omap/include/mach/mmc.h
+++ b/arch/arm/plat-omap/include/mach/mmc.h
@@ -37,6 +37,8 @@
 #define OMAP_MMC_MAX_SLOTS	2
 
 struct omap_mmc_platform_data {
+	/* back-link to device */
+	struct device *dev;
 
 	/* number of slots per controller */
 	unsigned nr_slots:2;
diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h
index f4362b8..85a6217 100644
--- a/arch/arm/plat-omap/include/mach/mux.h
+++ b/arch/arm/plat-omap/include/mach/mux.h
@@ -61,6 +61,16 @@
 					.pull_bit = bit, \
 					.pull_val = status,
 
+#define MUX_REG_850(reg, mode_offset, mode) .mux_reg_name = "OMAP850_IO_CONF_"#reg, \
+					.mux_reg = OMAP850_IO_CONF_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG_850(reg, bit, status)	.pull_name = "OMAP850_IO_CONF_"#reg, \
+					.pull_reg = OMAP850_IO_CONF_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
 #else
 
 #define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \
@@ -83,6 +93,15 @@
 					.pull_bit = bit, \
 					.pull_val = status,
 
+#define MUX_REG_850(reg, mode_offset, mode) \
+					.mux_reg = OMAP850_IO_CONF_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG_850(reg, bit, status)	.pull_reg = OMAP850_IO_CONF_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
 #endif /* CONFIG_OMAP_MUX_DEBUG */
 
 #define MUX_CFG(desc, mux_reg, mode_offset, mode,	\
@@ -98,7 +117,7 @@
 
 
 /*
- * OMAP730 has a slightly different config for the pin mux.
+ * OMAP730/850 has a slightly different config for the pin mux.
  * - config regs are the OMAP730_IO_CONF_x regs (see omap730.h) regs and
  *   not the FUNC_MUX_CTRL_x regs from hardware.h
  * - for pull-up/down, only has one enable bit which is is in the same register
@@ -114,6 +133,17 @@
 	PU_PD_REG(NA, 0)		\
 },
 
+#define MUX_CFG_850(desc, mux_reg, mode_offset, mode,	\
+		   pull_bit, pull_status, debug_status)\
+{							\
+	.name =	 desc,					\
+	.debug = debug_status,				\
+	MUX_REG_850(mux_reg, mode_offset, mode)		\
+	PULL_REG_850(mux_reg, pull_bit, pull_status)	\
+	PU_PD_REG(NA, 0)		\
+},
+
+
 #define MUX_CFG_24XX(desc, reg_offset, mode,			\
 				pull_en, pull_mode, dbg)	\
 {								\
@@ -221,6 +251,26 @@
 	W17_730_USB_VBUSI,
 };
 
+enum omap850_index {
+	/* OMAP 850 keyboard */
+	E2_850_KBR0,
+	J7_850_KBR1,
+	E1_850_KBR2,
+	F3_850_KBR3,
+	D2_850_KBR4,
+	C2_850_KBC0,
+	D3_850_KBC1,
+	E4_850_KBC2,
+	F4_850_KBC3,
+	E3_850_KBC4,
+
+	/* USB */
+	AA17_850_USB_DM,
+	W16_850_USB_PU_EN,
+	W17_850_USB_VBUSI,
+};
+
+
 enum omap1xxx_index {
 	/* UART1 (BT_UART_GATING)*/
 	UART1_TX = 0,
@@ -788,7 +838,20 @@
 	 *  - "_DOWN" suffix (GPIO3_DOWN) with internal pulldown
 	 *  - "_OUT" suffix (GPIO3_OUT) for output-only pins (unlike 24xx)
 	 */
+	AF26_34XX_GPIO0,
+	AF22_34XX_GPIO9,
 	AH8_34XX_GPIO29,
+	U8_34XX_GPIO54_OUT,
+	U8_34XX_GPIO54_DOWN,
+	L8_34XX_GPIO63,
+	G25_34XX_GPIO86_OUT,
+	AG4_34XX_GPIO134_OUT,
+	AE4_34XX_GPIO136_OUT,
+	AF6_34XX_GPIO140_UP,
+	AE6_34XX_GPIO141,
+	AF5_34XX_GPIO142,
+	AE5_34XX_GPIO143,
+	H19_34XX_GPIO164_OUT,
 	J25_34XX_GPIO170,
 };
 
diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h
index 8e0479f..ab64015 100644
--- a/arch/arm/plat-omap/include/mach/omap34xx.h
+++ b/arch/arm/plat-omap/include/mach/omap34xx.h
@@ -49,11 +49,39 @@
 #define OMAP343X_CTRL_BASE	OMAP343X_SCM_BASE
 
 #define OMAP34XX_IC_BASE	0x48200000
+
+#define OMAP3430_ISP_BASE		(L4_34XX_BASE + 0xBC000)
+#define OMAP3430_ISP_CBUFF_BASE		(OMAP3430_ISP_BASE + 0x0100)
+#define OMAP3430_ISP_CCP2_BASE		(OMAP3430_ISP_BASE + 0x0400)
+#define OMAP3430_ISP_CCDC_BASE		(OMAP3430_ISP_BASE + 0x0600)
+#define OMAP3430_ISP_HIST_BASE		(OMAP3430_ISP_BASE + 0x0A00)
+#define OMAP3430_ISP_H3A_BASE		(OMAP3430_ISP_BASE + 0x0C00)
+#define OMAP3430_ISP_PREV_BASE		(OMAP3430_ISP_BASE + 0x0E00)
+#define OMAP3430_ISP_RESZ_BASE		(OMAP3430_ISP_BASE + 0x1000)
+#define OMAP3430_ISP_SBL_BASE		(OMAP3430_ISP_BASE + 0x1200)
+#define OMAP3430_ISP_MMU_BASE		(OMAP3430_ISP_BASE + 0x1400)
+#define OMAP3430_ISP_CSI2A_BASE		(OMAP3430_ISP_BASE + 0x1800)
+#define OMAP3430_ISP_CSI2PHY_BASE	(OMAP3430_ISP_BASE + 0x1970)
+
+#define OMAP3430_ISP_END		(OMAP3430_ISP_BASE         + 0x06F)
+#define OMAP3430_ISP_CBUFF_END		(OMAP3430_ISP_CBUFF_BASE   + 0x077)
+#define OMAP3430_ISP_CCP2_END		(OMAP3430_ISP_CCP2_BASE    + 0x1EF)
+#define OMAP3430_ISP_CCDC_END		(OMAP3430_ISP_CCDC_BASE    + 0x0A7)
+#define OMAP3430_ISP_HIST_END		(OMAP3430_ISP_HIST_BASE    + 0x047)
+#define OMAP3430_ISP_H3A_END		(OMAP3430_ISP_H3A_BASE     + 0x05F)
+#define OMAP3430_ISP_PREV_END		(OMAP3430_ISP_PREV_BASE    + 0x09F)
+#define OMAP3430_ISP_RESZ_END		(OMAP3430_ISP_RESZ_BASE    + 0x0AB)
+#define OMAP3430_ISP_SBL_END		(OMAP3430_ISP_SBL_BASE     + 0x0FB)
+#define OMAP3430_ISP_MMU_END		(OMAP3430_ISP_MMU_BASE     + 0x06F)
+#define OMAP3430_ISP_CSI2A_END		(OMAP3430_ISP_CSI2A_BASE   + 0x16F)
+#define OMAP3430_ISP_CSI2PHY_END	(OMAP3430_ISP_CSI2PHY_BASE + 0x007)
+
 #define OMAP34XX_IVA_INTC_BASE	0x40000000
 #define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
 #define OMAP34XX_HSUSB_HOST_BASE	(L4_34XX_BASE + 0x64000)
 #define OMAP34XX_USBTLL_BASE	(L4_34XX_BASE + 0x62000)
 
+#define OMAP34XX_MAILBOX_BASE		(L4_34XX_BASE + 0x94000)
 
 #if defined(CONFIG_ARCH_OMAP3430)
 
diff --git a/arch/arm/plat-omap/include/mach/omap850.h b/arch/arm/plat-omap/include/mach/omap850.h
new file mode 100644
index 0000000..c33f679
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/omap850.h
@@ -0,0 +1,102 @@
+/* arch/arm/plat-omap/include/mach/omap850.h
+ *
+ * Hardware definitions for TI OMAP850 processor.
+ *
+ * Derived from omap730.h by Zebediah C. McClure <zmc@lurian.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 __ASM_ARCH_OMAP850_H
+#define __ASM_ARCH_OMAP850_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Base addresses
+ * ----------------------------------------------------------------------------
+ */
+
+/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
+
+#define OMAP850_DSP_BASE	0xE0000000
+#define OMAP850_DSP_SIZE	0x50000
+#define OMAP850_DSP_START	0xE0000000
+
+#define OMAP850_DSPREG_BASE	0xE1000000
+#define OMAP850_DSPREG_SIZE	SZ_128K
+#define OMAP850_DSPREG_START	0xE1000000
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP850 specific configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP850_CONFIG_BASE	0xfffe1000
+#define OMAP850_IO_CONF_0	0xfffe1070
+#define OMAP850_IO_CONF_1	0xfffe1074
+#define OMAP850_IO_CONF_2	0xfffe1078
+#define OMAP850_IO_CONF_3	0xfffe107c
+#define OMAP850_IO_CONF_4	0xfffe1080
+#define OMAP850_IO_CONF_5	0xfffe1084
+#define OMAP850_IO_CONF_6	0xfffe1088
+#define OMAP850_IO_CONF_7	0xfffe108c
+#define OMAP850_IO_CONF_8	0xfffe1090
+#define OMAP850_IO_CONF_9	0xfffe1094
+#define OMAP850_IO_CONF_10	0xfffe1098
+#define OMAP850_IO_CONF_11	0xfffe109c
+#define OMAP850_IO_CONF_12	0xfffe10a0
+#define OMAP850_IO_CONF_13	0xfffe10a4
+
+#define OMAP850_MODE_1		0xfffe1010
+#define OMAP850_MODE_2		0xfffe1014
+
+/* CSMI specials: in terms of base + offset */
+#define OMAP850_MODE2_OFFSET	0x14
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP850 traffic controller configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP850_FLASH_CFG_0	0xfffecc10
+#define OMAP850_FLASH_ACFG_0	0xfffecc50
+#define OMAP850_FLASH_CFG_1	0xfffecc14
+#define OMAP850_FLASH_ACFG_1	0xfffecc54
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP850 DSP control registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP850_ICR_BASE	0xfffbb800
+#define OMAP850_DSP_M_CTL	0xfffbb804
+#define OMAP850_DSP_MMU_BASE	0xfffed200
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP850 PCC_UPLD configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP850_PCC_UPLD_CTRL_BASE	(0xfffe0900)
+#define OMAP850_PCC_UPLD_CTRL		(OMAP850_PCC_UPLD_CTRL_BASE + 0x00)
+
+#endif /*  __ASM_ARCH_OMAP850_H */
+
diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h
index 37e2f0f..ce6ee79 100644
--- a/arch/arm/plat-omap/include/mach/pm.h
+++ b/arch/arm/plat-omap/include/mach/pm.h
@@ -118,18 +118,6 @@
 extern void prevent_idle_sleep(void);
 extern void allow_idle_sleep(void);
 
-/**
- * clk_deny_idle - Prevents the clock from being idled during MPU idle
- * @clk: clock signal handle
- */
-void clk_deny_idle(struct clk *clk);
-
-/**
- * clk_allow_idle - Counters previous clk_deny_idle
- * @clk: clock signal handle
- */
-void clk_allow_idle(struct clk *clk);
-
 extern void omap_pm_idle(void);
 extern void omap_pm_suspend(void);
 extern void omap730_cpu_suspend(unsigned short, unsigned short);
diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h
index 2806a9c..69c9e67 100644
--- a/arch/arm/plat-omap/include/mach/powerdomain.h
+++ b/arch/arm/plat-omap/include/mach/powerdomain.h
@@ -50,9 +50,9 @@
 
 /*
  * Maximum number of clockdomains that can be associated with a powerdomain.
- * CORE powerdomain is probably the worst case.
+ * CORE powerdomain on OMAP3 is the worst case
  */
-#define PWRDM_MAX_CLKDMS	3
+#define PWRDM_MAX_CLKDMS	4
 
 /* XXX A completely arbitrary number. What is reasonable here? */
 #define PWRDM_TRANSITION_BAILOUT 100000
@@ -145,6 +145,7 @@
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
diff --git a/arch/arm/plat-omap/include/mach/prcm.h b/arch/arm/plat-omap/include/mach/prcm.h
index 56eba0f..24ac3c7 100644
--- a/arch/arm/plat-omap/include/mach/prcm.h
+++ b/arch/arm/plat-omap/include/mach/prcm.h
@@ -20,10 +20,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ASM_ARM_ARCH_OMAP_PRCM_H
+#define __ASM_ARM_ARCH_OMAP_PRCM_H
 
 u32 omap_prcm_get_reset_sources(void);
+void omap_prcm_arch_reset(char mode);
 
 #endif
 
diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h
index a98c6c3..adc7352 100644
--- a/arch/arm/plat-omap/include/mach/sdrc.h
+++ b/arch/arm/plat-omap/include/mach/sdrc.h
@@ -4,10 +4,12 @@
 /*
  * OMAP2/3 SDRC/SMS register definitions
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
  *
- * Written by Paul Walmsley
+ * Tony Lindgren
+ * Paul Walmsley
+ * Richard Woodruff
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -64,14 +66,62 @@
  * SMS register access
  */
 
-
-#define OMAP242X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP2420_SMS_BASE + reg)
-#define OMAP243X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP243X_SMS_BASE + reg)
-#define OMAP343X_SMS_REGADDR(reg)	IO_ADDRESS(OMAP343X_SMS_BASE + reg)
+#define OMAP242X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg)
+#define OMAP243X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg)
+#define OMAP343X_SMS_REGADDR(reg)					\
+			(void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg)
 
 /* SMS register offsets - read/write with sms_{read,write}_reg() */
 
 #define SMS_SYSCONFIG		0x010
 /* REVISIT: fill in other SMS registers here */
 
+
+#ifndef __ASSEMBLER__
+
+/**
+ * struct omap_sdrc_params - SDRC parameters for a given SDRC clock rate
+ * @rate: SDRC clock rate (in Hz)
+ * @actim_ctrla: Value to program to SDRC_ACTIM_CTRLA for this rate
+ * @actim_ctrlb: Value to program to SDRC_ACTIM_CTRLB for this rate
+ * @rfr_ctrl: Value to program to SDRC_RFR_CTRL for this rate
+ * @mr: Value to program to SDRC_MR for this rate
+ *
+ * This structure holds a pre-computed set of register values for the
+ * SDRC for a given SDRC clock rate and SDRAM chip.  These are
+ * intended to be pre-computed and specified in an array in the board-*.c
+ * files.  The structure is keyed off the 'rate' field.
+ */
+struct omap_sdrc_params {
+	unsigned long rate;
+	u32 actim_ctrla;
+	u32 actim_ctrlb;
+	u32 rfr_ctrl;
+	u32 mr;
+};
+
+void __init omap2_sdrc_init(struct omap_sdrc_params *sp);
+struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r);
+
+#ifdef CONFIG_ARCH_OMAP2
+
+struct memory_timings {
+	u32 m_type;		/* ddr = 1, sdr = 0 */
+	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
+	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
+	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
+	u32 base_cs;		/* base chip select to use for calculations */
+};
+
+extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
+
+u32 omap2xxx_sdrc_dll_is_unlocked(void);
+u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
+
+#endif  /* CONFIG_ARCH_OMAP2 */
+
+#endif  /* __ASSEMBLER__ */
+
 #endif
diff --git a/arch/arm/plat-omap/include/mach/system.h b/arch/arm/plat-omap/include/mach/system.h
index 06923f2..1060e34 100644
--- a/arch/arm/plat-omap/include/mach/system.h
+++ b/arch/arm/plat-omap/include/mach/system.h
@@ -9,12 +9,14 @@
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 
+#include <mach/prcm.h>
+
 #ifndef CONFIG_MACH_VOICEBLUE
 #define voiceblue_reset()		do {} while (0)
+#else
+extern void voiceblue_reset(void);
 #endif
 
-extern void omap_prcm_arch_reset(char mode);
-
 static inline void arch_idle(void)
 {
 	cpu_do_idle();
@@ -38,7 +40,7 @@
 		omap_writew(1, ARM_RSTCT1);
 }
 
-static inline void arch_reset(char mode)
+static inline void arch_reset(char mode, const char *cmd)
 {
 	if (!cpu_class_is_omap2())
 		omap1_arch_reset(mode);
diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h
index a56a610..69f0cee 100644
--- a/arch/arm/plat-omap/include/mach/usb.h
+++ b/arch/arm/plat-omap/include/mach/usb.h
@@ -27,8 +27,18 @@
 #define UDC_BASE			OMAP2_UDC_BASE
 #define OMAP_OHCI_BASE			OMAP2_OHCI_BASE
 
+#ifdef CONFIG_USB_MUSB_SOC
+extern void usb_musb_init(void);
+#else
+static inline void usb_musb_init(void)
+{
+}
 #endif
 
+#endif
+
+void omap_usb_init(struct omap_usb_config *pdata);
+
 /*-------------------------------------------------------------------------*/
 
 /*
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index b52ce05..0abfbaa 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -1,10 +1,9 @@
 /*
  * OMAP mailbox driver
  *
- * Copyright (C) 2006 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
  *
- * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- *		Restructured by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,21 +21,98 @@
  *
  */
 
-#include <linux/init.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include <linux/blkdev.h>
-#include <linux/err.h>
 #include <linux/delay.h>
-#include <linux/io.h>
+
 #include <mach/mailbox.h>
-#include "mailbox.h"
+
+static int enable_seq_bit;
+module_param(enable_seq_bit, bool, 0);
+MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking.");
 
 static struct omap_mbox *mboxes;
 static DEFINE_RWLOCK(mboxes_lock);
 
+/*
+ * Mailbox sequence bit API
+ */
+
+/* seq_rcv should be initialized with any value other than
+ * 0 and 1 << 31, to allow either value for the first
+ * message.  */
+static inline void mbox_seq_init(struct omap_mbox *mbox)
+{
+	if (!enable_seq_bit)
+		return;
+
+	/* any value other than 0 and 1 << 31 */
+	mbox->seq_rcv = 0xffffffff;
+}
+
+static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
+{
+	if (!enable_seq_bit)
+		return;
+
+	/* add seq_snd to msg */
+	*msg = (*msg & 0x7fffffff) | mbox->seq_snd;
+	/* flip seq_snd */
+	mbox->seq_snd ^= 1 << 31;
+}
+
+static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+	mbox_msg_t seq;
+
+	if (!enable_seq_bit)
+		return 0;
+
+	seq = msg & (1 << 31);
+	if (seq == mbox->seq_rcv)
+		return -1;
+	mbox->seq_rcv = seq;
+	return 0;
+}
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+{
+	return mbox->ops->fifo_read(mbox);
+}
+static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+	mbox->ops->fifo_write(mbox, msg);
+}
+static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+{
+	return mbox->ops->fifo_empty(mbox);
+}
+static inline int mbox_fifo_full(struct omap_mbox *mbox)
+{
+	return mbox->ops->fifo_full(mbox);
+}
+
+/* Mailbox IRQ handle functions */
+static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	mbox->ops->enable_irq(mbox, irq);
+}
+static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	mbox->ops->disable_irq(mbox, irq);
+}
+static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	if (mbox->ops->ack_irq)
+		mbox->ops->ack_irq(mbox, irq);
+}
+static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	return mbox->ops->is_irq(mbox, irq);
+}
+
 /* Mailbox Sequence Bit function */
 void omap_mbox_init_seq(struct omap_mbox *mbox)
 {
@@ -136,7 +212,7 @@
 	unsigned long flags;
 
 	if (mbox->rxq->callback == NULL) {
-		sysfs_notify(&mbox->dev.kobj, NULL, "mbox");
+		sysfs_notify(&mbox->dev->kobj, NULL, "mbox");
 		return;
 	}
 
@@ -204,7 +280,7 @@
 	/* no more messages in the fifo. clear IRQ source. */
 	ack_mbox_irq(mbox, IRQ_RX);
 	enable_mbox_irq(mbox, IRQ_RX);
-	nomem:
+nomem:
 	schedule_work(&mbox->rxq->work);
 }
 
@@ -286,7 +362,7 @@
 static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL);
 
 static struct class omap_mbox_class = {
-	.name = "omap_mbox",
+	.name = "omap-mailbox",
 };
 
 static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
@@ -333,21 +409,6 @@
 			return ret;
 	}
 
-	mbox->dev.class = &omap_mbox_class;
-	dev_set_name(&mbox->dev, "%s", mbox->name);
-	dev_set_drvdata(&mbox->dev, mbox);
-
-	ret = device_register(&mbox->dev);
-	if (unlikely(ret))
-		goto fail_device_reg;
-
-	ret = device_create_file(&mbox->dev, &dev_attr_mbox);
-	if (unlikely(ret)) {
-		printk(KERN_ERR
-			"device_create_file failed: %d\n", ret);
-		goto fail_create_mbox;
-	}
-
 	ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED,
 				mbox->name, mbox);
 	if (unlikely(ret)) {
@@ -377,10 +438,6 @@
  fail_alloc_txq:
 	free_irq(mbox->irq, mbox);
  fail_request_irq:
-	device_remove_file(&mbox->dev, &dev_attr_mbox);
- fail_create_mbox:
-	device_unregister(&mbox->dev);
- fail_device_reg:
 	if (unlikely(mbox->ops->shutdown))
 		mbox->ops->shutdown(mbox);
 
@@ -393,8 +450,6 @@
 	mbox_queue_free(mbox->rxq);
 
 	free_irq(mbox->irq, mbox);
-	device_remove_file(&mbox->dev, &dev_attr_mbox);
-	class_unregister(&omap_mbox_class);
 
 	if (unlikely(mbox->ops->shutdown))
 		mbox->ops->shutdown(mbox);
@@ -440,7 +495,7 @@
 }
 EXPORT_SYMBOL(omap_mbox_put);
 
-int omap_mbox_register(struct omap_mbox *mbox)
+int omap_mbox_register(struct device *parent, struct omap_mbox *mbox)
 {
 	int ret = 0;
 	struct omap_mbox **tmp;
@@ -450,14 +505,31 @@
 	if (mbox->next)
 		return -EBUSY;
 
+	mbox->dev = device_create(&omap_mbox_class,
+				  parent, 0, mbox, "%s", mbox->name);
+	if (IS_ERR(mbox->dev))
+		return PTR_ERR(mbox->dev);
+
+	ret = device_create_file(mbox->dev, &dev_attr_mbox);
+	if (ret)
+		goto err_sysfs;
+
 	write_lock(&mboxes_lock);
 	tmp = find_mboxes(mbox->name);
-	if (*tmp)
+	if (*tmp) {
 		ret = -EBUSY;
-	else
-		*tmp = mbox;
+		write_unlock(&mboxes_lock);
+		goto err_find;
+	}
+	*tmp = mbox;
 	write_unlock(&mboxes_lock);
 
+	return 0;
+
+err_find:
+	device_remove_file(mbox->dev, &dev_attr_mbox);
+err_sysfs:
+	device_unregister(mbox->dev);
 	return ret;
 }
 EXPORT_SYMBOL(omap_mbox_register);
@@ -473,6 +545,8 @@
 			*tmp = mbox->next;
 			mbox->next = NULL;
 			write_unlock(&mboxes_lock);
+			device_remove_file(mbox->dev, &dev_attr_mbox);
+			device_unregister(mbox->dev);
 			return 0;
 		}
 		tmp = &(*tmp)->next;
@@ -501,4 +575,6 @@
 subsys_initcall(omap_mbox_class_init);
 module_exit(omap_mbox_class_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
+MODULE_AUTHOR("Toshihiro Kobayashi and Hiroshi DOYU");
diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h
deleted file mode 100644
index 67c6740..0000000
--- a/arch/arm/plat-omap/mailbox.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Mailbox internal functions
- *
- * Copyright (C) 2006 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.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.
- */
-
-#ifndef __ARCH_ARM_PLAT_MAILBOX_H
-#define __ARCH_ARM_PLAT_MAILBOX_H
-
-/*
- * Mailbox sequence bit API
- */
-#if defined(CONFIG_ARCH_OMAP1)
-#  define MBOX_USE_SEQ_BIT
-#elif defined(CONFIG_ARCH_OMAP2)
-#  define MBOX_USE_SEQ_BIT
-#endif
-
-#ifdef MBOX_USE_SEQ_BIT
-/* seq_rcv should be initialized with any value other than
- * 0 and 1 << 31, to allow either value for the first
- * message.  */
-static inline void mbox_seq_init(struct omap_mbox *mbox)
-{
-	/* any value other than 0 and 1 << 31 */
-	mbox->seq_rcv = 0xffffffff;
-}
-
-static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
-{
-	/* add seq_snd to msg */
-	*msg = (*msg & 0x7fffffff) | mbox->seq_snd;
-	/* flip seq_snd */
-	mbox->seq_snd ^= 1 << 31;
-}
-
-static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	mbox_msg_t seq = msg & (1 << 31);
-	if (seq == mbox->seq_rcv)
-		return -1;
-	mbox->seq_rcv = seq;
-	return 0;
-}
-#else
-static inline void mbox_seq_init(struct omap_mbox *mbox)
-{
-}
-static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg)
-{
-}
-static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	return 0;
-}
-#endif
-
-/* Mailbox FIFO handle functions */
-static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_read(mbox);
-}
-static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	mbox->ops->fifo_write(mbox, msg);
-}
-static inline int mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_empty(mbox);
-}
-static inline int mbox_fifo_full(struct omap_mbox *mbox)
-{
-	return mbox->ops->fifo_full(mbox);
-}
-
-/* Mailbox IRQ handle functions */
-static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	mbox->ops->enable_irq(mbox, irq);
-}
-static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	mbox->ops->disable_irq(mbox, irq);
-}
-static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (mbox->ops->ack_irq)
-		mbox->ops->ack_irq(mbox, irq);
-}
-static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	return mbox->ops->is_irq(mbox, irq);
-}
-
-#endif				/* __ARCH_ARM_PLAT_MAILBOX_H */
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index e5842e3..28b0a82 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -214,7 +214,6 @@
 int omap_mcbsp_request(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
-	int i;
 	int err;
 
 	if (!omap_mcbsp_check_valid_id(id)) {
@@ -223,23 +222,23 @@
 	}
 	mcbsp = id_to_mcbsp_ptr(id);
 
-	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
-		mcbsp->pdata->ops->request(id);
-
-	for (i = 0; i < mcbsp->num_clks; i++)
-		clk_enable(mcbsp->clks[i]);
-
 	spin_lock(&mcbsp->lock);
 	if (!mcbsp->free) {
 		dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
 			mcbsp->id);
 		spin_unlock(&mcbsp->lock);
-		return -1;
+		return -EBUSY;
 	}
 
 	mcbsp->free = 0;
 	spin_unlock(&mcbsp->lock);
 
+	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
+		mcbsp->pdata->ops->request(id);
+
+	clk_enable(mcbsp->iclk);
+	clk_enable(mcbsp->fclk);
+
 	/*
 	 * Make sure that transmitter, receiver and sample-rate generator are
 	 * not running before activating IRQs.
@@ -278,7 +277,6 @@
 void omap_mcbsp_free(unsigned int id)
 {
 	struct omap_mcbsp *mcbsp;
-	int i;
 
 	if (!omap_mcbsp_check_valid_id(id)) {
 		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
@@ -289,8 +287,14 @@
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(id);
 
-	for (i = mcbsp->num_clks - 1; i >= 0; i--)
-		clk_disable(mcbsp->clks[i]);
+	clk_disable(mcbsp->fclk);
+	clk_disable(mcbsp->iclk);
+
+	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
+		/* Free IRQs */
+		free_irq(mcbsp->rx_irq, (void *)mcbsp);
+		free_irq(mcbsp->tx_irq, (void *)mcbsp);
+	}
 
 	spin_lock(&mcbsp->lock);
 	if (mcbsp->free) {
@@ -302,12 +306,6 @@
 
 	mcbsp->free = 1;
 	spin_unlock(&mcbsp->lock);
-
-	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
-		/* Free IRQs */
-		free_irq(mcbsp->rx_irq, (void *)mcbsp);
-		free_irq(mcbsp->tx_irq, (void *)mcbsp);
-	}
 }
 EXPORT_SYMBOL(omap_mcbsp_free);
 
@@ -876,7 +874,6 @@
 	struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
 	struct omap_mcbsp *mcbsp;
 	int id = pdev->id - 1;
-	int i;
 	int ret = 0;
 
 	if (!pdata) {
@@ -899,7 +896,6 @@
 		ret = -ENOMEM;
 		goto exit;
 	}
-	mcbsp_ptr[id] = mcbsp;
 
 	spin_lock_init(&mcbsp->lock);
 	mcbsp->id = id + 1;
@@ -921,39 +917,32 @@
 	mcbsp->dma_rx_sync = pdata->dma_rx_sync;
 	mcbsp->dma_tx_sync = pdata->dma_tx_sync;
 
-	if (pdata->num_clks) {
-		mcbsp->num_clks = pdata->num_clks;
-		mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *),
-					GFP_KERNEL);
-		if (!mcbsp->clks) {
-			ret = -ENOMEM;
-			goto exit;
-		}
-		for (i = 0; i < mcbsp->num_clks; i++) {
-			mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]);
-			if (IS_ERR(mcbsp->clks[i])) {
-				dev_err(&pdev->dev,
-					"Invalid %s configuration for McBSP%d.\n",
-					pdata->clk_names[i], mcbsp->id);
-				ret = PTR_ERR(mcbsp->clks[i]);
-				goto err_clk;
-			}
-		}
+	mcbsp->iclk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(mcbsp->iclk)) {
+		ret = PTR_ERR(mcbsp->iclk);
+		dev_err(&pdev->dev, "unable to get ick: %d\n", ret);
+		goto err_iclk;
+	}
 
+	mcbsp->fclk = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(mcbsp->fclk)) {
+		ret = PTR_ERR(mcbsp->fclk);
+		dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
+		goto err_fclk;
 	}
 
 	mcbsp->pdata = pdata;
 	mcbsp->dev = &pdev->dev;
+	mcbsp_ptr[id] = mcbsp;
 	platform_set_drvdata(pdev, mcbsp);
 	return 0;
 
-err_clk:
-	while (i--)
-		clk_put(mcbsp->clks[i]);
-	kfree(mcbsp->clks);
+err_fclk:
+	clk_put(mcbsp->iclk);
+err_iclk:
 	iounmap(mcbsp->io_base);
 err_ioremap:
-	mcbsp->free = 0;
+	kfree(mcbsp);
 exit:
 	return ret;
 }
@@ -961,7 +950,6 @@
 static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
 {
 	struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
-	int i;
 
 	platform_set_drvdata(pdev, NULL);
 	if (mcbsp) {
@@ -970,18 +958,15 @@
 				mcbsp->pdata->ops->free)
 			mcbsp->pdata->ops->free(mcbsp->id);
 
-		for (i = mcbsp->num_clks - 1; i >= 0; i--) {
-			clk_disable(mcbsp->clks[i]);
-			clk_put(mcbsp->clks[i]);
-		}
+		clk_disable(mcbsp->fclk);
+		clk_disable(mcbsp->iclk);
+		clk_put(mcbsp->fclk);
+		clk_put(mcbsp->iclk);
 
 		iounmap(mcbsp->io_base);
 
-		if (mcbsp->num_clks) {
-			kfree(mcbsp->clks);
-			mcbsp->clks = NULL;
-			mcbsp->num_clks = 0;
-		}
+		mcbsp->fclk = NULL;
+		mcbsp->iclk = NULL;
 		mcbsp->free = 0;
 		mcbsp->dev = NULL;
 	}
@@ -1002,4 +987,3 @@
 	/* Register the McBSP driver */
 	return platform_driver_register(&omap_mcbsp_driver);
 }
-
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index be7bcaf..fa5297d 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -148,7 +148,7 @@
 		omap_sram_base = OMAP1_SRAM_VA;
 		omap_sram_start = OMAP1_SRAM_PA;
 
-		if (cpu_is_omap730())
+		if (cpu_is_omap7xx())
 			omap_sram_size = 0x32000;	/* 200K */
 		else if (cpu_is_omap15xx())
 			omap_sram_size = 0x30000;	/* 192K */
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index e278de6..509f2ed 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -729,30 +729,13 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct omap_usb_config platform_data;
-
-static int __init
-omap_usb_init(void)
+void __init omap_usb_init(struct omap_usb_config *pdata)
 {
-	const struct omap_usb_config *config;
-
-	config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
-	if (config == NULL) {
-		printk(KERN_ERR "USB: No board-specific "
-				"platform config found\n");
-		return -ENODEV;
-	}
-	platform_data = *config;
-
 	if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx())
-		omap_otg_init(&platform_data);
+		omap_otg_init(pdata);
 	else if (cpu_is_omap15xx())
-		omap_1510_usb_init(&platform_data);
-	else {
+		omap_1510_usb_init(pdata);
+	else
 		printk(KERN_ERR "USB: No init for your chip yet\n");
-		return -ENODEV;
-	}
-	return 0;
 }
 
-subsys_initcall(omap_usb_init);
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index 0d12c21..32eb9e3 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -19,7 +19,8 @@
 
 static DEFINE_SPINLOCK(gpio_lock);
 static const char *gpio_label[GPIO_MAX];  /* non null for allocated GPIOs */
-static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
+static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
+static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
 
 static inline void __set_direction(unsigned pin, int input)
 {
@@ -53,7 +54,7 @@
 {
 	unsigned long flags;
 
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) {
 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
 		return -EINVAL;
 	}
@@ -83,7 +84,7 @@
 	unsigned long flags;
 	u32 u;
 
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) {
 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
 		return -EINVAL;
 	}
@@ -161,7 +162,9 @@
 	unsigned long flags;
 	int ret;
 
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+	if (pin >= GPIO_MAX ||
+	    !(test_bit(pin, gpio_valid_input) ||
+	      test_bit(pin, gpio_valid_output))) {
 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
 		return -EINVAL;
 	}
@@ -183,7 +186,9 @@
 
 void gpio_free(unsigned pin)
 {
-	if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
+	if (pin >= GPIO_MAX ||
+	    !(test_bit(pin, gpio_valid_input) ||
+	      test_bit(pin, gpio_valid_output))) {
 		pr_debug("%s: invalid GPIO %d\n", __func__, pin);
 		return;
 	}
@@ -208,12 +213,18 @@
 	__set_direction(pin, 0);
 }
 
-void __init orion_gpio_set_valid(unsigned pin, int valid)
+void __init orion_gpio_set_valid(unsigned pin, int mode)
 {
-	if (valid)
-		__set_bit(pin, gpio_valid);
+	if (mode == 1)
+		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
+	if (mode & GPIO_INPUT_OK)
+		__set_bit(pin, gpio_valid_input);
 	else
-		__clear_bit(pin, gpio_valid);
+		__clear_bit(pin, gpio_valid_input);
+	if (mode & GPIO_OUTPUT_OK)
+		__set_bit(pin, gpio_valid_output);
+	else
+		__clear_bit(pin, gpio_valid_output);
 }
 
 void orion_gpio_set_blink(unsigned pin, int blink)
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index ec743e8..33f6c6a 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -25,9 +25,13 @@
  * Orion-specific GPIO API extensions.
  */
 void orion_gpio_set_unused(unsigned pin);
-void orion_gpio_set_valid(unsigned pin, int valid);
 void orion_gpio_set_blink(unsigned pin, int blink);
 
+#define GPIO_BIDI_OK		(1 << 0)
+#define GPIO_INPUT_OK		(1 << 1)
+#define GPIO_OUTPUT_OK		(1 << 2)
+void orion_gpio_set_valid(unsigned pin, int mode);
+
 /*
  * GPIO interrupt handling.
  */
diff --git a/arch/arm/plat-orion/include/plat/mvsdio.h b/arch/arm/plat-orion/include/plat/mvsdio.h
new file mode 100644
index 0000000..14ca886
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/mvsdio.h
@@ -0,0 +1,21 @@
+/*
+ * 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
+
+#include <linux/mbus.h>
+
+struct mvsdio_platform_data {
+	struct mbus_dram_target_info *dram;
+	unsigned int clock;
+	int gpio_card_detect;
+	int gpio_write_protect;
+};
+
+#endif
diff --git a/arch/arm/plat-pxa/Kconfig b/arch/arm/plat-pxa/Kconfig
new file mode 100644
index 0000000..b158e98
--- /dev/null
+++ b/arch/arm/plat-pxa/Kconfig
@@ -0,0 +1,3 @@
+if PLAT_PXA
+
+endif
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
new file mode 100644
index 0000000..8f2c4c7
--- /dev/null
+++ b/arch/arm/plat-pxa/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for code common across different PXA processor families
+#
+
+obj-y	:= dma.o
+
+obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
+obj-$(CONFIG_PXA3xx)		+= mfp.o
+obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/plat-pxa/dma.c
similarity index 93%
rename from arch/arm/mach-pxa/dma.c
rename to arch/arm/plat-pxa/dma.c
index 7de17fc..70aeee4 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/plat-pxa/dma.c
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/mach-pxa/dma.c
+ *  linux/arch/arm/plat-pxa/dma.c
  *
  *  PXA DMA registration and IRQ dispatching
  *
@@ -23,8 +23,6 @@
 #include <mach/hardware.h>
 #include <mach/dma.h>
 
-#include <mach/pxa-regs.h>
-
 struct dma_channel {
 	char *name;
 	pxa_dma_prio prio;
@@ -36,8 +34,8 @@
 static int num_dma_channels;
 
 int pxa_request_dma (char *name, pxa_dma_prio prio,
-			 void (*irq_handler)(int, void *),
-		 	 void *data)
+			void (*irq_handler)(int, void *),
+			void *data)
 {
 	unsigned long flags;
 	int i, found = 0;
@@ -113,7 +111,7 @@
 	return IRQ_HANDLED;
 }
 
-int __init pxa_init_dma(int num_ch)
+int __init pxa_init_dma(int irq, int num_ch)
 {
 	int i, ret;
 
@@ -131,7 +129,7 @@
 		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
 	}
 
-	ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+	ret = request_irq(irq, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
 	if (ret) {
 		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
 		kfree(dma_channels);
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
new file mode 100644
index 0000000..af819bf
--- /dev/null
+++ b/arch/arm/plat-pxa/gpio.c
@@ -0,0 +1,337 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  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.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/bootmem.h>
+
+#include <mach/gpio.h>
+
+int pxa_last_gpio;
+
+struct pxa_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem	*regbase;
+	char label[10];
+
+	unsigned long	irq_mask;
+	unsigned long	irq_edge_rise;
+	unsigned long	irq_edge_fall;
+
+#ifdef CONFIG_PM
+	unsigned long	saved_gplr;
+	unsigned long	saved_gpdr;
+	unsigned long	saved_grer;
+	unsigned long	saved_gfer;
+#endif
+};
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_chip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	/* this is early, we have to use bootmem allocator, and we really
+	 * want this to be allocated dynamically for different 'gpio_end'
+	 */
+	chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip));
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = irq_to_gpio(irq);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_chip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (__gpio_is_occupied(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	__raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
+	__raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				generic_handle_irq(gpio_to_irq(gpio_base + n));
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq_to_gpio(irq);
+	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq_to_gpio(irq);
+	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq_to_gpio(irq);
+	struct pxa_gpio_chip *c = gpio_to_chip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	__raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
+	__raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.ack		= pxa_ack_muxed_gpio,
+	.mask		= pxa_mask_muxed_gpio,
+	.unmask		= pxa_unmask_muxed_gpio,
+	.set_type	= pxa_gpio_irq_type,
+};
+
+void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
+{
+	struct pxa_gpio_chip *c;
+	int gpio, irq;
+
+	pxa_last_gpio = end;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(end);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
+		set_irq_chip(irq, &pxa_muxed_gpio_chip);
+		set_irq_handler(irq, handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Install handler for GPIO>=2 edge detect interrupts */
+	set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
+	pxa_muxed_gpio_chip.set_wake = fn;
+}
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static int pxa_gpio_resume(struct sys_device *dev)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+	return 0;
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct sysdev_class pxa_gpio_sysclass = {
+	.name		= "gpio",
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
+
+static int __init pxa_gpio_init(void)
+{
+	return sysdev_class_register(&pxa_gpio_sysclass);
+}
+
+core_initcall(pxa_gpio_init);
diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h
new file mode 100644
index 0000000..a7b91dc
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/dma.h
@@ -0,0 +1,85 @@
+#ifndef __PLAT_DMA_H
+#define __PLAT_DMA_H
+
+#define DMAC_REG(x)	(*((volatile u32 *)(DMAC_REGS_VIRT + (x))))
+
+#define DCSR(n)		DMAC_REG((n) << 2)
+#define DALGN		DMAC_REG(0x00a0)  /* DMA Alignment Register */
+#define DINT		DMAC_REG(0x00f0)  /* DMA Interrupt Register */
+#define DDADR(n)	DMAC_REG(0x0200 + ((n) << 4))
+#define DSADR(n)	DMAC_REG(0x0204 + ((n) << 4))
+#define DTADR(n)	DMAC_REG(0x0208 + ((n) << 4))
+#define DCMD(n)		DMAC_REG(0x020c + ((n) << 4))
+#define DRCMR(n)	DMAC_REG((((n) < 64) ? 0x0100 : 0x1100) + \
+				 (((n) & 0x3f) << 2))
+
+#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
+#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
+#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
+#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
+#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
+#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
+#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
+#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
+
+#define DCSR_EORIRQEN	(1 << 28)       /* End of Receive Interrupt Enable (R/W) */
+#define DCSR_EORJMPEN	(1 << 27)       /* Jump to next descriptor on EOR */
+#define DCSR_EORSTOPEN	(1 << 26)       /* STOP on an EOR */
+#define DCSR_SETCMPST	(1 << 25)       /* Set Descriptor Compare Status */
+#define DCSR_CLRCMPST	(1 << 24)       /* Clear Descriptor Compare Status */
+#define DCSR_CMPST	(1 << 10)       /* The Descriptor Compare Status */
+#define DCSR_EORINTR	(1 << 9)        /* The end of Receive */
+
+#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
+#define DRCMR_CHLNUM	0x1f		/* mask for Channel Number (read / write) */
+
+#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
+#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
+
+#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
+#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
+#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
+#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
+#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
+#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
+#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
+#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
+#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
+#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
+#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/*
+ * Descriptor structure for PXA's DMA engine
+ * Note: this structure must always be aligned to a 16-byte boundary.
+ */
+
+typedef struct pxa_dma_desc {
+	volatile u32 ddadr;	/* Points to the next descriptor + flags */
+	volatile u32 dsadr;	/* DSADR value for the current transfer */
+	volatile u32 dtadr;	/* DTADR value for the current transfer */
+	volatile u32 dcmd;	/* DCMD value for the current transfer */
+} pxa_dma_desc;
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
+/*
+ * DMA registration
+ */
+
+int __init pxa_init_dma(int irq, int num_ch);
+
+int pxa_request_dma (char *name,
+			 pxa_dma_prio prio,
+			 void (*irq_handler)(int, void *),
+			 void *data);
+
+void pxa_free_dma (int dma_ch);
+
+#endif /* __PLAT_DMA_H */
diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h
new file mode 100644
index 0000000..44248cb
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/gpio.h
@@ -0,0 +1,62 @@
+#ifndef __PLAT_GPIO_H
+#define __PLAT_GPIO_H
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
+		return GPLR(gpio) & GPIO_bit(gpio);
+	else
+		return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
+		if (value)
+			GPSR(gpio) = GPIO_bit(gpio);
+		else
+			GPCR(gpio) = GPIO_bit(gpio);
+	} else
+		__gpio_set_value(gpio, value);
+}
+
+#define gpio_cansleep		__gpio_cansleep
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(unsigned int irq, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+#endif /* __PLAT_GPIO_H */
diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h
new file mode 100644
index 0000000..6401946
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/mfp.h
@@ -0,0 +1,399 @@
+/*
+ * arch/arm/plat-pxa/include/plat/mfp.h
+ *
+ *   Common Multi-Function Pin Definitions
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ *
+ * 2007-8-21: eric miao <eric.miao@marvell.com>
+ *            initial version
+ *
+ *  This program is free software; you can 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_MFP_H
+#define __ASM_PLAT_MFP_H
+
+#define mfp_to_gpio(m)	((m) % 128)
+
+/* list of all the configurable MFP pins */
+enum {
+	MFP_PIN_INVALID = -1,
+
+	MFP_PIN_GPIO0 = 0,
+	MFP_PIN_GPIO1,
+	MFP_PIN_GPIO2,
+	MFP_PIN_GPIO3,
+	MFP_PIN_GPIO4,
+	MFP_PIN_GPIO5,
+	MFP_PIN_GPIO6,
+	MFP_PIN_GPIO7,
+	MFP_PIN_GPIO8,
+	MFP_PIN_GPIO9,
+	MFP_PIN_GPIO10,
+	MFP_PIN_GPIO11,
+	MFP_PIN_GPIO12,
+	MFP_PIN_GPIO13,
+	MFP_PIN_GPIO14,
+	MFP_PIN_GPIO15,
+	MFP_PIN_GPIO16,
+	MFP_PIN_GPIO17,
+	MFP_PIN_GPIO18,
+	MFP_PIN_GPIO19,
+	MFP_PIN_GPIO20,
+	MFP_PIN_GPIO21,
+	MFP_PIN_GPIO22,
+	MFP_PIN_GPIO23,
+	MFP_PIN_GPIO24,
+	MFP_PIN_GPIO25,
+	MFP_PIN_GPIO26,
+	MFP_PIN_GPIO27,
+	MFP_PIN_GPIO28,
+	MFP_PIN_GPIO29,
+	MFP_PIN_GPIO30,
+	MFP_PIN_GPIO31,
+	MFP_PIN_GPIO32,
+	MFP_PIN_GPIO33,
+	MFP_PIN_GPIO34,
+	MFP_PIN_GPIO35,
+	MFP_PIN_GPIO36,
+	MFP_PIN_GPIO37,
+	MFP_PIN_GPIO38,
+	MFP_PIN_GPIO39,
+	MFP_PIN_GPIO40,
+	MFP_PIN_GPIO41,
+	MFP_PIN_GPIO42,
+	MFP_PIN_GPIO43,
+	MFP_PIN_GPIO44,
+	MFP_PIN_GPIO45,
+	MFP_PIN_GPIO46,
+	MFP_PIN_GPIO47,
+	MFP_PIN_GPIO48,
+	MFP_PIN_GPIO49,
+	MFP_PIN_GPIO50,
+	MFP_PIN_GPIO51,
+	MFP_PIN_GPIO52,
+	MFP_PIN_GPIO53,
+	MFP_PIN_GPIO54,
+	MFP_PIN_GPIO55,
+	MFP_PIN_GPIO56,
+	MFP_PIN_GPIO57,
+	MFP_PIN_GPIO58,
+	MFP_PIN_GPIO59,
+	MFP_PIN_GPIO60,
+	MFP_PIN_GPIO61,
+	MFP_PIN_GPIO62,
+	MFP_PIN_GPIO63,
+	MFP_PIN_GPIO64,
+	MFP_PIN_GPIO65,
+	MFP_PIN_GPIO66,
+	MFP_PIN_GPIO67,
+	MFP_PIN_GPIO68,
+	MFP_PIN_GPIO69,
+	MFP_PIN_GPIO70,
+	MFP_PIN_GPIO71,
+	MFP_PIN_GPIO72,
+	MFP_PIN_GPIO73,
+	MFP_PIN_GPIO74,
+	MFP_PIN_GPIO75,
+	MFP_PIN_GPIO76,
+	MFP_PIN_GPIO77,
+	MFP_PIN_GPIO78,
+	MFP_PIN_GPIO79,
+	MFP_PIN_GPIO80,
+	MFP_PIN_GPIO81,
+	MFP_PIN_GPIO82,
+	MFP_PIN_GPIO83,
+	MFP_PIN_GPIO84,
+	MFP_PIN_GPIO85,
+	MFP_PIN_GPIO86,
+	MFP_PIN_GPIO87,
+	MFP_PIN_GPIO88,
+	MFP_PIN_GPIO89,
+	MFP_PIN_GPIO90,
+	MFP_PIN_GPIO91,
+	MFP_PIN_GPIO92,
+	MFP_PIN_GPIO93,
+	MFP_PIN_GPIO94,
+	MFP_PIN_GPIO95,
+	MFP_PIN_GPIO96,
+	MFP_PIN_GPIO97,
+	MFP_PIN_GPIO98,
+	MFP_PIN_GPIO99,
+	MFP_PIN_GPIO100,
+	MFP_PIN_GPIO101,
+	MFP_PIN_GPIO102,
+	MFP_PIN_GPIO103,
+	MFP_PIN_GPIO104,
+	MFP_PIN_GPIO105,
+	MFP_PIN_GPIO106,
+	MFP_PIN_GPIO107,
+	MFP_PIN_GPIO108,
+	MFP_PIN_GPIO109,
+	MFP_PIN_GPIO110,
+	MFP_PIN_GPIO111,
+	MFP_PIN_GPIO112,
+	MFP_PIN_GPIO113,
+	MFP_PIN_GPIO114,
+	MFP_PIN_GPIO115,
+	MFP_PIN_GPIO116,
+	MFP_PIN_GPIO117,
+	MFP_PIN_GPIO118,
+	MFP_PIN_GPIO119,
+	MFP_PIN_GPIO120,
+	MFP_PIN_GPIO121,
+	MFP_PIN_GPIO122,
+	MFP_PIN_GPIO123,
+	MFP_PIN_GPIO124,
+	MFP_PIN_GPIO125,
+	MFP_PIN_GPIO126,
+	MFP_PIN_GPIO127,
+	MFP_PIN_GPIO0_2,
+	MFP_PIN_GPIO1_2,
+	MFP_PIN_GPIO2_2,
+	MFP_PIN_GPIO3_2,
+	MFP_PIN_GPIO4_2,
+	MFP_PIN_GPIO5_2,
+	MFP_PIN_GPIO6_2,
+	MFP_PIN_GPIO7_2,
+	MFP_PIN_GPIO8_2,
+	MFP_PIN_GPIO9_2,
+	MFP_PIN_GPIO10_2,
+	MFP_PIN_GPIO11_2,
+	MFP_PIN_GPIO12_2,
+	MFP_PIN_GPIO13_2,
+	MFP_PIN_GPIO14_2,
+	MFP_PIN_GPIO15_2,
+	MFP_PIN_GPIO16_2,
+	MFP_PIN_GPIO17_2,
+
+	MFP_PIN_ULPI_STP,
+	MFP_PIN_ULPI_NXT,
+	MFP_PIN_ULPI_DIR,
+
+	MFP_PIN_nXCVREN,
+	MFP_PIN_DF_CLE_nOE,
+	MFP_PIN_DF_nADV1_ALE,
+	MFP_PIN_DF_SCLK_E,
+	MFP_PIN_DF_SCLK_S,
+	MFP_PIN_nBE0,
+	MFP_PIN_nBE1,
+	MFP_PIN_DF_nADV2_ALE,
+	MFP_PIN_DF_INT_RnB,
+	MFP_PIN_DF_nCS0,
+	MFP_PIN_DF_nCS1,
+	MFP_PIN_nLUA,
+	MFP_PIN_nLLA,
+	MFP_PIN_DF_nWE,
+	MFP_PIN_DF_ALE_nWE,
+	MFP_PIN_DF_nRE_nOE,
+	MFP_PIN_DF_ADDR0,
+	MFP_PIN_DF_ADDR1,
+	MFP_PIN_DF_ADDR2,
+	MFP_PIN_DF_ADDR3,
+	MFP_PIN_DF_IO0,
+	MFP_PIN_DF_IO1,
+	MFP_PIN_DF_IO2,
+	MFP_PIN_DF_IO3,
+	MFP_PIN_DF_IO4,
+	MFP_PIN_DF_IO5,
+	MFP_PIN_DF_IO6,
+	MFP_PIN_DF_IO7,
+	MFP_PIN_DF_IO8,
+	MFP_PIN_DF_IO9,
+	MFP_PIN_DF_IO10,
+	MFP_PIN_DF_IO11,
+	MFP_PIN_DF_IO12,
+	MFP_PIN_DF_IO13,
+	MFP_PIN_DF_IO14,
+	MFP_PIN_DF_IO15,
+	MFP_PIN_DF_nCS0_SM_nCS2,
+	MFP_PIN_DF_nCS1_SM_nCS3,
+	MFP_PIN_SM_nCS0,
+	MFP_PIN_SM_nCS1,
+	MFP_PIN_DF_WEn,
+	MFP_PIN_DF_REn,
+	MFP_PIN_DF_CLE_SM_OEn,
+	MFP_PIN_DF_ALE_SM_WEn,
+	MFP_PIN_DF_RDY0,
+	MFP_PIN_DF_RDY1,
+
+	MFP_PIN_SM_SCLK,
+	MFP_PIN_SM_BE0,
+	MFP_PIN_SM_BE1,
+	MFP_PIN_SM_ADV,
+	MFP_PIN_SM_ADVMUX,
+	MFP_PIN_SM_RDY,
+
+	MFP_PIN_MMC1_DAT7,
+	MFP_PIN_MMC1_DAT6,
+	MFP_PIN_MMC1_DAT5,
+	MFP_PIN_MMC1_DAT4,
+	MFP_PIN_MMC1_DAT3,
+	MFP_PIN_MMC1_DAT2,
+	MFP_PIN_MMC1_DAT1,
+	MFP_PIN_MMC1_DAT0,
+	MFP_PIN_MMC1_CMD,
+	MFP_PIN_MMC1_CLK,
+	MFP_PIN_MMC1_CD,
+	MFP_PIN_MMC1_WP,
+
+	/* additional pins on PXA930 */
+	MFP_PIN_GSIM_UIO,
+	MFP_PIN_GSIM_UCLK,
+	MFP_PIN_GSIM_UDET,
+	MFP_PIN_GSIM_nURST,
+	MFP_PIN_PMIC_INT,
+	MFP_PIN_RDY,
+
+	MFP_PIN_MAX,
+};
+
+/*
+ * a possible MFP configuration is represented by a 32-bit integer
+ *
+ * bit  0.. 9 - MFP Pin Number (1024 Pins Maximum)
+ * bit 10..12 - Alternate Function Selection
+ * bit 13..15 - Drive Strength
+ * bit 16..18 - Low Power Mode State
+ * bit 19..20 - Low Power Mode Edge Detection
+ * bit 21..22 - Run Mode Pull State
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * MFP_CFG_DEFAULT - default MFP configuration value, with
+ * 		  alternate function = 0,
+ * 		  drive strength = fast 3mA (MFP_DS03X)
+ * 		  low power mode = default
+ * 		  edge detection = none
+ *
+ * MFP_CFG	- default MFPR value with alternate function
+ * MFP_CFG_DRV	- default MFPR value with alternate function and
+ * 		  pin drive strength
+ * MFP_CFG_LPM	- default MFPR value with alternate function and
+ * 		  low power mode
+ * MFP_CFG_X	- default MFPR value with alternate function,
+ * 		  pin drive strength and low power mode
+ */
+
+typedef unsigned long mfp_cfg_t;
+
+#define MFP_PIN(x)		((x) & 0x3ff)
+
+#define MFP_AF0			(0x0 << 10)
+#define MFP_AF1			(0x1 << 10)
+#define MFP_AF2			(0x2 << 10)
+#define MFP_AF3			(0x3 << 10)
+#define MFP_AF4			(0x4 << 10)
+#define MFP_AF5			(0x5 << 10)
+#define MFP_AF6			(0x6 << 10)
+#define MFP_AF7			(0x7 << 10)
+#define MFP_AF_MASK		(0x7 << 10)
+#define MFP_AF(x)		(((x) >> 10) & 0x7)
+
+#define MFP_DS01X		(0x0 << 13)
+#define MFP_DS02X		(0x1 << 13)
+#define MFP_DS03X		(0x2 << 13)
+#define MFP_DS04X		(0x3 << 13)
+#define MFP_DS06X		(0x4 << 13)
+#define MFP_DS08X		(0x5 << 13)
+#define MFP_DS10X		(0x6 << 13)
+#define MFP_DS13X		(0x7 << 13)
+#define MFP_DS_MASK		(0x7 << 13)
+#define MFP_DS(x)		(((x) >> 13) & 0x7)
+
+#define MFP_LPM_DEFAULT		(0x0 << 16)
+#define MFP_LPM_DRIVE_LOW	(0x1 << 16)
+#define MFP_LPM_DRIVE_HIGH	(0x2 << 16)
+#define MFP_LPM_PULL_LOW	(0x3 << 16)
+#define MFP_LPM_PULL_HIGH	(0x4 << 16)
+#define MFP_LPM_FLOAT		(0x5 << 16)
+#define MFP_LPM_INPUT		(0x6 << 16)
+#define MFP_LPM_STATE_MASK	(0x7 << 16)
+#define MFP_LPM_STATE(x)	(((x) >> 16) & 0x7)
+
+#define MFP_LPM_EDGE_NONE	(0x0 << 19)
+#define MFP_LPM_EDGE_RISE	(0x1 << 19)
+#define MFP_LPM_EDGE_FALL	(0x2 << 19)
+#define MFP_LPM_EDGE_BOTH	(0x3 << 19)
+#define MFP_LPM_EDGE_MASK	(0x3 << 19)
+#define MFP_LPM_EDGE(x)		(((x) >> 19) & 0x3)
+
+#define MFP_PULL_NONE		(0x0 << 21)
+#define MFP_PULL_LOW		(0x1 << 21)
+#define MFP_PULL_HIGH		(0x2 << 21)
+#define MFP_PULL_BOTH		(0x3 << 21)
+#define MFP_PULL_MASK		(0x3 << 21)
+#define MFP_PULL(x)		(((x) >> 21) & 0x3)
+
+#define MFP_CFG_DEFAULT		(MFP_AF0 | MFP_DS03X | MFP_LPM_DEFAULT |\
+				 MFP_LPM_EDGE_NONE | MFP_PULL_NONE)
+
+#define MFP_CFG(pin, af)		\
+	((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\
+	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af))
+
+#define MFP_CFG_DRV(pin, af, drv)	\
+	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK)) |\
+	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv))
+
+#define MFP_CFG_LPM(pin, af, lpm)	\
+	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_LPM_STATE_MASK)) |\
+	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_LPM_##lpm))
+
+#define MFP_CFG_X(pin, af, drv, lpm)	\
+	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_DS_MASK | MFP_LPM_STATE_MASK)) |\
+	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##drv | MFP_LPM_##lpm))
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_ARCH_MMP)
+/*
+ * each MFP pin will have a MFPR register, since the offset of the
+ * register varies between processors, the processor specific code
+ * should initialize the pin offsets by mfp_init()
+ *
+ * mfp_init_base() - accepts a virtual base for all MFPR registers and
+ * initialize the MFP table to a default state
+ *
+ * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which
+ * represents a range of MFP pins from "start" to "end", with the offset
+ * begining at "offset", to define a single pin, let "end" = -1.
+ *
+ * use
+ *
+ * MFP_ADDR_X() to define a range of pins
+ * MFP_ADDR()   to define a single pin
+ * MFP_ADDR_END to signal the end of pin offset definitions
+ */
+struct mfp_addr_map {
+	unsigned int	start;
+	unsigned int	end;
+	unsigned long	offset;
+};
+
+#define MFP_ADDR_X(start, end, offset) \
+	{ MFP_PIN_##start, MFP_PIN_##end, offset }
+
+#define MFP_ADDR(pin, offset) \
+	{ MFP_PIN_##pin, -1, offset }
+
+#define MFP_ADDR_END	{ MFP_PIN_INVALID, 0 }
+
+void __init mfp_init_base(unsigned long mfpr_base);
+void __init mfp_init_addr(struct mfp_addr_map *map);
+
+/*
+ * mfp_{read, write}()	- for direct read/write access to the MFPR register
+ * mfp_config()		- for configuring a group of MFPR registers
+ * mfp_config_lpm()	- configuring all low power MFPR registers for suspend
+ * mfp_config_run()	- configuring all run time  MFPR registers after resume
+ */
+unsigned long mfp_read(int mfp);
+void mfp_write(int mfp, unsigned long mfpr_val);
+void mfp_config(unsigned long *mfp_cfgs, int num);
+void mfp_config_run(void);
+void mfp_config_lpm(void);
+#endif /* CONFIG_PXA3xx || CONFIG_ARCH_MMP */
+
+#endif /* __ASM_PLAT_MFP_H */
diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c
new file mode 100644
index 0000000..e716c62
--- /dev/null
+++ b/arch/arm/plat-pxa/mfp.c
@@ -0,0 +1,278 @@
+/*
+ * linux/arch/arm/plat-pxa/mfp.c
+ *
+ *   Multi-Function Pin Support
+ *
+ * Copyright (C) 2007 Marvell Internation Ltd.
+ *
+ * 2007-08-21: eric miao <eric.miao@marvell.com>
+ *             initial version
+ *
+ *  This program is free software; you can 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/init.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+
+#include <plat/mfp.h>
+
+#define MFPR_SIZE	(PAGE_SIZE)
+
+/* MFPR register bit definitions */
+#define MFPR_PULL_SEL		(0x1 << 15)
+#define MFPR_PULLUP_EN		(0x1 << 14)
+#define MFPR_PULLDOWN_EN	(0x1 << 13)
+#define MFPR_SLEEP_SEL		(0x1 << 9)
+#define MFPR_SLEEP_OE_N		(0x1 << 7)
+#define MFPR_EDGE_CLEAR		(0x1 << 6)
+#define MFPR_EDGE_FALL_EN	(0x1 << 5)
+#define MFPR_EDGE_RISE_EN	(0x1 << 4)
+
+#define MFPR_SLEEP_DATA(x)	((x) << 8)
+#define MFPR_DRIVE(x)		(((x) & 0x7) << 10)
+#define MFPR_AF_SEL(x)		(((x) & 0x7) << 0)
+
+#define MFPR_EDGE_NONE		(0)
+#define MFPR_EDGE_RISE		(MFPR_EDGE_RISE_EN)
+#define MFPR_EDGE_FALL		(MFPR_EDGE_FALL_EN)
+#define MFPR_EDGE_BOTH		(MFPR_EDGE_RISE | MFPR_EDGE_FALL)
+
+/*
+ * Table that determines the low power modes outputs, with actual settings
+ * used in parentheses for don't-care values. Except for the float output,
+ * the configured driven and pulled levels match, so if there is a need for
+ * non-LPM pulled output, the same configuration could probably be used.
+ *
+ * Output value  sleep_oe_n  sleep_data  pullup_en  pulldown_en  pull_sel
+ *                 (bit 7)    (bit 8)    (bit 14)     (bit 13)   (bit 15)
+ *
+ * Input            0          X(0)        X(0)        X(0)       0
+ * Drive 0          0          0           0           X(1)       0
+ * Drive 1          0          1           X(1)        0	  0
+ * Pull hi (1)      1          X(1)        1           0	  0
+ * Pull lo (0)      1          X(0)        0           1	  0
+ * Z (float)        1          X(0)        0           0	  0
+ */
+#define MFPR_LPM_INPUT		(0)
+#define MFPR_LPM_DRIVE_LOW	(MFPR_SLEEP_DATA(0) | MFPR_PULLDOWN_EN)
+#define MFPR_LPM_DRIVE_HIGH    	(MFPR_SLEEP_DATA(1) | MFPR_PULLUP_EN)
+#define MFPR_LPM_PULL_LOW      	(MFPR_LPM_DRIVE_LOW  | MFPR_SLEEP_OE_N)
+#define MFPR_LPM_PULL_HIGH     	(MFPR_LPM_DRIVE_HIGH | MFPR_SLEEP_OE_N)
+#define MFPR_LPM_FLOAT         	(MFPR_SLEEP_OE_N)
+#define MFPR_LPM_MASK		(0xe080)
+
+/*
+ * The pullup and pulldown state of the MFP pin at run mode is by default
+ * determined by the selected alternate function. In case that some buggy
+ * devices need to override this default behavior,  the definitions below
+ * indicates the setting of corresponding MFPR bits
+ *
+ * Definition       pull_sel  pullup_en  pulldown_en
+ * MFPR_PULL_NONE       0         0        0
+ * MFPR_PULL_LOW        1         0        1
+ * MFPR_PULL_HIGH       1         1        0
+ * MFPR_PULL_BOTH       1         1        1
+ */
+#define MFPR_PULL_NONE		(0)
+#define MFPR_PULL_LOW		(MFPR_PULL_SEL | MFPR_PULLDOWN_EN)
+#define MFPR_PULL_BOTH		(MFPR_PULL_LOW | MFPR_PULLUP_EN)
+#define MFPR_PULL_HIGH		(MFPR_PULL_SEL | MFPR_PULLUP_EN)
+
+/* mfp_spin_lock is used to ensure that MFP register configuration
+ * (most likely a read-modify-write operation) is atomic, and that
+ * mfp_table[] is consistent
+ */
+static DEFINE_SPINLOCK(mfp_spin_lock);
+
+static void __iomem *mfpr_mmio_base;
+
+struct mfp_pin {
+	unsigned long	config;		/* -1 for not configured */
+	unsigned long	mfpr_off;	/* MFPRxx Register offset */
+	unsigned long	mfpr_run;	/* Run-Mode Register Value */
+	unsigned long	mfpr_lpm;	/* Low Power Mode Register Value */
+};
+
+static struct mfp_pin mfp_table[MFP_PIN_MAX];
+
+/* mapping of MFP_LPM_* definitions to MFPR_LPM_* register bits */
+static const unsigned long mfpr_lpm[] = {
+	MFPR_LPM_INPUT,
+	MFPR_LPM_DRIVE_LOW,
+	MFPR_LPM_DRIVE_HIGH,
+	MFPR_LPM_PULL_LOW,
+	MFPR_LPM_PULL_HIGH,
+	MFPR_LPM_FLOAT,
+};
+
+/* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */
+static const unsigned long mfpr_pull[] = {
+	MFPR_PULL_NONE,
+	MFPR_PULL_LOW,
+	MFPR_PULL_HIGH,
+	MFPR_PULL_BOTH,
+};
+
+/* mapping of MFP_LPM_EDGE_* definitions to MFPR_EDGE_* register bits */
+static const unsigned long mfpr_edge[] = {
+	MFPR_EDGE_NONE,
+	MFPR_EDGE_RISE,
+	MFPR_EDGE_FALL,
+	MFPR_EDGE_BOTH,
+};
+
+#define mfpr_readl(off)			\
+	__raw_readl(mfpr_mmio_base + (off))
+
+#define mfpr_writel(off, val)		\
+	__raw_writel(val, mfpr_mmio_base + (off))
+
+#define mfp_configured(p)	((p)->config != -1)
+
+/*
+ * perform a read-back of any MFPR register to make sure the
+ * previous writings are finished
+ */
+#define mfpr_sync()	(void)__raw_readl(mfpr_mmio_base + 0)
+
+static inline void __mfp_config_run(struct mfp_pin *p)
+{
+	if (mfp_configured(p))
+		mfpr_writel(p->mfpr_off, p->mfpr_run);
+}
+
+static inline void __mfp_config_lpm(struct mfp_pin *p)
+{
+	if (mfp_configured(p)) {
+		unsigned long mfpr_clr = (p->mfpr_run & ~MFPR_EDGE_BOTH) | MFPR_EDGE_CLEAR;
+		if (mfpr_clr != p->mfpr_run)
+			mfpr_writel(p->mfpr_off, mfpr_clr);
+		if (p->mfpr_lpm != mfpr_clr)
+			mfpr_writel(p->mfpr_off, p->mfpr_lpm);
+	}
+}
+
+void mfp_config(unsigned long *mfp_cfgs, int num)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&mfp_spin_lock, flags);
+
+	for (i = 0; i < num; i++, mfp_cfgs++) {
+		unsigned long tmp, c = *mfp_cfgs;
+		struct mfp_pin *p;
+		int pin, af, drv, lpm, edge, pull;
+
+		pin = MFP_PIN(c);
+		BUG_ON(pin >= MFP_PIN_MAX);
+		p = &mfp_table[pin];
+
+		af  = MFP_AF(c);
+		drv = MFP_DS(c);
+		lpm = MFP_LPM_STATE(c);
+		edge = MFP_LPM_EDGE(c);
+		pull = MFP_PULL(c);
+
+		/* run-mode pull settings will conflict with MFPR bits of
+		 * low power mode state,  calculate mfpr_run and mfpr_lpm
+		 * individually if pull != MFP_PULL_NONE
+		 */
+		tmp = MFPR_AF_SEL(af) | MFPR_DRIVE(drv);
+
+		if (likely(pull == MFP_PULL_NONE)) {
+			p->mfpr_run = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+			p->mfpr_lpm = p->mfpr_run;
+		} else {
+			p->mfpr_lpm = tmp | mfpr_lpm[lpm] | mfpr_edge[edge];
+			p->mfpr_run = tmp | mfpr_pull[pull];
+		}
+
+		p->config = c; __mfp_config_run(p);
+	}
+
+	mfpr_sync();
+	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+unsigned long mfp_read(int mfp)
+{
+	unsigned long val, flags;
+
+	BUG_ON(mfp >= MFP_PIN_MAX);
+
+	spin_lock_irqsave(&mfp_spin_lock, flags);
+	val = mfpr_readl(mfp_table[mfp].mfpr_off);
+	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+
+	return val;
+}
+
+void mfp_write(int mfp, unsigned long val)
+{
+	unsigned long flags;
+
+	BUG_ON(mfp >= MFP_PIN_MAX);
+
+	spin_lock_irqsave(&mfp_spin_lock, flags);
+	mfpr_writel(mfp_table[mfp].mfpr_off, val);
+	mfpr_sync();
+	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void __init mfp_init_base(unsigned long mfpr_base)
+{
+	int i;
+
+	/* initialize the table with default - unconfigured */
+	for (i = 0; i < ARRAY_SIZE(mfp_table); i++)
+		mfp_table[i].config = -1;
+
+	mfpr_mmio_base = (void __iomem *)mfpr_base;
+}
+
+void __init mfp_init_addr(struct mfp_addr_map *map)
+{
+	struct mfp_addr_map *p;
+	unsigned long offset, flags;
+	int i;
+
+	spin_lock_irqsave(&mfp_spin_lock, flags);
+
+	for (p = map; p->start != MFP_PIN_INVALID; p++) {
+		offset = p->offset;
+		i = p->start;
+
+		do {
+			mfp_table[i].mfpr_off = offset;
+			mfp_table[i].mfpr_run = 0;
+			mfp_table[i].mfpr_lpm = 0;
+			offset += 4; i++;
+		} while ((i <= p->end) && (p->end != -1));
+	}
+
+	spin_unlock_irqrestore(&mfp_spin_lock, flags);
+}
+
+void mfp_config_lpm(void)
+{
+	struct mfp_pin *p = &mfp_table[0];
+	int pin;
+
+	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++)
+		__mfp_config_lpm(p);
+}
+
+void mfp_config_run(void)
+{
+	struct mfp_pin *p = &mfp_table[0];
+	int pin;
+
+	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++, p++)
+		__mfp_config_run(p);
+}
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
index 39195f9..8d7815d 100644
--- a/arch/arm/plat-s3c/Makefile
+++ b/arch/arm/plat-s3c/Makefile
@@ -18,6 +18,11 @@
 obj-y				+= gpio.o
 obj-y				+= gpio-config.o
 
+# PM support
+
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_S3C2410_PM_CHECK)	+= pm-check.o
+
 # devices
 
 obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
new file mode 100644
index 0000000..3779775
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -0,0 +1,174 @@
+/* linux/include/asm-arm/plat-s3c24xx/pm.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Written by 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.
+*/
+
+/* s3c_pm_init
+ *
+ * called from board at initialisation time to setup the power
+ * management
+*/
+
+#ifdef CONFIG_PM
+
+extern __init int s3c_pm_init(void);
+
+#else
+
+static inline int s3c_pm_init(void)
+{
+	return 0;
+}
+#endif
+
+/* configuration for the IRQ mask over sleep */
+extern unsigned long s3c_irqwake_intmask;
+extern unsigned long s3c_irqwake_eintmask;
+
+/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
+extern unsigned long s3c_irqwake_intallow;
+extern unsigned long s3c_irqwake_eintallow;
+
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
+/* Flags for PM Control */
+
+extern unsigned long s3c_pm_flags;
+
+/* from sleep.S */
+
+extern int  s3c_cpu_save(unsigned long *saveblk);
+extern void s3c_cpu_resume(void);
+
+extern void s3c2410_cpu_suspend(void);
+
+extern unsigned long s3c_sleep_save_phys;
+
+/* sleep save info */
+
+/**
+ * struct sleep_save - save information for shared peripherals.
+ * @reg: Pointer to the register to save.
+ * @val: Holder for the value saved from reg.
+ *
+ * This describes a list of registers which is used by the pm core and
+ * other subsystem to save and restore register values over suspend.
+ */
+struct sleep_save {
+	void __iomem	*reg;
+	unsigned long	val;
+};
+
+#define SAVE_ITEM(x) \
+	{ .reg = (x) }
+
+/**
+ * struct pm_uart_save - save block for core UART
+ * @ulcon: Save value for S3C2410_ULCON
+ * @ucon: Save value for S3C2410_UCON
+ * @ufcon: Save value for S3C2410_UFCON
+ * @umcon: Save value for S3C2410_UMCON
+ * @ubrdiv: Save value for S3C2410_UBRDIV
+ *
+ * Save block for UART registers to be held over sleep and restored if they
+ * are needed (say by debug).
+*/
+struct pm_uart_save {
+	u32	ulcon;
+	u32	ucon;
+	u32	ufcon;
+	u32	umcon;
+	u32	ubrdiv;
+};
+
+/* helper functions to save/restore lists of registers. */
+
+extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
+extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
+extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c_irqext_wake(unsigned int irqno, unsigned int state);
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c_irqext_wake NULL
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
+/* PM debug functions */
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+/**
+ * s3c_pm_dbg() - low level debug function for use in suspend/resume.
+ * @msg: The message to print.
+ *
+ * This function is used mainly to debug the resume process before the system
+ * can rely on printk/console output. It uses the low-level debugging output
+ * routine printascii() to do its work.
+ */
+extern void s3c_pm_dbg(const char *msg, ...);
+
+#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
+#else
+#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
+#endif
+
+/* suspend memory checking */
+
+#ifdef CONFIG_S3C2410_PM_CHECK
+extern void s3c_pm_check_prepare(void);
+extern void s3c_pm_check_restore(void);
+extern void s3c_pm_check_cleanup(void);
+extern void s3c_pm_check_store(void);
+#else
+#define s3c_pm_check_prepare() do { } while(0)
+#define s3c_pm_check_restore() do { } while(0)
+#define s3c_pm_check_cleanup() do { } while(0)
+#define s3c_pm_check_store()   do { } while(0)
+#endif
+
+/**
+ * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
+ *
+ * Setup all the necessary GPIO pins for waking the system on external
+ * interrupt.
+ */
+extern void s3c_pm_configure_extint(void);
+
+/**
+ * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ *
+ * Restore the state of the GPIO pins after sleep, which may involve ensuring
+ * that we do not glitch the state of the pins from that the bootloader's
+ * resume code has done.
+*/
+extern void s3c_pm_restore_gpios(void);
+
+/**
+ * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ *
+ * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ */
+extern void s3c_pm_save_gpios(void);
+
+/**
+ * s3c_pm_cb_flushcache - callback for assembly code
+ *
+ * Callback to issue flush_cache_all() as this call is
+ * not a directly callable object.
+ */
+extern void s3c_pm_cb_flushcache(void);
+
+extern void s3c_pm_save_core(void);
+extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h
index 6061de8..dc66a47 100644
--- a/arch/arm/plat-s3c/include/plat/uncompress.h
+++ b/arch/arm/plat-s3c/include/plat/uncompress.h
@@ -90,7 +90,10 @@
 {
 }
 
-#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
+#define __raw_writel(d, ad)			\
+	do {							\
+		*((volatile unsigned int __force *)(ad)) = (d); \
+	} while (0)
 
 /* CONFIG_S3C_BOOT_WATCHDOG
  *
diff --git a/arch/arm/plat-s3c/pm-check.c b/arch/arm/plat-s3c/pm-check.c
new file mode 100644
index 0000000..39f2555
--- /dev/null
+++ b/arch/arm/plat-s3c/pm-check.c
@@ -0,0 +1,242 @@
+/* linux/arch/arm/plat-s3c/pm-check.c
+ *  originally in linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004,2006,2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Power Mangament - suspend/resume memory corruptiuon check.
+ *
+ * This program is free software; you can 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/suspend.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+
+#include <plat/pm.h>
+
+#if CONFIG_S3C2410_PM_CHECK_CHUNKSIZE < 1
+#error CONFIG_S3C2410_PM_CHECK_CHUNKSIZE must be a positive non-zero value
+#endif
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;	/* size needed for the crc block */
+static u32 *crcs;	/* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c_pm_run_res
+ *
+ * go through the given resource list, and look for system ram
+*/
+
+static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+	while (ptr != NULL) {
+		if (ptr->child != NULL)
+			s3c_pm_run_res(ptr->child, fn, arg);
+
+		if ((ptr->flags & IORESOURCE_MEM) &&
+		    strcmp(ptr->name, "System RAM") == 0) {
+			S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
+				  (unsigned long)ptr->start,
+				  (unsigned long)ptr->end);
+			arg = (fn)(ptr, arg);
+		}
+
+		ptr = ptr->sibling;
+	}
+}
+
+static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+	s3c_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c_pm_countram(struct resource *res, u32 *val)
+{
+	u32 size = (u32)(res->end - res->start)+1;
+
+	size += CHECK_CHUNKSIZE-1;
+	size /= CHECK_CHUNKSIZE;
+
+	S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
+		  (unsigned long)res->start, (unsigned long)res->end, size);
+
+	*val += size * sizeof(u32);
+	return val;
+}
+
+/* s3c_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+void s3c_pm_check_prepare(void)
+{
+	crc_size = 0;
+
+	s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
+
+	S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
+
+	crcs = kmalloc(crc_size+4, GFP_KERNEL);
+	if (crcs == NULL)
+		printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
+{
+	unsigned long addr, left;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		*val = crc32_le(~0, phys_to_virt(addr), left);
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+void s3c_pm_check_store(void)
+{
+	if (crcs != NULL)
+		s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contains the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+	if ((what+whatsz) < ptr)
+		return 0;
+
+	if (what > (ptr+size))
+		return 0;
+
+	return 1;
+}
+
+/**
+ * s3c_pm_runcheck() - helper to check a resource on restore.
+ * @res: The resource to check
+ * @vak: Pointer to list of CRC32 values to check.
+ *
+ * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
+ * function runs the given memory resource checking it against the stored
+ * CRC to ensure that memory is restored. The function tries to skip as
+ * many of the areas used during the suspend process.
+ */
+static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
+{
+	void *save_at = phys_to_virt(s3c_sleep_save_phys);
+	unsigned long addr;
+	unsigned long left;
+	void *stkpage;
+	void *ptr;
+	u32 calc;
+
+	stkpage = (void *)((u32)&calc & ~PAGE_MASK);
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		ptr = phys_to_virt(addr);
+
+		if (in_region(ptr, left, stkpage, 4096)) {
+			S3C_PMDBG("skipping %08lx, has stack in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, crcs, crc_size)) {
+			S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, save_at, 32*4 )) {
+			S3C_PMDBG("skipping %08lx, has save block in\n", addr);
+			goto skip_check;
+		}
+
+		/* calculate and check the checksum */
+
+		calc = crc32_le(~0, ptr, left);
+		if (calc != *val) {
+			printk(KERN_ERR "Restore CRC error at "
+			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+			S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+			    addr, calc, *val);
+		}
+
+	skip_check:
+		val++;
+	}
+
+	return val;
+}
+
+/**
+ * s3c_pm_check_restore() - memory check called on resume
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+void s3c_pm_check_restore(void)
+{
+	if (crcs != NULL)
+		s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
+}
+
+/**
+ * s3c_pm_check_cleanup() - free memory resources
+ *
+ * Free the resources that where allocated by the suspend
+ * memory check code. We do this separately from the
+ * s3c_pm_check_restore() function as we cannot call any
+ * functions that might sleep during that resume.
+ */
+void s3c_pm_check_cleanup(void)
+{
+	kfree(crcs);
+	crcs = NULL;
+}
+
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
new file mode 100644
index 0000000..061182c
--- /dev/null
+++ b/arch/arm/plat-s3c/pm.c
@@ -0,0 +1,363 @@
+/* linux/arch/arm/plat-s3c/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2004,2006,2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C common power management (suspend to ram) support.
+ *
+ * This program is free software; you can 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/suspend.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-mem.h>
+#include <mach/regs-irq.h>
+#include <asm/irq.h>
+
+#include <plat/pm.h>
+#include <plat/pm-core.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+/* Debug code:
+ *
+ * This code supports debug output to the low level UARTs for use on
+ * resume before the console layer is available.
+*/
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+extern void printascii(const char *);
+
+void s3c_pm_dbg(const char *fmt, ...)
+{
+	va_list va;
+	char buff[256];
+
+	va_start(va, fmt);
+	vsprintf(buff, fmt, va);
+	va_end(va);
+
+	printascii(buff);
+}
+
+static inline void s3c_pm_debug_init(void)
+{
+	/* restart uart clocks so we can use them to output */
+	s3c_pm_debug_init_uart();
+}
+
+#else
+#define s3c_pm_debug_init() do { } while(0)
+
+#endif /* CONFIG_S3C2410_PM_DEBUG */
+
+/* Save the UART configurations if we are configured for debug. */
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
+{
+	void __iomem *regs = S3C_VA_UARTx(uart);
+
+	save->ulcon = __raw_readl(regs + S3C2410_ULCON);
+	save->ucon = __raw_readl(regs + S3C2410_UCON);
+	save->ufcon = __raw_readl(regs + S3C2410_UFCON);
+	save->umcon = __raw_readl(regs + S3C2410_UMCON);
+	save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
+}
+
+static void s3c_pm_save_uarts(void)
+{
+	struct pm_uart_save *save = uart_save;
+	unsigned int uart;
+
+	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
+		s3c_pm_save_uart(uart, save);
+}
+
+static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
+{
+	void __iomem *regs = S3C_VA_UARTx(uart);
+
+	__raw_writel(save->ulcon, regs + S3C2410_ULCON);
+	__raw_writel(save->ucon,  regs + S3C2410_UCON);
+	__raw_writel(save->ufcon, regs + S3C2410_UFCON);
+	__raw_writel(save->umcon, regs + S3C2410_UMCON);
+	__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
+}
+
+static void s3c_pm_restore_uarts(void)
+{
+	struct pm_uart_save *save = uart_save;
+	unsigned int uart;
+
+	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
+		s3c_pm_restore_uart(uart, save);
+}
+#else
+static void s3c_pm_save_uarts(void) { }
+static void s3c_pm_restore_uarts(void) { }
+#endif
+
+/* The IRQ ext-int code goes here, it is too small to currently bother
+ * with its own file. */
+
+unsigned long s3c_irqwake_intmask	= 0xffffffffL;
+unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
+
+int s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
+
+	if (!(s3c_irqwake_eintallow & bit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_eintmask |= bit;
+	else
+		s3c_irqwake_eintmask &= ~bit;
+
+	return 0;
+}
+
+/* helper functions to save and restore register state */
+
+/**
+ * s3c_pm_do_save() - save a set of registers for restoration on resume.
+ * @ptr: Pointer to an array of registers.
+ * @count: Size of the ptr array.
+ *
+ * Run through the list of registers given, saving their contents in the
+ * array for later restoration when we wakeup.
+ */
+void s3c_pm_do_save(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		ptr->val = __raw_readl(ptr->reg);
+		S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+	}
+}
+
+/**
+ * s3c_pm_do_restore() - restore register values from the save list.
+ * @ptr: Pointer to an array of registers.
+ * @count: Size of the ptr array.
+ *
+ * Restore the register values saved from s3c_pm_do_save().
+ *
+ * Note, we do not use S3C_PMDBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c_pm_do_restore(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/**
+ * s3c_pm_do_restore_core() - early restore register values from save list.
+ *
+ * This is similar to s3c_pm_do_restore() except we try and minimise the
+ * side effects of the function in case registers that hardware might need
+ * to work has been restored.
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++)
+		__raw_writel(ptr->val, ptr->reg);
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+				    unsigned long mask)
+{
+	int i;
+
+	which &= ~mask;
+
+	for (i = 0; i <= 31; i++) {
+		if (which & (1L<<i)) {
+			S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
+		}
+	}
+}
+
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c_pm_enter(suspend_state_t state)
+{
+	static unsigned long regs_save[16];
+
+	/* ensure the debug is initialised (if enabled) */
+
+	s3c_pm_debug_init();
+
+	S3C_PMDBG("%s(%d)\n", __func__, state);
+
+	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+		printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
+		return -EINVAL;
+	}
+
+	/* check if we have anything to wake-up with... bad things seem
+	 * to happen if you suspend with no wakeup (system will often
+	 * require a full power-cycle)
+	*/
+
+	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+		printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
+		printk(KERN_ERR "%s: Aborting sleep\n", __func__);
+		return -EINVAL;
+	}
+
+	/* store the physical address of the register recovery block */
+
+	s3c_sleep_save_phys = virt_to_phys(regs_save);
+
+	S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
+
+	/* save all necessary core registers not covered by the drivers */
+
+	s3c_pm_save_gpios();
+	s3c_pm_save_uarts();
+	s3c_pm_save_core();
+
+	/* set the irq configuration for wake */
+
+	s3c_pm_configure_extint();
+
+	S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+	s3c_pm_arch_prepare_irqs();
+
+	/* call cpu specific preparation */
+
+	pm_cpu_prep();
+
+	/* flush cache back to ram */
+
+	flush_cache_all();
+
+	s3c_pm_check_store();
+
+	/* send the cpu to sleep... */
+
+	s3c_pm_arch_stop_clocks();
+
+	/* s3c_cpu_save will also act as our return point from when
+	 * we resume as it saves its own register state and restores it
+	 * during the resume.  */
+
+	s3c_cpu_save(regs_save);
+
+	/* restore the cpu state using the kernel's cpu init code. */
+
+	cpu_init();
+
+	/* restore the system state */
+
+	s3c_pm_restore_core();
+	s3c_pm_restore_uarts();
+	s3c_pm_restore_gpios();
+
+	s3c_pm_debug_init();
+
+	/* check what irq (if any) restored the system */
+
+	s3c_pm_arch_show_resume_irqs();
+
+	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
+
+	s3c_pm_check_restore();
+
+	/* ok, let's return from sleep */
+
+	S3C_PMDBG("S3C PM Resume (post-restore)\n");
+	return 0;
+}
+
+/* callback from assembly code */
+void s3c_pm_cb_flushcache(void)
+{
+	flush_cache_all();
+}
+
+static int s3c_pm_prepare(void)
+{
+	/* prepare check area if configured */
+
+	s3c_pm_check_prepare();
+	return 0;
+}
+
+static void s3c_pm_finish(void)
+{
+	s3c_pm_check_cleanup();
+}
+
+static struct platform_suspend_ops s3c_pm_ops = {
+	.enter		= s3c_pm_enter,
+	.prepare	= s3c_pm_prepare,
+	.finish		= s3c_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+/* s3c_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c_pm_init(void)
+{
+	printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
+
+	suspend_set_ops(&s3c_pm_ops);
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 1e0767b..636cb12 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-clock.o
 obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
 obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= irq-pm.o
 obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_PWM)		+= pwm.o
 obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index 3d48370..1a8347c 100644
--- a/arch/arm/plat-s3c24xx/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -201,5 +201,5 @@
 
 	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
 
-	s3c2410_pm_init();
+	s3c_pm_init();
 }
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index 542062f..1932b7e 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -182,7 +182,7 @@
  * with the caches enabled. It seems at least the S3C2440 has a problem
  * resetting if there is bus activity interrupted by the reset.
  */
-static void s3c24xx_pm_restart(char mode)
+static void s3c24xx_pm_restart(char mode, const char *cmd)
 {
 	if (mode != 's') {
 		unsigned long flags;
@@ -191,12 +191,12 @@
 		__cpuc_flush_kern_all();
 		__cpuc_flush_user_all();
 
-		arch_reset(mode);
+		arch_reset(mode, cmd);
 		local_irq_restore(flags);
 	}
 
 	/* fallback, or unhandled */
-	arm_machine_restart(mode);
+	arm_machine_restart(mode, cmd);
 }
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
diff --git a/arch/arm/plat-s3c24xx/include/plat/irq.h b/arch/arm/plat-s3c24xx/include/plat/irq.h
index 45746a9..69e1be8 100644
--- a/arch/arm/plat-s3c24xx/include/plat/irq.h
+++ b/arch/arm/plat-s3c24xx/include/plat/irq.h
@@ -10,6 +10,12 @@
  * published by the Free Software Foundation.
 */
 
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+
 #define irqdbf(x...)
 #define irqdbf2(x...)
 
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
index fef8ea8..eed8f78 100644
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ b/arch/arm/plat-s3c24xx/include/plat/map.h
@@ -31,6 +31,8 @@
 #define S3C24XX_SZ_UART	   SZ_1M
 #define S3C_UART_OFFSET	   (0x4000)
 
+#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
+
 /* Timers */
 #define S3C24XX_VA_TIMER   S3C_VA_TIMER
 #define S3C2410_PA_TIMER   (0x51000000)
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm-core.h b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
new file mode 100644
index 0000000..c758821
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
@@ -0,0 +1,59 @@
+/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+	/* re-start uart clocks */
+	tmp |= S3C2410_CLKCON_UART0;
+	tmp |= S3C2410_CLKCON_UART1;
+	tmp |= S3C2410_CLKCON_UART2;
+
+	__raw_writel(tmp, S3C2410_CLKCON);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+	/* ack any outstanding external interrupts before we go to sleep */
+
+	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+}
+
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+				    unsigned long mask);
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+		  __raw_readl(S3C2410_SRCPND),
+		  __raw_readl(S3C2410_EINTPEND));
+
+	s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+				s3c_irqwake_intmask);
+
+	s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+				s3c_irqwake_eintmask);
+}
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm.h b/arch/arm/plat-s3c24xx/include/plat/pm.h
deleted file mode 100644
index cc62366..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/pm.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/pm.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Written by 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.
-*/
-
-/* s3c2410_pm_init
- *
- * called from board at initialisation time to setup the power
- * management
-*/
-
-#ifdef CONFIG_PM
-
-extern __init int s3c2410_pm_init(void);
-
-#else
-
-static inline int s3c2410_pm_init(void)
-{
-	return 0;
-}
-#endif
-
-/* configuration for the IRQ mask over sleep */
-extern unsigned long s3c_irqwake_intmask;
-extern unsigned long s3c_irqwake_eintmask;
-
-/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
-extern unsigned long s3c_irqwake_intallow;
-extern unsigned long s3c_irqwake_eintallow;
-
-/* per-cpu sleep functions */
-
-extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
-
-/* Flags for PM Control */
-
-extern unsigned long s3c_pm_flags;
-
-/* from sleep.S */
-
-extern int  s3c2410_cpu_save(unsigned long *saveblk);
-extern void s3c2410_cpu_suspend(void);
-extern void s3c2410_cpu_resume(void);
-
-extern unsigned long s3c2410_sleep_save_phys;
-
-/* sleep save info */
-
-struct sleep_save {
-	void __iomem	*reg;
-	unsigned long	val;
-};
-
-#define SAVE_ITEM(x) \
-	{ .reg = (x) }
-
-extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
-extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
-
-#ifdef CONFIG_PM
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
diff --git a/arch/arm/plat-s3c24xx/irq-pm.c b/arch/arm/plat-s3c24xx/irq-pm.c
new file mode 100644
index 0000000..b7acf1a
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/irq-pm.c
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-s3c24xx/irq-om.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C24XX - IRQ PM 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
+
+int s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+	if (!(s3c_irqwake_intallow & irqbit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_intmask |= irqbit;
+	else
+		s3c_irqwake_intmask &= ~irqbit;
+
+	return 0;
+}
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C2410_INTMSK),
+	SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 0192ecd..9587377 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/plat-s3c24xx/irq.c
  *
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics 
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -16,38 +16,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog:
- *
- *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
- *                Fixed compile warnings
- *
- *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
- *                Fixed s3c_extirq_type
- *
- *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
- *                Addition of ADC/TC demux
- *
- *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
- *		  Fix for set_irq_type() on low EINT numbers
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Tidy up KF's patch and sort out new release
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Add support for power management controls
- *
- *   04-Nov-2004  Ben Dooks
- *		  Fix standard IRQ wake for EINT0..4 and RTC
- *
- *   22-Feb-2005  Ben Dooks
- *		  Fixed edge-triggering on ADC IRQ
- *
- *   28-Jun-2005  Ben Dooks
- *		  Mark IRQ_LCD valid
- *
- *   25-Jul-2005  Ben Dooks
- *		  Split the S3C2440 IRQ code to separate file
 */
 
 #include <linux/init.h>
@@ -55,81 +23,16 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/sysdev.h>
-#include <linux/io.h>
 
-#include <mach/hardware.h>
 #include <asm/irq.h>
-
 #include <asm/mach/irq.h>
 
 #include <plat/regs-irqtype.h>
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
 #include <plat/irq.h>
 
-/* wakeup irq control */
-
-#ifdef CONFIG_PM
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
-unsigned long s3c_irqwake_intmask	= 0xffffffffL;
-unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
-unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
-
-int
-s3c_irq_wake(unsigned int irqno, unsigned int state)
-{
-	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
-
-	if (!(s3c_irqwake_intallow & irqbit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_intmask |= irqbit;
-	else
-		s3c_irqwake_intmask &= ~irqbit;
-
-	return 0;
-}
-
-static int
-s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
-	unsigned long bit = 1L << (irqno - EXTINT_OFF);
-
-	if (!(s3c_irqwake_eintallow & bit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_eintmask |= bit;
-	else
-		s3c_irqwake_eintmask &= ~bit;
-
-	return 0;
-}
-
-#else
-#define s3c_irqext_wake NULL
-#define s3c_irq_wake NULL
-#endif
-
-
 static void
 s3c_irq_mask(unsigned int irqno)
 {
@@ -590,59 +493,6 @@
 	}
 }
 
-#ifdef CONFIG_PM
-
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S3C2410_INTMSK),
-	SAVE_ITEM(S3C2410_INTSUBMSK),
-};
-
-/* the extint values move between the s3c2410/s3c2440 and the s3c2412
- * so we use an array to hold them, and to calculate the address of
- * the register at run-time
-*/
-
-static unsigned long save_extint[3];
-static unsigned long save_eintflt[4];
-static unsigned long save_eintmask;
-
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-int s3c24xx_irq_resume(struct sys_device *dev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
-
 /* s3c24xx_init_irq
  *
  * Initialise S3C2410 IRQ system
diff --git a/arch/arm/plat-s3c24xx/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
index 21dfa74..da0d321 100644
--- a/arch/arm/plat-s3c24xx/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -61,7 +61,7 @@
 
 	__raw_writel(gstatus4, S3C2410_GSTATUS4);
 
-	return s3c2410_pm_init();
+	return s3c_pm_init();
 }
 
 arch_initcall(pm_simtec_init);
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index 34ef18e..062a293 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -31,14 +31,9 @@
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
 #include <linux/serial_core.h>
 #include <linux/io.h>
 
-#include <asm/cacheflush.h>
-#include <mach/hardware.h>
-
 #include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
@@ -49,10 +44,6 @@
 
 #include <plat/pm.h>
 
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
 #define PFX "s3c24xx-pm: "
 
 static struct sleep_save core_save[] = {
@@ -120,328 +111,14 @@
 	SAVE_ITEM(S3C2410_DCLKCON),
 };
 
-#ifdef CONFIG_S3C2410_PM_DEBUG
 
-#define SAVE_UART(va) \
-	SAVE_ITEM((va) + S3C2410_ULCON), \
-	SAVE_ITEM((va) + S3C2410_UCON), \
-	SAVE_ITEM((va) + S3C2410_UFCON), \
-	SAVE_ITEM((va) + S3C2410_UMCON), \
-	SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
-	SAVE_UART(S3C24XX_VA_UART0),
-	SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
-	SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-extern void printascii(const char *);
-
-void pm_dbg(const char *fmt, ...)
-{
-	va_list va;
-	char buff[256];
-
-	va_start(va, fmt);
-	vsprintf(buff, fmt, va);
-	va_end(va);
-
-	printascii(buff);
-}
-
-static void s3c2410_pm_debug_init(void)
-{
-	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-	/* re-start uart clocks */
-	tmp |= S3C2410_CLKCON_UART0;
-	tmp |= S3C2410_CLKCON_UART1;
-	tmp |= S3C2410_CLKCON_UART2;
-
-	__raw_writel(tmp, S3C2410_CLKCON);
-	udelay(10);
-}
-
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
-#endif
-
-#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size;	/* size needed for the crc block */
-static u32 *crcs;	/* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c2410_pm_run_res
- *
- * go thorugh the given resource list, and look for system ram
-*/
-
-static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
-{
-	while (ptr != NULL) {
-		if (ptr->child != NULL)
-			s3c2410_pm_run_res(ptr->child, fn, arg);
-
-		if ((ptr->flags & IORESOURCE_MEM) &&
-		    strcmp(ptr->name, "System RAM") == 0) {
-			DBG("Found system RAM at %08lx..%08lx\n",
-			    ptr->start, ptr->end);
-			arg = (fn)(ptr, arg);
-		}
-
-		ptr = ptr->sibling;
-	}
-}
-
-static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
-	s3c2410_pm_run_res(&iomem_resource, fn, arg);
-}
-
-static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
-{
-	u32 size = (u32)(res->end - res->start)+1;
-
-	size += CHECK_CHUNKSIZE-1;
-	size /= CHECK_CHUNKSIZE;
-
-	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
-
-	*val += size * sizeof(u32);
-	return val;
-}
-
-/* s3c2410_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-static void s3c2410_pm_check_prepare(void)
-{
-	crc_size = 0;
-
-	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
-
-	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
-
-	crcs = kmalloc(crc_size+4, GFP_KERNEL);
-	if (crcs == NULL)
-		printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
-
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
-	unsigned long addr, left;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		*val = crc32_le(~0, phys_to_virt(addr), left);
-		val++;
-	}
-
-	return val;
-}
-
-/* s3c2410_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-static void s3c2410_pm_check_store(void)
-{
-	if (crcs != NULL)
-		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
-}
-
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contatins the
- * what..what+whatsz
-*/
-
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
-	if ((what+whatsz) < ptr)
-		return 0;
-
-	if (what > (ptr+size))
-		return 0;
-
-	return 1;
-}
-
-static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
-{
-	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
-	unsigned long addr;
-	unsigned long left;
-	void *ptr;
-	u32 calc;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		ptr = phys_to_virt(addr);
-
-		if (in_region(ptr, left, crcs, crc_size)) {
-			DBG("skipping %08lx, has crc block in\n", addr);
-			goto skip_check;
-		}
-
-		if (in_region(ptr, left, save_at, 32*4 )) {
-			DBG("skipping %08lx, has save block in\n", addr);
-			goto skip_check;
-		}
-
-		/* calculate and check the checksum */
-
-		calc = crc32_le(~0, ptr, left);
-		if (calc != *val) {
-			printk(KERN_ERR PFX "Restore CRC error at "
-			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
-			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
-			    addr, calc, *val);
-		}
-
-	skip_check:
-		val++;
-	}
-
-	return val;
-}
-
-/* s3c2410_pm_check_restore
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-
-static void s3c2410_pm_check_restore(void)
-{
-	if (crcs != NULL) {
-		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
-		kfree(crcs);
-		crcs = NULL;
-	}
-}
-
-#else
-
-#define s3c2410_pm_check_prepare() do { } while(0)
-#define s3c2410_pm_check_restore() do { } while(0)
-#define s3c2410_pm_check_store()   do { } while(0)
-#endif
-
-/* helper functions to save and restore register state */
-
-void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		ptr->val = __raw_readl(ptr->reg);
-		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-	}
-}
-
-/* s3c2410_pm_do_restore
- *
- * restore the system from the given list of saved registers
- *
- * Note, we do not use DBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
-
-void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
-		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_do_restore_core
- *
- * similar to s3c2410_pm_do_restore_core
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
-
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
-					unsigned long mask)
-{
-	int i;
-
-	which &= ~mask;
-
-	for (i = 0; i <= 31; i++) {
-		if ((which) & (1L<<i)) {
-			DBG("IRQ %d asserted at resume\n", start+i);
-		}
-	}
-}
-
-/* s3c2410_pm_check_resume_pin
+/* s3c_pm_check_resume_pin
  *
  * check to see if the pin is configured correctly for sleep mode, and
  * make any necessary adjustments if it is not
 */
 
-static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
 {
 	unsigned long irqstate;
 	unsigned long pinstate;
@@ -456,21 +133,21 @@
 
 	if (!irqstate) {
 		if (pinstate == S3C2410_GPIO_IRQ)
-			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+			S3C_PMDBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
 	} else {
 		if (pinstate == S3C2410_GPIO_IRQ) {
-			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+			S3C_PMDBG("Disabling IRQ %d (pin %d)\n", irq, pin);
 			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
 		}
 	}
 }
 
-/* s3c2410_pm_configure_extint
+/* s3c_pm_configure_extint
  *
  * configure all external interrupt pins
 */
 
-static void s3c2410_pm_configure_extint(void)
+void s3c_pm_configure_extint(void)
 {
 	int pin;
 
@@ -480,11 +157,11 @@
 	*/
 
 	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+		s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
 	}
 
 	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+		s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
 	}
 }
 
@@ -494,12 +171,12 @@
 #define OFFS_DAT	(S3C2410_GPADAT - S3C2410_GPACON)
 #define OFFS_UP		(S3C2410_GPBUP  - S3C2410_GPBCON)
 
-/* s3c2410_pm_save_gpios()
+/* s3c_pm_save_gpios()
  *
  * Save the state of the GPIOs
  */
 
-static void s3c2410_pm_save_gpios(void)
+void s3c_pm_save_gpios(void)
 {
 	struct gpio_sleep *gps = gpio_save;
 	unsigned int gpio;
@@ -538,7 +215,10 @@
 	return con == 1;
 }
 
-/* s3c2410_pm_restore_gpio()
+/**
+ * s3c2410_pm_restore_gpio() - restore the given GPIO bank
+ * @index: The number of the GPIO bank being resumed.
+ * @gps: The sleep confgiuration for the bank.
  *
  * Restore one of the GPIO banks that was saved during suspend. This is
  * not as simple as once thought, due to the possibility of glitches
@@ -646,8 +326,8 @@
 		__raw_writel(gps->gpup, base + OFFS_UP);
 	}
 
-	DBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
-	    index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+	S3C_PMDBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
+		  index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
 }
 
 
@@ -656,7 +336,7 @@
  * Restore the state of the GPIOs
  */
 
-static void s3c2410_pm_restore_gpios(void)
+void s3c_pm_restore_gpios(void)
 {
 	struct gpio_sleep *gps = gpio_save;
 	int gpio;
@@ -666,150 +346,15 @@
 	}
 }
 
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
+void s3c_pm_restore_core(void)
 {
-	unsigned long regs_save[16];
-
-	/* ensure the debug is initialised (if enabled) */
-
-	s3c2410_pm_debug_init();
-
-	DBG("s3c2410_pm_enter(%d)\n", state);
-
-	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
-		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
-		return -EINVAL;
-	}
-
-	/* check if we have anything to wake-up with... bad things seem
-	 * to happen if you suspend with no wakeup (system will often
-	 * require a full power-cycle)
-	*/
-
-	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
-		printk(KERN_ERR PFX "Aborting sleep\n");
-		return -EINVAL;
-	}
-
-	/* prepare check area if configured */
-
-	s3c2410_pm_check_prepare();
-
-	/* store the physical address of the register recovery block */
-
-	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
-
-	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
-
-	/* save all necessary core registers not covered by the drivers */
-
-	s3c2410_pm_save_gpios();
-	s3c2410_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
-	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
-	/* set the irq configuration for wake */
-
-	s3c2410_pm_configure_extint();
-
-	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-	/* ack any outstanding external interrupts before we go to sleep */
-
-	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
-	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
-	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
-	/* call cpu specific preparation */
-
-	pm_cpu_prep();
-
-	/* flush cache back to ram */
-
-	flush_cache_all();
-
-	s3c2410_pm_check_store();
-
-	/* send the cpu to sleep... */
-
-	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-
-	/* s3c2410_cpu_save will also act as our return point from when
-	 * we resume as it saves its own register state, so use the return
-	 * code to differentiate return from save and return from sleep */
-
-	if (s3c2410_cpu_save(regs_save) == 0) {
-		flush_cache_all();
-		pm_cpu_sleep();
-	}
-
-	/* restore the cpu state */
-
-	cpu_init();
-
-	/* restore the system state */
-
-	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
-	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-	s3c2410_pm_restore_gpios();
-
-	s3c2410_pm_debug_init();
-
-	/* check what irq (if any) restored the system */
-
-	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-	    __raw_readl(S3C2410_SRCPND),
-	    __raw_readl(S3C2410_EINTPEND));
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-				    s3c_irqwake_intmask);
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-				    s3c_irqwake_eintmask);
-
-	DBG("post sleep, preparing to return\n");
-
-	s3c2410_pm_check_restore();
-
-	/* ok, let's return from sleep */
-
-	DBG("S3C2410 PM Resume (post-restore)\n");
-	return 0;
+	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
 }
 
-static struct platform_suspend_ops s3c2410_pm_ops = {
-	.enter		= s3c2410_pm_enter,
-	.valid		= suspend_valid_only_mem,
-};
-
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
-
-int __init s3c2410_pm_init(void)
+void s3c_pm_save_core(void)
 {
-	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-	suspend_set_ops(&s3c2410_pm_ops);
-	return 0;
+	s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
 }
+
diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
index c1de6bb..1364317 100644
--- a/arch/arm/plat-s3c24xx/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -145,13 +145,13 @@
 
 static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
 {
-	s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
 	return 0;
 }
 
 static int s3c244x_resume(struct sys_device *dev)
 {
-	s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
 	return 0;
 }
 
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index 76594b2..e73e3b6e 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -41,25 +41,13 @@
 
 	.text
 
-	/* s3c2410_cpu_save
-	 *
-	 * save enough of the CPU state to allow us to re-start
-	 * pm.c code. as we store items like the sp/lr, we will
-	 * end up returning from this function when the cpu resumes
-	 * so the return value is set to mark this.
-	 *
-	 * This arangement means we avoid having to flush the cache
-	 * from this code.
+	/* s3c_cpu_save
 	 *
 	 * entry:
-	 *	r0 = pointer to save block
-	 *
-	 * exit:
-	 *	r0 = 0 => we stored everything
-	 *	     1 => resumed from sleep
+	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
 	*/
 
-ENTRY(s3c2410_cpu_save)
+ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
 
 	@@ store co-processor registers
@@ -71,20 +59,25 @@
 
 	stmia	r0, { r4 - r13 }
 
-	mov	r0, #0
-	ldmfd	sp, { r4 - r12, pc }
+	@@ write our state back to RAM
+	bl	s3c_pm_cb_flushcache
 
+	@@ jump to final code to send system to sleep
+	ldr	r0, =pm_cpu_sleep
+	@@ldr	pc, [ r0 ]
+	ldr	r0, [ r0 ]
+	mov	pc, r0
+	
 	@@ return to the caller, after having the MMU
 	@@ turned on, this restores the last bits from the
 	@@ stack
 resume_with_mmu:
-	mov	r0, #1
 	ldmfd	sp!, { r4 - r12, pc }
 
 	.ltorg
 
 	@@ the next bits sit in the .data segment, even though they
-	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
+	@@ happen to be code... the s3c_sleep_save_phys needs to be
 	@@ accessed by the resume code before it can restore the MMU.
 	@@ This means that the variable has to be close enough for the
 	@@ code to read it... since the .text segment needs to be RO,
@@ -92,19 +85,19 @@
 
 	.data
 
-	.global	s3c2410_sleep_save_phys
-s3c2410_sleep_save_phys:
+	.global	s3c_sleep_save_phys
+s3c_sleep_save_phys:
 	.word	0
 
 
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
-	 * s3c2410_cpu_resume entry.
+	 * s3c_cpu_resume entry.
 	*/
 
 	.word	0x2bedf00d
 
-	/* s3c2410_cpu_resume
+	/* s3c_cpu_resume
 	 *
 	 * resume code entry for bootloader to call
 	 *
@@ -113,7 +106,7 @@
 	 * must not write to the code segment (code is read-only)
 	*/
 
-ENTRY(s3c2410_cpu_resume)
+ENTRY(s3c_cpu_resume)
 	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
 	msr	cpsr_c, r0
 
@@ -145,7 +138,7 @@
 	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
 	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
 
-	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
+	ldr	r0, s3c_sleep_save_phys		@ address of restore block
 	ldmia	r0, { r4 - r13 }
 
 	mcr	p15, 0, r4, c13, c0, 0		@ PID
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c
index fbde183..91f49a3 100644
--- a/arch/arm/plat-s3c64xx/cpu.c
+++ b/arch/arm/plat-s3c64xx/cpu.c
@@ -96,6 +96,11 @@
 		.pfn		= __phys_to_pfn(S3C64XX_PA_GPIO),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C64XX_VA_MODEM,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
 	},
 };
 
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
new file mode 100644
index 0000000..82342f6
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - GPIO memory port register definitions
+ */
+
+#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H
+#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__
+
+#define S3C64XX_MEM0CONSTOP	S3C64XX_GPIOREG(0x1B0)
+#define S3C64XX_MEM1CONSTOP	S3C64XX_GPIOREG(0x1B4)
+
+#define S3C64XX_MEM0CONSLP0	S3C64XX_GPIOREG(0x1C0)
+#define S3C64XX_MEM0CONSLP1	S3C64XX_GPIOREG(0x1C4)
+#define S3C64XX_MEM1CONSLP	S3C64XX_GPIOREG(0x1C8)
+
+#define S3C64XX_MEM0DRVCON	S3C64XX_GPIOREG(0x1D0)
+#define S3C64XX_MEM1DRVCON	S3C64XX_GPIOREG(0x1D4)
+
+#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */
+
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
index 75b873d..81f7f6e 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
@@ -13,23 +13,175 @@
 
 /* Base addresses for each of the banks */
 
-#define S3C64XX_GPA_BASE	(S3C64XX_VA_GPIO + 0x0000)
-#define S3C64XX_GPB_BASE	(S3C64XX_VA_GPIO + 0x0020)
-#define S3C64XX_GPC_BASE	(S3C64XX_VA_GPIO + 0x0040)
-#define S3C64XX_GPD_BASE	(S3C64XX_VA_GPIO + 0x0060)
-#define S3C64XX_GPE_BASE	(S3C64XX_VA_GPIO + 0x0080)
-#define S3C64XX_GPF_BASE	(S3C64XX_VA_GPIO + 0x00A0)
-#define S3C64XX_GPG_BASE	(S3C64XX_VA_GPIO + 0x00C0)
-#define S3C64XX_GPH_BASE	(S3C64XX_VA_GPIO + 0x00E0)
-#define S3C64XX_GPI_BASE	(S3C64XX_VA_GPIO + 0x0100)
-#define S3C64XX_GPJ_BASE	(S3C64XX_VA_GPIO + 0x0120)
-#define S3C64XX_GPK_BASE	(S3C64XX_VA_GPIO + 0x0800)
-#define S3C64XX_GPL_BASE	(S3C64XX_VA_GPIO + 0x0810)
-#define S3C64XX_GPM_BASE	(S3C64XX_VA_GPIO + 0x0820)
-#define S3C64XX_GPN_BASE	(S3C64XX_VA_GPIO + 0x0830)
-#define S3C64XX_GPO_BASE	(S3C64XX_VA_GPIO + 0x0140)
-#define S3C64XX_GPP_BASE	(S3C64XX_VA_GPIO + 0x0160)
-#define S3C64XX_GPQ_BASE	(S3C64XX_VA_GPIO + 0x0180)
+#define S3C64XX_GPIOREG(reg)	(S3C64XX_VA_GPIO + (reg))
+
+#define S3C64XX_GPA_BASE	S3C64XX_GPIOREG(0x0000)
+#define S3C64XX_GPB_BASE	S3C64XX_GPIOREG(0x0020)
+#define S3C64XX_GPC_BASE	S3C64XX_GPIOREG(0x0040)
+#define S3C64XX_GPD_BASE	S3C64XX_GPIOREG(0x0060)
+#define S3C64XX_GPE_BASE	S3C64XX_GPIOREG(0x0080)
+#define S3C64XX_GPF_BASE	S3C64XX_GPIOREG(0x00A0)
+#define S3C64XX_GPG_BASE	S3C64XX_GPIOREG(0x00C0)
+#define S3C64XX_GPH_BASE	S3C64XX_GPIOREG(0x00E0)
+#define S3C64XX_GPI_BASE	S3C64XX_GPIOREG(0x0100)
+#define S3C64XX_GPJ_BASE	S3C64XX_GPIOREG(0x0120)
+#define S3C64XX_GPK_BASE	S3C64XX_GPIOREG(0x0800)
+#define S3C64XX_GPL_BASE	S3C64XX_GPIOREG(0x0810)
+#define S3C64XX_GPM_BASE	S3C64XX_GPIOREG(0x0820)
+#define S3C64XX_GPN_BASE	S3C64XX_GPIOREG(0x0830)
+#define S3C64XX_GPO_BASE	S3C64XX_GPIOREG(0x0140)
+#define S3C64XX_GPP_BASE	S3C64XX_GPIOREG(0x0160)
+#define S3C64XX_GPQ_BASE	S3C64XX_GPIOREG(0x0180)
+
+/* SPCON */
+
+#define S3C64XX_SPCON		S3C64XX_GPIOREG(0x1A0)
+
+#define S3C64XX_SPCON_DRVCON_CAM_MASK		(0x3 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_SHIFT		(30)
+#define S3C64XX_SPCON_DRVCON_CAM_2mA		(0x0 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_4mA		(0x1 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_7mA		(0x2 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_9mA		(0x3 << 30)
+
+#define S3C64XX_SPCON_DRVCON_HSSPI_MASK		(0x3 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_SHIFT	(28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_2mA		(0x0 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_4mA		(0x1 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_7mA		(0x2 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_9mA		(0x3 << 28)
+
+#define S3C64XX_SPCON_DRVCON_HSMMC_MASK		(0x3 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_SHIFT	(26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_2mA		(0x0 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_4mA		(0x1 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_7mA		(0x2 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_9mA		(0x3 << 26)
+
+#define S3C64XX_SPCON_DRVCON_LCD_MASK		(0x3 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_SHIFT		(24)
+#define S3C64XX_SPCON_DRVCON_LCD_2mA		(0x0 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_4mA		(0x1 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_7mA		(0x2 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_9mA		(0x3 << 24)
+
+#define S3C64XX_SPCON_DRVCON_MODEM_MASK		(0x3 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_SHIFT	(22)
+#define S3C64XX_SPCON_DRVCON_MODEM_2mA		(0x0 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_4mA		(0x1 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_7mA		(0x2 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_9mA		(0x3 << 22)
+
+#define S3C64XX_SPCON_nRSTOUT_OEN		(1 << 21)
+
+#define S3C64XX_SPCON_DRVCON_SPICLK1_MASK	(0x3 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_SHIFT	(18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_2mA	(0x0 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_4mA	(0x1 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_7mA	(0x2 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_9mA	(0x3 << 18)
+
+#define S3C64XX_SPCON_MEM1_DQS_PUD_MASK		(0x3 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_SHIFT	(16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_DISABLED	(0x0 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_DOWN		(0x1 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_UP		(0x2 << 16)
+
+#define S3C64XX_SPCON_MEM1_D_PUD1_MASK		(0x3 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_SHIFT		(14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_DISABLED	(0x0 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_DOWN		(0x1 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_UP		(0x2 << 14)
+
+#define S3C64XX_SPCON_MEM1_D_PUD0_MASK		(0x3 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_SHIFT		(12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_DISABLED	(0x0 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_DOWN		(0x1 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_UP		(0x2 << 12)
+
+#define S3C64XX_SPCON_MEM0_D_PUD_MASK		(0x3 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_SHIFT		(8)
+#define S3C64XX_SPCON_MEM0_D_PUD_DISABLED	(0x0 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_DOWN		(0x1 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_UP		(0x2 << 8)
+
+#define S3C64XX_SPCON_USBH_DMPD			(1 << 7)
+#define S3C64XX_SPCON_USBH_DPPD			(1 << 6)
+#define S3C64XX_SPCON_USBH_PUSW2		(1 << 5)
+#define S3C64XX_SPCON_USBH_PUSW1		(1 << 4)
+#define S3C64XX_SPCON_USBH_SUSPND		(1 << 3)
+
+#define S3C64XX_SPCON_LCD_SEL_MASK		(0x3 << 0)
+#define S3C64XX_SPCON_LCD_SEL_SHIFT		(0)
+#define S3C64XX_SPCON_LCD_SEL_HOST		(0x0 << 0)
+#define S3C64XX_SPCON_LCD_SEL_RGB		(0x1 << 0)
+#define S3C64XX_SPCON_LCD_SEL_606_656		(0x2 << 0)
+
+
+/* External interrupt registers */
+
+#define S3C64XX_EINT12CON	S3C64XX_GPIOREG(0x200)
+#define S3C64XX_EINT34CON	S3C64XX_GPIOREG(0x204)
+#define S3C64XX_EINT56CON	S3C64XX_GPIOREG(0x208)
+#define S3C64XX_EINT78CON	S3C64XX_GPIOREG(0x20C)
+#define S3C64XX_EINT9CON	S3C64XX_GPIOREG(0x210)
+
+#define S3C64XX_EINT12FLTCON	S3C64XX_GPIOREG(0x220)
+#define S3C64XX_EINT34FLTCON	S3C64XX_GPIOREG(0x224)
+#define S3C64XX_EINT56FLTCON	S3C64XX_GPIOREG(0x228)
+#define S3C64XX_EINT78FLTCON	S3C64XX_GPIOREG(0x22C)
+#define S3C64XX_EINT9FLTCON	S3C64XX_GPIOREG(0x230)
+
+#define S3C64XX_EINT12MASK	S3C64XX_GPIOREG(0x240)
+#define S3C64XX_EINT34MASK	S3C64XX_GPIOREG(0x244)
+#define S3C64XX_EINT56MASK	S3C64XX_GPIOREG(0x248)
+#define S3C64XX_EINT78MASK	S3C64XX_GPIOREG(0x24C)
+#define S3C64XX_EINT9MASK	S3C64XX_GPIOREG(0x250)
+
+#define S3C64XX_EINT12PEND	S3C64XX_GPIOREG(0x260)
+#define S3C64XX_EINT34PEND	S3C64XX_GPIOREG(0x264)
+#define S3C64XX_EINT56PEND	S3C64XX_GPIOREG(0x268)
+#define S3C64XX_EINT78PEND	S3C64XX_GPIOREG(0x26C)
+#define S3C64XX_EINT9PEND	S3C64XX_GPIOREG(0x270)
+
+#define S3C64XX_PRIORITY	S3C64XX_GPIOREG(0x280)
+#define S3C64XX_PRIORITY_ARB(x)	(1 << (x))
+
+#define S3C64XX_SERVICE		S3C64XX_GPIOREG(0x284)
+#define S3C64XX_SERVICEPEND	S3C64XX_GPIOREG(0x288)
+
+#define S3C64XX_EINT0CON0	S3C64XX_GPIOREG(0x900)
+#define S3C64XX_EINT0CON1	S3C64XX_GPIOREG(0x904)
+#define S3C64XX_EINT0FLTCON0	S3C64XX_GPIOREG(0x910)
+#define S3C64XX_EINT0FLTCON1	S3C64XX_GPIOREG(0x914)
+#define S3C64XX_EINT0FLTCON2	S3C64XX_GPIOREG(0x918)
+#define S3C64XX_EINT0FLTCON3	S3C64XX_GPIOREG(0x91C)
+
+#define S3C64XX_EINT0MASK	S3C64XX_GPIOREG(0x920)
+#define S3C64XX_EINT0PEND	S3C64XX_GPIOREG(0x924)
+
+/* GPIO sleep configuration */
+
+#define S3C64XX_SPCONSLP	S3C64XX_GPIOREG(0x880)
+
+#define S3C64XX_SPCONSLP_TDO_PULLDOWN	(1 << 14)
+#define S3C64XX_SPCONSLP_CKE1INIT	(1 << 5)
+
+#define S3C64XX_SPCONSLP_RSTOUT_MASK	(0x3 << 12)
+#define S3C64XX_SPCONSLP_RSTOUT_OUT0	(0x0 << 12)
+#define S3C64XX_SPCONSLP_RSTOUT_OUT1	(0x1 << 12)
+#define S3C64XX_SPCONSLP_RSTOUT_HIZ	(0x2 << 12)
+
+#define S3C64XX_SPCONSLP_KPCOL_MASK	(0x3 << 0)
+#define S3C64XX_SPCONSLP_KPCOL_OUT0	(0x0 << 0)
+#define S3C64XX_SPCONSLP_KPCOL_OUT1	(0x1 << 0)
+#define S3C64XX_SPCONSLP_KPCOL_INP	(0x2 << 0)
+
+
+#define S3C64XX_SLPEN		S3C64XX_GPIOREG(0x930)
+
+#define S3C64XX_SLPEN_USE_xSLP		(1 << 0)
+#define S3C64XX_SLPEN_CFG_BYSLPEN	(1 << 1)
 
 #endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */
 
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-modem.h b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h
new file mode 100644
index 0000000..49f7759
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h
@@ -0,0 +1,31 @@
+/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - modem block registers
+ *
+ * This program is free software; you can 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 __PLAT_S3C64XX_REGS_MODEM_H
+#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__
+
+#define S3C64XX_MODEMREG(x)	(S3C64XX_VA_MODEM + (x))
+
+#define S3C64XX_MODEM_INT2AP			S3C64XX_MODEMREG(0x0)
+#define S3C64XX_MODEM_INT2MODEM			S3C64XX_MODEMREG(0x4)
+#define S3C64XX_MODEM_MIFCON			S3C64XX_MODEMREG(0x8)
+#define S3C64XX_MODEM_MIFPCON			S3C64XX_MODEMREG(0xC)
+#define S3C64XX_MODEM_INTCLR			S3C64XX_MODEMREG(0x10)
+#define S3C64XX_MODEM_DMA_TXADDR		S3C64XX_MODEMREG(0x14)
+#define S3C64XX_MODEM_DMA_RXADDR		S3C64XX_MODEMREG(0x18)
+
+#define MIFPCON_INT2M_LEVEL			(1 << 4)
+#define MIFPCON_LCD_BYPASS			(1 << 3)
+
+#endif /* __PLAT_S3C64XX_REGS_MODEM_H */
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h
index d8ed829..69b78d9 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h
@@ -17,6 +17,10 @@
 
 #define S3C_SYSREG(x)		(S3C_VA_SYS + (x))
 
+#define S3C64XX_AHB_CON0	S3C_SYSREG(0x100)
+#define S3C64XX_AHB_CON1	S3C_SYSREG(0x104)
+#define S3C64XX_AHB_CON2	S3C_SYSREG(0x108)
+
 #define S3C64XX_OTHERS		S3C_SYSREG(0x900)
 
 #define S3C64XX_OTHERS_USBMASK	(1 << 16)
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
new file mode 100644
index 0000000..270d96a
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
@@ -0,0 +1,116 @@
+/* arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - syscon power and sleep control registers
+ *
+ * This program is free software; you can 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 __PLAT_S3C64XX_REGS_SYSCON_POWER_H
+#define __PLAT_S3C64XX_REGS_SYSCON_POWER_H __FILE__
+
+#define S3C64XX_PWR_CFG				S3C_SYSREG(0x804)
+
+#define S3C64XX_PWRCFG_OSC_OTG_DISABLE		(1 << 17)
+#define S3C64XX_PWRCFG_MMC2_DISABLE		(1 << 16)
+#define S3C64XX_PWRCFG_MMC1_DISABLE		(1 << 15)
+#define S3C64XX_PWRCFG_MMC0_DISABLE		(1 << 14)
+#define S3C64XX_PWRCFG_HSI_DISABLE		(1 << 13)
+#define S3C64XX_PWRCFG_TS_DISABLE		(1 << 12)
+#define S3C64XX_PWRCFG_RTC_TICK_DISABLE		(1 << 11)
+#define S3C64XX_PWRCFG_RTC_ALARM_DISABLE	(1 << 10)
+#define S3C64XX_PWRCFG_MSM_DISABLE		(1 << 9)
+#define S3C64XX_PWRCFG_KEY_DISABLE		(1 << 8)
+#define S3C64XX_PWRCFG_BATF_DISABLE		(1 << 7)
+
+#define S3C64XX_PWRCFG_CFG_WFI_MASK		(0x3 << 5)
+#define S3C64XX_PWRCFG_CFG_WFI_SHIFT		(5)
+#define S3C64XX_PWRCFG_CFG_WFI_IGNORE		(0x0 << 5)
+#define S3C64XX_PWRCFG_CFG_WFI_IDLE		(0x1 << 5)
+#define S3C64XX_PWRCFG_CFG_WFI_STOP		(0x2 << 5)
+#define S3C64XX_PWRCFG_CFG_WFI_SLEEP		(0x3 << 5)
+
+#define S3C64XX_PWRCFG_CFG_BATFLT_MASK		(0x3 << 3)
+#define S3C64XX_PWRCFG_CFG_BATFLT_SHIFT		(3)
+#define S3C64XX_PWRCFG_CFG_BATFLT_IGNORE	(0x0 << 3)
+#define S3C64XX_PWRCFG_CFG_BATFLT_IRQ		(0x1 << 3)
+#define S3C64XX_PWRCFG_CFG_BATFLT_SLEEP		(0x3 << 3)
+
+#define S3C64XX_PWRCFG_CFG_BAT_WAKE		(1 << 2)
+#define S3C64XX_PWRCFG_OSC27_EN			(1 << 0)
+
+#define S3C64XX_EINT_MASK			S3C_SYSREG(0x808)
+
+#define S3C64XX_NORMAL_CFG			S3C_SYSREG(0x810)
+
+#define S3C64XX_NORMALCFG_IROM_ON		(1 << 30)
+#define S3C64XX_NORMALCFG_DOMAIN_ETM_ON		(1 << 16)
+#define S3C64XX_NORMALCFG_DOMAIN_S_ON		(1 << 15)
+#define S3C64XX_NORMALCFG_DOMAIN_F_ON		(1 << 14)
+#define S3C64XX_NORMALCFG_DOMAIN_P_ON		(1 << 13)
+#define S3C64XX_NORMALCFG_DOMAIN_I_ON		(1 << 12)
+#define S3C64XX_NORMALCFG_DOMAIN_G_ON		(1 << 10)
+#define S3C64XX_NORMALCFG_DOMAIN_V_ON		(1 << 9)
+
+#define S3C64XX_STOP_CFG			S3C_SYSREG(0x814)
+
+#define S3C64XX_STOPCFG_MEMORY_ARM_ON		(1 << 29)
+#define S3C64XX_STOPCFG_TOP_MEMORY_ON		(1 << 20)
+#define S3C64XX_STOPCFG_ARM_LOGIC_ON		(1 << 17)
+#define S3C64XX_STOPCFG_TOP_LOGIC_ON		(1 << 8)
+#define S3C64XX_STOPCFG_OSC_EN			(1 << 0)
+
+#define S3C64XX_SLEEP_CFG			S3C_SYSREG(0x818)
+
+#define S3C64XX_SLEEPCFG_OSC_EN			(1 << 0)
+
+#define S3C64XX_STOP_MEM_CFG			S3C_SYSREG(0x81c)
+
+#define S3C64XX_STOPMEMCFG_MODEMIF_RETAIN	(1 << 6)
+#define S3C64XX_STOPMEMCFG_HOSTIF_RETAIN	(1 << 5)
+#define S3C64XX_STOPMEMCFG_OTG_RETAIN		(1 << 4)
+#define S3C64XX_STOPMEMCFG_HSMCC_RETAIN		(1 << 3)
+#define S3C64XX_STOPMEMCFG_IROM_RETAIN		(1 << 2)
+#define S3C64XX_STOPMEMCFG_IRDA_RETAIN		(1 << 1)
+#define S3C64XX_STOPMEMCFG_NFCON_RETAIN		(1 << 0)
+
+#define S3C64XX_OSC_STABLE			S3C_SYSREG(0x824)
+#define S3C64XX_PWR_STABLE			S3C_SYSREG(0x828)
+
+#define S3C64XX_WAKEUP_STAT			S3C_SYSREG(0x908)
+
+#define S3C64XX_WAKEUPSTAT_MMC2			(1 << 11)
+#define S3C64XX_WAKEUPSTAT_MMC1			(1 << 10)
+#define S3C64XX_WAKEUPSTAT_MMC0			(1 << 9)
+#define S3C64XX_WAKEUPSTAT_HSI			(1 << 8)
+#define S3C64XX_WAKEUPSTAT_BATFLT		(1 << 6)
+#define S3C64XX_WAKEUPSTAT_MSM			(1 << 5)
+#define S3C64XX_WAKEUPSTAT_KEY			(1 << 4)
+#define S3C64XX_WAKEUPSTAT_TS			(1 << 3)
+#define S3C64XX_WAKEUPSTAT_RTC_TICK		(1 << 2)
+#define S3C64XX_WAKEUPSTAT_RTC_ALARM		(1 << 1)
+#define S3C64XX_WAKEUPSTAT_EINT			(1 << 0)
+
+#define S3C64XX_BLK_PWR_STAT			S3C_SYSREG(0x90c)
+
+#define S3C64XX_BLKPWRSTAT_G			(1 << 7)
+#define S3C64XX_BLKPWRSTAT_ETM			(1 << 6)
+#define S3C64XX_BLKPWRSTAT_S			(1 << 5)
+#define S3C64XX_BLKPWRSTAT_F			(1 << 4)
+#define S3C64XX_BLKPWRSTAT_P			(1 << 3)
+#define S3C64XX_BLKPWRSTAT_I			(1 << 2)
+#define S3C64XX_BLKPWRSTAT_V			(1 << 1)
+#define S3C64XX_BLKPWRSTAT_TOP			(1 << 0)
+
+#define S3C64XX_INFORM0				S3C_SYSREG(0xA00)
+#define S3C64XX_INFORM1				S3C_SYSREG(0xA04)
+#define S3C64XX_INFORM2				S3C_SYSREG(0xA08)
+#define S3C64XX_INFORM3				S3C_SYSREG(0xA0C)
+
+#endif /* __PLAT_S3C64XX_REGS_SYSCON_POWER_H */
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
index cf52482..47e5155 100644
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ b/arch/arm/plat-s3c64xx/irq-eint.c
@@ -27,20 +27,6 @@
 #include <mach/map.h>
 #include <plat/cpu.h>
 
-/* GPIO is 0x7F008xxx, */
-#define S3C64XX_GPIOREG(x)	(S3C64XX_VA_GPIO + (x))
-
-#define S3C64XX_EINT0CON0	S3C64XX_GPIOREG(0x900)
-#define S3C64XX_EINT0CON1	S3C64XX_GPIOREG(0x904)
-#define S3C64XX_EINT0FLTCON0	S3C64XX_GPIOREG(0x910)
-#define S3C64XX_EINT0FLTCON1	S3C64XX_GPIOREG(0x914)
-#define S3C64XX_EINT0FLTCON2	S3C64XX_GPIOREG(0x918)
-#define S3C64XX_EINT0FLTCON3	S3C64XX_GPIOREG(0x91C)
-
-#define S3C64XX_EINT0MASK	S3C64XX_GPIOREG(0x920)
-#define S3C64XX_EINT0PEND	S3C64XX_GPIOREG(0x924)
-
-
 #define eint_offset(irq)	((irq) - IRQ_EINT(0))
 #define eint_irq_to_bit(irq)	(1 << eint_offset(irq))
 
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index b4211d8..945e0d2 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Thu Mar 12 18:01:45 2009
+# Last update: Mon Mar 23 20:09:01 2009
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -2124,3 +2124,11 @@
 fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
+ccw9p9215		MACH_CCW9P9215		CCW9P9215		2137
+dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
+ts219			MACH_TS219		TS219			2139
+tny_a9263		MACH_TNY_A9263		TNY_A9263		2140
+apollo			MACH_APOLLO		APOLLO			2141
+at91cap9stk		MACH_AT91CAP9STK	AT91CAP9STK		2142
+spc300			MACH_SPC300		SPC300			2143
+eko			MACH_EKO		EKO			2144
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 8de86e4..c8c98dd 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -377,6 +377,4 @@
 	u32 flags;
 };
 
-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
 extern void vfp_save_state(void *location, u32 fpexc);
-#endif
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index c92a08b..a5a4e57 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -172,7 +172,6 @@
 					@ retry the faulted instruction
 ENDPROC(vfp_support_entry)
 
-#if defined(CONFIG_SMP) || defined(CONFIG_PM)
 ENTRY(vfp_save_state)
 	@ Save the current VFP state
 	@ r0 - save location
@@ -190,7 +189,6 @@
 	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
 	mov	pc, lr
 ENDPROC(vfp_save_state)
-#endif
 
 last_VFP_context_address:
 	.word	last_VFP_context
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 9f476a1..75457b3 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -377,6 +377,55 @@
 static inline void vfp_pm_init(void) { }
 #endif /* CONFIG_PM */
 
+/*
+ * Synchronise the hardware VFP state of a thread other than current with the
+ * saved one. This function is used by the ptrace mechanism.
+ */
+#ifdef CONFIG_SMP
+void vfp_sync_state(struct thread_info *thread)
+{
+	/*
+	 * On SMP systems, the VFP state is automatically saved at every
+	 * context switch. We mark the thread VFP state as belonging to a
+	 * non-existent CPU so that the saved one will be reloaded when
+	 * needed.
+	 */
+	thread->vfpstate.hard.cpu = NR_CPUS;
+}
+#else
+void vfp_sync_state(struct thread_info *thread)
+{
+	unsigned int cpu = get_cpu();
+	u32 fpexc = fmrx(FPEXC);
+
+	/*
+	 * If VFP is enabled, the previous state was already saved and
+	 * last_VFP_context updated.
+	 */
+	if (fpexc & FPEXC_EN)
+		goto out;
+
+	if (!last_VFP_context[cpu])
+		goto out;
+
+	/*
+	 * Save the last VFP state on this CPU.
+	 */
+	fmxr(FPEXC, fpexc | FPEXC_EN);
+	vfp_save_state(last_VFP_context[cpu], fpexc);
+	fmxr(FPEXC, fpexc);
+
+	/*
+	 * Set the context to NULL to force a reload the next time the thread
+	 * uses the VFP.
+	 */
+	last_VFP_context[cpu] = NULL;
+
+out:
+	put_cpu();
+}
+#endif
+
 #include <linux/smp.h>
 
 /*
@@ -427,6 +476,18 @@
 		 * in place; report VFP support to userspace.
 		 */
 		elf_hwcap |= HWCAP_VFP;
+#ifdef CONFIG_VFPv3
+		if (VFP_arch >= 3) {
+			elf_hwcap |= HWCAP_VFPv3;
+
+			/*
+			 * Check for VFPv3 D16. CPUs in this configuration
+			 * only have 16 x 64bit registers.
+			 */
+			if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
+				elf_hwcap |= HWCAP_VFPv3D16;
+		}
+#endif
 #ifdef CONFIG_NEON
 		/*
 		 * Check for the presence of the Advanced SIMD
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index 281f4b6..c121d6e 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -1,7 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Feb 20 10:01:44 2009
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -43,7 +42,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -314,7 +313,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -375,7 +374,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -634,6 +632,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -793,6 +792,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -816,6 +816,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -865,7 +871,26 @@
 # CONFIG_SOUND is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_SDH_BFIN=m
+CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND=y
+CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ=y
+# CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
@@ -1121,7 +1146,6 @@
 # CONFIG_KGDB is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB_TESTCASE is not set
 CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_HWERR is not set
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 8e2b855..3e562b2 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,7 +42,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -55,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -132,15 +132,20 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
-CONFIG_BF_REV_0_0=y
-# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_0 is not set
+CONFIG_BF_REV_0_1=y
 # CONFIG_BF_REV_0_2 is not set
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
@@ -313,7 +318,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -374,7 +379,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -583,7 +587,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -637,6 +643,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -815,6 +822,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -838,6 +846,7 @@
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
 # CONFIG_SENSORS_ADT7473 is not set
 # CONFIG_SENSORS_ATXP1 is not set
@@ -896,6 +905,12 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -904,8 +919,10 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -940,55 +957,7 @@
 # Console display driver support
 #
 CONFIG_DUMMY_CONSOLE=y
-CONFIG_SOUND=m
-CONFIG_SOUND_OSS_CORE=y
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_PCM_OSS_PLUGINS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_SPI=y
-
-#
-# ALSA Blackfin devices
-#
-# CONFIG_SND_BLACKFIN_AD1836 is not set
-# CONFIG_SND_BFIN_AD73322 is not set
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_CAIAQ is not set
-CONFIG_SND_SOC=m
-CONFIG_SND_SOC_AC97_BUS=y
-CONFIG_SND_BF5XX_I2S=m
-CONFIG_SND_BF5XX_SOC_SSM2602=m
-# CONFIG_SND_BF5XX_SOC_AD73311 is not set
-CONFIG_SND_BF5XX_AC97=m
-CONFIG_SND_BF5XX_MMAP_SUPPORT=y
-# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
-CONFIG_SND_BF5XX_SOC_SPORT=m
-CONFIG_SND_BF5XX_SOC_I2S=m
-CONFIG_SND_BF5XX_SOC_AC97=m
-CONFIG_SND_BF5XX_SOC_AD1980=m
-CONFIG_SND_BF5XX_SPORT_NUM=0
-# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
-# CONFIG_SND_SOC_ALL_CODECS is not set
-CONFIG_SND_SOC_AD1980=m
-CONFIG_SND_SOC_SSM2602=m
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=m
+# CONFIG_SOUND is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
@@ -1063,13 +1032,15 @@
 CONFIG_USB_MUSB_SOC=y
 
 #
-# Blackfin high speed USB support
+# Blackfin high speed USB Support
 #
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
 CONFIG_MUSB_PIO_ONLY=y
+CONFIG_MUSB_DMA_POLL=y
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1081,18 +1052,33 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
 
 #
 # USB port drivers
@@ -1124,6 +1110,30 @@
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2272 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1158,12 +1168,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1384,6 +1396,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1423,6 +1442,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index a50050f..911b5db 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -36,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -133,15 +132,20 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
-CONFIG_BF_REV_0_0=y
-# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_0 is not set
+CONFIG_BF_REV_0_1=y
 # CONFIG_BF_REV_0_2 is not set
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
@@ -314,7 +318,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -375,7 +379,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -626,7 +629,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -681,6 +686,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -755,8 +761,8 @@
 # CONFIG_SPI_ADC_BF533 is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-# CONFIG_BFIN_SPORT is not set
+CONFIG_BF5xx_PPI=m
+CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
@@ -859,6 +865,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -871,60 +878,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -940,6 +894,12 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -948,8 +908,10 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -1000,6 +962,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=m
 CONFIG_LCD_LTV350QV=m
@@ -1152,13 +1115,15 @@
 CONFIG_USB_MUSB_SOC=y
 
 #
-# Blackfin high speed USB support
+# Blackfin high speed USB Support
 #
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
 CONFIG_MUSB_PIO_ONLY=y
+CONFIG_MUSB_DMA_POLL=y
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1170,18 +1135,33 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
 
 #
 # USB port drivers
@@ -1213,6 +1193,30 @@
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2272 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1247,12 +1251,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1473,6 +1479,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1512,6 +1525,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 0a2a00d..4c41e03 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -36,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -133,10 +132,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=3
 CONFIG_BF_REV_MAX=6
@@ -157,7 +161,6 @@
 # CONFIG_BFIN533_BLUETECHNIX_CM is not set
 # CONFIG_H8606_HVSISTEMAS is not set
 # CONFIG_BFIN532_IP0X is not set
-# CONFIG_GENERIC_BF533_BOARD is not set
 
 #
 # BF533/2/1 Specific Configuration
@@ -277,7 +280,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -575,6 +578,7 @@
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -608,6 +612,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -714,6 +719,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -726,22 +732,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -752,6 +743,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -760,7 +757,7 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -826,6 +823,7 @@
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1046,6 +1044,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1084,6 +1089,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index eb02758..9c482cd 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -36,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -133,10 +132,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=3
 CONFIG_BF_REV_MAX=6
@@ -157,7 +161,6 @@
 # CONFIG_BFIN533_BLUETECHNIX_CM is not set
 # CONFIG_H8606_HVSISTEMAS is not set
 # CONFIG_BFIN532_IP0X is not set
-# CONFIG_GENERIC_BF533_BOARD is not set
 
 #
 # BF533/2/1 Specific Configuration
@@ -277,7 +280,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -578,7 +581,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -612,6 +617,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -671,10 +677,10 @@
 # CONFIG_SPI_ADC_BF533 is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
+CONFIG_BF5xx_PPI=m
+CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_TWI_LCD=m
+# CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
@@ -765,6 +771,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -777,60 +784,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -841,6 +795,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -851,6 +811,7 @@
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -909,6 +870,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -1018,12 +980,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1244,6 +1208,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1282,6 +1253,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 9e62b9f..591f6ed 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -1,7 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Dec 30 17:24:37 2008
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -37,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -134,10 +132,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=2
 CONFIG_BF_REV_MAX=3
@@ -184,7 +187,6 @@
 # CONFIG_BFIN537_BLUETECHNIX_TCM is not set
 # CONFIG_PNAV10 is not set
 # CONFIG_CAMSIG_MINOTAUR is not set
-# CONFIG_GENERIC_BF537_BOARD is not set
 
 #
 # BF537 Specific Configuration
@@ -589,7 +591,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -644,6 +648,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -706,10 +711,10 @@
 # CONFIG_SPI_ADC_BF533 is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+CONFIG_BF5xx_PPI=m
 CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_TWI_LCD=m
+# CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
 CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
@@ -808,6 +813,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -820,60 +826,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -884,6 +837,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -894,6 +853,7 @@
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -957,6 +917,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=m
 # CONFIG_LCD_LTV350QV is not set
@@ -1074,12 +1035,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1300,6 +1263,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1338,6 +1308,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index dd6ad6b..1a8e8c3 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -42,7 +42,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -55,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -132,10 +132,15 @@
 CONFIG_BF538=y
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=4
 CONFIG_BF_REV_MAX=5
@@ -293,7 +298,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -354,7 +359,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -645,6 +649,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -690,7 +695,7 @@
 # CONFIG_TOUCHSCREEN_AD7877 is not set
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 CONFIG_TOUCHSCREEN_AD7879_SPI=y
-CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879=y
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -718,8 +723,8 @@
 # CONFIG_SPI_ADC_BF533 is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
+CONFIG_BF5xx_PPI=m
+CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
@@ -762,7 +767,7 @@
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
-CONFIG_I2C=y
+CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_CHARDEV is not set
 CONFIG_I2C_HELPER_AUTO=y
@@ -774,7 +779,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
-CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI=m
 CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_OCORES is not set
@@ -818,6 +823,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -830,60 +836,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -894,6 +847,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -904,6 +863,7 @@
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -954,6 +914,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -1007,12 +968,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1233,6 +1196,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1271,6 +1241,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index 6bc2fb1..2cd1c2b 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -36,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -133,16 +132,21 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 CONFIG_BF548=y
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=0
 CONFIG_BF_REV_MAX=2
-CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
-# CONFIG_BF_REV_0_2 is not set
+CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
@@ -348,7 +352,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 CONFIG_DMA_UNCACHED_2M=y
 # CONFIG_DMA_UNCACHED_1M is not set
@@ -413,7 +417,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -512,9 +515,9 @@
 #
 CONFIG_IRTTY_SIR=m
 CONFIG_BFIN_SIR=m
-CONFIG_BFIN_SIR3=y
 # CONFIG_BFIN_SIR0 is not set
 # CONFIG_BFIN_SIR2 is not set
+CONFIG_BFIN_SIR3=y
 CONFIG_SIR_BFIN_DMA=y
 # CONFIG_SIR_BFIN_PIO is not set
 
@@ -538,7 +541,8 @@
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
 CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
@@ -554,7 +558,9 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -668,7 +674,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -743,6 +751,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -751,8 +760,16 @@
 # Wireless LAN
 #
 # CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=m
+# CONFIG_LIBERTAS_USB is not set
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_POWEROF2_BLOCKSIZE_ONLY=y
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
 # CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_HOSTAP is not set
 
 #
 # USB Network Adapters
@@ -844,8 +861,8 @@
 # CONFIG_SPI_ADC_BF533 is not set
 # CONFIG_BF5xx_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-# CONFIG_BFIN_SPORT is not set
+CONFIG_BF5xx_PPI=m
+CONFIG_BFIN_SPORT=m
 # CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
@@ -950,6 +967,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -962,60 +980,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -1031,6 +996,12 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -1039,8 +1010,10 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -1092,6 +1065,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -1243,15 +1217,15 @@
 CONFIG_USB_MUSB_SOC=y
 
 #
-# Blackfin high speed USB support
+# Blackfin high speed USB Support
 #
 CONFIG_USB_MUSB_HOST=y
 # CONFIG_USB_MUSB_PERIPHERAL is not set
 # CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_HDRC_HCD=y
-# CONFIG_MUSB_PIO_ONLY is not set
-CONFIG_USB_INVENTRA_DMA=y
-# CONFIG_USB_TI_CPPI_DMA is not set
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_MUSB_DMA_POLL=y
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -1263,11 +1237,11 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -1321,7 +1295,31 @@
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
-CONFIG_MMC=m
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2272 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
@@ -1337,8 +1335,9 @@
 # MMC/SD/SDIO Host Controller Drivers
 #
 # CONFIG_MMC_SDHCI is not set
-CONFIG_SDH_BFIN=m
+CONFIG_SDH_BFIN=y
 # CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND is not set
+# CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ is not set
 # CONFIG_MMC_SPI is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1373,12 +1372,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1641,6 +1642,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1680,6 +1688,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 69714fb..4a6ea8e 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -36,14 +36,13 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +55,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -133,10 +132,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 CONFIG_BF561=y
 # CONFIG_SMP is not set
 CONFIG_BF_REV_MIN=3
@@ -166,7 +170,6 @@
 CONFIG_BFIN561_EZKIT=y
 # CONFIG_BFIN561_TEPLA is not set
 # CONFIG_BFIN561_BLUETECHNIX_CM is not set
-# CONFIG_GENERIC_BF561_BOARD is not set
 
 #
 # BF561 Specific Configuration
@@ -316,7 +319,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
+CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
@@ -382,7 +385,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -612,6 +614,7 @@
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -645,6 +648,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -751,6 +755,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -763,22 +768,7 @@
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -789,6 +779,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -797,7 +793,7 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -1041,6 +1037,13 @@
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1079,6 +1082,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig
index 017c6ea..ef1a2c8 100644
--- a/arch/blackfin/configs/BlackStamp_defconfig
+++ b/arch/blackfin/configs/BlackStamp_defconfig
@@ -43,7 +43,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,7 +56,7 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index d880ef7..e2fc588 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -43,7 +43,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,13 +56,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
index 085211b..65a8bbb 100644
--- a/arch/blackfin/configs/CM-BF533_defconfig
+++ b/arch/blackfin/configs/CM-BF533_defconfig
@@ -46,7 +46,7 @@
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index 750203e..9b7e9d78 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -46,7 +46,7 @@
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
index dec8a7d..569523c 100644
--- a/arch/blackfin/configs/CM-BF537U_defconfig
+++ b/arch/blackfin/configs/CM-BF537U_defconfig
@@ -46,7 +46,7 @@
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index f410430..035b635 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -46,7 +46,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index 346bc7a..7015e42 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -46,7 +46,7 @@
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
index bd553da..dfc8e1d 100644
--- a/arch/blackfin/configs/H8606_defconfig
+++ b/arch/blackfin/configs/H8606_defconfig
@@ -45,7 +45,7 @@
 # CONFIG_RELAY is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -56,7 +56,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index 7db9387..95a5f91 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -46,7 +46,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -57,7 +57,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index ad09670..78e2408 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
+# Linux kernel version: 2.6.28.7
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -35,13 +35,12 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -53,13 +52,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -130,10 +129,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=2
 CONFIG_BF_REV_MAX=3
@@ -180,7 +184,6 @@
 # CONFIG_BFIN537_BLUETECHNIX_TCM is not set
 CONFIG_PNAV10=y
 # CONFIG_CAMSIG_MINOTAUR is not set
-# CONFIG_GENERIC_BF537_BOARD is not set
 
 #
 # BF537 Specific Configuration
@@ -341,7 +344,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -538,7 +540,9 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -593,6 +597,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_AX88180 is not set
 CONFIG_NETDEV_10000=y
@@ -776,6 +781,7 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
 
 #
@@ -799,6 +805,7 @@
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
 # CONFIG_SENSORS_ADT7473 is not set
 # CONFIG_SENSORS_ATXP1 is not set
@@ -845,6 +852,12 @@
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -853,8 +866,10 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -910,6 +925,7 @@
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 # CONFIG_LCD_LTV350QV is not set
@@ -966,7 +982,7 @@
 #
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
@@ -1003,12 +1019,14 @@
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
 # CONFIG_RTC_DRV_R9701 is not set
 # CONFIG_RTC_DRV_RS5C348 is not set
@@ -1196,6 +1214,10 @@
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1230,6 +1252,7 @@
 #
 # CONFIG_CRYPTO_FIPS is not set
 # CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index a46529c..2bc0779 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -49,7 +49,7 @@
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -61,7 +61,7 @@
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig
index 97a1f1d..e65b3a4 100644
--- a/arch/blackfin/configs/TCM-BF537_defconfig
+++ b/arch/blackfin/configs/TCM-BF537_defconfig
@@ -39,7 +39,7 @@
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 CONFIG_SYSCTL_SYSCALL=y
@@ -51,13 +51,13 @@
 # CONFIG_ELF_CORE is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
+# CONFIG_FUTEX is not set
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
-CONFIG_AIO=y
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index 1306e6b..0292d58 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -110,7 +110,7 @@
 struct bfin5xx_spi_master {
 	u16 num_chipselect;
 	u8 enable_dma;
-	u16 pin_req[4];
+	u16 pin_req[7];
 };
 
 /* spi_board_info.controller_data for SPI slave devices,
diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h
index 65a651d..b558908 100644
--- a/arch/blackfin/include/asm/bfin_sport.h
+++ b/arch/blackfin/include/asm/bfin_sport.h
@@ -9,6 +9,13 @@
 #ifndef __BFIN_SPORT_H__
 #define __BFIN_SPORT_H__
 
+#ifdef __KERNEL__
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#endif
+
 #define SPORT_MAJOR	237
 #define SPORT_NR_DEVS	2
 
@@ -119,7 +126,7 @@
 	int tx_len;
 	int tx_sent;
 
-	int sport_err_irq;
+	int err_irq;
 
 	struct mutex mutex;	/* mutual exclusion semaphore */
 	struct task_struct *task;
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index d4a082e..fe13961 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -110,7 +110,7 @@
 * MODIFICATION HISTORY :
 **************************************************************/
 
-#ifndef BF548_FAMILY
+#ifndef CONFIG_BF54x
 void set_gpio_dir(unsigned, unsigned short);
 void set_gpio_inen(unsigned, unsigned short);
 void set_gpio_polar(unsigned, unsigned short);
@@ -303,7 +303,10 @@
 
 static inline int gpio_to_irq(unsigned gpio)
 {
-	return (gpio + GPIO_IRQ_BASE);
+	if (likely(gpio < MAX_BLACKFIN_GPIOS))
+		return gpio + GPIO_IRQ_BASE;
+
+	return -EINVAL;
 }
 
 static inline int irq_to_gpio(unsigned irq)
diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h
index 0520d2a..b0f847a 100644
--- a/arch/blackfin/include/asm/gptimers.h
+++ b/arch/blackfin/include/asm/gptimers.h
@@ -15,16 +15,16 @@
 #include <asm/blackfin.h>
 
 /*
- * BF537/BF527: 8 timers:
+ * BF51x/BF52x/BF537: 8 timers:
  */
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+#if defined(CONFIG_BF51x) || defined(CONFIG_BF52x) || defined(BF537_FAMILY)
 # define MAX_BLACKFIN_GPTIMERS 8
 # define TIMER0_GROUP_REG      TIMER_ENABLE
 #endif
 /*
  * BF54x: 11 timers (BF542: 8 timers):
  */
-#if defined(BF548_FAMILY)
+#if defined(CONFIG_BF54x)
 # ifdef CONFIG_BF542
 #  define MAX_BLACKFIN_GPTIMERS 8
 # else
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 51dac55..a0678da 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -69,7 +69,7 @@
 static struct gpio_port_t * const gpio_array[] = {
 #if defined(BF533_FAMILY) || defined(BF538_FAMILY)
 	(struct gpio_port_t *) FIO_FLAG_D,
-#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 	(struct gpio_port_t *) PORTFIO,
 	(struct gpio_port_t *) PORTGIO,
 	(struct gpio_port_t *) PORTHIO,
@@ -77,7 +77,7 @@
 	(struct gpio_port_t *) FIO0_FLAG_D,
 	(struct gpio_port_t *) FIO1_FLAG_D,
 	(struct gpio_port_t *) FIO2_FLAG_D,
-#elif defined(BF548_FAMILY)
+#elif defined(CONFIG_BF54x)
 	(struct gpio_port_t *)PORTA_FER,
 	(struct gpio_port_t *)PORTB_FER,
 	(struct gpio_port_t *)PORTC_FER,
@@ -93,7 +93,7 @@
 #endif
 };
 
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 static unsigned short * const port_fer[] = {
 	(unsigned short *) PORTF_FER,
 	(unsigned short *) PORTG_FER,
@@ -109,11 +109,11 @@
 
 static const
 u8 pmux_offset[][16] = {
-#  if defined(BF527_FAMILY)
+#  if defined(CONFIG_BF52x)
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
 	{ 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
-#  elif defined(BF518_FAMILY)
+#  elif defined(CONFIG_BF51x)
 	{ 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
 	{ 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
 	{ 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
@@ -139,7 +139,7 @@
 
 inline int check_gpio(unsigned gpio)
 {
-#if defined(BF548_FAMILY)
+#if defined(CONFIG_BF54x)
 	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
 	    || gpio == GPIO_PH14 || gpio == GPIO_PH15
 	    || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
@@ -187,13 +187,13 @@
 	if (check_gpio(gpio))
 		return;
 
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 	if (usage == GPIO_USAGE)
 		*port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
 	else
 		*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
 	SSYNC();
-#elif defined(BF548_FAMILY)
+#elif defined(CONFIG_BF54x)
 	if (usage == GPIO_USAGE)
 		gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
 	else
@@ -273,7 +273,7 @@
 		}
 	}
 }
-#elif defined(BF548_FAMILY)
+#elif defined(CONFIG_BF54x)
 inline void portmux_setup(unsigned short per)
 {
 	u32 pmux;
@@ -297,7 +297,7 @@
 
 	return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
 }
-#elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
+#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 inline void portmux_setup(unsigned short per)
 {
 	u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
@@ -322,7 +322,7 @@
 arch_initcall(bfin_gpio_init);
 
 
-#ifndef BF548_FAMILY
+#ifndef CONFIG_BF54x
 /***********************************************************
 *
 * FUNCTIONS: Blackfin General Purpose Ports Access Functions
@@ -489,7 +489,7 @@
 	IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
 #elif defined(BF538_FAMILY)
 	IRQ_PORTF_INTB
-#elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
+#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 	IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
 #elif defined(BF561_FAMILY)
 	IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
@@ -586,7 +586,7 @@
 		gpio_array[bank]->maskb = 0;
 
 		if (mask) {
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 			gpio_bank_saved[bank].fer   = *port_fer[bank];
 #endif
 			gpio_bank_saved[bank].inen  = gpio_array[bank]->inen;
@@ -631,7 +631,7 @@
 		bank = gpio_bank(i);
 
 		if (mask) {
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 			*port_fer[bank]   	= gpio_bank_saved[bank].fer;
 #endif
 			gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
@@ -657,9 +657,9 @@
 	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		bank = gpio_bank(i);
 
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
 		gpio_bank_saved[bank].fer = *port_fer[bank];
-#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 		gpio_bank_saved[bank].mux = *port_mux[bank];
 #else
 		if (bank == 0)
@@ -685,8 +685,8 @@
 	for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
 		bank = gpio_bank(i);
 
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
-#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
+#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x)
+#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 		*port_mux[bank] = gpio_bank_saved[bank].mux;
 #else
 		if (bank == 0)
@@ -710,7 +710,7 @@
 
 
 #endif
-#else /* BF548_FAMILY */
+#else /* CONFIG_BF54x */
 #ifdef CONFIG_PM
 
 u32 bfin_pm_standby_setup(void)
@@ -762,7 +762,7 @@
 }
 EXPORT_SYMBOL(get_gpio_dir);
 
-#endif /* BF548_FAMILY */
+#endif /* CONFIG_BF54x */
 
 /***********************************************************
 *
@@ -802,7 +802,8 @@
 	 */
 	if (unlikely(!check_gpio(ident) &&
 	    reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		printk(KERN_ERR
 		       "%s: Peripheral %d is already reserved as GPIO by %s !\n",
 		       __func__, ident, get_label(ident));
@@ -817,7 +818,7 @@
 		 * be requested and used by several drivers
 		 */
 
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 		if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
 #else
 		if (!(per & P_MAYSHARE)) {
@@ -830,7 +831,8 @@
 			if (cmp_label(ident, label) == 0)
 				goto anyway;
 
-			dump_stack();
+			if (system_state == SYSTEM_BOOTING)
+				dump_stack();
 			printk(KERN_ERR
 			       "%s: Peripheral %d function %d is already reserved by %s !\n",
 			       __func__, ident, P_FUNCT2MUX(per), get_label(ident));
@@ -946,14 +948,16 @@
 	}
 
 	if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
 		       gpio, get_label(gpio));
 		local_irq_restore_hw(flags);
 		return -EBUSY;
 	}
 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
@@ -964,7 +968,7 @@
 		printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
 		       " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
 	}
-#ifndef BF548_FAMILY
+#ifndef CONFIG_BF54x
 	else {	/* Reset POLAR setting when acquiring a gpio for the first time */
 		set_gpio_polar(gpio, 0);
 	}
@@ -993,7 +997,8 @@
 	local_irq_save_hw(flags);
 
 	if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		gpio_error(gpio);
 		local_irq_restore_hw(flags);
 		return;
@@ -1017,7 +1022,8 @@
 	local_irq_save_hw(flags);
 
 	if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n",
 		       gpio);
@@ -1025,7 +1031,8 @@
 		return -EBUSY;
 	}
 	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		printk(KERN_ERR
 		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
 		       gpio, get_label(gpio));
@@ -1057,7 +1064,8 @@
 	local_irq_save_hw(flags);
 
 	if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
-		dump_stack();
+		if (system_state == SYSTEM_BOOTING)
+			dump_stack();
 		gpio_error(gpio);
 		local_irq_restore_hw(flags);
 		return;
@@ -1072,7 +1080,7 @@
 
 static inline void __bfin_gpio_direction_input(unsigned gpio)
 {
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 	gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
 #else
 	gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
@@ -1100,13 +1108,13 @@
 
 void bfin_gpio_irq_prepare(unsigned gpio)
 {
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 	unsigned long flags;
 #endif
 
 	port_setup(gpio, GPIO_USAGE);
 
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 	local_irq_save_hw(flags);
 	__bfin_gpio_direction_input(gpio);
 	local_irq_restore_hw(flags);
@@ -1135,7 +1143,7 @@
 
 	gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
 	gpio_set_value(gpio, value);
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 	gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
 #else
 	gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
@@ -1150,7 +1158,7 @@
 
 int bfin_gpio_get_value(unsigned gpio)
 {
-#ifdef BF548_FAMILY
+#ifdef CONFIG_BF54x
 	return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
 #else
 	unsigned long flags;
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 4b4341d..27952ae 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -183,6 +183,7 @@
 		. = ALIGN(4);
 		__etext_l1 = .;
 	}
+	ASSERT (SIZEOF(.text_l1) <= L1_CODE_LENGTH, "L1 text overflow!")
 
 	.data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
 	{
@@ -200,6 +201,7 @@
 		. = ALIGN(4);
 		__ebss_l1 = .;
 	}
+	ASSERT (SIZEOF(.data_a_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
 
 	.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
 	{
@@ -214,6 +216,7 @@
 		. = ALIGN(4);
 		__ebss_b_l1 = .;
 	}
+	ASSERT (SIZEOF(.data_b_l1) <= L1_DATA_B_LENGTH, "L1 data B overflow!")
 
 	__l2_lma_start = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
 
@@ -239,6 +242,7 @@
 		. = ALIGN(4);
 		__ebss_l2 = .;
 	}
+	ASSERT (SIZEOF(.text_data_l1) <= L2_LENGTH, "L2 overflow!")
 
 	/* Force trailing alignment of our init section so that when we
 	 * free our init memory, we don't leave behind a partial page.
diff --git a/arch/blackfin/mach-bf518/include/mach/blackfin.h b/arch/blackfin/mach-bf518/include/mach/blackfin.h
index d1a2b9c..267bb7c 100644
--- a/arch/blackfin/mach-bf518/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf518/include/mach/blackfin.h
@@ -32,8 +32,6 @@
 #ifndef _MACH_BLACKFIN_H_
 #define _MACH_BLACKFIN_H_
 
-#define BF518_FAMILY
-
 #include "bf518.h"
 #include "mem_map.h"
 #include "defBF512.h"
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
index 9521e17..dfe492d 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
@@ -45,4 +45,71 @@
 
 /* The following are the #defines needed by ADSP-BF514 that are not in the common header */
 
+/* Removable Storage Interface Registers */
+
+#define bfin_read_RSI_PWR_CTL()        bfin_read16(RSI_PWR_CONTROL)
+#define bfin_write_RSI_PWR_CTL(val)    bfin_write16(RSI_PWR_CONTROL, val)
+#define bfin_read_RSI_CLK_CTL()	       bfin_read16(RSI_CLK_CONTROL)
+#define bfin_write_RSI_CLK_CTL(val)    bfin_write16(RSI_CLK_CONTROL, val)
+#define bfin_read_RSI_ARGUMENT()       bfin_read32(RSI_ARGUMENT)
+#define bfin_write_RSI_ARGUMENT(val)   bfin_write32(RSI_ARGUMENT, val)
+#define bfin_read_RSI_COMMAND()        bfin_read16(RSI_COMMAND)
+#define bfin_write_RSI_COMMAND(val)    bfin_write16(RSI_COMMAND, val)
+#define bfin_read_RSI_RESP_CMD()       bfin_read16(RSI_RESP_CMD)
+#define bfin_write_RSI_RESP_CMD(val)   bfin_write16(RSI_RESP_CMD, val)
+#define bfin_read_RSI_RESPONSE0()      bfin_read32(RSI_RESPONSE0)
+#define bfin_write_RSI_RESPONSE0(val)  bfin_write32(RSI_RESPONSE0, val)
+#define bfin_read_RSI_RESPONSE1()      bfin_read32(RSI_RESPONSE1)
+#define bfin_write_RSI_RESPONSE1(val)  bfin_write32(RSI_RESPONSE1, val)
+#define bfin_read_RSI_RESPONSE2()      bfin_read32(RSI_RESPONSE2)
+#define bfin_write_RSI_RESPONSE2(val)  bfin_write32(RSI_RESPONSE2, val)
+#define bfin_read_RSI_RESPONSE3()      bfin_read32(RSI_RESPONSE3)
+#define bfin_write_RSI_RESPONSE3(val)  bfin_write32(RSI_RESPONSE3, val)
+#define bfin_read_RSI_DATA_TIMER()     bfin_read32(RSI_DATA_TIMER)
+#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
+#define bfin_read_RSI_DATA_LGTH()      bfin_read16(RSI_DATA_LGTH)
+#define bfin_write_RSI_DATA_LGTH(val)  bfin_write16(RSI_DATA_LGTH, val)
+#define bfin_read_RSI_DATA_CTL()       bfin_read16(RSI_DATA_CONTROL)
+#define bfin_write_RSI_DATA_CTL(val)   bfin_write16(RSI_DATA_CONTROL, val)
+#define bfin_read_RSI_DATA_CNT()       bfin_read16(RSI_DATA_CNT)
+#define bfin_write_RSI_DATA_CNT(val)   bfin_write16(RSI_DATA_CNT, val)
+#define bfin_read_RSI_STATUS()         bfin_read32(RSI_STATUS)
+#define bfin_write_RSI_STATUS(val)     bfin_write32(RSI_STATUS, val)
+#define bfin_read_RSI_STATUS_CLR()     bfin_read16(RSI_STATUSCL)
+#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
+#define bfin_read_RSI_MASK0()          bfin_read32(RSI_MASK0)
+#define bfin_write_RSI_MASK0(val)      bfin_write32(RSI_MASK0, val)
+#define bfin_read_RSI_MASK1()          bfin_read32(RSI_MASK1)
+#define bfin_write_RSI_MASK1(val)      bfin_write32(RSI_MASK1, val)
+#define bfin_read_RSI_FIFO_CNT()       bfin_read16(RSI_FIFO_CNT)
+#define bfin_write_RSI_FIFO_CNT(val)   bfin_write16(RSI_FIFO_CNT, val)
+#define bfin_read_RSI_CEATA_CTL()      bfin_read16(RSI_CEATA_CONTROL)
+#define bfin_write_RSI_CEATA_CTL(val)  bfin_write16(RSI_CEATA_CONTROL, val)
+#define bfin_read_RSI_FIFO()           bfin_read32(RSI_FIFO)
+#define bfin_write_RSI_FIFO(val)       bfin_write32(RSI_FIFO, val)
+#define bfin_read_RSI_E_STATUS()       bfin_read16(RSI_ESTAT)
+#define bfin_write_RSI_E_STATUS(val)   bfin_write16(RSI_ESTAT, val)
+#define bfin_read_RSI_E_MASK()         bfin_read16(RSI_EMASK)
+#define bfin_write_RSI_E_MASK(val)     bfin_write16(RSI_EMASK, val)
+#define bfin_read_RSI_CFG()            bfin_read16(RSI_CONFIG)
+#define bfin_write_RSI_CFG(val)        bfin_write16(RSI_CONFIG, val)
+#define bfin_read_RSI_RD_WAIT_EN()     bfin_read16(RSI_RD_WAIT_EN)
+#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
+#define bfin_read_RSI_PID0()           bfin_read16(RSI_PID0)
+#define bfin_write_RSI_PID0(val)       bfin_write16(RSI_PID0, val)
+#define bfin_read_RSI_PID1()           bfin_read16(RSI_PID1)
+#define bfin_write_RSI_PID1(val)       bfin_write16(RSI_PID1, val)
+#define bfin_read_RSI_PID2()           bfin_read16(RSI_PID2)
+#define bfin_write_RSI_PID2(val)       bfin_write16(RSI_PID2, val)
+#define bfin_read_RSI_PID3()           bfin_read16(RSI_PID3)
+#define bfin_write_RSI_PID3(val)       bfin_write16(RSI_PID3, val)
+#define bfin_read_RSI_PID4()           bfin_read16(RSI_PID4)
+#define bfin_write_RSI_PID4(val)       bfin_write16(RSI_PID4, val)
+#define bfin_read_RSI_PID5()           bfin_read16(RSI_PID5)
+#define bfin_write_RSI_PID5(val)       bfin_write16(RSI_PID5, val)
+#define bfin_read_RSI_PID6()           bfin_read16(RSI_PID6)
+#define bfin_write_RSI_PID6(val)       bfin_write16(RSI_PID6, val)
+#define bfin_read_RSI_PID7()           bfin_read16(RSI_PID7)
+#define bfin_write_RSI_PID7(val)       bfin_write16(RSI_PID7, val)
+
 #endif /* _CDEF_BF514_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
index 4e26ccf..14df43d 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
@@ -210,4 +210,71 @@
 #define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
 #define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
 
+/* Removable Storage Interface Registers */
+
+#define bfin_read_RSI_PWR_CTL()        bfin_read16(RSI_PWR_CONTROL)
+#define bfin_write_RSI_PWR_CTL(val)    bfin_write16(RSI_PWR_CONTROL, val)
+#define bfin_read_RSI_CLK_CTL()	       bfin_read16(RSI_CLK_CONTROL)
+#define bfin_write_RSI_CLK_CTL(val)    bfin_write16(RSI_CLK_CONTROL, val)
+#define bfin_read_RSI_ARGUMENT()       bfin_read32(RSI_ARGUMENT)
+#define bfin_write_RSI_ARGUMENT(val)   bfin_write32(RSI_ARGUMENT, val)
+#define bfin_read_RSI_COMMAND()        bfin_read16(RSI_COMMAND)
+#define bfin_write_RSI_COMMAND(val)    bfin_write16(RSI_COMMAND, val)
+#define bfin_read_RSI_RESP_CMD()       bfin_read16(RSI_RESP_CMD)
+#define bfin_write_RSI_RESP_CMD(val)   bfin_write16(RSI_RESP_CMD, val)
+#define bfin_read_RSI_RESPONSE0()      bfin_read32(RSI_RESPONSE0)
+#define bfin_write_RSI_RESPONSE0(val)  bfin_write32(RSI_RESPONSE0, val)
+#define bfin_read_RSI_RESPONSE1()      bfin_read32(RSI_RESPONSE1)
+#define bfin_write_RSI_RESPONSE1(val)  bfin_write32(RSI_RESPONSE1, val)
+#define bfin_read_RSI_RESPONSE2()      bfin_read32(RSI_RESPONSE2)
+#define bfin_write_RSI_RESPONSE2(val)  bfin_write32(RSI_RESPONSE2, val)
+#define bfin_read_RSI_RESPONSE3()      bfin_read32(RSI_RESPONSE3)
+#define bfin_write_RSI_RESPONSE3(val)  bfin_write32(RSI_RESPONSE3, val)
+#define bfin_read_RSI_DATA_TIMER()     bfin_read32(RSI_DATA_TIMER)
+#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
+#define bfin_read_RSI_DATA_LGTH()      bfin_read16(RSI_DATA_LGTH)
+#define bfin_write_RSI_DATA_LGTH(val)  bfin_write16(RSI_DATA_LGTH, val)
+#define bfin_read_RSI_DATA_CTL()       bfin_read16(RSI_DATA_CONTROL)
+#define bfin_write_RSI_DATA_CTL(val)   bfin_write16(RSI_DATA_CONTROL, val)
+#define bfin_read_RSI_DATA_CNT()       bfin_read16(RSI_DATA_CNT)
+#define bfin_write_RSI_DATA_CNT(val)   bfin_write16(RSI_DATA_CNT, val)
+#define bfin_read_RSI_STATUS()         bfin_read32(RSI_STATUS)
+#define bfin_write_RSI_STATUS(val)     bfin_write32(RSI_STATUS, val)
+#define bfin_read_RSI_STATUS_CLR()     bfin_read16(RSI_STATUSCL)
+#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
+#define bfin_read_RSI_MASK0()          bfin_read32(RSI_MASK0)
+#define bfin_write_RSI_MASK0(val)      bfin_write32(RSI_MASK0, val)
+#define bfin_read_RSI_MASK1()          bfin_read32(RSI_MASK1)
+#define bfin_write_RSI_MASK1(val)      bfin_write32(RSI_MASK1, val)
+#define bfin_read_RSI_FIFO_CNT()       bfin_read16(RSI_FIFO_CNT)
+#define bfin_write_RSI_FIFO_CNT(val)   bfin_write16(RSI_FIFO_CNT, val)
+#define bfin_read_RSI_CEATA_CTL()      bfin_read16(RSI_CEATA_CONTROL)
+#define bfin_write_RSI_CEATA_CTL(val)  bfin_write16(RSI_CEATA_CONTROL, val)
+#define bfin_read_RSI_FIFO()           bfin_read32(RSI_FIFO)
+#define bfin_write_RSI_FIFO(val)       bfin_write32(RSI_FIFO, val)
+#define bfin_read_RSI_E_STATUS()       bfin_read16(RSI_ESTAT)
+#define bfin_write_RSI_E_STATUS(val)   bfin_write16(RSI_ESTAT, val)
+#define bfin_read_RSI_E_MASK()         bfin_read16(RSI_EMASK)
+#define bfin_write_RSI_E_MASK(val)     bfin_write16(RSI_EMASK, val)
+#define bfin_read_RSI_CFG()            bfin_read16(RSI_CONFIG)
+#define bfin_write_RSI_CFG(val)        bfin_write16(RSI_CONFIG, val)
+#define bfin_read_RSI_RD_WAIT_EN()     bfin_read16(RSI_RD_WAIT_EN)
+#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
+#define bfin_read_RSI_PID0()           bfin_read16(RSI_PID0)
+#define bfin_write_RSI_PID0(val)       bfin_write16(RSI_PID0, val)
+#define bfin_read_RSI_PID1()           bfin_read16(RSI_PID1)
+#define bfin_write_RSI_PID1(val)       bfin_write16(RSI_PID1, val)
+#define bfin_read_RSI_PID2()           bfin_read16(RSI_PID2)
+#define bfin_write_RSI_PID2(val)       bfin_write16(RSI_PID2, val)
+#define bfin_read_RSI_PID3()           bfin_read16(RSI_PID3)
+#define bfin_write_RSI_PID3(val)       bfin_write16(RSI_PID3, val)
+#define bfin_read_RSI_PID4()           bfin_read16(RSI_PID4)
+#define bfin_write_RSI_PID4(val)       bfin_write16(RSI_PID4, val)
+#define bfin_read_RSI_PID5()           bfin_read16(RSI_PID5)
+#define bfin_write_RSI_PID5(val)       bfin_write16(RSI_PID5, val)
+#define bfin_read_RSI_PID6()           bfin_read16(RSI_PID6)
+#define bfin_write_RSI_PID6(val)       bfin_write16(RSI_PID6, val)
+#define bfin_read_RSI_PID7()           bfin_read16(RSI_PID7)
+#define bfin_write_RSI_PID7(val)       bfin_write16(RSI_PID7, val)
+
 #endif /* _CDEF_BF516_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF514.h b/arch/blackfin/mach-bf518/include/mach/defBF514.h
index 543f291..56ee5a7 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF514.h
@@ -110,4 +110,139 @@
 #define RSI_PID6                       0xFFC03FF8 /* RSI Peripheral ID Register 6 */
 #define RSI_PID7                       0xFFC03FFC /* RSI Peripheral ID Register 7 */
 
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for SDH_COMMAND */
+
+#define                   CMD_IDX  0x3f       /* Command Index */
+#define                   CMD_RSP  0x40       /* Response */
+#define                 CMD_L_RSP  0x80       /* Long Response */
+#define                 CMD_INT_E  0x100      /* Command Interrupt */
+#define                CMD_PEND_E  0x200      /* Command Pending */
+#define                     CMD_E  0x400      /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define                    PWR_ON  0x3        /* Power On */
+#if 0
+#define                       TBD  0x3c       /* TBD */
+#endif
+#define                 SD_CMD_OD  0x40       /* Open Drain Output */
+#define                   ROD_CTL  0x80       /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define                    CLKDIV  0xff       /* MC_CLK Divisor */
+#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
+#define                  PWR_SV_E  0x200      /* Power Save Enable */
+#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
+#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define                  RESP_CMD  0x3f       /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define                     DTX_E  0x1        /* Data Transfer Enable */
+#define                   DTX_DIR  0x2        /* Data Transfer Direction */
+#define                  DTX_MODE  0x4        /* Data Transfer Mode */
+#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
+#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
+#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
+#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
+#define               DAT_TIME_OUT  0x8        /* Data Time Out */
+#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
+#define                RX_OVERRUN  0x20       /* Receive Overrun */
+#define              CMD_RESP_END  0x40       /* CMD Response End */
+#define                  CMD_SENT  0x80       /* CMD Sent */
+#define                   DAT_END  0x100      /* Data End */
+#define             START_BIT_ERR  0x200      /* Start Bit Error */
+#define               DAT_BLK_END  0x400      /* Data Block End */
+#define                   CMD_ACT  0x800      /* CMD Active */
+#define                    TX_ACT  0x1000     /* Transmit Active */
+#define                    RX_ACT  0x2000     /* Receive Active */
+#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
+#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
+#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
+#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
+#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
+#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
+#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
+#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
+#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
+#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
+#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
+#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
+#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
+#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
+#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
+#define              DAT_END_STAT  0x100      /* Data End Status */
+#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
+#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
+#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
+#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
+#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
+#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
+#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
+#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
+#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
+#define              DAT_END_MASK  0x100      /* Data End Mask */
+#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
+#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
+#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
+#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
+#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
+#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
+#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
+#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
+#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
+#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
+#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
+#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
+#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define                FIFO_COUNT  0x7fff     /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
+#define               SD_CARD_DET  0x10       /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
+#define                   SCD_MSK  0x40       /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define                   CLKS_EN  0x1        /* Clocks Enable */
+#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
+#define                       MWE  0x8        /* Moving Window Enable */
+#define                    SD_RST  0x10       /* SDMMC Reset */
+#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
+#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
+#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define                       RWR  0x1        /* Read Wait Request */
+
 #endif /* _DEF_BF514_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF516.h b/arch/blackfin/mach-bf518/include/mach/defBF516.h
index 149a269..dfc9384 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF516.h
@@ -487,4 +487,139 @@
 #define RSI_PID6                       0xFFC03FF8 /* RSI Peripheral ID Register 6 */
 #define RSI_PID7                       0xFFC03FFC /* RSI Peripheral ID Register 7 */
 
+/* ********************************************************** */
+/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
+/*     and MULTI BIT READ MACROS                              */
+/* ********************************************************** */
+
+/* Bit masks for SDH_COMMAND */
+
+#define                   CMD_IDX  0x3f       /* Command Index */
+#define                   CMD_RSP  0x40       /* Response */
+#define                 CMD_L_RSP  0x80       /* Long Response */
+#define                 CMD_INT_E  0x100      /* Command Interrupt */
+#define                CMD_PEND_E  0x200      /* Command Pending */
+#define                     CMD_E  0x400      /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define                    PWR_ON  0x3        /* Power On */
+#if 0
+#define                       TBD  0x3c       /* TBD */
+#endif
+#define                 SD_CMD_OD  0x40       /* Open Drain Output */
+#define                   ROD_CTL  0x80       /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define                    CLKDIV  0xff       /* MC_CLK Divisor */
+#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
+#define                  PWR_SV_E  0x200      /* Power Save Enable */
+#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
+#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define                  RESP_CMD  0x3f       /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define                     DTX_E  0x1        /* Data Transfer Enable */
+#define                   DTX_DIR  0x2        /* Data Transfer Direction */
+#define                  DTX_MODE  0x4        /* Data Transfer Mode */
+#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
+#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
+#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
+#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
+#define               DAT_TIME_OUT  0x8        /* Data Time Out */
+#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
+#define                RX_OVERRUN  0x20       /* Receive Overrun */
+#define              CMD_RESP_END  0x40       /* CMD Response End */
+#define                  CMD_SENT  0x80       /* CMD Sent */
+#define                   DAT_END  0x100      /* Data End */
+#define             START_BIT_ERR  0x200      /* Start Bit Error */
+#define               DAT_BLK_END  0x400      /* Data Block End */
+#define                   CMD_ACT  0x800      /* CMD Active */
+#define                    TX_ACT  0x1000     /* Transmit Active */
+#define                    RX_ACT  0x2000     /* Receive Active */
+#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
+#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
+#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
+#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
+#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
+#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
+#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
+#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
+#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
+#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
+#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
+#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
+#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
+#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
+#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
+#define              DAT_END_STAT  0x100      /* Data End Status */
+#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
+#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
+#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
+#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
+#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
+#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
+#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
+#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
+#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
+#define              DAT_END_MASK  0x100      /* Data End Mask */
+#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
+#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
+#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
+#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
+#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
+#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
+#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
+#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
+#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
+#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
+#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
+#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
+#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define                FIFO_COUNT  0x7fff     /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
+#define               SD_CARD_DET  0x10       /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
+#define                   SCD_MSK  0x40       /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define                   CLKS_EN  0x1        /* Clocks Enable */
+#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
+#define                       MWE  0x8        /* Moving Window Enable */
+#define                    SD_RST  0x10       /* SDMMC Reset */
+#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
+#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
+#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define                       RWR  0x1        /* Read Wait Request */
+
 #endif /* _DEF_BF516_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/blackfin.h b/arch/blackfin/mach-bf527/include/mach/blackfin.h
index 297821e..417abcd 100644
--- a/arch/blackfin/mach-bf527/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf527/include/mach/blackfin.h
@@ -32,8 +32,6 @@
 #ifndef _MACH_BLACKFIN_H_
 #define _MACH_BLACKFIN_H_
 
-#define BF527_FAMILY
-
 #include "bf527.h"
 #include "mem_map.h"
 #include "defBF522.h"
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index cd04c5e..0572926 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -843,6 +843,71 @@
 };
 #endif  /* spi master and devices */
 
+#if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE)
+
+/* SPORT SPI controller data */
+static struct bfin5xx_spi_master bfin_sport_spi0_info = {
+	.num_chipselect = 1, /* master only supports one device */
+	.enable_dma = 0,  /* master don't support DMA */
+	.pin_req = {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_DRPRI,
+		P_SPORT0_RSCLK, P_SPORT0_TFS, P_SPORT0_RFS, 0},
+};
+
+static struct resource bfin_sport_spi0_resource[] = {
+	[0] = {
+		.start = SPORT0_TCR1,
+		.end   = SPORT0_TCR1 + 0xFF,
+		.flags = IORESOURCE_MEM,
+		},
+	[1] = {
+		.start = IRQ_SPORT0_ERROR,
+		.end   = IRQ_SPORT0_ERROR,
+		.flags = IORESOURCE_IRQ,
+		},
+};
+
+static struct platform_device bfin_sport_spi0_device = {
+	.name = "bfin-sport-spi",
+	.id = 1, /* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_sport_spi0_resource),
+	.resource = bfin_sport_spi0_resource,
+	.dev = {
+		.platform_data = &bfin_sport_spi0_info, /* Passed to driver */
+	},
+};
+
+static struct bfin5xx_spi_master bfin_sport_spi1_info = {
+	.num_chipselect = 1, /* master only supports one device */
+	.enable_dma = 0,  /* master don't support DMA */
+	.pin_req = {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_DRPRI,
+		P_SPORT1_RSCLK, P_SPORT1_TFS, P_SPORT1_RFS, 0},
+};
+
+static struct resource bfin_sport_spi1_resource[] = {
+	[0] = {
+		.start = SPORT1_TCR1,
+		.end   = SPORT1_TCR1 + 0xFF,
+		.flags = IORESOURCE_MEM,
+		},
+	[1] = {
+		.start = IRQ_SPORT1_ERROR,
+		.end   = IRQ_SPORT1_ERROR,
+		.flags = IORESOURCE_IRQ,
+		},
+};
+
+static struct platform_device bfin_sport_spi1_device = {
+	.name = "bfin-sport-spi",
+	.id = 2, /* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_sport_spi1_resource),
+	.resource = bfin_sport_spi1_resource,
+	.dev = {
+		.platform_data = &bfin_sport_spi1_info, /* Passed to driver */
+	},
+};
+
+#endif  /* sport spi master and devices */
+
 #if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
 static struct platform_device bfin_fb_device = {
 	.name = "bf537-lq035",
@@ -1073,6 +1138,141 @@
 };
 #endif
 
+#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE)
+#include <linux/mfd/adp5520.h>
+
+	/*
+	 *  ADP5520/5501 Backlight Data
+	 */
+
+static struct adp5520_backlight_platfrom_data adp5520_backlight_data = {
+	.fade_in 		= FADE_T_1200ms,
+	.fade_out 		= FADE_T_1200ms,
+	.fade_led_law 		= BL_LAW_LINEAR,
+	.en_ambl_sens 		= 1,
+	.abml_filt 		= BL_AMBL_FILT_640ms,
+	.l1_daylight_max 	= BL_CUR_mA(15),
+	.l1_daylight_dim 	= BL_CUR_mA(0),
+	.l2_office_max 		= BL_CUR_mA(7),
+	.l2_office_dim 		= BL_CUR_mA(0),
+	.l3_dark_max 		= BL_CUR_mA(3),
+	.l3_dark_dim 		= BL_CUR_mA(0),
+	.l2_trip 		= L2_COMP_CURR_uA(700),
+	.l2_hyst 		= L2_COMP_CURR_uA(50),
+	.l3_trip 		= L3_COMP_CURR_uA(80),
+	.l3_hyst 		= L3_COMP_CURR_uA(20),
+};
+
+	/*
+	 *  ADP5520/5501 LEDs Data
+	 */
+
+#include <linux/leds.h>
+
+static struct led_info adp5520_leds[] = {
+	{
+		.name = "adp5520-led1",
+		.default_trigger = "none",
+		.flags = FLAG_ID_ADP5520_LED1_ADP5501_LED0 | LED_OFFT_600ms,
+	},
+#ifdef ADP5520_EN_ALL_LEDS
+	{
+		.name = "adp5520-led2",
+		.default_trigger = "none",
+		.flags = FLAG_ID_ADP5520_LED2_ADP5501_LED1,
+	},
+	{
+		.name = "adp5520-led3",
+		.default_trigger = "none",
+		.flags = FLAG_ID_ADP5520_LED3_ADP5501_LED2,
+	},
+#endif
+};
+
+static struct adp5520_leds_platfrom_data adp5520_leds_data = {
+	.num_leds = ARRAY_SIZE(adp5520_leds),
+	.leds = adp5520_leds,
+	.fade_in = FADE_T_600ms,
+	.fade_out = FADE_T_600ms,
+	.led_on_time = LED_ONT_600ms,
+};
+
+	/*
+	 *  ADP5520 GPIO Data
+	 */
+
+static struct adp5520_gpio_platfrom_data adp5520_gpio_data = {
+	.gpio_start = 50,
+	.gpio_en_mask = GPIO_C1 | GPIO_C2 | GPIO_R2,
+	.gpio_pullup_mask = GPIO_C1 | GPIO_C2 | GPIO_R2,
+};
+
+	/*
+	 *  ADP5520 Keypad Data
+	 */
+
+#include <linux/input.h>
+static const unsigned short adp5520_keymap[ADP5520_KEYMAPSIZE] = {
+	[KEY(0, 0)]	= KEY_GRAVE,
+	[KEY(0, 1)]	= KEY_1,
+	[KEY(0, 2)]	= KEY_2,
+	[KEY(0, 3)]	= KEY_3,
+	[KEY(1, 0)]	= KEY_4,
+	[KEY(1, 1)]	= KEY_5,
+	[KEY(1, 2)]	= KEY_6,
+	[KEY(1, 3)]	= KEY_7,
+	[KEY(2, 0)]	= KEY_8,
+	[KEY(2, 1)]	= KEY_9,
+	[KEY(2, 2)]	= KEY_0,
+	[KEY(2, 3)]	= KEY_MINUS,
+	[KEY(3, 0)]	= KEY_EQUAL,
+	[KEY(3, 1)]	= KEY_BACKSLASH,
+	[KEY(3, 2)]	= KEY_BACKSPACE,
+	[KEY(3, 3)]	= KEY_ENTER,
+};
+
+static struct adp5520_keys_platfrom_data adp5520_keys_data = {
+	.rows_en_mask	= ROW_R3 | ROW_R2 | ROW_R1 | ROW_R0,
+	.cols_en_mask	= COL_C3 | COL_C2 | COL_C1 | COL_C0,
+	.keymap		= adp5520_keymap,
+	.keymapsize	= ARRAY_SIZE(adp5520_keymap),
+	.repeat		= 0,
+};
+
+	/*
+	 *  ADP5520/5501 Multifuction Device Init Data
+	 */
+
+static struct adp5520_subdev_info adp5520_subdevs[] = {
+	{
+		.name = "adp5520-backlight",
+		.id = ID_ADP5520,
+		.platform_data = &adp5520_backlight_data,
+	},
+	{
+		.name = "adp5520-led",
+		.id = ID_ADP5520,
+		.platform_data = &adp5520_leds_data,
+	},
+	{
+		.name = "adp5520-gpio",
+		.id = ID_ADP5520,
+		.platform_data = &adp5520_gpio_data,
+	},
+	{
+		.name = "adp5520-keys",
+		.id = ID_ADP5520,
+		.platform_data = &adp5520_keys_data,
+	},
+};
+
+static struct adp5520_platform_data adp5520_pdev_data = {
+	.num_subdevs = ARRAY_SIZE(adp5520_subdevs),
+	.subdevs = adp5520_subdevs,
+};
+
+#endif
+
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
 	{
@@ -1105,6 +1305,13 @@
 		.platform_data = (void *)&adp5588_kpad_data,
 	},
 #endif
+#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE)
+	{
+		I2C_BOARD_INFO("pmic-adp5520", 0x32),
+		.irq = IRQ_PF7,
+		.platform_data = (void *)&adp5520_pdev_data,
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -1120,8 +1327,11 @@
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-#define PATA_INT	IRQ_PF5
+#define CF_IDE_NAND_CARD_USE_HDD_INTERFACE
+/* #define CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE */
 
+#ifdef CF_IDE_NAND_CARD_USE_HDD_INTERFACE
+#define PATA_INT	IRQ_PF5
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 1,
 	.irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
@@ -1144,6 +1354,24 @@
 		.flags = IORESOURCE_IRQ,
 	},
 };
+#elif defined(CF_IDE_NAND_CARD_USE_CF_IN_COMMON_MEMORY_MODE)
+static struct pata_platform_info bfin_pata_platform_data = {
+	.ioport_shift = 0,
+};
+
+static struct resource bfin_pata_resources[] = {
+	{
+		.start = 0x20211820,
+		.end = 0x2021183F,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = 0x2021181C,
+		.end = 0x2021181F,
+		.flags = IORESOURCE_MEM,
+	},
+};
+#endif
 
 static struct platform_device bfin_pata_device = {
 	.name = "pata_platform",
@@ -1232,6 +1460,11 @@
 	&bfin_spi0_device,
 #endif
 
+#if defined(CONFIG_SPI_BFIN_SPORT) || defined(CONFIG_SPI_BFIN_SPORT_MODULE)
+	&bfin_sport_spi0_device,
+	&bfin_sport_spi1_device,
+#endif
+
 #if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
 	&bfin_fb_device,
 #endif
diff --git a/arch/blackfin/mach-bf548/include/mach/blackfin.h b/arch/blackfin/mach-bf548/include/mach/blackfin.h
index 0c0e3e2..cf6c150 100644
--- a/arch/blackfin/mach-bf548/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf548/include/mach/blackfin.h
@@ -32,8 +32,6 @@
 #ifndef _MACH_BLACKFIN_H_
 #define _MACH_BLACKFIN_H_
 
-#define BF548_FAMILY
-
 #include "bf548.h"
 #include "mem_map.h"
 #include "anomaly.h"
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index f48a6ae..bce5a84 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -287,7 +287,7 @@
 static int bfin_pm_valid(suspend_state_t state)
 {
 	return (state == PM_SUSPEND_STANDBY
-#ifndef BF533_FAMILY
+#if !(defined(BF533_FAMILY) || defined(CONFIG_BF561))
 	/*
 	 * On BF533/2/1:
 	 * If we enter Hibernate the SCKE Pin is driven Low,
diff --git a/arch/m68k/include/asm/ide.h b/arch/m68k/include/asm/ide.h
index b996a3c..3958726 100644
--- a/arch/m68k/include/asm/ide.h
+++ b/arch/m68k/include/asm/ide.h
@@ -30,101 +30,28 @@
 #define _M68K_IDE_H
 
 #ifdef __KERNEL__
-
-
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#ifdef CONFIG_ATARI
-#include <linux/interrupt.h>
-#include <asm/atari_stdma.h>
-#endif
-
-#ifdef CONFIG_MAC
-#include <asm/macints.h>
-#endif
-
 /*
  * Get rid of defs from io.h - ide has its private and conflicting versions
  * Since so far no single m68k platform uses ISA/PCI I/O space for IDE, we
  * always use the `raw' MMIO versions
  */
-#undef inb
-#undef inw
-#undef insw
-#undef inl
-#undef insl
-#undef outb
-#undef outw
-#undef outsw
-#undef outl
-#undef outsl
 #undef readb
 #undef readw
-#undef readl
 #undef writeb
 #undef writew
-#undef writel
 
-#define inb				in_8
-#define inw				in_be16
-#define insw(port, addr, n)		raw_insw((u16 *)port, addr, n)
-#define inl				in_be32
-#define insl(port, addr, n)		raw_insl((u32 *)port, addr, n)
-#define outb(val, port)			out_8(port, val)
-#define outw(val, port)			out_be16(port, val)
-#define outsw(port, addr, n)		raw_outsw((u16 *)port, addr, n)
-#define outl(val, port)			out_be32(port, val)
-#define outsl(port, addr, n)		raw_outsl((u32 *)port, addr, n)
 #define readb				in_8
 #define readw				in_be16
 #define __ide_mm_insw(port, addr, n)	raw_insw((u16 *)port, addr, n)
-#define readl				in_be32
 #define __ide_mm_insl(port, addr, n)	raw_insl((u32 *)port, addr, n)
 #define writeb(val, port)		out_8(port, val)
 #define writew(val, port)		out_be16(port, val)
 #define __ide_mm_outsw(port, addr, n)	raw_outsw((u16 *)port, addr, n)
-#define writel(val, port)		out_be32(port, val)
 #define __ide_mm_outsl(port, addr, n)	raw_outsl((u32 *)port, addr, n)
-#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
-#define insw_swapw(port, addr, n)	raw_insw_swapw((u16 *)port, addr, n)
-#define outsw_swapw(port, addr, n)	raw_outsw_swapw((u16 *)port, addr, n)
-#endif
-
-#ifdef CONFIG_BLK_DEV_FALCON_IDE
-#define IDE_ARCH_LOCK
-
-extern int falconide_intr_lock;
-
-static __inline__ void ide_release_lock (void)
-{
-	if (MACH_IS_ATARI) {
-		if (falconide_intr_lock == 0) {
-			printk("ide_release_lock: bug\n");
-			return;
-		}
-		falconide_intr_lock = 0;
-		stdma_release();
-	}
-}
-
-static __inline__ void
-ide_get_lock(irq_handler_t handler, void *data)
-{
-	if (MACH_IS_ATARI) {
-		if (falconide_intr_lock == 0) {
-			if (in_interrupt() > 0)
-				panic( "Falcon IDE hasn't ST-DMA lock in interrupt" );
-			stdma_lock(handler, data);
-			falconide_intr_lock = 1;
-		}
-	}
-}
-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
-
-#define IDE_ARCH_ACK_INTR
-#define ide_ack_intr(hwif)	((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
 
 #endif /* __KERNEL__ */
 #endif /* _M68K_IDE_H */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 206cb79..dc78719 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -77,7 +77,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config MACH_DECSTATION
 	bool "DECstations"
@@ -132,7 +131,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
 	select SYS_SUPPORTS_100HZ
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
 	 This a family of machines based on the MIPS R4030 chipset which was
 	 used by several vendors to build RISC/os and Windows NT workstations.
@@ -154,7 +152,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config LEMOTE_FULONG
 	bool "Lemote Fulong mini-PC"
@@ -175,7 +172,6 @@
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_HAS_EARLY_PRINTK
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
 	select CPU_HAS_WB
 	help
@@ -250,7 +246,6 @@
 	select CEVT_R4K
 	select CSRC_R4K
 	select SYS_HAS_CPU_VR41XX
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config NXP_STB220
 	bool "NXP STB220 board"
@@ -364,7 +359,6 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_SMP
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
 	  This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
 	  workstations.  To compile a Linux kernel that runs on these, say Y
@@ -563,7 +557,6 @@
 	select CEVT_R4K
 	select CSRC_R4K
 	select DMA_NONCOHERENT
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select HW_HAS_PCI
 	select IRQ_CPU
 	select SYS_HAS_CPU_MIPS32_R1
@@ -700,8 +693,7 @@
 	default y
 
 config GENERIC_HARDIRQS_NO__DO_IRQ
-	bool
-	default n
+	def_bool y
 
 #
 # Select some configuration options automatically based on user selections.
@@ -920,7 +912,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select GENERIC_GPIO
 	select CPU_MIPSR2_IRQ_VI
 
@@ -939,7 +930,6 @@
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select GENERIC_GPIO
 
 config SWAP_IO_SPACE
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 22dab2e..8d544c7 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -720,11 +720,17 @@
 	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
 endif
 
+install:
+	$(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+	$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
+	$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
+
 archclean:
 	@$(MAKE) $(clean)=arch/mips/boot
 	@$(MAKE) $(clean)=arch/mips/lasat
 
 define archhelp
+	echo '  install              - install kernel into $(INSTALL_PATH)'
 	echo '  vmlinux.ecoff        - ECOFF boot image'
 	echo '  vmlinux.bin          - Raw binary boot image'
 	echo '  vmlinux.srec         - SREC boot image'
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig
index 7f8ef13..8128aeb 100644
--- a/arch/mips/alchemy/Kconfig
+++ b/arch/mips/alchemy/Kconfig
@@ -134,4 +134,4 @@
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_APM_EMULATION
-	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/mips/alchemy/common/gpio.c b/arch/mips/alchemy/common/gpio.c
index e660ddd..91a9c44 100644
--- a/arch/mips/alchemy/common/gpio.c
+++ b/arch/mips/alchemy/common/gpio.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *  Copyright (C) 2007-2009, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
  *  	Architecture specific GPIO support
  *
  *  This program is free software; you can redistribute	 it and/or modify it
@@ -27,122 +27,175 @@
  * 	others have a second one : GPIO2
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/gpio.h>
 
-#define gpio1 sys
+struct au1000_gpio_chip {
+	struct gpio_chip	chip;
+	void __iomem		*regbase;
+};
+
 #if !defined(CONFIG_SOC_AU1000)
-
-static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
-#define GPIO2_OUTPUT_ENABLE_MASK 	0x00010000
-
-static int au1xxx_gpio2_read(unsigned gpio)
+static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset)
 {
-	gpio -= AU1XXX_GPIO_BASE;
-	return ((gpio2->pinstate >> gpio) & 0x01);
+	u32 mask = 1 << offset;
+	struct au1000_gpio_chip *gpch;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+	return readl(gpch->regbase + AU1000_GPIO2_ST) & mask;
 }
 
-static void au1xxx_gpio2_write(unsigned gpio, int value)
+static void au1000_gpio2_set(struct gpio_chip *chip,
+				unsigned offset, int value)
 {
-	gpio -= AU1XXX_GPIO_BASE;
+	u32 mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset));
+	struct au1000_gpio_chip *gpch;
+	unsigned long flags;
 
-	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+
+	local_irq_save(flags);
+	writel(mask, gpch->regbase + AU1000_GPIO2_OUT);
+	local_irq_restore(flags);
 }
 
-static int au1xxx_gpio2_direction_input(unsigned gpio)
+static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	gpio -= AU1XXX_GPIO_BASE;
-	gpio2->dir &= ~(0x01 << gpio);
+	u32 mask = 1 << offset;
+	u32 tmp;
+	struct au1000_gpio_chip *gpch;
+	unsigned long flags;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+
+	local_irq_save(flags);
+	tmp = readl(gpch->regbase + AU1000_GPIO2_DIR);
+	tmp &= ~mask;
+	writel(tmp, gpch->regbase + AU1000_GPIO2_DIR);
+	local_irq_restore(flags);
+
 	return 0;
 }
 
-static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
+static int au1000_gpio2_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
 {
-	gpio -= AU1XXX_GPIO_BASE;
-	gpio2->dir |= 0x01 << gpio;
-	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
+	u32 mask = 1 << offset;
+	u32 out_mask = ((GPIO2_OUT_EN_MASK << offset) | (!!value << offset));
+	u32 tmp;
+	struct au1000_gpio_chip *gpch;
+	unsigned long flags;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+
+	local_irq_save(flags);
+	tmp = readl(gpch->regbase + AU1000_GPIO2_DIR);
+	tmp |= mask;
+	writel(tmp, gpch->regbase + AU1000_GPIO2_DIR);
+	writel(out_mask, gpch->regbase + AU1000_GPIO2_OUT);
+	local_irq_restore(flags);
+
 	return 0;
 }
-
 #endif /* !defined(CONFIG_SOC_AU1000) */
 
-static int au1xxx_gpio1_read(unsigned gpio)
+static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset)
 {
-	return (gpio1->pinstaterd >> gpio) & 0x01;
+	u32 mask = 1 << offset;
+	struct au1000_gpio_chip *gpch;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+	return readl(gpch->regbase + AU1000_GPIO1_ST) & mask;
 }
 
-static void au1xxx_gpio1_write(unsigned gpio, int value)
+static void au1000_gpio1_set(struct gpio_chip *chip,
+				unsigned offset, int value)
 {
+	u32 mask = 1 << offset;
+	u32 reg_offset;
+	struct au1000_gpio_chip *gpch;
+	unsigned long flags;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+
 	if (value)
-		gpio1->outputset = (0x01 << gpio);
+		reg_offset = AU1000_GPIO1_OUT;
 	else
-		/* Output a zero */
-		gpio1->outputclr = (0x01 << gpio);
+		reg_offset = AU1000_GPIO1_CLR;
+
+	local_irq_save(flags);
+	writel(mask, gpch->regbase + reg_offset);
+	local_irq_restore(flags);
 }
 
-static int au1xxx_gpio1_direction_input(unsigned gpio)
+static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	gpio1->pininputen = (0x01 << gpio);
+	u32 mask = 1 << offset;
+	struct au1000_gpio_chip *gpch;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+	writel(mask, gpch->regbase + AU1000_GPIO1_ST);
+
 	return 0;
 }
 
-static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
+static int au1000_gpio1_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
 {
-	gpio1->trioutclr = (0x01 & gpio);
-	au1xxx_gpio1_write(gpio, value);
+	u32 mask = 1 << offset;
+	struct au1000_gpio_chip *gpch;
+
+	gpch = container_of(chip, struct au1000_gpio_chip, chip);
+
+	writel(mask, gpch->regbase + AU1000_GPIO1_TRI_OUT);
+	au1000_gpio1_set(chip, offset, value);
+
 	return 0;
 }
 
-int au1xxx_gpio_get_value(unsigned gpio)
-{
-	if (gpio >= AU1XXX_GPIO_BASE)
-#if defined(CONFIG_SOC_AU1000)
-		return 0;
-#else
-		return au1xxx_gpio2_read(gpio);
+struct au1000_gpio_chip au1000_gpio_chip[] = {
+	[0] = {
+		.regbase			= (void __iomem *)SYS_BASE,
+		.chip = {
+			.label			= "au1000-gpio1",
+			.direction_input	= au1000_gpio1_direction_input,
+			.direction_output	= au1000_gpio1_direction_output,
+			.get			= au1000_gpio1_get,
+			.set			= au1000_gpio1_set,
+			.base			= 0,
+			.ngpio			= 32,
+		},
+	},
+#if !defined(CONFIG_SOC_AU1000)
+	[1] = {
+		.regbase                        = (void __iomem *)GPIO2_BASE,
+		.chip = {
+			.label                  = "au1000-gpio2",
+			.direction_input        = au1000_gpio2_direction_input,
+			.direction_output       = au1000_gpio2_direction_output,
+			.get                    = au1000_gpio2_get,
+			.set                    = au1000_gpio2_set,
+			.base                   = AU1XXX_GPIO_BASE,
+			.ngpio                  = 32,
+		},
+	},
 #endif
-	else
-		return au1xxx_gpio1_read(gpio);
-}
-EXPORT_SYMBOL(au1xxx_gpio_get_value);
+};
 
-void au1xxx_gpio_set_value(unsigned gpio, int value)
+static int __init au1000_gpio_init(void)
 {
-	if (gpio >= AU1XXX_GPIO_BASE)
-#if defined(CONFIG_SOC_AU1000)
-		;
-#else
-		au1xxx_gpio2_write(gpio, value);
-#endif
-	else
-		au1xxx_gpio1_write(gpio, value);
-}
-EXPORT_SYMBOL(au1xxx_gpio_set_value);
-
-int au1xxx_gpio_direction_input(unsigned gpio)
-{
-	if (gpio >= AU1XXX_GPIO_BASE)
-#if defined(CONFIG_SOC_AU1000)
-		return -ENODEV;
-#else
-		return au1xxx_gpio2_direction_input(gpio);
+	gpiochip_add(&au1000_gpio_chip[0].chip);
+#if !defined(CONFIG_SOC_AU1000)
+	gpiochip_add(&au1000_gpio_chip[1].chip);
 #endif
 
-	return au1xxx_gpio1_direction_input(gpio);
+	return 0;
 }
-EXPORT_SYMBOL(au1xxx_gpio_direction_input);
+arch_initcall(au1000_gpio_init);
 
-int au1xxx_gpio_direction_output(unsigned gpio, int value)
-{
-	if (gpio >= AU1XXX_GPIO_BASE)
-#if defined(CONFIG_SOC_AU1000)
-		return -ENODEV;
-#else
-		return au1xxx_gpio2_direction_output(gpio, value);
-#endif
-
-	return au1xxx_gpio1_direction_output(gpio, value);
-}
-EXPORT_SYMBOL(au1xxx_gpio_direction_output);
diff --git a/arch/mips/alchemy/devboards/pb1200/platform.c b/arch/mips/alchemy/devboards/pb1200/platform.c
index 9530329..0d68e19 100644
--- a/arch/mips/alchemy/devboards/pb1200/platform.c
+++ b/arch/mips/alchemy/devboards/pb1200/platform.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
+#include <linux/smc91x.h>
 
 #include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1100_mmc.h>
@@ -131,6 +132,12 @@
 	.resource	= ide_resources
 };
 
+static struct smc91x_platdata smc_data = {
+	.flags	= SMC91X_NOWAIT | SMC91X_USE_16BIT,
+	.leda	= RPC_LED_100_10,
+	.ledb	= RPC_LED_TX_RX,
+};
+
 static struct resource smc91c111_resources[] = {
 	[0] = {
 		.name	= "smc91x-regs",
@@ -146,6 +153,9 @@
 };
 
 static struct platform_device smc91c111_device = {
+	.dev	= {
+		.platform_data	= &smc_data,
+	},
 	.name		= "smc91x",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(smc91c111_resources),
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 1c2a7fa..d6903c3 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -14,3 +14,5 @@
 obj-y += octeon-memcpy.o
 
 obj-$(CONFIG_SMP)                     += smp.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
index 553d36c..008f657 100644
--- a/arch/mips/cavium-octeon/flash_setup.c
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -57,7 +57,7 @@
 		flash_map.bankwidth = 1;
 		flash_map.virt = ioremap(flash_map.phys, flash_map.size);
 		pr_notice("Bootbus flash: Setting flash for %luMB flash at "
-			  "0x%08lx\n", flash_map.size >> 20, flash_map.phys);
+			  "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
 		simple_map_init(&flash_map);
 		mymtd = do_map_probe("cfi_probe", &flash_map);
 		if (mymtd) {
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index fc72984..1c19af8 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -31,7 +31,7 @@
 
 static void octeon_irq_core_eoi(unsigned int irq)
 {
-	irq_desc_t *desc = irq_desc + irq;
+	struct irq_desc *desc = irq_desc + irq;
 	unsigned int bit = irq - OCTEON_IRQ_SW0;
 	/*
 	 * If an IRQ is being processed while we are disabling it the
diff --git a/arch/mips/emma/markeins/irq.c b/arch/mips/emma/markeins/irq.c
index c2583ec..2bbc41a 100644
--- a/arch/mips/emma/markeins/irq.c
+++ b/arch/mips/emma/markeins/irq.c
@@ -80,9 +80,9 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
-		set_irq_chip_and_handler(EMMA2RH_IRQ_BASE + i,
-					 &emma2rh_irq_controller,
-					 handle_level_irq);
+		set_irq_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
+					      &emma2rh_irq_controller,
+					      handle_level_irq, "level");
 }
 
 static void emma2rh_sw_irq_enable(unsigned int irq)
@@ -120,9 +120,9 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
-		set_irq_chip_and_handler(EMMA2RH_SW_IRQ_BASE + i,
-					 &emma2rh_sw_irq_controller,
-					 handle_level_irq);
+		set_irq_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
+					      &emma2rh_sw_irq_controller,
+					      handle_level_irq, "level");
 }
 
 static void emma2rh_gpio_irq_enable(unsigned int irq)
@@ -149,6 +149,12 @@
 
 static void emma2rh_gpio_irq_ack(unsigned int irq)
 {
+	irq -= EMMA2RH_GPIO_IRQ_BASE;
+	emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
+}
+
+static void emma2rh_gpio_irq_mask_ack(unsigned int irq)
+{
 	u32 reg;
 
 	irq -= EMMA2RH_GPIO_IRQ_BASE;
@@ -159,27 +165,12 @@
 	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 }
 
-static void emma2rh_gpio_irq_end(unsigned int irq)
-{
-	u32 reg;
-
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-
-		irq -= EMMA2RH_GPIO_IRQ_BASE;
-
-		reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
-		reg |= 1 << irq;
-		emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
-	}
-}
-
 struct irq_chip emma2rh_gpio_irq_controller = {
 	.name = "emma2rh_gpio_irq",
 	.ack = emma2rh_gpio_irq_ack,
 	.mask = emma2rh_gpio_irq_disable,
-	.mask_ack = emma2rh_gpio_irq_ack,
+	.mask_ack = emma2rh_gpio_irq_mask_ack,
 	.unmask = emma2rh_gpio_irq_enable,
-	.end = emma2rh_gpio_irq_end,
 };
 
 void emma2rh_gpio_irq_init(void)
@@ -187,8 +178,9 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
-		set_irq_chip(EMMA2RH_GPIO_IRQ_BASE + i,
-			     &emma2rh_gpio_irq_controller);
+		set_irq_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
+					      &emma2rh_gpio_irq_controller,
+					      handle_edge_irq, "edge");
 }
 
 static struct irqaction irq_cascade = {
@@ -213,8 +205,7 @@
 		    emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
 
 #ifdef EMMA2RH_SW_CASCADE
-	if (intStatus &
-	    (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+	if (intStatus & (1UL << EMMA2RH_SW_CASCADE)) {
 		u32 swIntStatus;
 		swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
 		    & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
@@ -225,6 +216,8 @@
 			}
 		}
 	}
+	/* Skip S/W interrupt */
+	intStatus &= ~(1UL << EMMA2RH_SW_CASCADE);
 #endif
 
 	for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
@@ -238,8 +231,7 @@
 		    emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
 
 #ifdef EMMA2RH_GPIO_CASCADE
-	if (intStatus &
-	    (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+	if (intStatus & (1UL << (EMMA2RH_GPIO_CASCADE % 32))) {
 		u32 gpioIntStatus;
 		gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
 		    & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
@@ -250,6 +242,8 @@
 			}
 		}
 	}
+	/* Skip GPIO interrupt */
+	intStatus &= ~(1UL << (EMMA2RH_GPIO_CASCADE % 32));
 #endif
 
 	for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
diff --git a/arch/mips/emma/markeins/platform.c b/arch/mips/emma/markeins/platform.c
index d5f47e4..80ae12e 100644
--- a/arch/mips/emma/markeins/platform.c
+++ b/arch/mips/emma/markeins/platform.c
@@ -110,6 +110,7 @@
 static struct  plat_serial8250_port platform_serial_ports[] = {
 	[0] = {
 		.membase= (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3),
+		.mapbase = EMMA2RH_PFUR0_BASE + 3,
 		.irq = EMMA2RH_IRQ_PFUR0,
 		.uartclk = EMMA2RH_SERIAL_CLOCK,
 		.regshift = 4,
@@ -117,6 +118,7 @@
 		.flags = EMMA2RH_SERIAL_FLAGS,
        }, [1] = {
 		.membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3),
+		.mapbase = EMMA2RH_PFUR1_BASE + 3,
 		.irq = EMMA2RH_IRQ_PFUR1,
 		.uartclk = EMMA2RH_SERIAL_CLOCK,
 		.regshift = 4,
@@ -124,6 +126,7 @@
 		.flags = EMMA2RH_SERIAL_FLAGS,
        }, [2] = {
 		.membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3),
+		.mapbase = EMMA2RH_PFUR2_BASE + 3,
 		.irq = EMMA2RH_IRQ_PFUR2,
 		.uartclk = EMMA2RH_SERIAL_CLOCK,
 		.regshift = 4,
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index c018727..3bdc0e3 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -209,8 +209,7 @@
 	 * MIPS32 class processors
 	 */
 	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
-	CPU_AU1000, CPU_AU1100, CPU_AU1200, CPU_AU1210, CPU_AU1250, CPU_AU1500,
-	CPU_AU1550, CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
+	CPU_ALCHEMY, CPU_PR4450, CPU_BCM3302, CPU_BCM4710,
 
 	/*
 	 * MIPS64 class processors
diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index 134e1fc..a12d971 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -87,7 +87,7 @@
 	: "=r" (tmp));							\
 } while (0)
 
-#elif defined(CONFIG_CPU_MIPSR1)
+#elif defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MACH_ALCHEMY)
 
 /*
  * These are slightly complicated by the fact that we guarantee R1 kernels to
@@ -139,7 +139,7 @@
 } while (0)
 
 #elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
-      defined(CONFIG_CPU_R5500)
+      defined(CONFIG_CPU_R5500) || defined(CONFIG_MACH_ALCHEMY)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
diff --git a/arch/mips/include/asm/mach-au1x00/cpu-feature-overrides.h b/arch/mips/include/asm/mach-au1x00/cpu-feature-overrides.h
new file mode 100644
index 0000000..d5df0ca
--- /dev/null
+++ b/arch/mips/include/asm/mach-au1x00/cpu-feature-overrides.h
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to 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 __ASM_MACH_AU1X00_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_AU1X00_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_tlb			1
+#define cpu_has_4kex			1
+#define cpu_has_3k_cache		0
+#define cpu_has_4k_cache		1
+#define cpu_has_tx39_cache		0
+#define cpu_has_fpu			0
+#define cpu_has_counter			1
+#define cpu_has_watch			1
+#define cpu_has_divec			1
+#define cpu_has_vce			0
+#define cpu_has_cache_cdex_p		0
+#define cpu_has_cache_cdex_s		0
+#define cpu_has_mcheck			1
+#define cpu_has_ejtag			1
+#define cpu_has_llsc			1
+#define cpu_has_mips16			0
+#define cpu_has_mdmx			0
+#define cpu_has_mips3d			0
+#define cpu_has_smartmips		0
+#define cpu_has_vtag_icache		0
+#define cpu_has_dc_aliases		0
+#define cpu_has_ic_fills_f_dc		1
+#define cpu_has_mips32r1		1
+#define cpu_has_mips32r2		0
+#define cpu_has_mips64r1		0
+#define cpu_has_mips64r2		0
+#define cpu_has_dsp			0
+#define cpu_has_mipsmt			0
+#define cpu_has_userlocal		0
+#define cpu_has_nofpuex			0
+#define cpu_has_64bits			0
+#define cpu_has_64bit_zero_reg		0
+#define cpu_has_vint			0
+#define cpu_has_veic			0
+#define cpu_has_inclusive_pcaches	0
+
+#define cpu_dcache_line_size()		32
+#define cpu_icache_line_size()		32
+
+#endif /* __ASM_MACH_AU1X00_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h b/arch/mips/include/asm/mach-au1x00/gpio.h
index 2dc61e0..34d9b72 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio.h
@@ -5,65 +5,29 @@
 
 #define AU1XXX_GPIO_BASE	200
 
-struct au1x00_gpio2 {
-	u32	dir;
-	u32	reserved;
-	u32	output;
-	u32	pinstate;
-	u32	inten;
-	u32	enable;
-};
+/* GPIO bank 1 offsets */
+#define AU1000_GPIO1_TRI_OUT	0x0100
+#define AU1000_GPIO1_OUT	0x0108
+#define AU1000_GPIO1_ST		0x0110
+#define AU1000_GPIO1_CLR	0x010C
 
-extern int au1xxx_gpio_get_value(unsigned gpio);
-extern void au1xxx_gpio_set_value(unsigned gpio, int value);
-extern int au1xxx_gpio_direction_input(unsigned gpio);
-extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+/* GPIO bank 2 offsets */
+#define AU1000_GPIO2_DIR	0x00
+#define AU1000_GPIO2_RSVD	0x04
+#define AU1000_GPIO2_OUT	0x08
+#define AU1000_GPIO2_ST		0x0C
+#define AU1000_GPIO2_INT	0x10
+#define AU1000_GPIO2_EN		0x14
 
+#define GPIO2_OUT_EN_MASK	0x00010000
 
-/* Wrappers for the arch-neutral GPIO API */
+#define gpio_to_irq(gpio)	NULL
 
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	/* Not yet implemented */
-	return 0;
-}
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
 
-static inline void gpio_free(unsigned gpio)
-{
-	/* Not yet implemented */
-}
+#define gpio_cansleep __gpio_cansleep
 
-static inline int gpio_direction_input(unsigned gpio)
-{
-	return au1xxx_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	return au1xxx_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return au1xxx_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	au1xxx_gpio_set_value(gpio, value);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return gpio;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return irq;
-}
-
-/* For cansleep */
 #include <asm-generic/gpio.h>
 
 #endif /* _AU1XXX_GPIO_H_ */
diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h
index 7f0b034..c0da1a8 100644
--- a/arch/mips/include/asm/mips-boards/generic.h
+++ b/arch/mips/include/asm/mips-boards/generic.h
@@ -71,8 +71,6 @@
 
 #define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
 
-extern int mips_revision_corid;
-
 #define MIPS_REVISION_SCON_OTHER	   0
 #define MIPS_REVISION_SCON_SOCITSC	   1
 #define MIPS_REVISION_SCON_SOCITSCP	   2
diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 43c207e7..64ffc02 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -15,6 +15,8 @@
 
 #include <linux/cpumask.h>
 
+struct task_struct;
+
 struct plat_smp_ops {
 	void (*send_ipi_single)(int cpu, unsigned int action);
 	void (*send_ipi_mask)(cpumask_t mask, unsigned int action);
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 0884947..10e8244 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -76,7 +76,7 @@
 		"2:							\n"
 		"	.subsection 2					\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
-		"5:	sll	%[ticket], 5				\n"
+		"	sll	%[ticket], 5				\n"
 		"							\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"	 subu	%[ticket], 1				\n"
@@ -85,7 +85,7 @@
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
-		"	b	5b					\n"
+		"	b	4b					\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
@@ -113,7 +113,7 @@
 		"	 ll	%[ticket], %[ticket_ptr]		\n"
 		"							\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
-		"5:	sll	%[ticket], 5				\n"
+		"	sll	%[ticket], 5				\n"
 		"							\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"	 subu	%[ticket], 1				\n"
@@ -122,7 +122,7 @@
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
-		"	b	5b					\n"
+		"	b	4b					\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.set pop					\n"
diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h
index bcbb8d6..7956e69 100644
--- a/arch/mips/include/asm/types.h
+++ b/arch/mips/include/asm/types.h
@@ -4,12 +4,18 @@
  * for more details.
  *
  * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
+ * Copyright (C) 2008 Wind River Systems,
+ *   written by Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #ifndef _ASM_TYPES_H
 #define _ASM_TYPES_H
 
-#if _MIPS_SZLONG == 64
+/*
+ * We don't use int-l64.h for the kernel anymore but still use it for
+ * userspace to avoid code changes.
+ */
+#if (_MIPS_SZLONG == 64) && !defined(__KERNEL__)
 # include <asm-generic/int-l64.h>
 #else
 # include <asm-generic/int-ll64.h>
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
index c672c08..f0fd636 100644
--- a/arch/mips/jazz/jazzdma.c
+++ b/arch/mips/jazz/jazzdma.c
@@ -68,8 +68,7 @@
 	 */
 	pgtbl = (VDMA_PGTBL_ENTRY *)__get_free_pages(GFP_KERNEL | GFP_DMA,
 						    get_order(VDMA_PGTBL_SIZE));
-	if (!pgtbl)
-		BUG();
+	BUG_ON(!pgtbl);
 	dma_cache_wback_inv((unsigned long)pgtbl, VDMA_PGTBL_SIZE);
 	pgtbl = (VDMA_PGTBL_ENTRY *)KSEG1ADDR(pgtbl);
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 1bdbcad..b13b8eb 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -183,13 +183,7 @@
 	case CPU_TX49XX:
 		cpu_wait = r4k_wait_irqoff;
 		break;
-	case CPU_AU1000:
-	case CPU_AU1100:
-	case CPU_AU1500:
-	case CPU_AU1550:
-	case CPU_AU1200:
-	case CPU_AU1210:
-	case CPU_AU1250:
+	case CPU_ALCHEMY:
 		cpu_wait = au1k_wait;
 		break;
 	case CPU_20KC:
@@ -783,37 +777,30 @@
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_AU1_REV1:
 	case PRID_IMP_AU1_REV2:
+		c->cputype = CPU_ALCHEMY;
 		switch ((c->processor_id >> 24) & 0xff) {
 		case 0:
-			c->cputype = CPU_AU1000;
 			__cpu_name[cpu] = "Au1000";
 			break;
 		case 1:
-			c->cputype = CPU_AU1500;
 			__cpu_name[cpu] = "Au1500";
 			break;
 		case 2:
-			c->cputype = CPU_AU1100;
 			__cpu_name[cpu] = "Au1100";
 			break;
 		case 3:
-			c->cputype = CPU_AU1550;
 			__cpu_name[cpu] = "Au1550";
 			break;
 		case 4:
-			c->cputype = CPU_AU1200;
 			__cpu_name[cpu] = "Au1200";
-			if ((c->processor_id & 0xff) == 2) {
-				c->cputype = CPU_AU1250;
+			if ((c->processor_id & 0xff) == 2)
 				__cpu_name[cpu] = "Au1250";
-			}
 			break;
 		case 5:
-			c->cputype = CPU_AU1210;
 			__cpu_name[cpu] = "Au1210";
 			break;
 		default:
-			panic("Unknown Au Core!");
+			__cpu_name[cpu] = "Au1xxx";
 			break;
 		}
 		break;
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 963c16d..6a8cd28 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -140,14 +140,16 @@
 
 		switch (imp->im_type) {
 		case MSC01_IRQ_EDGE:
-			set_irq_chip(irqbase+n, &msc_edgeirq_type);
+			set_irq_chip_and_handler_name(irqbase + n,
+				&msc_edgeirq_type, handle_edge_irq, "edge");
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
 			else
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
 			break;
 		case MSC01_IRQ_LEVEL:
-			set_irq_chip(irqbase+n, &msc_levelirq_type);
+			set_irq_chip_and_handler_name(irqbase+n,
+				&msc_levelirq_type, handle_level_irq, "level");
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
 			else
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 0ee2567..55c8a3c 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -112,7 +112,8 @@
 	 */
 	if (cpu_has_mipsmt)
 		for (i = irq_base; i < irq_base + 2; i++)
-			set_irq_chip(i, &mips_mt_cpu_irq_controller);
+			set_irq_chip_and_handler(i, &mips_mt_cpu_irq_controller,
+						 handle_percpu_irq);
 
 	for (i = irq_base + 2; i < irq_base + 8; i++)
 		set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 2a47271..6242bc6 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -133,9 +133,9 @@
 	return sys_ftruncate(fd, merge_64(a2, a3));
 }
 
-SYSCALL_DEFINE5(32_llseek, unsigned long, fd, unsigned long, offset_high,
-	unsigned long, offset_low, loff_t __user *, result,
-	unsigned long, origin)
+SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
+		unsigned int, offset_low, loff_t __user *, result,
+		unsigned int, origin)
 {
 	return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 4430a1f..2950b97 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -277,7 +277,8 @@
 	 * not selected. Once that done we can determine the low bound
 	 * of usable memory.
 	 */
-	reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
+	reserved_end = max(init_initrd(),
+			   (unsigned long) PFN_UP(__pa_symbol(&_end)));
 
 	/*
 	 * max_low_pfn is not a number of pages. The number of pages
diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c
index ead6c30..878e373 100644
--- a/arch/mips/kernel/smp-up.c
+++ b/arch/mips/kernel/smp-up.c
@@ -13,7 +13,7 @@
 /*
  * Send inter-processor interrupt
  */
-void up_send_ipi_single(int cpu, unsigned int action)
+static void up_send_ipi_single(int cpu, unsigned int action)
 {
 	panic(KERN_ERR "%s called", __func__);
 }
@@ -27,31 +27,31 @@
  *  After we've done initial boot, this function is called to allow the
  *  board code to clean up state, if needed
  */
-void __cpuinit up_init_secondary(void)
+static void __cpuinit up_init_secondary(void)
 {
 }
 
-void __cpuinit up_smp_finish(void)
+static void __cpuinit up_smp_finish(void)
 {
 }
 
 /* Hook for after all CPUs are online */
-void up_cpus_done(void)
+static void up_cpus_done(void)
 {
 }
 
 /*
  * Firmware CPU startup hook
  */
-void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle)
+static void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle)
 {
 }
 
-void __init up_smp_setup(void)
+static void __init up_smp_setup(void)
 {
 }
 
-void __init up_prepare_cpus(unsigned int max_cpus)
+static void __init up_prepare_cpus(unsigned int max_cpus)
 {
 }
 
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 3da9470..c937506 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -44,7 +44,7 @@
 #include <asm/mipsmtregs.h>
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
+static volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
 int __cpu_number_map[NR_CPUS];		/* Map physical to logical */
 int __cpu_logical_map[NR_CPUS];		/* Map logical to physical */
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 29fadac..e83da17 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1277,8 +1277,7 @@
 	u32 *w;
 	unsigned char *b;
 
-	if (!cpu_has_veic && !cpu_has_vint)
-		BUG();
+	BUG_ON(!cpu_has_veic && !cpu_has_vint);
 
 	if (addr == NULL) {
 		handler = (unsigned long) do_default_vi;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 871e828..58d9075 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1026,13 +1026,7 @@
 		c->icache.flags |= MIPS_CACHE_VTAG;
 		break;
 
-	case CPU_AU1000:
-	case CPU_AU1500:
-	case CPU_AU1100:
-	case CPU_AU1550:
-	case CPU_AU1200:
-	case CPU_AU1210:
-	case CPU_AU1250:
+	case CPU_ALCHEMY:
 		c->icache.flags |= MIPS_CACHE_IC_F_DC;
 		break;
 	}
@@ -1244,7 +1238,7 @@
 	/*
 	 * Au1100 errata actually keeps silence about this bit, so we set it
 	 * just in case for those revisions that require it to be set according
-	 * to arch/mips/au1000/common/cputable.c
+	 * to the (now gone) cpu table.
 	 */
 	case 0x02030200: /* Au1100 AB */
 	case 0x02030201: /* Au1100 BA */
@@ -1314,11 +1308,10 @@
 		break;
 	/*
 	 * We need to catch the early Alchemy SOCs with
-	 * the write-only co_config.od bit and set it back to one...
+	 * the write-only co_config.od bit and set it back to one on:
+	 * Au1000 rev DA, HA, HB;  Au1100 AB, BA, BC, Au1500 AB
 	 */
-	case CPU_AU1000: /* rev. DA, HA, HB */
-	case CPU_AU1100: /* rev. AB, BA, BC ?? */
-	case CPU_AU1500: /* rev. AB */
+	case CPU_ALCHEMY:
 		au1x00_fixup_config_od();
 		break;
 
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 8f2cd8e..060d28d 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -17,8 +17,7 @@
 
 void __kunmap(struct page *page)
 {
-	if (in_interrupt())
-		BUG();
+	BUG_ON(in_interrupt());
 	if (!PageHighMem(page))
 		return;
 	kunmap_high(page);
@@ -46,8 +45,7 @@
 	idx = type + KM_TYPE_NR*smp_processor_id();
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
-	if (!pte_none(*(kmap_pte-idx)))
-		BUG();
+	BUG_ON(!pte_none(*(kmap_pte - idx)));
 #endif
 	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
 	local_flush_tlb_one((unsigned long)vaddr);
@@ -66,8 +64,7 @@
 		return;
 	}
 
-	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
-		BUG();
+	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
 
 	/*
 	 * force other mappings to Oops if they'll try to access
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 137c14b..d934894 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -307,8 +307,7 @@
 				if (pmd_none(*pmd)) {
 					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 					set_pmd(pmd, __pmd((unsigned long)pte));
-					if (pte != pte_offset_kernel(pmd, 0))
-						BUG();
+					BUG_ON(pte != pte_offset_kernel(pmd, 0));
 				}
 				vaddr += PMD_SIZE;
 			}
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index 59945b9..0c43248 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -27,8 +27,7 @@
 	end = address + size;
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
-	if (address >= end)
-		BUG();
+	BUG_ON(address >= end);
 	pfn = phys_addr >> PAGE_SHIFT;
 	do {
 		if (!pte_none(*pte)) {
@@ -52,8 +51,7 @@
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	phys_addr -= address;
-	if (address >= end)
-		BUG();
+	BUG_ON(address >= end);
 	do {
 		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
@@ -75,8 +73,7 @@
 	phys_addr -= address;
 	dir = pgd_offset(&init_mm, address);
 	flush_cache_all();
-	if (address >= end)
-		BUG();
+	BUG_ON(address >= end);
 	do {
 		pud_t *pud;
 		pmd_t *pmd;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index f335cf6..0615b62 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -292,13 +292,6 @@
 	case CPU_R4300:
 	case CPU_5KC:
 	case CPU_TX49XX:
-	case CPU_AU1000:
-	case CPU_AU1100:
-	case CPU_AU1500:
-	case CPU_AU1550:
-	case CPU_AU1200:
-	case CPU_AU1210:
-	case CPU_AU1250:
 	case CPU_PR4450:
 		uasm_i_nop(p);
 		tlbw(p);
@@ -321,6 +314,7 @@
 	case CPU_R5500:
 		if (m4kc_tlbp_war())
 			uasm_i_nop(p);
+	case CPU_ALCHEMY:
 		tlbw(p);
 		break;
 
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index 4832af2..475038a 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -48,7 +48,7 @@
 
 int init_debug = 0;
 
-int mips_revision_corid;
+static int mips_revision_corid;
 int mips_revision_sconid;
 
 /* Bonito64 system controller register base. */
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index 7d05e68..04cebad 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -66,7 +66,7 @@
 	printk("Slice %c got %cbe at 0x%lx\n", 'A' + cpu, data ? 'd' : 'i',
 	       regs->cp0_epc);
 	printk("Hub information:\n");
-	printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND));
+	printk("ERR_INT_PEND = 0x%06llx\n", LOCAL_HUB_L(PI_ERR_INT_PEND));
 	errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A);
 	errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A);
 	dump_hub_information(errst0, errst1);
diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c
index 64459e7..a1f21d9 100644
--- a/arch/mips/sgi-ip27/ip27-nmi.c
+++ b/arch/mips/sgi-ip27/ip27-nmi.c
@@ -143,8 +143,8 @@
 	pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0);
 	pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1);
 
-	printk("PI_INT_MASK0: %16lx PI_INT_MASK1: %16lx\n", mask0, mask1);
-	printk("PI_INT_PEND0: %16lx PI_INT_PEND1: %16lx\n", pend0, pend1);
+	printk("PI_INT_MASK0: %16Lx PI_INT_MASK1: %16Lx\n", mask0, mask1);
+	printk("PI_INT_PEND0: %16Lx PI_INT_PEND1: %16Lx\n", pend0, pend1);
 	printk("\n\n");
 }
 
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 0d6b666..0aefc53 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -325,16 +325,11 @@
 {
 	unsigned long mace_int;
 
-	switch (irq) {
-	case MACEISA_PARALLEL_IRQ:
-	case MACEISA_SERIAL1_TDMAPR_IRQ:
-	case MACEISA_SERIAL2_TDMAPR_IRQ:
-		/* edge triggered */
-		mace_int = mace->perif.ctrl.istat;
-		mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ));
-		mace->perif.ctrl.istat = mace_int;
-		break;
-	}
+	/* edge triggered */
+	mace_int = mace->perif.ctrl.istat;
+	mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ));
+	mace->perif.ctrl.istat = mace_int;
+
 	disable_maceisa_irq(irq);
 }
 
@@ -344,7 +339,16 @@
 		enable_maceisa_irq(irq);
 }
 
-static struct irq_chip ip32_maceisa_interrupt = {
+static struct irq_chip ip32_maceisa_level_interrupt = {
+	.name		= "IP32 MACE ISA",
+	.ack		= disable_maceisa_irq,
+	.mask		= disable_maceisa_irq,
+	.mask_ack	= disable_maceisa_irq,
+	.unmask		= enable_maceisa_irq,
+	.end		= end_maceisa_irq,
+};
+
+static struct irq_chip ip32_maceisa_edge_interrupt = {
 	.name		= "IP32 MACE ISA",
 	.ack		= mask_and_ack_maceisa_irq,
 	.mask		= disable_maceisa_irq,
@@ -500,27 +504,50 @@
 	for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) {
 		switch (irq) {
 		case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ:
-			set_irq_chip(irq, &ip32_mace_interrupt);
+			set_irq_chip_and_handler_name(irq,&ip32_mace_interrupt,
+				handle_level_irq, "level");
 			break;
+
 		case MACEPCI_SCSI0_IRQ ...  MACEPCI_SHARED2_IRQ:
-			set_irq_chip(irq, &ip32_macepci_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&ip32_macepci_interrupt, handle_level_irq,
+				"level");
 			break;
+
 		case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ:
-			set_irq_chip(irq, &crime_edge_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&crime_edge_interrupt, handle_edge_irq, "edge");
 			break;
 		case CRIME_CPUERR_IRQ:
 		case CRIME_MEMERR_IRQ:
-			set_irq_chip(irq, &crime_level_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&crime_level_interrupt, handle_level_irq,
+				"level");
 			break;
+
 		case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ:
 		case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ:
-			set_irq_chip(irq, &crime_edge_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&crime_edge_interrupt, handle_edge_irq, "edge");
 			break;
+
 		case CRIME_VICE_IRQ:
-			set_irq_chip(irq, &crime_edge_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&crime_edge_interrupt, handle_edge_irq, "edge");
 			break;
+
+		case MACEISA_PARALLEL_IRQ:
+		case MACEISA_SERIAL1_TDMAPR_IRQ:
+		case MACEISA_SERIAL2_TDMAPR_IRQ:
+			set_irq_chip_and_handler_name(irq,
+				&ip32_maceisa_edge_interrupt, handle_edge_irq,
+				"edge");
+			break;
+
 		default:
-			set_irq_chip(irq, &ip32_maceisa_interrupt);
+			set_irq_chip_and_handler_name(irq,
+				&ip32_maceisa_level_interrupt, handle_level_irq,
+				"level");
 			break;
 		}
 	}
diff --git a/arch/mips/sgi-ip32/ip32-memory.c b/arch/mips/sgi-ip32/ip32-memory.c
index ca93ecf..828ce13 100644
--- a/arch/mips/sgi-ip32/ip32-memory.c
+++ b/arch/mips/sgi-ip32/ip32-memory.c
@@ -36,7 +36,7 @@
 		if (base + size > (256 << 20))
 			base += CRIME_HI_MEM_BASE;
 
-		printk("CRIME MC: bank %u base 0x%016lx size %luMiB\n",
+		printk("CRIME MC: bank %u base 0x%016Lx size %LuMiB\n",
 			bank, base, size >> 20);
 		add_memory_region(base, size, BOOT_MEM_RAM);
 	}
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 12b465d..352352b 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -236,7 +236,7 @@
 	int i;
 
 	for (i = 0; i < BCM1480_NR_IRQS; i++) {
-		set_irq_chip(i, &bcm1480_irq_type);
+		set_irq_chip_and_handler(i, &bcm1480_irq_type, handle_level_irq);
 		bcm1480_irq_owner[i] = 0;
 	}
 }
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 808ac29..c08ff58 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -220,7 +220,7 @@
 	int i;
 
 	for (i = 0; i < SB1250_NR_IRQS; i++) {
-		set_irq_chip(i, &sb1250_irq_type);
+		set_irq_chip_and_handler(i, &sb1250_irq_type, handle_level_irq);
 		sb1250_irq_owner[i] = 0;
 	}
 }
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 3f8cf5e..7dd76fb 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -219,7 +219,7 @@
 	int i;
 
 	for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
-		set_irq_chip(i, &a20r_irq_type);
+		set_irq_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
 	sni_hwint = a20r_hwint;
 	change_c0_status(ST0_IM, IE_IRQ0);
 	setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 834650f..74e6c67 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -304,7 +304,7 @@
 	mips_cpu_irq_init();
 	/* Actually we've got more interrupts to handle ...  */
 	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
-		set_irq_chip(i, &pcimt_irq_type);
+		set_irq_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
 	sni_hwint = sni_pcimt_hwint;
 	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
 }
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index e5f12cf..071a957 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -246,7 +246,7 @@
 
 	mips_cpu_irq_init();
 	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-		set_irq_chip(i, &pcit_irq_type);
+		set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 	*(volatile u32 *)SNI_PCIT_INT_REG = 0;
 	sni_hwint = sni_pcit_hwint;
 	change_c0_status(ST0_IM, IE_IRQ1);
@@ -259,7 +259,7 @@
 
 	mips_cpu_irq_init();
 	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-		set_irq_chip(i, &pcit_irq_type);
+		set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 	*(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
 	sni_hwint = sni_pcit_hwint_cplus;
 	change_c0_status(ST0_IM, IE_IRQ0);
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 5310aa7..b4352a0 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -487,7 +487,7 @@
 	mips_cpu_irq_init();
 	/* Actually we've got more interrupts to handle ...  */
 	for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
-		set_irq_chip(i, &rm200_irq_type);
+		set_irq_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
 	sni_hwint = sni_rm200_hwint;
 	change_c0_status(ST0_IM, IE_IRQ0);
 	setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq);
diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig
index 226e8bb..0db7cf3 100644
--- a/arch/mips/txx9/Kconfig
+++ b/arch/mips/txx9/Kconfig
@@ -20,7 +20,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config TOSHIBA_JMR3927
 	bool "Toshiba JMR-TX3927 board"
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 74cc312..ad6b1c0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -111,6 +111,7 @@
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select HAVE_IDE
 	select HAVE_IOREMAP_PROT
@@ -312,7 +313,7 @@
 
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
-	depends on (PPC_PRPMC2800 || PPC_MULTIPLATFORM) && EXPERIMENTAL
+	depends on BOOK3S && EXPERIMENTAL
 	help
 	  kexec is a system call that implements the ability to shutdown your
 	  current kernel, and to start another kernel.  It is like a reboot
@@ -409,6 +410,18 @@
 	depends on PPC64
 	default n
 
+config STDBINUTILS
+	bool "Using standard binutils settings"
+	depends on 44x
+	default y
+	help
+	  Turning this option off allows you to select 256KB PAGE_SIZE on 44x.
+	  Note, that kernel will be able to run only those applications,
+	  which had been compiled using binutils later than 2.17.50.0.3 with
+	  '-zmax-page-size' set to 256K (the default is 64K). Or, if using
+	  the older binutils, you can patch them with a trivial patch, which
+	  changes the ELF_MAXPAGESIZE definition from 0x10000 to 0x40000.
+
 choice
 	prompt "Page size"
 	default PPC_4K_PAGES
@@ -444,6 +457,19 @@
 	bool "64k page size" if 44x || PPC_STD_MMU_64
 	select PPC_HAS_HASH_64K if PPC_STD_MMU_64
 
+config PPC_256K_PAGES
+	bool "256k page size" if 44x
+	depends on !STDBINUTILS && (!SHMEM || BROKEN)
+	help
+	  Make the page size 256k.
+
+	  As the ELF standard only requires alignment to support page
+	  sizes up to 64k, you will need to compile all of your user
+	  space applications with a non-standard binutils settings
+	  (see the STDBINUTILS description for details).
+
+	  Say N unless you know what you are doing.
+
 endchoice
 
 config FORCE_MAX_ZONEORDER
@@ -456,6 +482,8 @@
 	default "9" if PPC_STD_MMU_32 && PPC_16K_PAGES
 	range 7 64 if PPC_STD_MMU_32 && PPC_64K_PAGES
 	default "7" if PPC_STD_MMU_32 && PPC_64K_PAGES
+	range 5 64 if PPC_STD_MMU_32 && PPC_256K_PAGES
+	default "5" if PPC_STD_MMU_32 && PPC_256K_PAGES
 	range 11 64
 	default "11"
 	help
@@ -594,6 +622,7 @@
 config FSL_PCI
  	bool
 	select PPC_INDIRECT_PCI
+	select PCI_QUIRKS
 
 config 4xx_SOC
 	bool
@@ -730,6 +759,22 @@
 	hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
 	default "0x30000000"
 
+config LOWMEM_CAM_NUM_BOOL
+	bool "Set number of CAMs to use to map low memory"
+	depends on ADVANCED_OPTIONS && FSL_BOOKE
+	help
+	  This option allows you to set the maximum number of CAM slots that
+	  will be used to map low memory.  There are a limited number of slots
+	  available and even more limited number that will fit in the L1 MMU.
+	  However, using more entries will allow mapping more low memory.  This
+	  can be useful in optimizing the layout of kernel virtual memory.
+
+	  Say N here unless you know what you are doing.
+
+config LOWMEM_CAM_NUM
+	int "Number of CAMs to use to map low memory" if LOWMEM_CAM_NUM_BOOL
+	default 3
+
 config RELOCATABLE
 	bool "Build a relocatable kernel (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
@@ -794,7 +839,7 @@
 
 config PHYSICAL_ALIGN
 	hex
-	default "0x10000000" if FSL_BOOKE
+	default "0x04000000" if FSL_BOOKE
 	help
 	  This value puts the alignment restrictions on physical address
 	  where kernel is loaded and run from. Kernel is compiled for an
@@ -815,31 +860,6 @@
 	default "0x80000000" if PPC_PREP || PPC_8xx
 	default "0xc0000000"
 
-config CONSISTENT_START_BOOL
-	bool "Set custom consistent memory pool address"
-	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
-	help
-	  This option allows you to set the base virtual address
-	  of the consistent memory pool.  This pool of virtual
-	  memory is used to make consistent memory allocations.
-
-config CONSISTENT_START
-	hex "Base virtual address of consistent memory pool" if CONSISTENT_START_BOOL
-	default "0xfd000000" if (NOT_COHERENT_CACHE && 8xx)
-	default "0xff100000" if NOT_COHERENT_CACHE
-
-config CONSISTENT_SIZE_BOOL
-	bool "Set custom consistent memory pool size"
-	depends on ADVANCED_OPTIONS && NOT_COHERENT_CACHE
-	help
-	  This option allows you to set the size of the
-	  consistent memory pool.  This pool of virtual memory
-	  is used to make consistent memory allocations.
-
-config CONSISTENT_SIZE
-	hex "Size of consistent memory pool" if CONSISTENT_SIZE_BOOL
-	default "0x00200000" if NOT_COHERENT_CACHE
-
 config PIN_TLB
 	bool "Pinned Kernel TLBs (860 ONLY)"
 	depends on ADVANCED_OPTIONS && 8xx
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 08f7cc0..22091bb 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -129,7 +129,7 @@
 
 config BOOTX_TEXT
 	bool "Support for early boot text console (BootX or OpenFirmware only)"
-	depends on PPC_OF && PPC_MULTIPLATFORM
+	depends on PPC_OF && PPC_BOOK3S
 	help
 	  Say Y here to see progress messages from the boot firmware in text
 	  mode. Requires either BootX or Open Firmware.
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 72d17f5..551fc58 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -147,8 +147,8 @@
 				   arch/powerpc/mm/ \
 				   arch/powerpc/lib/ \
 				   arch/powerpc/sysdev/ \
-				   arch/powerpc/platforms/
-core-$(CONFIG_MATH_EMULATION)	+= arch/powerpc/math-emu/
+				   arch/powerpc/platforms/ \
+				   arch/powerpc/math-emu/
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
 core-$(CONFIG_KVM) 		+= arch/powerpc/kvm/
 
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index e84df33..4458abb 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -70,7 +70,7 @@
 		cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
 		cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
 		virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
-		cuboot-acadia.c
+		cuboot-acadia.c cuboot-amigaone.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -235,7 +235,9 @@
 					   dtbImage.adder875-redboot
 
 # Board ports in arch/powerpc/platform/52xx/Kconfig
-image-$(CONFIG_PPC_LITE5200)		+= cuImage.lite5200 cuImage.lite5200b
+image-$(CONFIG_PPC_LITE5200)		+= cuImage.lite5200 lite5200.dtb
+image-$(CONFIG_PPC_LITE5200)		+= cuImage.lite5200b lite5200b.dtb
+image-$(CONFIG_PPC_MEDIA5200)		+= cuImage.media5200 media5200.dtb
 
 # Board ports in arch/powerpc/platform/82xx/Kconfig
 image-$(CONFIG_MPC8272_ADS)		+= cuImage.mpc8272ads
@@ -274,6 +276,9 @@
 image-$(CONFIG_MPC7448HPC2)		+= cuImage.mpc7448hpc2
 image-$(CONFIG_PPC_C2K)			+= cuImage.c2k
 
+# Board port in arch/powerpc/platform/amigaone/Kconfig
+image-$(CONFIG_AMIGAONE)		+= cuImage.amigaone
+
 # For 32-bit powermacs, build the COFF and miboot images
 # as well as the ELF images.
 ifeq ($(CONFIG_PPC32),y)
diff --git a/arch/powerpc/boot/cuboot-amigaone.c b/arch/powerpc/boot/cuboot-amigaone.c
new file mode 100644
index 0000000..d502967
--- /dev/null
+++ b/arch/powerpc/boot/cuboot-amigaone.c
@@ -0,0 +1,35 @@
+/*
+ * Old U-boot compatibility for AmigaOne
+ *
+ * Author: Gerhard Pircher (gerhard_pircher@gmx.net)
+ *
+ *   Based on cuboot-83xx.c
+ * Copyright (c) 2007 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 "ops.h"
+#include "stdio.h"
+#include "cuboot.h"
+
+#include "ppcboot.h"
+
+static bd_t bd;
+
+static void platform_fixups(void)
+{
+	dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
+	dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);
+}
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                   unsigned long r6, unsigned long r7)
+{
+	CUBOOT_INIT();
+	fdt_init(_dtb_start);
+	serial_console_init();
+	platform_ops.fixups = platform_fixups;
+}
diff --git a/arch/powerpc/boot/dts/amigaone.dts b/arch/powerpc/boot/dts/amigaone.dts
new file mode 100644
index 0000000..26549fc
--- /dev/null
+++ b/arch/powerpc/boot/dts/amigaone.dts
@@ -0,0 +1,173 @@
+/*
+ * AmigaOne Device Tree Source
+ *
+ * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net)
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/;
+
+/ {
+	model = "AmigaOne";
+	compatible = "eyetech,amigaone";
+	coherency-off;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// 33.3 MHz, from U-boot
+			clock-frequency = <0>;		// From U-boot
+			bus-frequency = <0>;		// From U-boot
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0>;				// From U-boot
+	};
+
+	pci@80000000 {
+		device_type = "pci";
+		compatible = "mai-logic,articia-s";
+		bus-frequency = <33333333>;
+		bus-range = <0 0xff>;
+		ranges = <0x01000000 0 0x00000000 0xfe000000 0 0x00c00000	// PCI I/O
+		          0x02000000 0 0x80000000 0x80000000 0 0x7d000000	// PCI memory
+		          0x02000000 0 0x00000000 0xfd000000 0 0x01000000>;	// PCI alias memory (ISA)
+		// Configuration address and data register.
+		reg = <0xfec00cf8 4
+		       0xfee00cfc 4>;
+		8259-interrupt-acknowledge = <0xfef00000>;
+		// Do not define a interrupt-parent here, if there is no
+		// interrupt-map property.
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		isa@7 {
+			device_type = "isa";
+			compatible = "pciclass,0601";
+			vendor-id = <0x00001106>;
+			device-id = <0x00000686>;
+			revision-id = <0x00000010>;
+			class-code = <0x00060100>;
+			subsystem-id = <0>;
+			subsystem-vendor-id = <0>;
+			devsel-speed = <0x00000001>;
+			min-grant = <0>;
+			max-latency = <0>;
+			/* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */
+			ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00010000>;
+			interrupt-parent = <&i8259>;
+			#interrupt-cells = <2>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+
+			dma-controller@0 {
+				compatible = "pnpPNP,200";
+				reg = <1 0x00000000 0x00000020
+				       1 0x00000080 0x00000010
+				       1 0x000000c0 0x00000020>;
+			};
+
+			i8259: interrupt-controller@20 {
+				device_type = "interrupt-controller";
+				compatible = "pnpPNP,000";
+				interrupt-controller;
+				reg = <1 0x00000020 0x00000002
+				       1 0x000000a0 0x00000002
+				       1 0x000004d0 0x00000002>;
+				reserved-interrupts = <2>;
+				#interrupt-cells = <2>;
+			};
+
+			timer@40 {
+				// Also adds pcspkr to platform devices.
+				compatible = "pnpPNP,100";
+				reg = <1 0x00000040 0x00000020>;
+			};
+
+			8042@60 {
+				device_type = "8042";
+				reg = <1 0x00000060 0x00000001
+				       1 0x00000064 0x00000001>;
+				interrupts = <1 3 12 3>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				keyboard@0 {
+					compatible = "pnpPNP,303";
+					reg = <0>;
+				};
+
+				mouse@1 {
+					compatible = "pnpPNP,f03";
+					reg = <1>;
+				};
+			};
+
+			rtc@70 {
+				compatible = "pnpPNP,b00";
+				reg = <1 0x00000070 0x00000002>;
+				interrupts = <8 3>;
+			};
+
+			serial@3f8 {
+				device_type = "serial";
+				compatible = "pnpPNP,501","pnpPNP,500";
+				reg = <1 0x000003f8 0x00000008>;
+				interrupts = <4 3>;
+				clock-frequency = <1843200>;
+				current-speed = <115200>;
+			};
+
+			serial@2f8 {
+				device_type = "serial";
+				compatible = "pnpPNP,501","pnpPNP,500";
+				reg = <1 0x000002f8 0x00000008>;
+				interrupts = <3 3>;
+				clock-frequency = <1843200>;
+				current-speed = <115200>;
+			};
+
+			parallel@378 {
+				device_type = "parallel";
+				// No ECP support for now, otherwise add "pnpPNP,401".
+				compatible = "pnpPNP,400";
+				reg = <1 0x00000378 0x00000003
+				       1 0x00000778 0x00000003>;
+			};
+
+			fdc@3f0 {
+				device_type = "fdc";
+				compatible = "pnpPNP,700";
+				reg = <1 0x000003f0 0x00000008>;
+				interrupts = <6 3>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				disk@0 {
+					reg = <0>;
+				};
+			};
+		};
+	};
+
+	chosen {
+		linux,stdout-path = "/pci@80000000/isa@7/serial@3f8";
+	};
+};
diff --git a/arch/powerpc/boot/dts/asp834x-redboot.dts b/arch/powerpc/boot/dts/asp834x-redboot.dts
index 524af7e..7da84fd 100644
--- a/arch/powerpc/boot/dts/asp834x-redboot.dts
+++ b/arch/powerpc/boot/dts/asp834x-redboot.dts
@@ -181,70 +181,76 @@
 			phy_type = "ulpi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 08 e5 11 32 33 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			linux,network-index = <0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 08 e5 11 32 34 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			linux,network-index = <1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 4447def..5fd1ad0 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -149,6 +149,20 @@
 					/*RXDE*/  0x5 0x4>;
 		};
 
+                USB0: ehci@bffd0400 {
+                        compatible = "ibm,usb-ehci-460ex", "usb-ehci";
+                        interrupt-parent = <&UIC2>;
+                        interrupts = <0x1d 4>;
+                        reg = <4 0xbffd0400 0x90 4 0xbffd0490 0x70>;
+                };
+
+                USB1: usb@bffd0000 {
+                        compatible = "ohci-le";
+                        reg = <4 0xbffd0000 0x60>;
+                        interrupt-parent = <&UIC2>;
+                        interrupts = <0x1e 4>;
+                };
+
 		POB0: opb {
 			compatible = "ibm,opb-460ex", "ibm,opb";
 			#address-cells = <1>;
@@ -252,6 +266,20 @@
 				reg = <0xef600700 0x00000014>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <0x2 0x4>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+                                rtc@68 {
+                                        compatible = "stm,m41t80";
+                                        reg = <0x68>;
+					interrupt-parent = <&UIC2>;
+					interrupts = <0x19 0x8>;
+                                };
+                                sttm@48 {
+                                        compatible = "ad,ad7414";
+                                        reg = <0x48>;
+					interrupt-parent = <&UIC1>;
+					interrupts = <0x14 0x8>;
+                                };
 			};
 
 			IIC1: i2c@ef600800 {
diff --git a/arch/powerpc/boot/dts/cm5200.dts b/arch/powerpc/boot/dts/cm5200.dts
index 2f74cc4..cee8080 100644
--- a/arch/powerpc/boot/dts/cm5200.dts
+++ b/arch/powerpc/boot/dts/cm5200.dts
@@ -17,6 +17,7 @@
 	compatible = "schindler,cm5200";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -66,7 +67,6 @@
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x600 0x10>;
 			interrupts = <1 9 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl,has-wdt;
 		};
 
@@ -74,84 +74,76 @@
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x610 0x10>;
 			interrupts = <1 10 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@620 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x620 0x10>;
 			interrupts = <1 11 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@630 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x630 0x10>;
 			interrupts = <1 12 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@640 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x640 0x10>;
 			interrupts = <1 13 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@650 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x650 0x10>;
 			interrupts = <1 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@660 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x660 0x10>;
 			interrupts = <1 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@670 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x670 0x10>;
 			interrupts = <1 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
 			reg = <0x800 0x100>;
 			interrupts = <1 5 0 1 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
-		gpio@b00 {
+		gpio_simple: gpio@b00 {
 			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
 			interrupts = <1 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
-		gpio@c00 {
+		gpio_wkup: gpio@c00 {
 			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
 			reg = <0xc00 0x40>;
 			interrupts = <1 8 0 0 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		spi@f00 {
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
 			interrupts = <2 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		dma-controller@1200 {
@@ -161,7 +153,6 @@
 			              3 4 0  3 5 0  3 6 0  3 7 0
 			              3 8 0  3 9 0  3 10 0  3 11 0
 			              3 12 0  3 13 0  3 14 0  3 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		xlb@1f00 {
@@ -170,48 +161,34 @@
 		};
 
 		serial@2000 {		// PSC1
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <0>;  // Logical port assignment
 			reg = <0x2000 0x100>;
 			interrupts = <2 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		serial@2200 {		// PSC2
-			device_type = "serial";
-			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <1>;  // Logical port assignment
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 			reg = <0x2200 0x100>;
 			interrupts = <2 2 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		serial@2400 {		// PSC3
-			device_type = "serial";
-			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <2>;  // Logical port assignment
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 			reg = <0x2400 0x100>;
 			interrupts = <2 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		serial@2c00 {		// PSC6
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <5>;  // Logical port assignment
 			reg = <0x2c00 0x100>;
 			interrupts = <2 4 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <2 5 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			phy-handle = <&phy0>;
 		};
 
@@ -221,10 +198,8 @@
 			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
 			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
 			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
-			interrupt-parent = <&mpc5200_pic>;
 
 			phy0: ethernet-phy@0 {
-				device_type = "ethernet-phy";
 				reg = <0>;
 			};
 		};
@@ -235,7 +210,6 @@
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
 			reg = <0x3d40 0x40>;
 			interrupts = <2 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 		};
 
@@ -245,9 +219,8 @@
 		};
 	};
 
-	lpb {
-		model = "fsl,lpb";
-		compatible = "fsl,lpb";
+	localbus {
+		compatible = "fsl,mpc5200b-lpb","simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <0 0 0xfc000000 0x2000000>;
diff --git a/arch/powerpc/boot/dts/digsy_mtc.dts b/arch/powerpc/boot/dts/digsy_mtc.dts
new file mode 100644
index 0000000..4c36186
--- /dev/null
+++ b/arch/powerpc/boot/dts/digsy_mtc.dts
@@ -0,0 +1,254 @@
+/*
+ * Digsy MTC board Device Tree Source
+ *
+ * Copyright (C) 2009 Semihalf
+ *
+ * Based on the CM5200 by M. Balakowicz
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/;
+
+/ {
+	model = "intercontrol,digsy-mtc";
+	compatible = "intercontrol,digsy-mtc";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;		// L1, 16K
+			i-cache-size = <0x4000>;		// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x02000000>;	// 32MB
+	};
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200b-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		timer@610 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x610 0x10>;
+			interrupts = <1 10 0>;
+		};
+
+		timer@620 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x620 0x10>;
+			interrupts = <1 11 0>;
+		};
+
+		timer@630 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x630 0x10>;
+			interrupts = <1 12 0>;
+		};
+
+		timer@640 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x640 0x10>;
+			interrupts = <1 13 0>;
+		};
+
+		timer@650 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x650 0x10>;
+			interrupts = <1 14 0>;
+		};
+
+		timer@660 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x660 0x10>;
+			interrupts = <1 15 0>;
+		};
+
+		timer@670 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x670 0x10>;
+			interrupts = <1 16 0>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpio_wkup: gpio@c00 {
+			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+			reg = <0xc00 0x40>;
+			interrupts = <1 8 0 0 3 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		spi@f00 {
+			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+			reg = <0xf00 0x20>;
+			interrupts = <2 13 0 2 14 0>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		serial@2600 {		// PSC4
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			reg = <0x2600 0x100>;
+			interrupts = <2 11 0>;
+		};
+
+		serial@2800 {		// PSC5
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			reg = <0x2800 0x100>;
+			interrupts = <2 12 0>;
+		};
+
+		ethernet@3000 {
+			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			phy-handle = <&phy0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+
+			phy0: ethernet-phy@0 {
+				reg = <0>;
+			};
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+			fsl5200-clocking;
+
+			rtc@50 {
+				compatible = "at,24c08";
+				reg = <0x50>;
+			};
+
+			rtc@68 {
+				compatible = "dallas,ds1339";
+				reg = <0x68>;
+			};
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	lpb {
+		compatible = "fsl,mpc5200b-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0xff000000 0x1000000>;
+
+		// 16-bit flash device at LocalPlus Bus CS0
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x1000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@0 {
+				label = "kernel";
+				reg = <0x0 0x00200000>;
+			};
+			partition@200000 {
+				label = "root";
+				reg = <0x00200000 0x00300000>;
+			};
+			partition@500000 {
+				label = "user";
+				reg = <0x00500000 0x00a00000>;
+			};
+			partition@f00000 {
+				label = "u-boot";
+				reg = <0x00f00000 0x100000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts
new file mode 100644
index 0000000..d47ad07
--- /dev/null
+++ b/arch/powerpc/boot/dts/gef_ppc9a.dts
@@ -0,0 +1,367 @@
+/*
+ * GE Fanuc PPC9A Device Tree Source
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_ppc9a.dtb gef_ppc9a.dts
+ */
+
+/dts-v1/;
+
+/ {
+	model = "GEF_PPC9A";
+	compatible = "gef,ppc9a";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8641@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// From uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+		PowerPC,8641@1 {
+			device_type = "cpu";
+			reg = <1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// From uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;	// set by uboot
+	};
+
+	localbus@fef05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8641-localbus", "simple-bus";
+		reg = <0xfef05000 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0 0 0xff000000 0x01000000	// 16MB Boot flash
+			  1 0 0xe8000000 0x08000000	// Paged Flash 0
+			  2 0 0xe0000000 0x08000000	// Paged Flash 1
+			  3 0 0xfc100000 0x00020000	// NVRAM
+			  4 0 0xfc000000 0x00008000	// FPGA
+			  5 0 0xfc008000 0x00008000	// AFIX FPGA
+			  6 0 0xfd000000 0x00800000	// IO FPGA (8-bit)
+			  7 0 0xfd800000 0x00800000>;	// IO FPGA (32-bit)
+
+		/* flash@0,0 is a mirror of part of the memory in flash@1,0
+		flash@0,0 {
+			compatible = "gef,ppc9a-firmware-mirror", "cfi-flash";
+			reg = <0x0 0x0 0x1000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "firmware";
+				reg = <0x0 0x1000000>;
+				read-only;
+			};
+		};
+		*/
+
+		flash@1,0 {
+			compatible = "gef,ppc9a-paged-flash", "cfi-flash";
+			reg = <0x1 0x0 0x8000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "user";
+				reg = <0x0 0x7800000>;
+			};
+			partition@7800000 {
+				label = "firmware";
+				reg = <0x7800000 0x800000>;
+				read-only;
+			};
+		};
+
+		fpga@4,0 {
+			compatible = "gef,ppc9a-fpga-regs";
+			reg = <0x4 0x0 0x40>;
+		};
+
+		wdt@4,2000 {
+			compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
+				"gef,fpga-wdt";
+			reg = <0x4 0x2000 0x8>;
+			interrupts = <0x1a 0x4>;
+			interrupt-parent = <&gef_pic>;
+		};
+		/* Second watchdog available, driver currently supports one.
+		wdt@4,2010 {
+			compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
+				"gef,fpga-wdt";
+			reg = <0x4 0x2010 0x8>;
+			interrupts = <0x1b 0x4>;
+			interrupt-parent = <&gef_pic>;
+		};
+		*/
+		gef_pic: pic@4,4000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "gef,ppc9a-fpga-pic", "gef,fpga-pic-1.00";
+			reg = <0x4 0x4000 0x20>;
+			interrupts = <0x8
+				      0x9>;
+			interrupt-parent = <&mpic>;
+
+		};
+		gef_gpio: gpio@7,14000 {
+			#gpio-cells = <2>;
+			compatible = "gef,ppc9a-gpio", "gef,sbc610-gpio";
+			reg = <0x7 0x14000 0x24>;
+			gpio-controller;
+		};
+	};
+
+	soc@fef00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		compatible = "fsl,mpc8641-soc", "simple-bus";
+		ranges = <0x0 0xfef00000 0x00100000>;
+		reg = <0xfef00000 0x100000>;	// CCSRBAR 1M
+		bus-frequency = <33333333>;
+
+		i2c1: i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <0x2b 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			hwmon@48 {
+				compatible = "national,lm92";
+				reg = <0x48>;
+			};
+
+			hwmon@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			rtc@51 {
+				compatible = "epson,rx8581";
+				reg = <0x00000051>;
+			};
+
+			eti@6b {
+				compatible = "dallas,ds1682";
+				reg = <0x6b>;
+			};
+		};
+
+		i2c2: i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <0x2b 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x9 0x4>;
+					reg = <1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x8 0x4>;
+					reg = <3>;
+				};
+			};
+		};
+
+		enet1: ethernet@26000 {
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "gmii";
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <0x2a 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <0x1c 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		global-utilities@e0000 {
+			compatible = "fsl,mpc8641-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	pci0: pcie@fef08000 {
+		compatible = "fsl,mpc8641-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xfef08000 0x1000>;
+		bus-range = <0x0 0xff>;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+			  0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <0x18 0x2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
+		>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0x0 0x80000000
+				  0x02000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x01000000 0x0 0x00000000
+				  0x01000000 0x0 0x00000000
+				  0x0 0x00400000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts
new file mode 100644
index 0000000..1569117
--- /dev/null
+++ b/arch/powerpc/boot/dts/gef_sbc310.dts
@@ -0,0 +1,367 @@
+/*
+ * GE Fanuc SBC310 Device Tree Source
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_sbc310.dtb gef_sbc310.dts
+ */
+
+/dts-v1/;
+
+/ {
+	model = "GEF_SBC310";
+	compatible = "gef,sbc310";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8641@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// From uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+		PowerPC,8641@1 {
+			device_type = "cpu";
+			reg = <1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <32768>;		// L1, 32K
+			i-cache-size = <32768>;		// L1, 32K
+			timebase-frequency = <0>;	// From uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;	// set by uboot
+	};
+
+	localbus@fef05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8641-localbus", "simple-bus";
+		reg = <0xfef05000 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0 0 0xff000000 0x01000000	// 16MB Boot flash
+			  1 0 0xe0000000 0x08000000	// Paged Flash 0
+			  2 0 0xe8000000 0x08000000	// Paged Flash 1
+			  3 0 0xfc100000 0x00020000	// NVRAM
+			  4 0 0xfc000000 0x00010000>;	// FPGA
+
+		/* flash@0,0 is a mirror of part of the memory in flash@1,0
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x01000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "firmware";
+				reg = <0x00000000 0x01000000>;
+				read-only;
+			};
+		};
+		*/
+
+		flash@1,0 {
+			compatible = "cfi-flash";
+			reg = <1 0 0x8000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "user";
+				reg = <0x00000000 0x07800000>;
+			};
+			partition@7800000 {
+				label = "firmware";
+				reg = <0x07800000 0x00800000>;
+				read-only;
+			};
+		};
+
+		fpga@4,0 {
+			compatible = "gef,fpga-regs";
+			reg = <0x4 0x0 0x40>;
+		};
+
+		wdt@4,2000 {
+			#interrupt-cells = <2>;
+			device_type = "watchdog";
+			compatible = "gef,fpga-wdt";
+			reg = <0x4 0x2000 0x8>;
+			interrupts = <0x1a 0x4>;
+			interrupt-parent = <&gef_pic>;
+		};
+/*
+		wdt@4,2010 {
+			#interrupt-cells = <2>;
+			device_type = "watchdog";
+			compatible = "gef,fpga-wdt";
+			reg = <0x4 0x2010 0x8>;
+			interrupts = <0x1b 0x4>;
+			interrupt-parent = <&gef_pic>;
+		};
+*/
+		gef_pic: pic@4,4000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "gef,fpga-pic";
+			reg = <0x4 0x4000 0x20>;
+			interrupts = <0x8
+				      0x9>;
+			interrupt-parent = <&mpic>;
+
+		};
+		gef_gpio: gpio@4,8000 {
+			#gpio-cells = <2>;
+			compatible = "gef,sbc310-gpio";
+			reg = <0x4 0x8000 0x24>;
+			gpio-controller;
+		};
+	};
+
+	soc@fef00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x0 0xfef00000 0x00100000>;
+		reg = <0xfef00000 0x100000>;	// CCSRBAR 1M
+		bus-frequency = <33333333>;
+
+		i2c1: i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <0x2b 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			rtc@51 {
+				compatible = "epson,rx8581";
+				reg = <0x00000051>;
+			};
+		};
+
+		i2c2: i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <0x2b 0x2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			hwmon@48 {
+				compatible = "national,lm92";
+				reg = <0x48>;
+			};
+
+			hwmon@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+
+			eti@6b {
+				compatible = "dallas,ds1682";
+				reg = <0x6b>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8641-dma-channel",
+					   "fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x9 0x4>;
+					reg = <1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x8 0x4>;
+					reg = <3>;
+				};
+			};
+		};
+
+		enet1: ethernet@26000 {
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "gmii";
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <0x2a 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <0x1c 0x2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		mpic: pic@40000 {
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		global-utilities@e0000 {
+			compatible = "fsl,mpc8641-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+	};
+
+	pci0: pcie@fef08000 {
+		compatible = "fsl,mpc8641-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xfef08000 0x1000>;
+		bus-range = <0x0 0xff>;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+			  0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <0x18 0x2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0000 0x0 0x0 0x1 &mpic 0x0 0x2
+			0x0000 0x0 0x0 0x2 &mpic 0x1 0x2
+			0x0000 0x0 0x0 0x3 &mpic 0x2 0x2
+			0x0000 0x0 0x0 0x4 &mpic 0x3 0x2
+		>;
+
+		pcie@0 {
+			reg = <0 0 0 0 0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x02000000 0x0 0x80000000
+				  0x02000000 0x0 0x80000000
+				  0x0 0x40000000
+
+				  0x01000000 0x0 0x00000000
+				  0x01000000 0x0 0x00000000
+				  0x0 0x00400000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
index e78c355..6582dbd 100644
--- a/arch/powerpc/boot/dts/gef_sbc610.dts
+++ b/arch/powerpc/boot/dts/gef_sbc610.dts
@@ -71,7 +71,7 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc8641-localbus", "simple-bus";
-		reg = <0xf8005000 0x1000>;
+		reg = <0xfef05000 0x1000>;
 		interrupts = <19 2>;
 		interrupt-parent = <&mpic>;
 
@@ -202,34 +202,37 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&gef_pic>;
-				interrupts = <0x9 0x4>;
-				reg = <1>;
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&gef_pic>;
-				interrupts = <0x8 0x4>;
-				reg = <3>;
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "gmii";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x9 0x4>;
+					reg = <1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&gef_pic>;
+					interrupts = <0x8 0x4>;
+					reg = <3>;
+				};
+			};
 		};
 
 		enet1: ethernet@26000 {
diff --git a/arch/powerpc/boot/dts/ksi8560.dts b/arch/powerpc/boot/dts/ksi8560.dts
index 3bfff47..308fe7c 100644
--- a/arch/powerpc/boot/dts/ksi8560.dts
+++ b/arch/powerpc/boot/dts/ksi8560.dts
@@ -124,67 +124,72 @@
 			};
 		};
 
-		mdio@24520 {					/* For TSECs */
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			PHY1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-
-			PHY2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			/* Mac address filled in by bootwrapper */
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&PHY1>;
+
+			mdio@520 {					/* For TSECs */
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				PHY1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+
+				PHY2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			/* Mac address filled in by bootwrapper */
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&PHY2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		mpic: pic@40000 {
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 3f7a5dc..de30b3f 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -17,6 +17,7 @@
 	compatible = "fsl,lite5200";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -58,96 +59,74 @@
 			// 5200 interrupts are encoded into two levels;
 			interrupt-controller;
 			#interrupt-cells = <3>;
-			device_type = "interrupt-controller";
 			compatible = "fsl,mpc5200-pic";
 			reg = <0x500 0x80>;
 		};
 
 		timer@600 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <0>;
 			reg = <0x600 0x10>;
 			interrupts = <1 9 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl,has-wdt;
 		};
 
 		timer@610 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <1>;
 			reg = <0x610 0x10>;
 			interrupts = <1 10 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@620 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <2>;
 			reg = <0x620 0x10>;
 			interrupts = <1 11 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@630 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <3>;
 			reg = <0x630 0x10>;
 			interrupts = <1 12 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@640 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <4>;
 			reg = <0x640 0x10>;
 			interrupts = <1 13 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@650 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <5>;
 			reg = <0x650 0x10>;
 			interrupts = <1 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@660 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <6>;
 			reg = <0x660 0x10>;
 			interrupts = <1 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@670 {	// General Purpose Timer
 			compatible = "fsl,mpc5200-gpt";
-			cell-index = <7>;
 			reg = <0x670 0x10>;
 			interrupts = <1 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200-rtc";
 			reg = <0x800 0x100>;
 			interrupts = <1 5 0 1 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		can@900 {
 			compatible = "fsl,mpc5200-mscan";
-			cell-index = <0>;
 			interrupts = <2 17 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x900 0x80>;
 		};
 
 		can@980 {
 			compatible = "fsl,mpc5200-mscan";
-			cell-index = <1>;
 			interrupts = <2 18 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x980 0x80>;
 		};
 
@@ -155,39 +134,33 @@
 			compatible = "fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
 			interrupts = <1 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		gpio@c00 {
 			compatible = "fsl,mpc5200-gpio-wkup";
 			reg = <0xc00 0x40>;
 			interrupts = <1 8 0 0 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		spi@f00 {
 			compatible = "fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
 			interrupts = <2 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		dma-controller@1200 {
-			device_type = "dma-controller";
 			compatible = "fsl,mpc5200-bestcomm";
 			reg = <0x1200 0x80>;
 			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
 			              3 4 0  3 5 0  3 6 0  3 7 0
 			              3 8 0  3 9 0  3 10 0  3 11 0
 			              3 12 0  3 13 0  3 14 0  3 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		xlb@1f00 {
@@ -196,13 +169,10 @@
 		};
 
 		serial@2000 {		// PSC1
-			device_type = "serial";
 			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <0>;  // Logical port assignment
 			cell-index = <0>;
 			reg = <0x2000 0x100>;
 			interrupts = <2 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		// PSC2 in ac97 mode example
@@ -211,7 +181,6 @@
 		//	cell-index = <1>;
 		//	reg = <0x2200 0x100>;
 		//	interrupts = <2 2 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC3 in CODEC mode example
@@ -220,27 +189,22 @@
 		//	cell-index = <2>;
 		//	reg = <0x2400 0x100>;
 		//	interrupts = <2 3 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC4 in uart mode example
 		//serial@2600 {		// PSC4
-		//	device_type = "serial";
 		//	compatible = "fsl,mpc5200-psc-uart";
 		//	cell-index = <3>;
 		//	reg = <0x2600 0x100>;
 		//	interrupts = <2 11 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC5 in uart mode example
 		//serial@2800 {		// PSC5
-		//	device_type = "serial";
 		//	compatible = "fsl,mpc5200-psc-uart";
 		//	cell-index = <4>;
 		//	reg = <0x2800 0x100>;
 		//	interrupts = <2 12 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC6 in spi mode example
@@ -249,16 +213,13 @@
 		//	cell-index = <5>;
 		//	reg = <0x2c00 0x100>;
 		//	interrupts = <2 4 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <2 5 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			phy-handle = <&phy0>;
 		};
 
@@ -268,30 +229,24 @@
 			compatible = "fsl,mpc5200-mdio";
 			reg = <0x3000 0x400>;	// fec range, since we need to setup fec interrupts
 			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
-			interrupt-parent = <&mpc5200_pic>;
 
 			phy0: ethernet-phy@1 {
-				device_type = "ethernet-phy";
 				reg = <1>;
 			};
 		};
 
 		ata@3a00 {
-			device_type = "ata";
 			compatible = "fsl,mpc5200-ata";
 			reg = <0x3a00 0x100>;
 			interrupts = <2 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		i2c@3d00 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <0>;
 			reg = <0x3d00 0x40>;
 			interrupts = <2 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 		};
 
@@ -299,14 +254,12 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <1>;
 			reg = <0x3d40 0x40>;
 			interrupts = <2 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 		};
 		sram@8000 {
-			compatible = "fsl,mpc5200-sram","sram";
+			compatible = "fsl,mpc5200-sram";
 			reg = <0x8000 0x4000>;
 		};
 	};
@@ -325,7 +278,6 @@
 				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
 		clock-frequency = <0>; // From boot loader
 		interrupts = <2 8 0 2 9 0 2 10 0>;
-		interrupt-parent = <&mpc5200_pic>;
 		bus-range = <0 0>;
 		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
 			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 63e3bb4..c63e356 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -17,6 +17,7 @@
 	compatible = "fsl,lite5200b";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -58,136 +59,112 @@
 			// 5200 interrupts are encoded into two levels;
 			interrupt-controller;
 			#interrupt-cells = <3>;
-			device_type = "interrupt-controller";
 			compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
 			reg = <0x500 0x80>;
 		};
 
 		timer@600 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <0>;
 			reg = <0x600 0x10>;
 			interrupts = <1 9 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl,has-wdt;
 		};
 
 		timer@610 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <1>;
 			reg = <0x610 0x10>;
 			interrupts = <1 10 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@620 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <2>;
 			reg = <0x620 0x10>;
 			interrupts = <1 11 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@630 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <3>;
 			reg = <0x630 0x10>;
 			interrupts = <1 12 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@640 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <4>;
 			reg = <0x640 0x10>;
 			interrupts = <1 13 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@650 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <5>;
 			reg = <0x650 0x10>;
 			interrupts = <1 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@660 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <6>;
 			reg = <0x660 0x10>;
 			interrupts = <1 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@670 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <7>;
 			reg = <0x670 0x10>;
 			interrupts = <1 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
 			reg = <0x800 0x100>;
 			interrupts = <1 5 0 1 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		can@900 {
 			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			cell-index = <0>;
 			interrupts = <2 17 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x900 0x80>;
 		};
 
 		can@980 {
 			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			cell-index = <1>;
 			interrupts = <2 18 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x980 0x80>;
 		};
 
-		gpio@b00 {
+		gpio_simple: gpio@b00 {
 			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
 			interrupts = <1 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
-		gpio@c00 {
+		gpio_wkup: gpio@c00 {
 			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
 			reg = <0xc00 0x40>;
 			interrupts = <1 8 0 0 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		spi@f00 {
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
 			interrupts = <2 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		dma-controller@1200 {
-			device_type = "dma-controller";
 			compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
 			reg = <0x1200 0x80>;
 			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
 			              3 4 0  3 5 0  3 6 0  3 7 0
 			              3 8 0  3 9 0  3 10 0  3 11 0
 			              3 12 0  3 13 0  3 14 0  3 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		xlb@1f00 {
@@ -196,13 +173,10 @@
 		};
 
 		serial@2000 {		// PSC1
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <0>;  // Logical port assignment
 			cell-index = <0>;
 			reg = <0x2000 0x100>;
 			interrupts = <2 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		// PSC2 in ac97 mode example
@@ -211,7 +185,6 @@
 		//	cell-index = <1>;
 		//	reg = <0x2200 0x100>;
 		//	interrupts = <2 2 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC3 in CODEC mode example
@@ -220,27 +193,22 @@
 		//	cell-index = <2>;
 		//	reg = <0x2400 0x100>;
 		//	interrupts = <2 3 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC4 in uart mode example
 		//serial@2600 {		// PSC4
-		//	device_type = "serial";
 		//	compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		//	cell-index = <3>;
 		//	reg = <0x2600 0x100>;
 		//	interrupts = <2 11 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC5 in uart mode example
 		//serial@2800 {		// PSC5
-		//	device_type = "serial";
 		//	compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
 		//	cell-index = <4>;
 		//	reg = <0x2800 0x100>;
 		//	interrupts = <2 12 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		// PSC6 in spi mode example
@@ -249,49 +217,40 @@
 		//	cell-index = <5>;
 		//	reg = <0x2c00 0x100>;
 		//	interrupts = <2 4 0>;
-		//	interrupt-parent = <&mpc5200_pic>;
 		//};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <2 5 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio", "fsl,mpc5200-mdio";
+			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
 			reg = <0x3000 0x400>;	// fec range, since we need to setup fec interrupts
 			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
-			interrupt-parent = <&mpc5200_pic>;
 
 			phy0: ethernet-phy@0 {
-				device_type = "ethernet-phy";
 				reg = <0>;
 			};
 		};
 
 		ata@3a00 {
-			device_type = "ata";
 			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
 			reg = <0x3a00 0x100>;
 			interrupts = <2 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		i2c@3d00 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <0>;
 			reg = <0x3d00 0x40>;
 			interrupts = <2 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 		};
 
@@ -299,14 +258,13 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <1>;
 			reg = <0x3d40 0x40>;
 			interrupts = <2 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 		};
+
 		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram","sram";
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
 			reg = <0x8000 0x4000>;
 		};
 	};
@@ -330,7 +288,6 @@
 				 0xc800 0 0 4 &mpc5200_pic 0 0 3>;
 		clock-frequency = <0>; // From boot loader
 		interrupts = <2 8 0 2 9 0 2 10 0>;
-		interrupt-parent = <&mpc5200_pic>;
 		bus-range = <0 0>;
 		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
 			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
diff --git a/arch/powerpc/boot/dts/media5200.dts b/arch/powerpc/boot/dts/media5200.dts
new file mode 100644
index 0000000..e297d8b
--- /dev/null
+++ b/arch/powerpc/boot/dts/media5200.dts
@@ -0,0 +1,318 @@
+/*
+ * Freescale Media5200 board Device Tree Source
+ *
+ * Copyright 2009 Secret Lab Technologies Ltd.
+ * Grant Likely <grant.likely@secretlab.ca>
+ * Steven Cavanagh <scavanagh@secretlab.ca>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/;
+
+/ {
+	model = "fsl,media5200";
+	compatible = "fsl,media5200";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	aliases {
+		console = &console;
+		ethernet0 = &eth0;
+	};
+
+	chosen {
+		linux,stdout-path = &console;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;		// L1, 16K
+			i-cache-size = <0x4000>;		// L1, 16K
+			timebase-frequency = <33000000>;	// 33 MHz, these were configured by U-Boot
+			bus-frequency = <132000000>;		// 132 MHz
+			clock-frequency = <396000000>;		// 396 MHz
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB RAM
+	};
+
+	soc@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200b-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <132000000>;// 132 MHz
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		timer@610 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x610 0x10>;
+			interrupts = <1 10 0>;
+		};
+
+		timer@620 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x620 0x10>;
+			interrupts = <1 11 0>;
+		};
+
+		timer@630 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x630 0x10>;
+			interrupts = <1 12 0>;
+		};
+
+		timer@640 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x640 0x10>;
+			interrupts = <1 13 0>;
+		};
+
+		timer@650 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x650 0x10>;
+			interrupts = <1 14 0>;
+		};
+
+		timer@660 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x660 0x10>;
+			interrupts = <1 15 0>;
+		};
+
+		timer@670 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x670 0x10>;
+			interrupts = <1 16 0>;
+		};
+
+		rtc@800 {	// Real time clock
+			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+			reg = <0x800 0x100>;
+			interrupts = <1 5 0 1 6 0>;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpio_wkup: gpio@c00 {
+			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+			reg = <0xc00 0x40>;
+			interrupts = <1 8 0 0 3 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		spi@f00 {
+			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+			reg = <0xf00 0x20>;
+			interrupts = <2 13 0 2 14 0>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0x100>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		// PSC6 in uart mode
+		console: serial@2c00 {		// PSC6
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			cell-index = <5>;
+			port-number = <0>;  // Logical port assignment
+			reg = <0x2c00 0x100>;
+			interrupts = <2 4 0>;
+		};
+
+		eth0: ethernet@3000 {
+			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			phy-handle = <&phy0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;	// fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
+
+			phy0: ethernet-phy@0 {
+				reg = <0>;
+			};
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+			fsl5200-clocking;
+		};
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+			fsl5200-clocking;
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &media5200_fpga 0 2 // 1st slot
+				 0xc000 0 0 2 &media5200_fpga 0 3
+				 0xc000 0 0 3 &media5200_fpga 0 4
+				 0xc000 0 0 4 &media5200_fpga 0 5
+
+				 0xc800 0 0 1 &media5200_fpga 0 3 // 2nd slot
+				 0xc800 0 0 2 &media5200_fpga 0 4
+				 0xc800 0 0 3 &media5200_fpga 0 5
+				 0xc800 0 0 4 &media5200_fpga 0 2
+
+				 0xd000 0 0 1 &media5200_fpga 0 4 // miniPCI
+				 0xd000 0 0 2 &media5200_fpga 0 5
+
+				 0xe000 0 0 1 &media5200_fpga 0 5 // CoralIP
+				>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		interrupt-parent = <&mpc5200_pic>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
+			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200b-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		ranges = < 0 0 0xfc000000 0x02000000
+			   1 0 0xfe000000 0x02000000
+			   2 0 0xf0010000 0x00010000
+			   3 0 0xf0020000 0x00010000 >;
+
+		flash@0,0 {
+			compatible = "amd,am29lv28ml", "cfi-flash";
+			reg = <0 0x0 0x2000000>;		// 32 MB
+			bank-width = <4>;			// Width in bytes of the flash bank
+			device-width = <2>;			// Two devices on each bank
+		};
+
+		flash@1,0 {
+			compatible = "amd,am29lv28ml", "cfi-flash";
+			reg = <1 0 0x2000000>;			// 32 MB
+			bank-width = <4>;			// Width in bytes of the flash bank
+			device-width = <2>;			// Two devices on each bank
+		};
+
+		media5200_fpga: fpga@2,0 {
+			compatible = "fsl,media5200-fpga";
+			interrupt-controller;
+			#interrupt-cells = <2>;	// 0:bank 1:id; no type field
+			reg = <2 0 0x10000>;
+
+			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <0 0 3	// IRQ bank 0
+			              1 1 3>;	// IRQ bank 1
+		};
+
+		uart@3,0 {
+			compatible = "ti,tl16c752bpt";
+			reg = <3 0 0x10000>;
+			interrupt-parent = <&media5200_fpga>;
+			interrupts = <0 0  0 1>; // 2 irqs
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/motionpro.dts b/arch/powerpc/boot/dts/motionpro.dts
index 52ba6f9..7be8ca0 100644
--- a/arch/powerpc/boot/dts/motionpro.dts
+++ b/arch/powerpc/boot/dts/motionpro.dts
@@ -17,6 +17,7 @@
 	compatible = "promess,motionpro";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -66,7 +67,6 @@
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x600 0x10>;
 			interrupts = <1 9 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl,has-wdt;
 		};
 
@@ -74,35 +74,30 @@
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x610 0x10>;
 			interrupts = <1 10 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@620 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x620 0x10>;
 			interrupts = <1 11 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@630 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x630 0x10>;
 			interrupts = <1 12 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@640 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x640 0x10>;
 			interrupts = <1 13 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		timer@650 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
 			reg = <0x650 0x10>;
 			interrupts = <1 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		motionpro-led@660 {	// Motion-PRO status LED
@@ -110,7 +105,6 @@
 			label = "motionpro-statusled";
 			reg = <0x660 0x10>;
 			interrupts = <1 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			blink-delay = <100>; // 100 msec
 		};
 
@@ -119,49 +113,46 @@
 			label = "motionpro-readyled";
 			reg = <0x670 0x10>;
 			interrupts = <1 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
 			reg = <0x800 0x100>;
 			interrupts = <1 5 0 1 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		can@980 {
 			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
 			interrupts = <2 18 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x980 0x80>;
 		};
 
-		gpio@b00 {
+		gpio_simple: gpio@b00 {
 			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
 			interrupts = <1 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
-		gpio@c00 {
+		gpio_wkup: gpio@c00 {
 			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
 			reg = <0xc00 0x40>;
 			interrupts = <1 8 0 0 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		spi@f00 {
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
 			interrupts = <2 13 0 2 14 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
 			interrupts = <2 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		dma-controller@1200 {
@@ -171,7 +162,6 @@
 			              3 4 0  3 5 0  3 6 0  3 7 0
 			              3 8 0  3 9 0  3 10 0  3 11 0
 			              3 12 0  3 13 0  3 14 0  3 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		xlb@1f00 {
@@ -180,12 +170,9 @@
 		};
 
 		serial@2000 {		// PSC1
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <0>;  // Logical port assignment
 			reg = <0x2000 0x100>;
 			interrupts = <2 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		// PSC2 in spi master mode 
@@ -194,26 +181,20 @@
 			cell-index = <1>;
 			reg = <0x2200 0x100>;
 			interrupts = <2 2 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		// PSC5 in uart mode
 		serial@2800 {		// PSC5
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <4>;  // Logical port assignment
 			reg = <0x2800 0x100>;
 			interrupts = <2 12 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <2 5 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			phy-handle = <&phy0>;
 		};
 
@@ -223,10 +204,8 @@
 			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
 			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
 			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
-			interrupt-parent = <&mpc5200_pic>;
 
 			phy0: ethernet-phy@2 {
-				device_type = "ethernet-phy";
 				reg = <2>;
 			};
 		};
@@ -235,7 +214,6 @@
 			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
 			reg = <0x3a00 0x100>;
 			interrupts = <2 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		i2c@3d40 {
@@ -244,7 +222,6 @@
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
 			reg = <0x3d40 0x40>;
 			interrupts = <2 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 
 			rtc@68 {
@@ -259,8 +236,8 @@
 		};
 	};
 
-	lpb {
-		compatible = "fsl,lpb";
+	localbus {
+		compatible = "fsl,mpc5200b-lpb","simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <0 0 0xff000000 0x01000000
@@ -273,7 +250,6 @@
 			compatible = "promess,motionpro-kollmorgen";
 			reg = <1 0 0x10000>;
 			interrupts = <1 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		// 8-bit board CPLD on LocalPlus Bus CS2
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 3ebf7ec..761faa7 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -180,7 +180,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			sleep = <&pmc 0x20000000>;
-			ranges;
+			ranges = <0x0 0x24000 0x1000>;
 
 			cell-index = <0>;
 			device_type = "network";
@@ -195,11 +195,11 @@
 			fixed-link = <1 1 1000 0 0>;
 			fsl,magic-packet;
 
-			mdio@24520 {
+			mdio@520 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,gianfar-mdio";
-				reg = <0x24520 0x20>;
+				reg = <0x520 0x20>;
 				phy4: ethernet-phy@4 {
 					interrupt-parent = <&ipic>;
 					interrupts = <20 0x8>;
@@ -221,6 +221,7 @@
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <34 0x8 33 0x8 32 0x8>;
 			interrupt-parent = <&ipic>;
@@ -229,11 +230,11 @@
 			sleep = <&pmc 0x10000000>;
 			fsl,magic-packet;
 
-			mdio@25520 {
+			mdio@520 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "fsl,gianfar-tbi";
-				reg = <0x25520 0x20>;
+				reg = <0x520 0x20>;
 
 				tbi1: tbi-phy@11 {
 					reg = <0x11>;
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts
index 7178416..3f4c5fb 100644
--- a/arch/powerpc/boot/dts/mpc8315erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8315erdb.dts
@@ -22,6 +22,8 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
 	};
 
 	cpus {
@@ -188,66 +190,74 @@
 			phy_type = "utmi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&ipic>;
-				interrupts = <20 0x8>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&ipic>;
-				interrupts = <19 0x8>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = < &phy0 >;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&ipic>;
+					interrupts = <20 0x8>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&ipic>;
+					interrupts = <19 0x8>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = < &phy1 >;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -349,4 +359,66 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pci1: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8315-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000>;
+		ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb1000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 1 8
+				 0 0 0 2 &ipic 1 8
+				 0 0 0 3 &ipic 1 8
+				 0 0 0 4 &ipic 1 8>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa0000000
+				  0x02000000 0 0xa0000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8315-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe000a000 0x00001000>;
+		ranges = <0x02000000 0 0xc0000000 0xc0000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xd1000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 2 8
+				 0 0 0 2 &ipic 2 8
+				 0 0 0 3 &ipic 2 8
+				 0 0 0 4 &ipic 2 8>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xc0000000
+				  0x02000000 0 0xc0000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index b5eda94..1ae38f0 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -170,57 +170,52 @@
 			phy_type = "ulpi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			/* Vitesse 8201 */
-			phy1c: ethernet-phy@1c {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x1c>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy1c>;
 			linux,network-index = <0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				/* Vitesse 8201 */
+				phy1c: ethernet-phy@1c {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x1c>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			interrupt-parent = <&ipic>;
@@ -228,6 +223,18 @@
 			fixed-link = <1 1 1000 0 0>;
 			linux,network-index = <1>;
 			tbi-handle = <&tbi1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
index c87a601..662abe1 100644
--- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -149,37 +149,41 @@
 			phy_type = "ulpi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			/* Vitesse 8201 */
-			phy1c: ethernet-phy@1c {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x1c>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy1c>;
 			linux,network-index = <0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				/* Vitesse 8201 */
+				phy1c: ethernet-phy@1c {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x1c>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index d9adba0..d9f0a23 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -167,69 +167,76 @@
 			phy_type = "ulpi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			linux,network-index = <0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			linux,network-index = <1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts
index 1d14d70..9637080 100644
--- a/arch/powerpc/boot/dts/mpc8377_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8377_mds.dts
@@ -23,6 +23,8 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
 	};
 
 	cpus {
@@ -127,21 +129,38 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
+		sleep-nexus {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
-			interrupt-parent = <&ipic>;
-			dfsrr;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
 
-			rtc@68 {
-				compatible = "dallas,ds1374";
-				reg = <0x68>;
-				interrupts = <19 0x8>;
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
 				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				rtc@68 {
+					compatible = "dallas,ds1374";
+					reg = <0x68>;
+					interrupts = <19 0x8>;
+					interrupt-parent = <&ipic>;
+				};
+			};
+
+			sdhci@2e000 {
+				compatible = "fsl,mpc8377-esdhc", "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -174,70 +193,83 @@
 			interrupts = <38 0x8>;
 			dr_mode = "host";
 			phy_type = "ulpi";
+			sleep = <&pmc 0x00c00000>;
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy3>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -309,14 +341,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
-		};
-
-		sdhc@2e000 {
-			model = "eSDHC";
-			compatible = "fsl,esdhc";
-			reg = <0x2e000 0x1000>;
-			interrupts = <42 0x8>;
-			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		sata@18000 {
@@ -324,6 +349,7 @@
 			reg = <0x18000 0x1000>;
 			interrupts = <44 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x000000c0>;
 		};
 
 		sata@19000 {
@@ -331,6 +357,7 @@
 			reg = <0x19000 0x1000>;
 			interrupts = <45 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000030>;
 		};
 
 		/* IPIC
@@ -346,6 +373,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8377-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -400,6 +434,7 @@
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
+		sleep = <&pmc 0x00010000>;
 		clock-frequency = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
@@ -409,4 +444,68 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pci1: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000>;
+		ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 1 8
+				 0 0 0 2 &ipic 1 8
+				 0 0 0 3 &ipic 1 8
+				 0 0 0 4 &ipic 1 8>;
+		sleep = <&pmc 0x00300000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa8000000
+				  0x02000000 0 0xa8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe000a000 0x00001000>;
+		ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xd8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 2 8
+				 0 0 0 2 &ipic 2 8
+				 0 0 0 3 &ipic 2 8
+				 0 0 0 4 &ipic 2 8>;
+		sleep = <&pmc 0x000c0000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xc8000000
+				  0x02000000 0 0xc8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8377_rdb.dts b/arch/powerpc/boot/dts/mpc8377_rdb.dts
index 9413af3..0533393 100644
--- a/arch/powerpc/boot/dts/mpc8377_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8377_rdb.dts
@@ -22,6 +22,8 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
 	};
 
 	cpus {
@@ -107,26 +109,72 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
+		gpio1: gpio-controller@c00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
+			reg = <0xc00 0x100>;
+			interrupts = <74 0x8>;
 			interrupt-parent = <&ipic>;
-			dfsrr;
-			rtc@68 {
-				compatible = "dallas,ds1339";
-				reg = <0x68>;
+			gpio-controller;
+		};
+
+		gpio2: gpio-controller@d00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio";
+			reg = <0xd00 0x100>;
+			interrupts = <75 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
+		sleep-nexus {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
+
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
+				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				dtt@48 {
+					compatible = "national,lm75";
+					reg = <0x48>;
+				};
+
+				at24@50 {
+					compatible = "at24,24c256";
+					reg = <0x50>;
+				};
+
+				rtc@68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+
+				mcu_pio: mcu@a {
+					#gpio-cells = <2>;
+					compatible = "fsl,mc9s08qg8-mpc8377erdb",
+						     "fsl,mcu-mpc8349emitx";
+					reg = <0x0a>;
+					gpio-controller;
+				};
 			};
 
-			mcu_pio: mcu@a {
-				#gpio-cells = <2>;
-				compatible = "fsl,mc9s08qg8-mpc8377erdb",
-					     "fsl,mcu-mpc8349emitx";
-				reg = <0x0a>;
-				gpio-controller;
+			sdhci@2e000 {
+				compatible = "fsl,mpc8377-esdhc", "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -197,64 +245,76 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <38 0x8>;
 			phy_type = "ulpi";
+			sleep = <&pmc 0x00c00000>;
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			fixed-link = <1 1 1000 0 0>;
 			tbi-handle = <&tbi1>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -287,6 +347,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		sata@18000 {
@@ -294,6 +355,7 @@
 			reg = <0x18000 0x1000>;
 			interrupts = <44 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x000000c0>;
 		};
 
 		sata@19000 {
@@ -301,6 +363,7 @@
 			reg = <0x19000 0x1000>;
 			interrupts = <45 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000030>;
 		};
 
 		/* IPIC
@@ -316,6 +379,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8377-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -341,6 +411,7 @@
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
@@ -350,4 +421,68 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pci1: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000>;
+		ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 1 8
+				 0 0 0 2 &ipic 1 8
+				 0 0 0 3 &ipic 1 8
+				 0 0 0 4 &ipic 1 8>;
+		sleep = <&pmc 0x00300000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa8000000
+				  0x02000000 0 0xa8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe000a000 0x00001000>;
+		ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xd8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 2 8
+				 0 0 0 2 &ipic 2 8
+				 0 0 0 3 &ipic 2 8
+				 0 0 0 4 &ipic 2 8>;
+		sleep = <&pmc 0x000c0000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xc8000000
+				  0x02000000 0 0xc8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts
index b85fc02..651ff2f 100644
--- a/arch/powerpc/boot/dts/mpc8378_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8378_mds.dts
@@ -23,6 +23,8 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
 	};
 
 	cpus {
@@ -127,21 +129,38 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
+		sleep-nexus {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
-			interrupt-parent = <&ipic>;
-			dfsrr;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
 
-			rtc@68 {
-				compatible = "dallas,ds1374";
-				reg = <0x68>;
-				interrupts = <19 0x8>;
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
 				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				rtc@68 {
+					compatible = "dallas,ds1374";
+					reg = <0x68>;
+					interrupts = <19 0x8>;
+					interrupt-parent = <&ipic>;
+				};
+			};
+
+			sdhci@2e000 {
+				compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -213,70 +232,83 @@
 			interrupts = <38 0x8>;
 			dr_mode = "host";
 			phy_type = "ulpi";
+			sleep = <&pmc 0x00c00000>;
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy3>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -309,14 +341,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
-		};
-
-		sdhc@2e000 {
-			model = "eSDHC";
-			compatible = "fsl,esdhc";
-			reg = <0x2e000 0x1000>;
-			interrupts = <42 0x8>;
-			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		/* IPIC
@@ -332,6 +357,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8378-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -387,6 +419,7 @@
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
 		clock-frequency = <0>;
+		sleep = <&pmc 0x00010000>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
@@ -395,4 +428,68 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pci1: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8378-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000>;
+		ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 1 8
+				 0 0 0 2 &ipic 1 8
+				 0 0 0 3 &ipic 1 8
+				 0 0 0 4 &ipic 1 8>;
+		sleep = <&pmc 0x00300000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa8000000
+				  0x02000000 0 0xa8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8378-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe000a000 0x00001000>;
+		ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xd8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 2 8
+				 0 0 0 2 &ipic 2 8
+				 0 0 0 3 &ipic 2 8
+				 0 0 0 4 &ipic 2 8>;
+		sleep = <&pmc 0x000c0000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xc8000000
+				  0x02000000 0 0xc8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8378_rdb.dts b/arch/powerpc/boot/dts/mpc8378_rdb.dts
index 23c10ce..5d90e85 100644
--- a/arch/powerpc/boot/dts/mpc8378_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8378_rdb.dts
@@ -22,6 +22,8 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
 	};
 
 	cpus {
@@ -107,26 +109,72 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
+		gpio1: gpio-controller@c00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8378-gpio", "fsl,mpc8349-gpio";
+			reg = <0xc00 0x100>;
+			interrupts = <74 0x8>;
 			interrupt-parent = <&ipic>;
-			dfsrr;
-			rtc@68 {
-				compatible = "dallas,ds1339";
-				reg = <0x68>;
+			gpio-controller;
+		};
+
+		gpio2: gpio-controller@d00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8378-gpio", "fsl,mpc8349-gpio";
+			reg = <0xd00 0x100>;
+			interrupts = <75 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
+		sleep-nexus {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
+
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
+				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				dtt@48 {
+					compatible = "national,lm75";
+					reg = <0x48>;
+				};
+
+				at24@50 {
+					compatible = "at24,24c256";
+					reg = <0x50>;
+				};
+
+				rtc@68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+
+				mcu_pio: mcu@a {
+					#gpio-cells = <2>;
+					compatible = "fsl,mc9s08qg8-mpc8378erdb",
+						     "fsl,mcu-mpc8349emitx";
+					reg = <0x0a>;
+					gpio-controller;
+				};
 			};
 
-			mcu_pio: mcu@a {
-				#gpio-cells = <2>;
-				compatible = "fsl,mc9s08qg8-mpc8378erdb",
-					     "fsl,mcu-mpc8349emitx";
-				reg = <0x0a>;
-				gpio-controller;
+			sdhci@2e000 {
+				compatible = "fsl,mpc8378-esdhc", "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -197,62 +245,76 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <38 0x8>;
 			phy_type = "ulpi";
+			sleep = <&pmc 0x00c00000>;
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
+			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			fixed-link = <1 1 1000 0 0>;
+			tbi-handle = <&tbi1>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -285,6 +347,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		/* IPIC
@@ -300,6 +363,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8378-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -325,6 +395,7 @@
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
@@ -334,4 +405,68 @@
 		compatible = "fsl,mpc8349-pci";
 		device_type = "pci";
 	};
+
+	pci1: pcie@e0009000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8378-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe0009000 0x00001000>;
+		ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000
+		          0x01000000 0 0x00000000 0xb8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 1 8
+				 0 0 0 2 &ipic 1 8
+				 0 0 0 3 &ipic 1 8
+				 0 0 0 4 &ipic 1 8>;
+		sleep = <&pmc 0x00300000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xa8000000
+				  0x02000000 0 0xa8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
+
+	pci2: pcie@e000a000 {
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		compatible = "fsl,mpc8378-pcie", "fsl,mpc8314-pcie";
+		reg = <0xe000a000 0x00001000>;
+		ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xd8000000 0 0x00800000>;
+		bus-range = <0 255>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &ipic 2 8
+				 0 0 0 2 &ipic 2 8
+				 0 0 0 3 &ipic 2 8
+				 0 0 0 4 &ipic 2 8>;
+		sleep = <&pmc 0x000c0000>;
+		clock-frequency = <0>;
+
+		pcie@0 {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			reg = <0 0 0 0 0>;
+			ranges = <0x02000000 0 0xc8000000
+				  0x02000000 0 0xc8000000
+				  0 0x10000000
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00800000>;
+		};
+	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts
index acf06c4..d6f208b 100644
--- a/arch/powerpc/boot/dts/mpc8379_mds.dts
+++ b/arch/powerpc/boot/dts/mpc8379_mds.dts
@@ -127,21 +127,38 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
+		sleep-nexus {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
-			interrupt-parent = <&ipic>;
-			dfsrr;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
 
-			rtc@68 {
-				compatible = "dallas,ds1374";
-				reg = <0x68>;
-				interrupts = <19 0x8>;
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
 				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				rtc@68 {
+					compatible = "dallas,ds1374";
+					reg = <0x68>;
+					interrupts = <19 0x8>;
+					interrupt-parent = <&ipic>;
+				};
+			};
+
+			sdhci@2e000 {
+				compatible = "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -213,69 +230,83 @@
 			interrupts = <38 0x8>;
 			dr_mode = "host";
 			phy_type = "ulpi";
-		};
-
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&ipic>;
-				interrupts = <18 0x8>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
+			sleep = <&pmc 0x00c00000>;
 		};
 
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&ipic>;
+					interrupts = <18 0x8>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy3>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -308,14 +339,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
-		};
-
-		sdhc@2e000 {
-			model = "eSDHC";
-			compatible = "fsl,esdhc";
-			reg = <0x2e000 0x1000>;
-			interrupts = <42 0x8>;
-			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		sata@18000 {
@@ -323,6 +347,7 @@
 			reg = <0x18000 0x1000>;
 			interrupts = <44 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x000000c0>;
 		};
 
 		sata@19000 {
@@ -330,6 +355,7 @@
 			reg = <0x19000 0x1000>;
 			interrupts = <45 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000030>;
 		};
 
 		sata@1a000 {
@@ -337,6 +363,7 @@
 			reg = <0x1a000 0x1000>;
 			interrupts = <46 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x0000000c>;
 		};
 
 		sata@1b000 {
@@ -344,6 +371,7 @@
 			reg = <0x1b000 0x1000>;
 			interrupts = <47 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000003>;
 		};
 
 		/* IPIC
@@ -359,6 +387,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8379-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -413,6 +448,7 @@
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
+		sleep = <&pmc 0x00010000>;
 		clock-frequency = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8379_rdb.dts b/arch/powerpc/boot/dts/mpc8379_rdb.dts
index 72cdc3c..98ae95b 100644
--- a/arch/powerpc/boot/dts/mpc8379_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8379_rdb.dts
@@ -107,26 +107,72 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
+		gpio1: gpio-controller@c00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8379-gpio", "fsl,mpc8349-gpio";
+			reg = <0xc00 0x100>;
+			interrupts = <74 0x8>;
 			interrupt-parent = <&ipic>;
-			dfsrr;
-			rtc@68 {
-				compatible = "dallas,ds1339";
-				reg = <0x68>;
+			gpio-controller;
+		};
+
+		gpio2: gpio-controller@d00 {
+			#gpio-cells = <2>;
+			compatible = "fsl,mpc8379-gpio", "fsl,mpc8349-gpio";
+			reg = <0xd00 0x100>;
+			interrupts = <75 0x8>;
+			interrupt-parent = <&ipic>;
+			gpio-controller;
+		};
+
+		sleep-nexus {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x0c000000>;
+			ranges;
+
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
+				interrupt-parent = <&ipic>;
+				dfsrr;
+
+				dtt@48 {
+					compatible = "national,lm75";
+					reg = <0x48>;
+				};
+
+				at24@50 {
+					compatible = "at24,24c256";
+					reg = <0x50>;
+				};
+
+				rtc@68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+
+				mcu_pio: mcu@a {
+					#gpio-cells = <2>;
+					compatible = "fsl,mc9s08qg8-mpc8379erdb",
+						     "fsl,mcu-mpc8349emitx";
+					reg = <0x0a>;
+					gpio-controller;
+				};
 			};
 
-			mcu_pio: mcu@a {
-				#gpio-cells = <2>;
-				compatible = "fsl,mc9s08qg8-mpc8379erdb",
-					     "fsl,mcu-mpc8349emitx";
-				reg = <0x0a>;
-				gpio-controller;
+			sdhci@2e000 {
+				compatible = "fsl,mpc8379-esdhc";
+				reg = <0x2e000 0x1000>;
+				interrupts = <42 0x8>;
+				interrupt-parent = <&ipic>;
+				/* Filled in by U-Boot */
+				clock-frequency = <0>;
 			};
 		};
 
@@ -197,63 +243,76 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <38 0x8>;
 			phy_type = "ulpi";
-		};
-
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&ipic>;
-				interrupts = <17 0x8>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
+			sleep = <&pmc 0x00c00000>;
 		};
 
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+			sleep = <&pmc 0xc0000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&ipic>;
+					interrupts = <17 0x8>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			phy-connection-type = "mii";
 			interrupt-parent = <&ipic>;
 			fixed-link = <1 1 1000 0 0>;
 			tbi-handle = <&tbi1>;
+			sleep = <&pmc 0x30000000>;
+			fsl,magic-packet;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -286,6 +345,7 @@
 			fsl,channel-fifo-len = <24>;
 			fsl,exec-units-mask = <0x9fe>;
 			fsl,descriptor-types-mask = <0x3ab0ebf>;
+			sleep = <&pmc 0x03000000>;
 		};
 
 		sata@18000 {
@@ -293,6 +353,7 @@
 			reg = <0x18000 0x1000>;
 			interrupts = <44 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x000000c0>;
 		};
 
 		sata@19000 {
@@ -300,6 +361,7 @@
 			reg = <0x19000 0x1000>;
 			interrupts = <45 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000030>;
 		};
 
 		sata@1a000 {
@@ -307,6 +369,7 @@
 			reg = <0x1a000 0x1000>;
 			interrupts = <46 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x0000000c>;
 		};
 
 		sata@1b000 {
@@ -314,6 +377,7 @@
 			reg = <0x1b000 0x1000>;
 			interrupts = <47 0x8>;
 			interrupt-parent = <&ipic>;
+			sleep = <&pmc 0x00000003>;
 		};
 
 		/* IPIC
@@ -329,6 +393,13 @@
 			#interrupt-cells = <2>;
 			reg = <0x700 0x100>;
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8379-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 0x8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
 	pci0: pci@e0008500 {
@@ -354,6 +425,7 @@
 		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
 		          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
 		          0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+		sleep = <&pmc 0x00010000>;
 		clock-frequency = <66666666>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index 3c905df..b31c504 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -137,42 +137,6 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 0x1>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 0x1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		usb@22000 {
 			compatible = "fsl,mpc8536-usb2-mph", "fsl-usb2-mph";
 			reg = <0x22000 0x1000>;
@@ -194,31 +158,73 @@
 		};
 
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 0x1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 0x1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		usb@2b000 {
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index 79570ff..ddd67be 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -126,97 +126,106 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <7 1>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <7 1>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <41 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 221036a..e45097f 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -126,66 +126,72 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 0668d104..7c6932b 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -98,44 +98,6 @@
 			dfsrr;
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		dma@21300 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -178,31 +140,74 @@
 		};
 
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 			tbi-handle = <&tbi0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 			tbi-handle = <&tbi1>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index df774a7..804e903 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -142,129 +142,141 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 /* eTSEC 3/4 are currently broken
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
  */
 
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 053b01e..9484f07 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -126,66 +126,72 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 11b1bcb..cc2acf8 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -115,78 +115,84 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <7 1>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <7 1>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <7 1>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <7 1>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		mpic: pic@40000 {
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 1955bd9..9d52e3b 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -149,78 +149,84 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@7 {
-				interrupt-parent = <&mpic>;
-				interrupts = <1 1>;
-				reg = <0x7>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <2 1>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <1 1>;
-				reg = <0x2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <2 1>;
-				reg = <0x3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
  			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@7 {
+					interrupt-parent = <&mpic>;
+					interrupts = <1 1>;
+					reg = <0x7>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <2 1>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <1 1>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <2 1>;
+					reg = <0x3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
  			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index 359c3b7..6e79a41 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -1,7 +1,7 @@
 /*
  * MPC8572 DS Device Tree Source
  *
- * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ * Copyright 2007-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
@@ -312,129 +312,141 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x0>;
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x1>;
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x2>;
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x3>;
-			};
-
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x0>;
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x2>;
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x3>;
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy3>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -643,7 +655,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 			uli1575@0 {
 				reg = <0x0 0x0 0x0 0x0 0x0>;
 				#size-cells = <2>;
@@ -654,7 +666,7 @@
 
 					  0x1000000 0x0 0x0
 					  0x1000000 0x0 0x0
-					  0x0 0x100000>;
+					  0x0 0x10000>;
 				isa@1e {
 					device_type = "isa";
 					#interrupt-cells = <2>;
@@ -744,7 +756,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 		};
 	};
 
@@ -781,7 +793,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 		};
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8572ds_36b.dts b/arch/powerpc/boot/dts/mpc8572ds_36b.dts
new file mode 100644
index 0000000..dbd81a7
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8572ds_36b.dts
@@ -0,0 +1,799 @@
+/*
+ * MPC8572 DS Device Tree Source
+ *
+ * Copyright 2007-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.
+ */
+
+/dts-v1/;
+/ {
+	model = "fsl,MPC8572DS";
+	compatible = "fsl,MPC8572DS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8572@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		PowerPC,8572@1 {
+			device_type = "cpu";
+			reg = <0x1>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@fffe05000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+		reg = <0xf 0xffe05000 0 0x1000>;
+		interrupts = <19 2>;
+		interrupt-parent = <&mpic>;
+
+		ranges = <0x0 0x0 0xf 0xe8000000 0x08000000
+			  0x1 0x0 0xf 0xe0000000 0x08000000
+			  0x2 0x0 0xf 0xffa00000 0x00040000
+			  0x3 0x0 0xf 0xffdf0000 0x00008000
+			  0x4 0x0 0xf 0xffa40000 0x00040000
+			  0x5 0x0 0xf 0xffa80000 0x00040000
+			  0x6 0x0 0xf 0xffac0000 0x00040000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+			bank-width = <2>;
+			device-width = <1>;
+
+			ramdisk@0 {
+				reg = <0x0 0x03000000>;
+				read-only;
+			};
+
+			diagnostic@3000000 {
+				reg = <0x03000000 0x00e00000>;
+				read-only;
+			};
+
+			dink@3e00000 {
+				reg = <0x03e00000 0x00200000>;
+				read-only;
+			};
+
+			kernel@4000000 {
+				reg = <0x04000000 0x00400000>;
+				read-only;
+			};
+
+			jffs2@4400000 {
+				reg = <0x04400000 0x03b00000>;
+			};
+
+			dtb@7f00000 {
+				reg = <0x07f00000 0x00080000>;
+				read-only;
+			};
+
+			u-boot@7f80000 {
+				reg = <0x07f80000 0x00080000>;
+				read-only;
+			};
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			u-boot@0 {
+				reg = <0x0 0x02000000>;
+				read-only;
+			};
+
+			jffs2@2000000 {
+				reg = <0x02000000 0x10000000>;
+			};
+
+			ramdisk@12000000 {
+				reg = <0x12000000 0x08000000>;
+				read-only;
+			};
+
+			kernel@1a000000 {
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			dtb@1e000000 {
+				reg = <0x1e000000 0x01000000>;
+				read-only;
+			};
+
+			empty@1f000000 {
+				reg = <0x1f000000 0x21000000>;
+			};
+		};
+
+		nand@4,0 {
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <0x4 0x0 0x40000>;
+		};
+
+		nand@5,0 {
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <0x5 0x0 0x40000>;
+		};
+
+		nand@6,0 {
+			compatible = "fsl,mpc8572-fcm-nand",
+				     "fsl,elbc-fcm-nand";
+			reg = <0x6 0x0 0x40000>;
+		};
+	};
+
+	soc8572@fffe00000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x0 0xf 0xffe00000 0x100000>;
+		reg = <0xf 0xffe00000 0 0x1000>;	// CCSRBAR & soc regs, remove once parse code for immrbase fixed
+		bus-frequency = <0>;		// Filled out by uboot.
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		memory-controller@6000 {
+			compatible = "fsl,mpc8572-memory-controller";
+			reg = <0x6000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8572-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x100000>; // L2, 1M
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@c300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0xc300 0x4>;
+			ranges = <0x0 0xc100 0x200>;
+			cell-index = <1>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <76 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <77 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <78 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <79 2>;
+			};
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8572-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x0>;
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x1>;
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x2>;
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x3>;
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <2>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi2>;
+			phy-handle = <&phy2>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <3>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <37 2 38 2 39 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi3>;
+			phy-handle = <&phy3>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8572-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		msi@41600 {
+			compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+			reg = <0x41600 0x80>;
+			msi-available-ranges = <0 0x100>;
+			interrupts = <
+				0xe0 0
+				0xe1 0
+				0xe2 0
+				0xe3 0
+				0xe4 0
+				0xe5 0
+				0xe6 0
+				0xe7 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+				     "fsl,sec2.1", "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2 58 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x9fe>;
+			fsl,descriptor-types-mask = <0x3ab0ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+	};
+
+	pci0: pcie@fffe08000 {
+		cell-index = <0>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xf 0xffe08000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc 0x00000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x11 func 0 - PCI slot 1 */
+			0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 1 - PCI slot 1 */
+			0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 2 - PCI slot 1 */
+			0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 3 - PCI slot 1 */
+			0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 4 - PCI slot 1 */
+			0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 5 - PCI slot 1 */
+			0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 6 - PCI slot 1 */
+			0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x11 func 7 - PCI slot 1 */
+			0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
+			0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
+			0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
+			0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x12 func 0 - PCI slot 2 */
+			0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 1 - PCI slot 2 */
+			0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 2 - PCI slot 2 */
+			0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 3 - PCI slot 2 */
+			0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 4 - PCI slot 2 */
+			0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 5 - PCI slot 2 */
+			0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 6 - PCI slot 2 */
+			0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* IDSEL 0x12 func 7 - PCI slot 2 */
+			0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
+			0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
+			0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
+			0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			// IDSEL 0x1c  USB
+			0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
+			0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
+			0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
+			0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+			// IDSEL 0x1d  Audio
+			0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+			// IDSEL 0x1e Legacy
+			0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
+			0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+			// IDSEL 0x1f IDE/SATA
+			0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+			0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+
+			>;
+
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+			uli1575@0 {
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				#size-cells = <2>;
+				#address-cells = <3>;
+				ranges = <0x2000000 0x0 0xc0000000
+					  0x2000000 0x0 0xc0000000
+					  0x0 0x20000000
+
+					  0x1000000 0x0 0x0
+					  0x1000000 0x0 0x0
+					  0x0 0x10000>;
+				isa@1e {
+					device_type = "isa";
+					#interrupt-cells = <2>;
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0x0 0x0 0x0 0x0>;
+					ranges = <0x1 0x0 0x1000000 0x0 0x0
+						  0x1000>;
+					interrupt-parent = <&i8259>;
+
+					i8259: interrupt-controller@20 {
+						reg = <0x1 0x20 0x2
+						       0x1 0xa0 0x2
+						       0x1 0x4d0 0x2>;
+						interrupt-controller;
+						device_type = "interrupt-controller";
+						#address-cells = <0>;
+						#interrupt-cells = <2>;
+						compatible = "chrp,iic";
+						interrupts = <9 2>;
+						interrupt-parent = <&mpic>;
+					};
+
+					i8042@60 {
+						#size-cells = <0>;
+						#address-cells = <1>;
+						reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+						interrupts = <1 3 12 3>;
+						interrupt-parent =
+							<&i8259>;
+
+						keyboard@0 {
+							reg = <0x0>;
+							compatible = "pnpPNP,303";
+						};
+
+						mouse@1 {
+							reg = <0x1>;
+							compatible = "pnpPNP,f03";
+						};
+					};
+
+					rtc@70 {
+						compatible = "pnpPNP,b00";
+						reg = <0x1 0x70 0x2>;
+					};
+
+					gpio@400 {
+						reg = <0x1 0x400 0x80>;
+					};
+				};
+			};
+		};
+
+	};
+
+	pci1: pcie@fffe09000 {
+		cell-index = <1>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xf 0xffe09000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+
+	pci2: pcie@fffe0a000 {
+		cell-index = <2>;
+		compatible = "fsl,mpc8548-pcie";
+		device_type = "pci";
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xf 0xffe0a000 0 0x1000>;
+		bus-range = <0 255>;
+		ranges = <0x2000000 0x0 0xc0000000 0xc 0x40000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0xf 0xffc20000 0x0 0x00010000>;
+		clock-frequency = <33333333>;
+		interrupt-parent = <&mpic>;
+		interrupts = <26 2>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xc0000000
+				  0x2000000 0x0 0xc0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x10000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
index fd462ef..2bc0c71 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
@@ -6,7 +6,7 @@
  * This dts file allows core0 to have memory, l2, i2c, dma1, global-util, eth0,
  * eth1, crypto, pci0, pci1.
  *
- * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ * Copyright 2007-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
@@ -148,35 +148,38 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x0>;
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x1>;
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x0>;
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x1>;
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
@@ -227,7 +230,7 @@
 			device_type = "open-pic";
 			protected-sources = <
 			31 32 33 37 38 39       /* enet2 enet3 */
-			76 77 78 79 27 42	/* dma2 pci2 serial*/
+			76 77 78 79 26 42	/* dma2 pci2 serial*/
 			0xe0 0xe1 0xe2 0xe3     /* msi */
 			0xe4 0xe5 0xe6 0xe7
 			>;
@@ -376,7 +379,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 			uli1575@0 {
 				reg = <0x0 0x0 0x0 0x0 0x0>;
 				#size-cells = <2>;
@@ -387,7 +390,7 @@
 
 					  0x1000000 0x0 0x0
 					  0x1000000 0x0 0x0
-					  0x0 0x100000>;
+					  0x0 0x10000>;
 				isa@1e {
 					device_type = "isa";
 					#interrupt-cells = <2>;
@@ -477,7 +480,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 		};
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
index e35230f..159cb3a 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
@@ -7,7 +7,7 @@
  *
  * Please note to add "-b 1" for core1's dts compiling.
  *
- * Copyright 2007, 2008 Freescale Semiconductor Inc.
+ * Copyright 2007-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
@@ -186,7 +186,7 @@
 			protected-sources = <
 			18 16 10 42 45 58	/* MEM L2 mdio serial crypto */
 			29 30 34 35 36 40	/* enet0 enet1 */
-			24 26 20 21 22 23	/* pcie0 pcie1 dma1 */
+			24 25 20 21 22 23	/* pci0 pci1 dma1 */
 			43			/* i2c */
 			0x1 0x2 0x3 0x4         /* pci slot */
 			0x9 0xa 0xb 0xc         /* usb */
@@ -228,7 +228,7 @@
 
 				  0x1000000 0x0 0x0
 				  0x1000000 0x0 0x0
-				  0x0 0x100000>;
+				  0x0 0x10000>;
 		};
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index f724d72..1bd3ebe 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -217,6 +217,7 @@
 			codec-handle = <&cs4270>;
 			fsl,playback-dma = <&dma00>;
 			fsl,capture-dma = <&dma01>;
+			fsl,fifo-depth = <8>;
 		};
 
 		ssi@16100 {
@@ -225,6 +226,7 @@
 			reg = <0x16100 0x100>;
 			interrupt-parent = <&mpic>;
 			interrupts = <63 2>;
+			fsl,fifo-depth = <8>;
 		};
 
 		dma@21300 {
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 4481532..d72beb19 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -180,133 +180,144 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 		
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy3>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts
index be2c11c..8958347 100644
--- a/arch/powerpc/boot/dts/pcm030.dts
+++ b/arch/powerpc/boot/dts/pcm030.dts
@@ -19,6 +19,7 @@
 	compatible = "phytec,pcm030";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -29,26 +30,26 @@
 			reg = <0>;
 			d-cache-line-size = <32>;
 			i-cache-line-size = <32>;
-			d-cache-size = <0x4000>;	/* L1, 16K          */
-			i-cache-size = <0x4000>;	/* L1, 16K          */
-			timebase-frequency = <0>;	/* From Bootloader  */
-			bus-frequency = <0>;		/* From Bootloader  */
-			clock-frequency = <0>;		/* From Bootloader  */
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
 		};
 	};
 
 	memory {
 		device_type = "memory";
-		reg = <0x00000000 0x04000000>;	/* 64MB */
+		reg = <0x00000000 0x04000000>;	// 64MB
 	};
 
 	soc5200@f0000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "fsl,mpc5200b-immr";
-		ranges = <0x0 0xf0000000 0x0000c000>;
-		bus-frequency = <0>;		/* From bootloader */
-		system-frequency = <0>;		/* From bootloader */
+		ranges = <0 0xf0000000 0x0000c000>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
 
 		cdm@200 {
 			compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
@@ -56,87 +57,70 @@
 		};
 
 		mpc5200_pic: interrupt-controller@500 {
-			/* 5200 interrupts are encoded into two levels; */
+			// 5200 interrupts are encoded into two levels;
 			interrupt-controller;
 			#interrupt-cells = <3>;
-			device_type = "interrupt-controller";
 			compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
 			reg = <0x500 0x80>;
 		};
 
-		timer@600 {	/* General Purpose Timer */
+		timer@600 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <0>;
 			reg = <0x600 0x10>;
-			interrupts = <0x1 0x9 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 9 0>;
 			fsl,has-wdt;
 		};
 
-		timer@610 {	/* General Purpose Timer */
+		timer@610 {	// General Purpose Timer
 			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
-			cell-index = <1>;
 			reg = <0x610 0x10>;
-			interrupts = <0x1 0xa 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 10 0>;
 		};
 
-		gpt2: timer@620 { /* General Purpose Timer in GPIO mode */
+		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <2>;
 			reg = <0x620 0x10>;
-			interrupts = <0x1 0xb 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 11 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpt3: timer@630 { /* General Purpose Timer in GPIO mode */
+		gpt3: timer@630 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <3>;
 			reg = <0x630 0x10>;
-			interrupts = <0x1 0xc 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 12 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpt4: timer@640 { /* General Purpose Timer in GPIO mode */
+		gpt4: timer@640 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <4>;
 			reg = <0x640 0x10>;
-			interrupts = <0x1 0xd 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 13 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpt5: timer@650 { /* General Purpose Timer in GPIO mode */
+		gpt5: timer@650 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <5>;
 			reg = <0x650 0x10>;
-			interrupts = <0x1 0xe 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 14 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpt6: timer@660 { /* General Purpose Timer in GPIO mode */
+		gpt6: timer@660 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <6>;
 			reg = <0x660 0x10>;
-			interrupts = <0x1 0xf 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 15 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpt7: timer@670 { /* General Purpose Timer in GPIO mode */
+		gpt7: timer@670 {	// General Purpose Timer in GPIO mode
 			compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
-			cell-index = <7>;
 			reg = <0x670 0x10>;
-			interrupts = <0x1 0x10 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 16 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
@@ -144,40 +128,33 @@
 		rtc@800 {	// Real time clock
 			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
 			reg = <0x800 0x100>;
-			interrupts = <0x1 0x5 0x0 0x1 0x6 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 5 0 1 6 0>;
 		};
 
 		can@900 {
 			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			cell-index = <0>;
-			interrupts = <0x2 0x11 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 17 0>;
 			reg = <0x900 0x80>;
 		};
 
 		can@980 {
 			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
-			cell-index = <1>;
-			interrupts = <0x2 0x12 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 18 0>;
 			reg = <0x980 0x80>;
 		};
 
 		gpio_simple: gpio@b00 {
 			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
-			interrupts = <0x1 0x7 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 7 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
 
-		gpio_wkup: gpio-wkup@c00 {
+		gpio_wkup: gpio@c00 {
 			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
 			reg = <0xc00 0x40>;
-			interrupts = <0x1 0x8 0x0 0x0 0x3 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <1 8 0 0 3 0>;
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
@@ -185,26 +162,22 @@
 		spi@f00 {
 			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
 			reg = <0xf00 0x20>;
-			interrupts = <0x2 0xd 0x0 0x2 0xe 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 13 0 2 14 0>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
-			interrupts = <0x2 0x6 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 6 0>;
 		};
 
 		dma-controller@1200 {
-			device_type = "dma-controller";
 			compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
 			reg = <0x1200 0x80>;
-			interrupts = <0x3 0x0 0x0  0x3 0x1 0x0  0x3 0x2 0x0  0x3 0x3 0x0
-			              0x3 0x4 0x0  0x3 0x5 0x0  0x3 0x6 0x0  0x3 0x7 0x0
-			              0x3 0x8 0x0  0x3 0x9 0x0  0x3 0xa 0x0  0x3 0xb 0x0
-			              0x3 0xc 0x0  0x3 0xd 0x0  0x3 0xe 0x0  0x3 0xf 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
 		};
 
 		xlb@1f00 {
@@ -213,24 +186,19 @@
 		};
 
 		ac97@2000 { /* PSC1 in ac97 mode */
-			device_type = "sound";
 			compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
 			cell-index = <0>;
 			reg = <0x2000 0x100>;
-			interrupts = <0x2 0x2 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 1 0>;
 		};
 
 		/* PSC2 port is used by CAN1/2 */
 
 		serial@2400 { /* PSC3 in UART mode */
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <0>;
 			cell-index = <2>;
 			reg = <0x2400 0x100>;
-			interrupts = <0x2 0x3 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 3 0>;
 		};
 
 		/* PSC4 is ??? */
@@ -238,55 +206,44 @@
 		/* PSC5 is ??? */
 
 		serial@2c00 { /* PSC6 in UART mode */
-			device_type = "serial";
 			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
-			port-number = <1>;
 			cell-index = <5>;
 			reg = <0x2c00 0x100>;
-			interrupts = <0x2 0x4 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 4 0>;
 		};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
-			local-mac-address = [00 00 00 00 00 00];
-			interrupts = <0x2 0x5 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
 			phy-handle = <&phy0>;
 		};
 
 		mdio@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "fsl,mpc5200b-mdio", "fsl,mpc5200-mdio";
-			reg = <0x3000 0x400>;	/* fec range, since we need to setup fec interrupts */
-			interrupts = <0x2 0x5 0x0>;	/* these are for "mii command finished", not link changes & co. */
-			interrupt-parent = <&mpc5200_pic>;
+			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;	// fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
 
-			phy0:ethernet-phy@0 {
-				device_type = "ethernet-phy";
-				reg = <0x0>;
+			phy0: ethernet-phy@0 {
+				reg = <0>;
 			};
 		};
 
 		ata@3a00 {
-			device_type = "ata";
 			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
 			reg = <0x3a00 0x100>;
-			interrupts = <0x2 0x7 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 7 0>;
 		};
 
 		i2c@3d00 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <0>;
 			reg = <0x3d00 0x40>;
-			interrupts = <0x2 0xf 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 15 0>;
 			fsl5200-clocking;
 		};
 
@@ -294,10 +251,8 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-			cell-index = <1>;
 			reg = <0x3d40 0x40>;
-			interrupts = <0x2 0x10 0x0>;
-			interrupt-parent = <&mpc5200_pic>;
+			interrupts = <2 16 0>;
 			fsl5200-clocking;
 			rtc@51 {
 				compatible = "nxp,pcf8563";
@@ -307,7 +262,7 @@
 		};
 
 		sram@8000 {
-			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram","sram";
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
 			reg = <0x8000 0x4000>;
 		};
 
@@ -340,22 +295,21 @@
 		device_type = "pci";
 		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
 		reg = <0xf0000d00 0x100>;
-		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-		interrupt-map = <0xc000 0x0 0x0 0x1 &mpc5200_pic 0x0 0x0 0x3 /* 1st slot */
-				 0xc000 0x0 0x0 0x2 &mpc5200_pic 0x1 0x1 0x3
-				 0xc000 0x0 0x0 0x3 &mpc5200_pic 0x1 0x2 0x3
-				 0xc000 0x0 0x0 0x4 &mpc5200_pic 0x1 0x3 0x3
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
+				 0xc000 0 0 2 &mpc5200_pic 1 1 3
+				 0xc000 0 0 3 &mpc5200_pic 1 2 3
+				 0xc000 0 0 4 &mpc5200_pic 1 3 3
 
-				 0xc800 0x0 0x0 0x1 &mpc5200_pic 0x1 0x1 0x3 /* 2nd slot */
-				 0xc800 0x0 0x0 0x2 &mpc5200_pic 0x1 0x2 0x3
-				 0xc800 0x0 0x0 0x3 &mpc5200_pic 0x1 0x3 0x3
-				 0xc800 0x0 0x0 0x4 &mpc5200_pic 0x0 0x0 0x3>;
+				 0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
+				 0xc800 0 0 2 &mpc5200_pic 1 2 3
+				 0xc800 0 0 3 &mpc5200_pic 1 3 3
+				 0xc800 0 0 4 &mpc5200_pic 0 0 3>;
 		clock-frequency = <0>; // From boot loader
-		interrupts = <0x2 0x8 0x0 0x2 0x9 0x0 0x2 0xa 0x0>;
-		interrupt-parent = <&mpc5200_pic>;
+		interrupts = <2 8 0 2 9 0 2 10 0>;
 		bus-range = <0 0>;
-		ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-			  0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x10000000
-			  0x01000000 0x0 0x00000000 0xb0000000 0x0 0x01000000>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
+			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
 	};
 };
diff --git a/arch/powerpc/boot/dts/pcm032.dts b/arch/powerpc/boot/dts/pcm032.dts
new file mode 100644
index 0000000..0300426
--- /dev/null
+++ b/arch/powerpc/boot/dts/pcm032.dts
@@ -0,0 +1,392 @@
+/*
+ * phyCORE-MPC5200B-IO (pcm032) board Device Tree Source
+ *
+ * Copyright (C) 2006-2009 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.de>
+ * Juergen Beisert <j.beisert@pengutronix.de>
+ * Wolfram Sang <w.sang@pengutronix.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 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "phytec,pcm032";
+	compatible = "phytec,pcm032";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB
+	};
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200b-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		timer@610 {	// General Purpose Timer
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x610 0x10>;
+			interrupts = <1 10 0>;
+		};
+
+		gpt2: timer@620 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x620 0x10>;
+			interrupts = <1 11 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpt3: timer@630 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x630 0x10>;
+			interrupts = <1 12 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpt4: timer@640 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x640 0x10>;
+			interrupts = <1 13 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpt5: timer@650 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x650 0x10>;
+			interrupts = <1 14 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpt6: timer@660 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x660 0x10>;
+			interrupts = <1 15 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpt7: timer@670 {	// General Purpose Timer in GPIO mode
+			compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
+			reg = <0x670 0x10>;
+			interrupts = <1 16 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		rtc@800 {	// Real time clock
+			compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
+			reg = <0x800 0x100>;
+			interrupts = <1 5 0 1 6 0>;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200b-mscan","fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		gpio_wkup: gpio@c00 {
+			compatible = "fsl,mpc5200b-gpio-wkup","fsl,mpc5200-gpio-wkup";
+			reg = <0xc00 0x40>;
+			interrupts = <1 8 0 0 3 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		spi@f00 {
+			compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+			reg = <0xf00 0x20>;
+			interrupts = <2 13 0 2 14 0>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200b-ohci","fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			compatible = "fsl,mpc5200b-bestcomm","fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		ac97@2000 {	/* PSC1 is ac97 */
+			compatible = "fsl,mpc5200b-psc-ac97","fsl,mpc5200-psc-ac97";
+			cell-index = <0>;
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		/* PSC2 port is used by CAN1/2 */
+
+		serial@2400 { /* PSC3 in UART mode */
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			cell-index = <2>;
+			reg = <0x2400 0x100>;
+			interrupts = <2 3 0>;
+		};
+
+		/* PSC4 is ??? */
+
+		/* PSC5 is ??? */
+
+		serial@2c00 { /* PSC6 in UART mode */
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+			cell-index = <5>;
+			reg = <0x2c00 0x100>;
+			interrupts = <2 4 0>;
+		};
+
+		ethernet@3000 {
+			compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			phy-handle = <&phy0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;	// fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;	// these are for "mii command finished", not link changes & co.
+
+			phy0: ethernet-phy@0 {
+				reg = <0>;
+			};
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+			fsl5200-clocking;
+		};
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+			fsl5200-clocking;
+			rtc@51 {
+				compatible = "nxp,pcf8563";
+				reg = <0x51>;
+			};
+			eeprom@52 {
+				compatible = "at24,24c32";
+				reg = <0x52>;
+			};
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200b-pci","fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3 // 1st slot
+				 0xc000 0 0 2 &mpc5200_pic 1 1 3
+				 0xc000 0 0 3 &mpc5200_pic 1 2 3
+				 0xc000 0 0 4 &mpc5200_pic 1 3 3
+
+				 0xc800 0 0 1 &mpc5200_pic 1 1 3 // 2nd slot
+				 0xc800 0 0 2 &mpc5200_pic 1 2 3
+				 0xc800 0 0 3 &mpc5200_pic 1 3 3
+				 0xc800 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
+			  0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200b-lpb","fsl,mpc5200-lpb","simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		ranges = <0 0 0xfe000000 0x02000000
+			  1 0 0xfc000000 0x02000000
+			  2 0 0xfbe00000 0x00200000
+			  3 0 0xf9e00000 0x02000000
+			  4 0 0xf7e00000 0x02000000
+			  5 0 0xe6000000 0x02000000
+			  6 0 0xe8000000 0x02000000
+			  7 0 0xea000000 0x02000000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@0 {
+				label = "ubootl";
+				reg = <0x00000000 0x00040000>;
+			};
+			partition@40000 {
+				label = "kernel";
+				reg = <0x00040000 0x001c0000>;
+			};
+			partition@200000 {
+				label = "jffs2";
+				reg = <0x00200000 0x01d00000>;
+			};
+			partition@1f00000 {
+				label = "uboot";
+				reg = <0x01f00000 0x00040000>;
+			};
+			partition@1f40000 {
+				label = "env";
+				reg = <0x01f40000 0x00040000>;
+			};
+			partition@1f80000 {
+				label = "oftree";
+				reg = <0x01f80000 0x00040000>;
+			};
+			partition@1fc0000 {
+				label = "space";
+				reg = <0x01fc0000 0x00040000>;
+			};
+		};
+
+		sram@2,0 {
+			compatible = "mtd-ram";
+			reg = <2 0 0x00200000>;
+			bank-width = <2>;
+		};
+
+                /*
+		 * example snippets for FPGA
+		 *
+		 * fpga@3,0 {
+		 *         compatible = "fpga_driver";
+		 *         reg = <3 0 0x02000000>;
+		 *         bank-width = <4>;
+		 * };
+		 *
+		 * fpga@4,0 {
+		 *         compatible = "fpga_driver";
+		 *         reg = <4 0 0x02000000>;
+		 *         bank-width = <4>;
+		 * };
+                 */
+
+                /*
+		 * example snippets for free chipselects
+                 *
+		 * device@5,0 {
+		 *         compatible = "custom_driver";
+		 *         reg = <5 0 0x02000000>;
+		 * };
+                 *
+		 * device@6,0 {
+		 *         compatible = "custom_driver";
+		 *         reg = <6 0 0x02000000>;
+		 * };
+                 *
+		 * device@7,0 {
+		 *         compatible = "custom_driver";
+		 *         reg = <7 0 0x02000000>;
+		 * };
+                 */
+	};
+};
+
diff --git a/arch/powerpc/boot/dts/redwood.dts b/arch/powerpc/boot/dts/redwood.dts
new file mode 100644
index 0000000..ad402c4
--- /dev/null
+++ b/arch/powerpc/boot/dts/redwood.dts
@@ -0,0 +1,244 @@
+/*
+ * Device Tree Source for AMCC Redwood(460SX)
+ *
+ * Copyright 2008 AMCC <tmarri@amcc.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/;
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	model = "amcc,redwood";
+	compatible = "amcc,redwood";
+	dcr-parent = <&{/cpus/cpu@0}>;
+
+	aliases {
+		ethernet0 = &EMAC0;
+		serial0 = &UART0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			model = "PowerPC,460SX";
+			reg = <0x00000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+			timebase-frequency = <0>; /* Filled in by U-Boot */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+			dcr-controller;
+			dcr-access-method = "native";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+	};
+
+	UIC0: interrupt-controller0 {
+		compatible = "ibm,uic-460sx","ibm,uic";
+		interrupt-controller;
+		cell-index = <0>;
+		dcr-reg = <0x0c0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+	};
+
+	UIC1: interrupt-controller1 {
+		compatible = "ibm,uic-460sx","ibm,uic";
+		interrupt-controller;
+		cell-index = <1>;
+		dcr-reg = <0x0d0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC2: interrupt-controller2 {
+		compatible = "ibm,uic-460sx","ibm,uic";
+		interrupt-controller;
+		cell-index = <2>;
+		dcr-reg = <0x0e0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	UIC3: interrupt-controller3 {
+		compatible = "ibm,uic-460sx","ibm,uic";
+		interrupt-controller;
+		cell-index = <3>;
+		dcr-reg = <0x0f0 0x009>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		#interrupt-cells = <2>;
+		interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+		interrupt-parent = <&UIC0>;
+	};
+
+	SDR0: sdr {
+		compatible = "ibm,sdr-460sx";
+		dcr-reg = <0x00e 0x002>;
+	};
+
+	CPR0: cpr {
+		compatible = "ibm,cpr-460sx";
+		dcr-reg = <0x00c 0x002>;
+	};
+
+	plb {
+		compatible = "ibm,plb-460sx", "ibm,plb4";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+		clock-frequency = <0>; /* Filled in by U-Boot */
+
+		SDRAM0: sdram {
+			compatible = "ibm,sdram-460sx", "ibm,sdram-405gp";
+			dcr-reg = <0x010 0x002>;
+		};
+
+		MAL0: mcmal {
+			compatible = "ibm,mcmal-460sx", "ibm,mcmal2";
+			dcr-reg = <0x180 0x62>;
+			num-tx-chans = <4>;
+			num-rx-chans = <32>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			interrupt-parent = <&UIC1>;
+			interrupts = <	/*TXEOB*/ 0x6 0x4
+					/*RXEOB*/ 0x7 0x4
+					/*SERR*/  0x1 0x4
+					/*TXDE*/  0x2 0x4
+					/*RXDE*/  0x3 0x4
+					/*COAL TX0*/ 0x18 0x2
+					/*COAL TX1*/ 0x19 0x2
+					/*COAL TX2*/ 0x1a 0x2
+					/*COAL TX3*/ 0x1b 0x2
+					/*COAL RX0*/ 0x1c 0x2
+					/*COAL RX1*/ 0x1d 0x2
+					/*COAL RX2*/ 0x1e 0x2
+					/*COAL RX3*/ 0x1f 0x2>;
+		};
+
+		POB0: opb {
+			compatible = "ibm,opb-460sx", "ibm,opb";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+			clock-frequency = <0>; /* Filled in by U-Boot */
+
+			EBC0: ebc {
+				compatible = "ibm,ebc-460sx", "ibm,ebc";
+				dcr-reg = <0x012 0x002>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				/* ranges property is supplied by U-Boot */
+				interrupts = <0x6 0x4>;
+				interrupt-parent = <&UIC1>;
+
+				nor_flash@0,0 {
+					compatible = "amd,s29gl512n", "cfi-flash";
+					bank-width = <2>;
+					reg = <0x0000000 0x00000000 0x04000000>;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					partition@0 {
+						label = "kernel";
+						reg = <0x00000000 0x001e0000>;
+					};
+					partition@1e0000 {
+						label = "dtb";
+						reg = <0x001e0000 0x00020000>;
+					};
+					partition@200000 {
+						label = "ramdisk";
+						reg = <0x00200000 0x01400000>;
+					};
+					partition@1600000 {
+						label = "jffs2";
+						reg = <0x01600000 0x00400000>;
+					};
+					partition@1a00000 {
+						label = "user";
+						reg = <0x01a00000 0x02560000>;
+					};
+					partition@3f60000 {
+						label = "env";
+						reg = <0x03f60000 0x00040000>;
+					};
+					partition@3fa0000 {
+						label = "u-boot";
+						reg = <0x03fa0000 0x00060000>;
+					};
+				};
+			};
+
+			UART0: serial@ef600200 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0xef600200 0x00000008>;
+				virtual-reg = <0xef600200>;
+				clock-frequency = <0>; /* Filled in by U-Boot */
+				current-speed = <0>; /* Filled in by U-Boot */
+				interrupt-parent = <&UIC0>;
+				interrupts = <0x0 0x4>;
+			};
+
+			RGMII0: emac-rgmii@ef600900 {
+				compatible = "ibm,rgmii-460sx", "ibm,rgmii";
+				reg = <0xef600900 0x00000008>;
+			};
+
+			EMAC0: ethernet@ef600a00 {
+				device_type = "network";
+				compatible = "ibm,emac-460sx", "ibm,emac4";
+				interrupt-parent = <&EMAC0>;
+				interrupts = <0x0 0x1>;
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = </*Status*/ 0x0 &UIC0 0x13 0x4
+						 /*Wake*/   0x1 &UIC2 0x1d 0x4>;
+				reg = <0xef600a00 0x00000070>;
+				local-mac-address = [000000000000]; /* Filled in by U-Boot */
+				mal-device = <&MAL0>;
+				mal-tx-channel = <0>;
+				mal-rx-channel = <0>;
+				cell-index = <0>;
+				max-frame-size = <9000>;
+				rx-fifo-size = <4096>;
+				tx-fifo-size = <2048>;
+				phy-mode = "rgmii";
+				phy-map = <0x00000000>;
+				rgmii-device = <&RGMII0>;
+				rgmii-channel = <0>;
+				has-inverted-stacr-oc;
+				has-new-stacr-staopc;
+			};
+
+		};
+
+	};
+	chosen {
+		linux,stdout-path = "/plb/opb/serial@ef600200";
+	};
+
+};
diff --git a/arch/powerpc/boot/dts/sbc8349.dts b/arch/powerpc/boot/dts/sbc8349.dts
index 8d365a5..a36dbbc 100644
--- a/arch/powerpc/boot/dts/sbc8349.dts
+++ b/arch/powerpc/boot/dts/sbc8349.dts
@@ -159,68 +159,76 @@
 			phy_type = "ulpi";
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@19 {
-				interrupt-parent = <&ipic>;
-				interrupts = <20 0x8>;
-				reg = <0x19>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1a {
-				interrupt-parent = <&ipic>;
-				interrupts = <21 0x8>;
-				reg = <0x1a>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <32 0x8 33 0x8 34 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			linux,network-index = <0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@19 {
+					interrupt-parent = <&ipic>;
+					interrupts = <20 0x8>;
+					reg = <0x19>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1a {
+					interrupt-parent = <&ipic>;
+					interrupts = <21 0x8>;
+					reg = <0x1a>;
+					device_type = "ethernet-phy";
+				};
+
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 0x8 36 0x8 37 0x8>;
 			interrupt-parent = <&ipic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			linux,network-index = <1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/sbc8548.dts b/arch/powerpc/boot/dts/sbc8548.dts
index 2baf4a5..9c5079f 100644
--- a/arch/powerpc/boot/dts/sbc8548.dts
+++ b/arch/powerpc/boot/dts/sbc8548.dts
@@ -234,66 +234,72 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@19 {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x6 0x1>;
-				reg = <0x19>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1a {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x7 0x1>;
-				reg = <0x1a>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@19 {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x6 0x1>;
+					reg = <0x19>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1a {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x7 0x1>;
+					reg = <0x1a>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/sbc8560.dts b/arch/powerpc/boot/dts/sbc8560.dts
index 01542f7..b772405 100644
--- a/arch/powerpc/boot/dts/sbc8560.dts
+++ b/arch/powerpc/boot/dts/sbc8560.dts
@@ -139,77 +139,83 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy0: ethernet-phy@19 {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x6 0x1>;
-				reg = <0x19>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@1a {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x7 0x1>;
-				reg = <0x1a>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@1b {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x8 0x1>;
-				reg = <0x1b>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@1c {
-				interrupt-parent = <&mpic>;
-				interrupts = <0x8 0x1>;
-				reg = <0x1c>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+				phy0: ethernet-phy@19 {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x6 0x1>;
+					reg = <0x19>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@1a {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x7 0x1>;
+					reg = <0x1a>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@1b {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x8 0x1>;
+					reg = <0x1b>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@1c {
+					interrupt-parent = <&mpic>;
+					interrupts = <0x8 0x1>;
+					reg = <0x1c>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		mpic: pic@40000 {
diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
index 36db981..e3e914e 100644
--- a/arch/powerpc/boot/dts/sbc8641d.dts
+++ b/arch/powerpc/boot/dts/sbc8641d.dts
@@ -192,132 +192,144 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy0: ethernet-phy@1f {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0x1f>;
-				device_type = "ethernet-phy";
-			};
-			phy1: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <10 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30  2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@1f {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0x1f>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <10 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy2>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy3>;
 			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/socrates.dts b/arch/powerpc/boot/dts/socrates.dts
new file mode 100644
index 0000000..b8d0fc6
--- /dev/null
+++ b/arch/powerpc/boot/dts/socrates.dts
@@ -0,0 +1,338 @@
+/*
+ * Device Tree Source for the Socrates board (MPC8544).
+ *
+ * Copyright (c) 2008 Emcraft Systems.
+ * Sergei Poselenov, <sposelenov@emcraft.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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "abb,socrates";
+	compatible = "abb,socrates";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8544@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000>;	// Filled in by U-Boot
+	};
+
+	soc8544@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		ranges = <0x00000000 0xe0000000 0x00100000>;
+		reg = <0xe0000000 0x00001000>;	// CCSRBAR 1M
+		bus-frequency = <0>;		// Filled in by U-Boot
+		compatible = "fsl,mpc8544-immr", "simple-bus";
+
+		memory-controller@2000 {
+			compatible = "fsl,mpc8544-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,mpc8544-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;
+			cache-size = <0x40000>;	// L2, 256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+
+			dtt@28 {
+				compatible = "winbond,w83782d";
+				reg = <0x28>;
+			};
+			rtc@32 {
+				compatible = "epson,rx8025";
+				reg = <0x32>;
+				interrupts = <7 1>;
+				interrupt-parent = <&mpic>;
+			};
+			dtt@4c {
+				compatible = "dallas,ds75";
+				reg = <0x4c>;
+			};
+			ts@4a {
+				compatible = "ti,tsc2003";
+				reg = <0x4a>;
+				interrupt-parent = <&mpic>;
+				interrupts = <8 1>;
+			};
+		};
+
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <0x3100 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy0>;
+			tbi-handle = <&tbi0>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <0 1>;
+					reg = <0>;
+				};
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <0 1>;
+					reg = <1>;
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+				};
+			};
+		};
+
+		enet1: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <31 2 32 2 33 2>;
+			interrupt-parent = <&mpic>;
+			phy-handle = <&phy1>;
+			tbi-handle = <&tbi1>;
+			phy-connection-type = "rgmii-id";
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;
+			clock-frequency = <0>;
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			compatible = "fsl,mpc8548-guts";
+			reg = <0xe0000 0x1000>;
+			fsl,has-rstcr;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+	};
+
+
+	localbus {
+		compatible = "fsl,mpc8544-localbus",
+		             "fsl,pq3-localbus",
+			     "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0xe0005000 0x40>;
+
+		ranges = <0 0 0xfc000000 0x04000000
+			  2 0 0xc8000000 0x04000000
+			  3 0 0xc0000000 0x00100000
+			>; /* Overwritten by U-Boot */
+
+		nor_flash@0,0 {
+			compatible = "amd,s29gl256n", "cfi-flash";
+			bank-width = <2>;
+			reg = <0x0 0x000000 0x4000000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				label = "kernel";
+				reg = <0x0 0x1e0000>;
+				read-only;
+			};
+			partition@1e0000 {
+				label = "dtb";
+				reg = <0x1e0000 0x20000>;
+			};
+			partition@200000 {
+				label = "root";
+				reg = <0x200000 0x200000>;
+			};
+			partition@400000 {
+				label = "user";
+				reg = <0x400000 0x3b80000>;
+			};
+			partition@3f80000 {
+				label = "env";
+				reg = <0x3f80000 0x40000>;
+				read-only;
+			};
+			partition@3fc0000 {
+				label = "u-boot";
+				reg = <0x3fc0000 0x40000>;
+				read-only;
+			};
+		};
+
+		display@2,0 {
+			compatible = "fujitsu,lime";
+			reg = <2 0x0 0x4000000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <6 1>;
+		};
+
+		fpga_pic: fpga-pic@3,10 {
+			compatible = "abb,socrates-fpga-pic";
+			reg = <3 0x10 0x10>;
+			interrupt-controller;
+			/* IRQs 2, 10, 11, active low, level-sensitive */
+			interrupts = <2 1 10 1 11 1>;
+			interrupt-parent = <&mpic>;
+			#interrupt-cells = <3>;
+		};
+
+		spi@3,60 {
+			compatible = "abb,socrates-spi";
+			reg = <3 0x60 0x10>;
+			interrupts = <8 4 0>;	// number, type, routing
+			interrupt-parent = <&fpga_pic>;
+		};
+
+		nand@3,70 {
+			compatible = "abb,socrates-nand";
+			reg = <3 0x70 0x04>;
+			bank-width = <1>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			data@0 {
+				label = "data";
+				reg = <0x0 0x40000000>;
+			};
+		};
+
+		can@3,100 {
+			compatible = "philips,sja1000";
+			reg = <3 0x100 0x80>;
+			interrupts = <2 8 1>;	// number, type, routing
+			interrupt-parent = <&fpga_pic>;
+		};
+	};
+
+	pci0: pci@e0008000 {
+		cell-index = <0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+		reg = <0xe0008000 0x1000>;
+		clock-frequency = <66666666>;
+
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+				/* IDSEL 0x11 */
+				 0x8800 0x0 0x0 1 &mpic 5 1
+				/* IDSEL 0x12 */
+				 0x9000 0x0 0x0 1 &mpic 4 1>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0x0 0x0>;
+		ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x01000000>;
+	};
+
+};
diff --git a/arch/powerpc/boot/dts/stx_gp3_8560.dts b/arch/powerpc/boot/dts/stx_gp3_8560.dts
index fff33fe..8b17395 100644
--- a/arch/powerpc/boot/dts/stx_gp3_8560.dts
+++ b/arch/powerpc/boot/dts/stx_gp3_8560.dts
@@ -124,66 +124,72 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 4>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy4: ethernet-phy@4 {
-				interrupt-parent = <&mpic>;
-				interrupts = <5 4>;
-				reg = <4>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 4>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy4: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 4>;
+					reg = <4>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy4>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		mpic: pic@40000 {
diff --git a/arch/powerpc/boot/dts/tqm5200.dts b/arch/powerpc/boot/dts/tqm5200.dts
index 906302e..c9590b5 100644
--- a/arch/powerpc/boot/dts/tqm5200.dts
+++ b/arch/powerpc/boot/dts/tqm5200.dts
@@ -17,6 +17,7 @@
 	compatible = "tqc,tqm5200";
 	#address-cells = <1>;
 	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -66,36 +67,33 @@
 			compatible = "fsl,mpc5200-gpt";
 			reg = <0x600 0x10>;
 			interrupts = <1 9 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl,has-wdt;
 		};
 
 		can@900 {
 			compatible = "fsl,mpc5200-mscan";
 			interrupts = <2 17 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x900 0x80>;
 		};
 
 		can@980 {
 			compatible = "fsl,mpc5200-mscan";
 			interrupts = <2 18 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			reg = <0x980 0x80>;
 		};
 
-		gpio@b00 {
+		gpio_simple: gpio@b00 {
 			compatible = "fsl,mpc5200-gpio";
 			reg = <0xb00 0x40>;
 			interrupts = <1 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		usb@1000 {
 			compatible = "fsl,mpc5200-ohci","ohci-be";
 			reg = <0x1000 0xff>;
 			interrupts = <2 6 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		dma-controller@1200 {
@@ -105,7 +103,6 @@
 			              3 4 0  3 5 0  3 6 0  3 7 0
 			              3 8 0  3 9 0  3 10 0  3 11 0
 			              3 12 0  3 13 0  3 14 0  3 15 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		xlb@1f00 {
@@ -114,39 +111,28 @@
 		};
 
 		serial@2000 {		// PSC1
-			device_type = "serial";
 			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <0>;  // Logical port assignment
 			reg = <0x2000 0x100>;
 			interrupts = <2 1 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		serial@2200 {		// PSC2
-			device_type = "serial";
 			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <1>;  // Logical port assignment
 			reg = <0x2200 0x100>;
 			interrupts = <2 2 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		serial@2400 {		// PSC3
-			device_type = "serial";
 			compatible = "fsl,mpc5200-psc-uart";
-			port-number = <2>;  // Logical port assignment
 			reg = <0x2400 0x100>;
 			interrupts = <2 3 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		ethernet@3000 {
-			device_type = "network";
 			compatible = "fsl,mpc5200-fec";
 			reg = <0x3000 0x400>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <2 5 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			phy-handle = <&phy0>;
 		};
 
@@ -156,10 +142,8 @@
 			compatible = "fsl,mpc5200-mdio";
 			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
 			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
-			interrupt-parent = <&mpc5200_pic>;
 
 			phy0: ethernet-phy@0 {
-				device_type = "ethernet-phy";
 				reg = <0>;
 			};
 		};
@@ -168,7 +152,6 @@
 			compatible = "fsl,mpc5200-ata";
 			reg = <0x3a00 0x100>;
 			interrupts = <2 7 0>;
-			interrupt-parent = <&mpc5200_pic>;
 		};
 
 		i2c@3d40 {
@@ -177,7 +160,6 @@
 			compatible = "fsl,mpc5200-i2c","fsl-i2c";
 			reg = <0x3d40 0x40>;
 			interrupts = <2 16 0>;
-			interrupt-parent = <&mpc5200_pic>;
 			fsl5200-clocking;
 
 			 rtc@68 {
@@ -192,9 +174,8 @@
 		};
 	};
 
-	lpb {
-		model = "fsl,lpb";
-		compatible = "fsl,lpb";
+	localbus {
+		compatible = "fsl,mpc5200-lpb","simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <0 0 0xfc000000 0x02000000>;
@@ -223,7 +204,6 @@
 				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
 		clock-frequency = <0>; // From boot loader
 		interrupts = <2 8 0 2 9 0 2 10 0>;
-		interrupt-parent = <&mpc5200_pic>;
 		bus-range = <0 0>;
 		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
 			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
diff --git a/arch/powerpc/boot/dts/tqm8540.dts b/arch/powerpc/boot/dts/tqm8540.dts
index a693f01..ac9413a 100644
--- a/arch/powerpc/boot/dts/tqm8540.dts
+++ b/arch/powerpc/boot/dts/tqm8540.dts
@@ -84,6 +84,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -131,94 +136,103 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <41 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/tqm8541.dts b/arch/powerpc/boot/dts/tqm8541.dts
index 9e3f5f0d..c71bb5d 100644
--- a/arch/powerpc/boot/dts/tqm8541.dts
+++ b/arch/powerpc/boot/dts/tqm8541.dts
@@ -83,6 +83,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -130,72 +135,78 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 15086eb..28b1a95 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -85,6 +85,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -143,134 +148,146 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			phy4: ethernet-phy@4 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <4>;
-				device_type = "ethernet-phy";
-			};
-			phy5: ethernet-phy@5 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <5>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				phy4: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <4>;
+					device_type = "ethernet-phy";
+				};
+				phy5: ethernet-phy@5 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <5>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy4>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -365,14 +382,14 @@
 		can0@2,0 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x0 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 
 		can1@2,100 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x100 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index b7b65f5..826fb62 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -85,6 +85,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -143,134 +148,146 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@0 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			phy4: ethernet-phy@4 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <4>;
-				device_type = "ethernet-phy";
-			};
-			phy5: ethernet-phy@5 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <5>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@26520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x26520 0x20>;
-
-			tbi2: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@27520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x27520 0x20>;
-
-			tbi3: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@0 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				phy4: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <4>;
+					device_type = "ethernet-phy";
+				};
+				phy5: ethernet-phy@5 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <5>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet2: ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x26000 0x1000>;
+			ranges = <0x0 0x26000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <31 2 32 2 33 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi2>;
 			phy-handle = <&phy3>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi2: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet3: ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <0x27000 0x1000>;
+			ranges = <0x0 0x27000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 2 38 2 39 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi3>;
 			phy-handle = <&phy4>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi3: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
@@ -365,14 +382,14 @@
 		can0@2,0 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x0 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 
 		can1@2,100 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x100 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 
diff --git a/arch/powerpc/boot/dts/tqm8555.dts b/arch/powerpc/boot/dts/tqm8555.dts
index cf92b4e..a133ded 100644
--- a/arch/powerpc/boot/dts/tqm8555.dts
+++ b/arch/powerpc/boot/dts/tqm8555.dts
@@ -83,6 +83,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -130,72 +135,78 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		serial0: serial@4500 {
diff --git a/arch/powerpc/boot/dts/tqm8560.dts b/arch/powerpc/boot/dts/tqm8560.dts
index 9e1ab2d..649e2e5 100644
--- a/arch/powerpc/boot/dts/tqm8560.dts
+++ b/arch/powerpc/boot/dts/tqm8560.dts
@@ -85,6 +85,11 @@
 			interrupt-parent = <&mpic>;
 			dfsrr;
 
+			dtt@50 {
+				compatible = "national,lm75";
+				reg = <0x50>;
+			};
+
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -132,72 +137,78 @@
 			};
 		};
 
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-			phy2: ethernet-phy@2 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <2>;
-				device_type = "ethernet-phy";
-			};
-			phy3: ethernet-phy@3 {
-				interrupt-parent = <&mpic>;
-				interrupts = <8 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-			tbi0: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
-		mdio@25520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-tbi";
-			reg = <0x25520 0x20>;
-
-			tbi1: tbi-phy@11 {
-				reg = <0x11>;
-				device_type = "tbi-phy";
-			};
-		};
-
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2 30 2 34 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi0>;
 			phy-handle = <&phy2>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+				phy2: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <2>;
+					device_type = "ethernet-phy";
+				};
+				phy3: ethernet-phy@3 {
+					interrupt-parent = <&mpic>;
+					interrupts = <8 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
 			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <35 2 36 2 40 2>;
 			interrupt-parent = <&mpic>;
 			tbi-handle = <&tbi1>;
 			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
 		};
 
 		mpic: pic@40000 {
@@ -335,14 +346,14 @@
 		can0@2,0 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x0 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 
 		can1@2,100 {
 			compatible = "intel,82527"; // Bosch CC770
 			reg = <2 0x100 0x100>;
-			interrupts = <4 0>;
+			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
 		};
 	};
diff --git a/arch/powerpc/boot/dts/virtex440-ml507.dts b/arch/powerpc/boot/dts/virtex440-ml507.dts
index dc8e78e..52d8c1a 100644
--- a/arch/powerpc/boot/dts/virtex440-ml507.dts
+++ b/arch/powerpc/boot/dts/virtex440-ml507.dts
@@ -7,6 +7,15 @@
  * 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.
+ *
+ * ---
+ *
+ * Device Tree Generator version: 1.1
+ *
+ * CAUTION: This file is automatically generated by libgen.
+ * Version: Xilinx EDK 10.1.03 EDK_K_SP3.6
+ *
+ * XPS project directory: ml507_ppc440_emb_ref
  */
 
 /dts-v1/;
@@ -22,8 +31,8 @@
 		reg = < 0 0x10000000 >;
 	} ;
 	chosen {
-		bootargs = "console=ttyS0 ip=on root=/dev/ram";
-		linux,stdout-path = "/plb@0/serial@83e00000";
+		bootargs = "console=ttyS0 root=/dev/ram";
+		linux,stdout-path = &RS232_Uart_1;
 	} ;
 	cpus {
 		#address-cells = <1>;
@@ -136,19 +145,19 @@
 				compatible = "xlnx,ll-dma-1.00.a";
 				dcr-reg = < 0x80 0x11 >;
 				interrupt-parent = <&xps_intc_0>;
-				interrupts = < 9 2 0xa 2 >;
+				interrupts = < 10 2 11 2 >;
 			} ;
 		} ;
 	} ;
 	plb_v46_0: plb@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "xlnx,plb-v46-1.02.a", "simple-bus";
+		compatible = "xlnx,plb-v46-1.03.a", "simple-bus";
 		ranges ;
 		DIP_Switches_8Bit: gpio@81460000 {
 			compatible = "xlnx,xps-gpio-1.00.a";
 			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 6 2 >;
+			interrupts = < 7 2 >;
 			reg = < 0x81460000 0x10000 >;
 			xlnx,all-inputs = <1>;
 			xlnx,all-inputs-2 = <0>;
@@ -163,6 +172,86 @@
 			xlnx,tri-default = <0xffffffff>;
 			xlnx,tri-default-2 = <0xffffffff>;
 		} ;
+		FLASH: flash@fc000000 {
+			bank-width = <2>;
+			compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash";
+			reg = < 0xfc000000 0x2000000 >;
+			xlnx,family = "virtex5";
+			xlnx,include-datawidth-matching-0 = <0x1>;
+			xlnx,include-datawidth-matching-1 = <0x0>;
+			xlnx,include-datawidth-matching-2 = <0x0>;
+			xlnx,include-datawidth-matching-3 = <0x0>;
+			xlnx,include-negedge-ioregs = <0x0>;
+			xlnx,include-plb-ipif = <0x1>;
+			xlnx,include-wrbuf = <0x1>;
+			xlnx,max-mem-width = <0x10>;
+			xlnx,mch-native-dwidth = <0x20>;
+			xlnx,mch-plb-clk-period-ps = <0x2710>;
+			xlnx,mch-splb-awidth = <0x20>;
+			xlnx,mch0-accessbuf-depth = <0x10>;
+			xlnx,mch0-protocol = <0x0>;
+			xlnx,mch0-rddatabuf-depth = <0x10>;
+			xlnx,mch1-accessbuf-depth = <0x10>;
+			xlnx,mch1-protocol = <0x0>;
+			xlnx,mch1-rddatabuf-depth = <0x10>;
+			xlnx,mch2-accessbuf-depth = <0x10>;
+			xlnx,mch2-protocol = <0x0>;
+			xlnx,mch2-rddatabuf-depth = <0x10>;
+			xlnx,mch3-accessbuf-depth = <0x10>;
+			xlnx,mch3-protocol = <0x0>;
+			xlnx,mch3-rddatabuf-depth = <0x10>;
+			xlnx,mem0-width = <0x10>;
+			xlnx,mem1-width = <0x20>;
+			xlnx,mem2-width = <0x20>;
+			xlnx,mem3-width = <0x20>;
+			xlnx,num-banks-mem = <0x1>;
+			xlnx,num-channels = <0x2>;
+			xlnx,priority-mode = <0x0>;
+			xlnx,synch-mem-0 = <0x0>;
+			xlnx,synch-mem-1 = <0x0>;
+			xlnx,synch-mem-2 = <0x0>;
+			xlnx,synch-mem-3 = <0x0>;
+			xlnx,synch-pipedelay-0 = <0x2>;
+			xlnx,synch-pipedelay-1 = <0x2>;
+			xlnx,synch-pipedelay-2 = <0x2>;
+			xlnx,synch-pipedelay-3 = <0x2>;
+			xlnx,tavdv-ps-mem-0 = <0x1adb0>;
+			xlnx,tavdv-ps-mem-1 = <0x3a98>;
+			xlnx,tavdv-ps-mem-2 = <0x3a98>;
+			xlnx,tavdv-ps-mem-3 = <0x3a98>;
+			xlnx,tcedv-ps-mem-0 = <0x1adb0>;
+			xlnx,tcedv-ps-mem-1 = <0x3a98>;
+			xlnx,tcedv-ps-mem-2 = <0x3a98>;
+			xlnx,tcedv-ps-mem-3 = <0x3a98>;
+			xlnx,thzce-ps-mem-0 = <0x88b8>;
+			xlnx,thzce-ps-mem-1 = <0x1b58>;
+			xlnx,thzce-ps-mem-2 = <0x1b58>;
+			xlnx,thzce-ps-mem-3 = <0x1b58>;
+			xlnx,thzoe-ps-mem-0 = <0x1b58>;
+			xlnx,thzoe-ps-mem-1 = <0x1b58>;
+			xlnx,thzoe-ps-mem-2 = <0x1b58>;
+			xlnx,thzoe-ps-mem-3 = <0x1b58>;
+			xlnx,tlzwe-ps-mem-0 = <0x88b8>;
+			xlnx,tlzwe-ps-mem-1 = <0x0>;
+			xlnx,tlzwe-ps-mem-2 = <0x0>;
+			xlnx,tlzwe-ps-mem-3 = <0x0>;
+			xlnx,twc-ps-mem-0 = <0x2af8>;
+			xlnx,twc-ps-mem-1 = <0x3a98>;
+			xlnx,twc-ps-mem-2 = <0x3a98>;
+			xlnx,twc-ps-mem-3 = <0x3a98>;
+			xlnx,twp-ps-mem-0 = <0x11170>;
+			xlnx,twp-ps-mem-1 = <0x2ee0>;
+			xlnx,twp-ps-mem-2 = <0x2ee0>;
+			xlnx,twp-ps-mem-3 = <0x2ee0>;
+			xlnx,xcl0-linesize = <0x4>;
+			xlnx,xcl0-writexfer = <0x1>;
+			xlnx,xcl1-linesize = <0x4>;
+			xlnx,xcl1-writexfer = <0x1>;
+			xlnx,xcl2-linesize = <0x4>;
+			xlnx,xcl2-writexfer = <0x1>;
+			xlnx,xcl3-linesize = <0x4>;
+			xlnx,xcl3-writexfer = <0x1>;
+		} ;
 		Hard_Ethernet_MAC: xps-ll-temac@81c00000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -185,6 +274,19 @@
 				xlnx,txfifo = <0x1000>;
 			} ;
 		} ;
+		IIC_EEPROM: i2c@81600000 {
+			compatible = "xlnx,xps-iic-2.00.a";
+			interrupt-parent = <&xps_intc_0>;
+			interrupts = < 6 2 >;
+			reg = < 0x81600000 0x10000 >;
+			xlnx,clk-freq = <0x5f5e100>;
+			xlnx,family = "virtex5";
+			xlnx,gpo-width = <0x1>;
+			xlnx,iic-freq = <0x186a0>;
+			xlnx,scl-inertial-delay = <0x0>;
+			xlnx,sda-inertial-delay = <0x0>;
+			xlnx,ten-bit-adr = <0x0>;
+		} ;
 		LEDs_8Bit: gpio@81400000 {
 			compatible = "xlnx,xps-gpio-1.00.a";
 			reg = < 0x81400000 0x10000 >;
@@ -220,7 +322,7 @@
 		Push_Buttons_5Bit: gpio@81440000 {
 			compatible = "xlnx,xps-gpio-1.00.a";
 			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 7 2 >;
+			interrupts = < 8 2 >;
 			reg = < 0x81440000 0x10000 >;
 			xlnx,all-inputs = <1>;
 			xlnx,all-inputs-2 = <0>;
@@ -237,13 +339,13 @@
 		} ;
 		RS232_Uart_1: serial@83e00000 {
 			clock-frequency = <100000000>;
-			compatible = "xlnx,xps-uart16550-2.00.a", "ns16550";
-			current-speed = <0x2580>;
+			compatible = "xlnx,xps-uart16550-2.00.b", "ns16550";
+			current-speed = <9600>;
 			device_type = "serial";
 			interrupt-parent = <&xps_intc_0>;
-			interrupts = < 8 2 >;
+			interrupts = < 9 2 >;
 			reg = < 0x83e00000 0x10000 >;
-			reg-offset = <3>;
+			reg-offset = <0x1003>;
 			reg-shift = <2>;
 			xlnx,family = "virtex5";
 			xlnx,has-external-rclk = <0>;
@@ -268,7 +370,7 @@
 			compatible = "xlnx,xps-intc-1.00.a";
 			interrupt-controller ;
 			reg = < 0x81800000 0x10000 >;
-			xlnx,num-intr-inputs = <0xb>;
+			xlnx,num-intr-inputs = <0xc>;
 		} ;
 		xps_timebase_wdt_1: xps-timebase-wdt@83a00000 {
 			compatible = "xlnx,xps-timebase-wdt-1.00.b";
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index 8b3607c..f2156f0 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -117,7 +117,8 @@
 	if (devp == NULL)
 		goto err_out;
 
-	if (dt_is_compatible(devp, "ns16550"))
+	if (dt_is_compatible(devp, "ns16550") ||
+	    dt_is_compatible(devp, "pnpPNP,501"))
 		rc = ns16550_console_init(devp, &serial_cd);
 	else if (dt_is_compatible(devp, "marvell,mv64360-mpsc"))
 		rc = mpsc_console_init(devp, &serial_cd);
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 965c237..3ac75ae 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -186,6 +186,9 @@
     *-mpc85*|*-tqm85*|*-sbc85*)
         platformo=$object/cuboot-85xx.o
         ;;
+    *-amigaone)
+        link_address='0x800000'
+        ;;
     esac
     ;;
 ps3)
@@ -211,11 +214,11 @@
     binary=y
     ;;
 simpleboot-virtex440-*)
-    platformo="$object/simpleboot.o $object/virtex.o"
+    platformo="$object/fixed-head.o $object/simpleboot.o $object/virtex.o"
     binary=y
     ;;
 simpleboot-*)
-    platformo="$object/simpleboot.o"
+    platformo="$object/fixed-head.o $object/simpleboot.o"
     binary=y
     ;;
 asp834x-redboot)
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index 81cdcc4..f9a08ee 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Tue Jan 20 08:22:35 2009
+# Linux kernel version: 2.6.29-rc3
+# Mon Feb  2 13:13:04 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -74,6 +74,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
@@ -147,11 +156,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 CONFIG_PPC4xx_PCI_EXPRESS=y
 
@@ -373,6 +377,7 @@
 CONFIG_PROC_EVENTS=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -384,6 +389,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=35000
@@ -466,6 +472,15 @@
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
 #
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -533,13 +548,136 @@
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
-# CONFIG_I2C is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+CONFIG_SENSORS_AD7414=y
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
@@ -556,7 +694,12 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 
 #
@@ -574,6 +717,7 @@
 # Multimedia drivers
 #
 CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -590,7 +734,109 @@
 #
 # CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
 # CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
diff --git a/arch/powerpc/configs/44x/redwood_defconfig b/arch/powerpc/configs/44x/redwood_defconfig
new file mode 100644
index 0000000..e665433
--- /dev/null
+++ b/arch/powerpc/configs/44x/redwood_defconfig
@@ -0,0 +1,1176 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc3
+# Wed Feb  4 14:31:09 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_4xx=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+CONFIG_PPC4xx_PCI_EXPRESS=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_BAMBOO is not set
+# CONFIG_EBONY is not set
+# CONFIG_SAM440EP is not set
+# CONFIG_SEQUOIA is not set
+# CONFIG_TAISHAN is not set
+# CONFIG_KATMAI is not set
+# CONFIG_RAINIER is not set
+# CONFIG_WARP is not set
+# CONFIG_ARCHES is not set
+# CONFIG_CANYONLANDS is not set
+# CONFIG_GLACIER is not set
+CONFIG_REDWOOD=y
+# CONFIG_YOSEMITE is not set
+# CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
+CONFIG_PPC44x_SIMPLE=y
+# CONFIG_PPC4xx_GPIO is not set
+CONFIG_460SX=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_EXTRA_TARGETS=""
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_4xx_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_FUSION=y
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+CONFIG_FUSION_SAS=y
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+CONFIG_I2O=y
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+# CONFIG_I2O_CONFIG is not set
+# CONFIG_I2O_BUS is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+CONFIG_IBM_NEW_EMAC_DEBUG=y
+CONFIG_IBM_NEW_EMAC_ZMII=y
+CONFIG_IBM_NEW_EMAC_RGMII=y
+CONFIG_IBM_NEW_EMAC_TAH=y
+CONFIG_IBM_NEW_EMAC_EMAC4=y
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+CONFIG_E1000E=y
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=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_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=y
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SEQIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/85xx/socrates_defconfig b/arch/powerpc/configs/85xx/socrates_defconfig
new file mode 100644
index 0000000..0cc9048
--- /dev/null
+++ b/arch/powerpc/configs/85xx/socrates_defconfig
@@ -0,0 +1,1410 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26.2
+# Sat Oct 18 11:06:13 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+CONFIG_PPC_85xx=y
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+CONFIG_FSL_EMB_PERFMON=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_MPC85xx=y
+# CONFIG_MPC8540_ADS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC85xx_DS is not set
+CONFIG_SOCRATES=y
+# CONFIG_KSI8560 is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+# CONFIG_TQM8541 is not set
+# CONFIG_TQM8555 is not set
+# CONFIG_TQM8560 is not set
+# CONFIG_SBC8548 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_PHYSICAL_ALIGN=0x10000000
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+
+#
+# CAN Device Drivers
+#
+# CONFIG_CAN_VCAN is not set
+# CONFIG_CAN_OLD_DRIVERS is not set
+# CONFIG_CAN_SLCAN is not set
+CONFIG_CAN_SJA1000=y
+CONFIG_CAN_SJA1000_MEM_OF=y
+# CONFIG_CAN_EMS_PCI is not set
+# CONFIG_CAN_IXXAT_PCI is not set
+# CONFIG_CAN_PEAK_PCI is not set
+# CONFIG_CAN_KVASER_PCI is not set
+# CONFIG_CAN_MSCAN is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_NAND_FSL_ELBC is not set
+CONFIG_MTD_NAND_SOCRATES=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+CONFIG_TOUCHSCREEN_TSC2003=y
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_SOCRATES=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=y
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+CONFIG_SENSORS_LM75=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+CONFIG_SENSORS_W83781D=y
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_HWMON_DEBUG_CHIP=y
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_BOTH_ENDIAN=y
+# CONFIG_FB_BIG_ENDIAN is not set
+# CONFIG_FB_LITTLE_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_MB862XX=y
+# CONFIG_FB_MB862XX_PCI_GDC is not set
+CONFIG_FB_MB862XX_LIME=y
+# CONFIG_FB_PRE_INIT_FB is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_FSL_DIU is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+CONFIG_RTC_DRV_RX8025=y
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PPC=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
new file mode 100644
index 0000000..df2c163
--- /dev/null
+++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
@@ -0,0 +1,1889 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc7
+# Fri Mar 13 15:36:11 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_MPC8641_HPCN is not set
+# CONFIG_SBC8641D is not set
+# CONFIG_MPC8610_HPCD is not set
+CONFIG_GEF_PPC9A=y
+# CONFIG_GEF_SBC310 is not set
+# CONFIG_GEF_SBC610 is not set
+CONFIG_MPC8641=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_QUICC_ENGINE is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=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=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_SECURITY is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+# CONFIG_IP6_NF_MATCH_AH is not set
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_MH is not set
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_RAW=m
+# CONFIG_IP6_NF_SECURITY is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+# CONFIG_NET_SCH_MULTIQ is not set
+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_DRR is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_ATM_SOLOS is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM92=y
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+CONFIG_GEF_WDT=y
+# CONFIG_8xxx_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_ATM is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+# CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+CONFIG_RTC_DRV_RX8581=y
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
new file mode 100644
index 0000000..bd236b3
--- /dev/null
+++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
@@ -0,0 +1,1613 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc3
+# Wed Jan 28 23:05:34 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
+CONFIG_PPC_MSI_BITMAP=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_MPC8641_HPCN is not set
+# CONFIG_SBC8641D is not set
+# CONFIG_MPC8610_HPCD is not set
+CONFIG_GEF_SBC310=y
+# CONFIG_GEF_SBC610 is not set
+CONFIG_MPC8641=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_QUICC_ENGINE is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_LOWMEM_CAM_NUM=3
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=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=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_SIL24=y
+# CONFIG_SATA_FSL is not set
+# CONFIG_ATA_SFF is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM92=y
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ALIM7101_WDT is not set
+CONFIG_GEF_WDT=y
+# CONFIG_8xxx_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+# CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+CONFIG_RTC_DRV_RX8581=y
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig
new file mode 100644
index 0000000..b63cc38
--- /dev/null
+++ b/arch/powerpc/configs/amigaone_defconfig
@@ -0,0 +1,1636 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc3
+# Sun Feb  1 14:22:42 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_CHECK_CACHE_COHERENCY=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_AMIGAONE=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_NF_NAT_SIP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+# CONFIG_PARPORT_SERIAL is not set
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+# CONFIG_PARPORT_1284 is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_MMIO is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_ATL2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_DDC=y
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_XMON_DISASSEMBLY=y
+CONFIG_DEBUGGER=y
+CONFIG_IRQSTACKS=y
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 81afc8b..af0cd55 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Mon Jan 26 21:40:44 2009
+# Linux kernel version: 2.6.29-rc3
+# Fri Feb  6 09:48:53 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -388,7 +388,10 @@
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_TESTS is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_OF_PARTS is not set
 # CONFIG_MTD_AR7_PARTS is not set
@@ -502,7 +505,7 @@
 #
 # EEPROM support
 #
-# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_AT24=y
 # CONFIG_EEPROM_LEGACY is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
@@ -678,7 +681,7 @@
 # CONFIG_MARVELL_PHY is not set
 # CONFIG_DAVICOM_PHY is not set
 # CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
+CONFIG_LXT_PHY=y
 # CONFIG_CICADA_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_SMSC_PHY is not set
@@ -815,8 +818,6 @@
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -1281,7 +1282,61 @@
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 # CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 88c6295..2524018 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -2067,9 +2067,9 @@
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_HCALL_STATS is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
+CONFIG_CODE_PATCHING_SELFTEST=y
+CONFIG_FTR_FIXUP_SELFTEST=y
+CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
 # CONFIG_XMON_DEFAULT is not set
 CONFIG_XMON_DISASSEMBLY=y
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 107d9b9..37c32aba 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -11,9 +11,7 @@
  */
 
 #include <asm/types.h>
-
-#define PPC_NOP_INSTR		0x60000000
-#define PPC_LWSYNC_INSTR	0x7c2004ac
+#include <asm/ppc-opcode.h>
 
 /* Flags for create_branch:
  * "b"   == create_branch(addr, target, 0);
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 21172ba..80f315e 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -145,6 +145,7 @@
 #define CPU_FTR_USE_TB			ASM_CONST(0x0000000000000040)
 #define CPU_FTR_L2CSR			ASM_CONST(0x0000000000000080)
 #define CPU_FTR_601			ASM_CONST(0x0000000000000100)
+#define CPU_FTR_DBELL			ASM_CONST(0x0000000000000200)
 #define CPU_FTR_CAN_NAP			ASM_CONST(0x0000000000000400)
 #define CPU_FTR_L3CR			ASM_CONST(0x0000000000000800)
 #define CPU_FTR_L3_DISABLE_NAP		ASM_CONST(0x0000000000001000)
@@ -375,7 +376,8 @@
 	    CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
-	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE)
+	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
+	    CPU_FTR_DBELL)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
new file mode 100644
index 0000000..501189a
--- /dev/null
+++ b/arch/powerpc/include/asm/dbell.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 Freescale Semicondutor, 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.
+ *
+ * provides masks and opcode images for use by code generation, emulation
+ * and for instructions that older assemblers might not know about
+ */
+#ifndef _ASM_POWERPC_DBELL_H
+#define _ASM_POWERPC_DBELL_H
+
+#include <linux/smp.h>
+#include <linux/threads.h>
+
+#include <asm/ppc-opcode.h>
+
+#define PPC_DBELL_MSG_BRDCAST	(0x04000000)
+#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << 28)
+enum ppc_dbell {
+	PPC_DBELL = 0,		/* doorbell */
+	PPC_DBELL_CRIT = 1,	/* critical doorbell */
+	PPC_G_DBELL = 2,	/* guest doorbell */
+	PPC_G_DBELL_CRIT = 3,	/* guest critical doorbell */
+	PPC_G_DBELL_MC = 4,	/* guest mcheck doorbell */
+};
+
+#ifdef CONFIG_SMP
+extern unsigned long dbell_smp_message[NR_CPUS];
+extern void smp_dbell_message_pass(int target, int msg);
+#endif
+
+static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
+{
+	u32 msg = PPC_DBELL_TYPE(type) | (flags & PPC_DBELL_MSG_BRDCAST) |
+			(tag & 0x07ffffff);
+
+	__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+}
+
+#endif /* _ASM_POWERPC_DBELL_H */
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 86cef7d..c69f2b5 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -109,18 +109,8 @@
 	 * only ISA DMA device we support is the floppy and we have a hack
 	 * in the floppy driver directly to get a device for us.
 	 */
-
-	if (unlikely(dev == NULL) || dev->archdata.dma_ops == NULL) {
-#ifdef CONFIG_PPC64
+	if (unlikely(dev == NULL))
 		return NULL;
-#else
-		/* Use default on 32-bit if dma_ops is not set up */
-		/* TODO: Long term, we should fix drivers so that dev and
-		 * archdata dma_ops are set up for all buses.
-		 */
-		return &dma_direct_ops;
-#endif
-	}
 
 	return dev->archdata.dma_ops;
 }
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index b5600ce..1a856b1 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -8,6 +8,7 @@
 #endif
 
 #include <linux/types.h>
+
 #include <asm/ptrace.h>
 #include <asm/cputable.h>
 #include <asm/auxvec.h>
@@ -178,7 +179,8 @@
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (0x20000000)
+extern unsigned long randomize_et_dyn(unsigned long base);
+#define ELF_ET_DYN_BASE		(randomize_et_dyn(0x20000000))
 
 /*
  * Our registers are always unsigned longs, whether we're a 32 bit
@@ -270,6 +272,14 @@
 				       int uses_interp);
 #define VDSO_AUX_ENT(a,b) NEW_AUX_ENT(a,b);
 
+/* 1GB for 64bit, 8MB for 32bit */
+#define STACK_RND_MASK (is_32bit_task() ? \
+	(0x7ff >> (PAGE_SHIFT - 12)) : \
+	(0x3ffff >> (PAGE_SHIFT - 12)))
+
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
 #endif /* __KERNEL__ */
 
 /*
diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h
index 8428b38..d60fd18 100644
--- a/arch/powerpc/include/asm/fixmap.h
+++ b/arch/powerpc/include/asm/fixmap.h
@@ -61,7 +61,7 @@
  * Some hardware wants to get fixmapped without caching.
  */
 #define set_fixmap_nocache(idx, phys) \
-		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+		__set_fixmap(idx, phys, PAGE_KERNEL_NCG)
 
 #define clear_fixmap(idx) \
 		__set_fixmap(idx, 0, __pgprot(0))
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index e5f2ae8..dde1296 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -5,7 +5,44 @@
 #define MCOUNT_ADDR		((long)(_mcount))
 #define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
 
-#ifndef __ASSEMBLY__
+#ifdef __ASSEMBLY__
+
+/* Based off of objdump optput from glibc */
+
+#define MCOUNT_SAVE_FRAME			\
+	stwu	r1,-48(r1);			\
+	stw	r3, 12(r1);			\
+	stw	r4, 16(r1);			\
+	stw	r5, 20(r1);			\
+	stw	r6, 24(r1);			\
+	mflr	r3;				\
+	lwz	r4, 52(r1);			\
+	mfcr	r5;				\
+	stw	r7, 28(r1);			\
+	stw	r8, 32(r1);			\
+	stw	r9, 36(r1);			\
+	stw	r10,40(r1);			\
+	stw	r3, 44(r1);			\
+	stw	r5, 8(r1)
+
+#define MCOUNT_RESTORE_FRAME			\
+	lwz	r6, 8(r1);			\
+	lwz	r0, 44(r1);			\
+	lwz	r3, 12(r1);			\
+	mtctr	r0;				\
+	lwz	r4, 16(r1);			\
+	mtcr	r6;				\
+	lwz	r5, 20(r1);			\
+	lwz	r6, 24(r1);			\
+	lwz	r0, 52(r1);			\
+	lwz	r7, 28(r1);			\
+	lwz	r8, 32(r1);			\
+	mtlr	r0;				\
+	lwz	r9, 36(r1);			\
+	lwz	r10,40(r1);			\
+	addi	r1, r1, 48
+
+#else /* !__ASSEMBLY__ */
 extern void _mcount(void);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h
index 04e4a62..545028f 100644
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -39,15 +39,15 @@
  * chunk of RAM.
  */
 /*
- * We use one full pte table with 4K pages. And with 16K/64K pages pte
- * table covers enough memory (32MB and 512MB resp.) that both FIXMAP
- * and PKMAP can be placed in single pte table. We use 1024 pages for
- * PKMAP in case of 16K/64K pages.
+ * We use one full pte table with 4K pages. And with 16K/64K/256K pages pte
+ * table covers enough memory (32MB/512MB/2GB resp.), so that both FIXMAP
+ * and PKMAP can be placed in a single pte table. We use 512 pages for PKMAP
+ * in case of 16K/64K/256K page sizes.
  */
 #ifdef CONFIG_PPC_4K_PAGES
 #define PKMAP_ORDER	PTE_SHIFT
 #else
-#define PKMAP_ORDER	10
+#define PKMAP_ORDER	9
 #endif
 #define LAST_PKMAP	(1 << PKMAP_ORDER)
 #ifndef CONFIG_PPC_4K_PAGES
@@ -99,7 +99,7 @@
 #ifdef CONFIG_DEBUG_HIGHMEM
 	BUG_ON(!pte_none(*(kmap_pte-idx)));
 #endif
-	__set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+	__set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
 	local_flush_tlb_page(NULL, vaddr);
 
 	return (void*) vaddr;
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index f75a5fc..b7e034b 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -129,7 +129,7 @@
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
  */
-struct hw_interrupt_type;
+struct irq_chip;
 
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_HW_IRQ_H */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 494cd8b..001f2f1 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -632,6 +632,9 @@
  *   ioremap_flags and cannot be hooked (but can be used by a hook on one
  *   of the previous ones)
  *
+ * * __ioremap_caller is the same as above but takes an explicit caller
+ *   reference rather than using __builtin_return_address(0)
+ *
  * * __iounmap, is the low level implementation used by iounmap and cannot
  *   be hooked (but can be used by a hook on iounmap)
  *
@@ -646,6 +649,9 @@
 
 extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
 			       unsigned long flags);
+extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size,
+				      unsigned long flags, void *caller);
+
 extern void __iounmap(volatile void __iomem *addr);
 
 extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index 25aaa97..68235f7 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -97,7 +97,7 @@
 	u64	saved_gpr4;		// Saved GPR4                   x28-x2F
 	u64	saved_gpr5;		// Saved GPR5                   x30-x37
 
-	u8	reserved4;		// Reserved			x38-x38
+	u8	dtl_enable_mask;	// Dispatch Trace Log mask	x38-x38
 	u8	donate_dedicated_cpu;	// Donate dedicated CPU cycles  x39-x39
 	u8	fpregs_in_use;		// FP regs in use               x3A-x3A
 	u8	pmcregs_in_use;		// PMC regs in use              x3B-x3B
@@ -133,8 +133,10 @@
 //=============================================================================
 // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
 //=============================================================================
-	u32	page_ins;			// CMO Hint - # page ins by OS  x00-x04
-	u8	pmc_save_area[252];	// PMC interrupt Area           x04-xFF
+	u32	page_ins;		// CMO Hint - # page ins by OS  x00-x03
+	u8	reserved8[148];		// Reserved                     x04-x97
+	volatile u64 dtl_idx;		// Dispatch Trace Log head idx	x98-x9F
+	u8	reserved9[96];		// Reserved                     xA0-xFF
 } __attribute__((__aligned__(0x400)));
 
 extern struct lppaca lppaca[];
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 2740c44..0efdb1d 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -90,7 +90,7 @@
 	void		(*tce_flush)(struct iommu_table *tbl);
 
 	void __iomem *	(*ioremap)(phys_addr_t addr, unsigned long size,
-				   unsigned long flags);
+				   unsigned long flags, void *caller);
 	void		(*iounmap)(volatile void __iomem *token);
 
 #ifdef CONFIG_PM
@@ -327,8 +327,6 @@
  */
 /* Print a boot progress message. */
 void ppc64_boot_msg(unsigned int src, const char *msg);
-/* Print a termination message (print only -- does not stop the kernel) */
-void ppc64_terminate_msg(unsigned int src, const char *msg);
 
 static inline void log_error(char *buf, unsigned int err_type, int fatal)
 {
diff --git a/arch/powerpc/include/asm/mmu-44x.h b/arch/powerpc/include/asm/mmu-44x.h
index 27cc6fd..3c86576 100644
--- a/arch/powerpc/include/asm/mmu-44x.h
+++ b/arch/powerpc/include/asm/mmu-44x.h
@@ -83,6 +83,8 @@
 #define PPC44x_TLBE_SIZE	PPC44x_TLB_16K
 #elif (PAGE_SHIFT == 16)
 #define PPC44x_TLBE_SIZE	PPC44x_TLB_64K
+#elif (PAGE_SHIFT == 18)
+#define PPC44x_TLBE_SIZE	PPC44x_TLB_256K
 #else
 #error "Unsupported PAGE_SIZE"
 #endif
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h
new file mode 100644
index 0000000..7e74cff
--- /dev/null
+++ b/arch/powerpc/include/asm/mmu-book3e.h
@@ -0,0 +1,105 @@
+#ifndef _ASM_POWERPC_MMU_BOOK3E_H_
+#define _ASM_POWERPC_MMU_BOOK3E_H_
+/*
+ * Freescale Book-E/Book-3e (ISA 2.06+) MMU support
+ */
+
+/* Book-3e defined page sizes */
+#define BOOK3E_PAGESZ_1K	0
+#define BOOK3E_PAGESZ_2K	1
+#define BOOK3E_PAGESZ_4K	2
+#define BOOK3E_PAGESZ_8K	3
+#define BOOK3E_PAGESZ_16K	4
+#define BOOK3E_PAGESZ_32K	5
+#define BOOK3E_PAGESZ_64K	6
+#define BOOK3E_PAGESZ_128K	7
+#define BOOK3E_PAGESZ_256K	8
+#define BOOK3E_PAGESZ_512K	9
+#define BOOK3E_PAGESZ_1M	10
+#define BOOK3E_PAGESZ_2M	11
+#define BOOK3E_PAGESZ_4M	12
+#define BOOK3E_PAGESZ_8M	13
+#define BOOK3E_PAGESZ_16M	14
+#define BOOK3E_PAGESZ_32M	15
+#define BOOK3E_PAGESZ_64M	16
+#define BOOK3E_PAGESZ_128M	17
+#define BOOK3E_PAGESZ_256M	18
+#define BOOK3E_PAGESZ_512M	19
+#define BOOK3E_PAGESZ_1GB	20
+#define BOOK3E_PAGESZ_2GB	21
+#define BOOK3E_PAGESZ_4GB	22
+#define BOOK3E_PAGESZ_8GB	23
+#define BOOK3E_PAGESZ_16GB	24
+#define BOOK3E_PAGESZ_32GB	25
+#define BOOK3E_PAGESZ_64GB	26
+#define BOOK3E_PAGESZ_128GB	27
+#define BOOK3E_PAGESZ_256GB	28
+#define BOOK3E_PAGESZ_512GB	29
+#define BOOK3E_PAGESZ_1TB	30
+#define BOOK3E_PAGESZ_2TB	31
+
+#define MAS0_TLBSEL(x)	((x << 28) & 0x30000000)
+#define MAS0_ESEL(x)	((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x)	((x) & 0x00000FFF)
+
+#define MAS1_VALID 	0x80000000
+#define MAS1_IPROT	0x40000000
+#define MAS1_TID(x)	((x << 16) & 0x3FFF0000)
+#define MAS1_IND	0x00002000
+#define MAS1_TS		0x00001000
+#define MAS1_TSIZE(x)	((x << 7) & 0x00000F80)
+
+#define MAS2_EPN	0xFFFFF000
+#define MAS2_X0		0x00000040
+#define MAS2_X1		0x00000020
+#define MAS2_W		0x00000010
+#define MAS2_I		0x00000008
+#define MAS2_M		0x00000004
+#define MAS2_G		0x00000002
+#define MAS2_E		0x00000001
+#define MAS2_EPN_MASK(size)		(~0 << (size + 10))
+#define MAS2_VAL(addr, size, flags)	((addr) & MAS2_EPN_MASK(size) | (flags))
+
+#define MAS3_RPN	0xFFFFF000
+#define MAS3_U0		0x00000200
+#define MAS3_U1		0x00000100
+#define MAS3_U2		0x00000080
+#define MAS3_U3		0x00000040
+#define MAS3_UX		0x00000020
+#define MAS3_SX		0x00000010
+#define MAS3_UW		0x00000008
+#define MAS3_SW		0x00000004
+#define MAS3_UR		0x00000002
+#define MAS3_SR		0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_INDD	0x00008000
+#define MAS4_TSIZED(x)	MAS1_TSIZE(x)
+#define MAS4_X0D	0x00000040
+#define MAS4_X1D	0x00000020
+#define MAS4_WD		0x00000010
+#define MAS4_ID		0x00000008
+#define MAS4_MD		0x00000004
+#define MAS4_GD		0x00000002
+#define MAS4_ED		0x00000001
+
+#define MAS6_SPID0	0x3FFF0000
+#define MAS6_SPID1	0x00007FFE
+#define MAS6_ISIZE(x)	MAS1_TSIZE(x)
+#define MAS6_SAS	0x00000001
+#define MAS6_SPID	MAS6_SPID0
+
+#define MAS7_RPN	0xFFFFFFFF
+
+#ifndef __ASSEMBLY__
+
+extern unsigned int tlbcam_index;
+
+typedef struct {
+	unsigned int	id;
+	unsigned int	active;
+	unsigned long	vdso_base;
+} mm_context_t;
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_BOOK3E_H_ */
diff --git a/arch/powerpc/include/asm/mmu-fsl-booke.h b/arch/powerpc/include/asm/mmu-fsl-booke.h
deleted file mode 100644
index 4285b64..0000000
--- a/arch/powerpc/include/asm/mmu-fsl-booke.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_
-#define _ASM_POWERPC_MMU_FSL_BOOKE_H_
-/*
- * Freescale Book-E MMU support
- */
-
-/* Book-E defined page sizes */
-#define BOOKE_PAGESZ_1K		0
-#define BOOKE_PAGESZ_4K		1
-#define BOOKE_PAGESZ_16K	2
-#define BOOKE_PAGESZ_64K	3
-#define BOOKE_PAGESZ_256K	4
-#define BOOKE_PAGESZ_1M		5
-#define BOOKE_PAGESZ_4M		6
-#define BOOKE_PAGESZ_16M	7
-#define BOOKE_PAGESZ_64M	8
-#define BOOKE_PAGESZ_256M	9
-#define BOOKE_PAGESZ_1GB	10
-#define BOOKE_PAGESZ_4GB	11
-#define BOOKE_PAGESZ_16GB	12
-#define BOOKE_PAGESZ_64GB	13
-#define BOOKE_PAGESZ_256GB	14
-#define BOOKE_PAGESZ_1TB	15
-
-#define MAS0_TLBSEL(x)	((x << 28) & 0x30000000)
-#define MAS0_ESEL(x)	((x << 16) & 0x0FFF0000)
-#define MAS0_NV(x)	((x) & 0x00000FFF)
-
-#define MAS1_VALID 	0x80000000
-#define MAS1_IPROT	0x40000000
-#define MAS1_TID(x)	((x << 16) & 0x3FFF0000)
-#define MAS1_TS		0x00001000
-#define MAS1_TSIZE(x)	((x << 8) & 0x00000F00)
-
-#define MAS2_EPN	0xFFFFF000
-#define MAS2_X0		0x00000040
-#define MAS2_X1		0x00000020
-#define MAS2_W		0x00000010
-#define MAS2_I		0x00000008
-#define MAS2_M		0x00000004
-#define MAS2_G		0x00000002
-#define MAS2_E		0x00000001
-#define MAS2_EPN_MASK(size)		(~0 << (2*(size) + 10))
-#define MAS2_VAL(addr, size, flags)	((addr) & MAS2_EPN_MASK(size) | (flags))
-
-#define MAS3_RPN	0xFFFFF000
-#define MAS3_U0		0x00000200
-#define MAS3_U1		0x00000100
-#define MAS3_U2		0x00000080
-#define MAS3_U3		0x00000040
-#define MAS3_UX		0x00000020
-#define MAS3_SX		0x00000010
-#define MAS3_UW		0x00000008
-#define MAS3_SW		0x00000004
-#define MAS3_UR		0x00000002
-#define MAS3_SR		0x00000001
-
-#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
-#define MAS4_TIDDSEL	0x000F0000
-#define MAS4_TSIZED(x)	MAS1_TSIZE(x)
-#define MAS4_X0D	0x00000040
-#define MAS4_X1D	0x00000020
-#define MAS4_WD		0x00000010
-#define MAS4_ID		0x00000008
-#define MAS4_MD		0x00000004
-#define MAS4_GD		0x00000002
-#define MAS4_ED		0x00000001
-
-#define MAS6_SPID0	0x3FFF0000
-#define MAS6_SPID1	0x00007FFE
-#define MAS6_SAS	0x00000001
-#define MAS6_SPID	MAS6_SPID0
-
-#define MAS7_RPN	0xFFFFFFFF
-
-#ifndef __ASSEMBLY__
-
-extern unsigned int tlbcam_index;
-
-typedef struct {
-	unsigned int	id;
-	unsigned int	active;
-	unsigned long	vdso_base;
-} mm_context_t;
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 68b7526..98c104a 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -284,8 +284,6 @@
 			  unsigned long number_of_pages);
 extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
 
-extern void htab_initialize(void);
-extern void htab_initialize_secondary(void);
 extern void hpte_init_native(void);
 extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 6e76399..cbf1543 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -36,9 +36,9 @@
  */
 #define MMU_FTR_USE_TLBIVAX_BCAST	ASM_CONST(0x00040000)
 
-/* Enable use of tlbilx invalidate-by-PID variant.
+/* Enable use of tlbilx invalidate instructions.
  */
-#define MMU_FTR_USE_TLBILX_PID		ASM_CONST(0x00080000)
+#define MMU_FTR_USE_TLBILX		ASM_CONST(0x00080000)
 
 /* This indicates that the processor cannot handle multiple outstanding
  * broadcast tlbivax or tlbsync. This makes the code use a spinlock
@@ -46,6 +46,12 @@
  */
 #define MMU_FTR_LOCK_BCAST_INVAL	ASM_CONST(0x00100000)
 
+/* This indicates that the processor doesn't handle way selection
+ * properly and needs SW to track and update the LRU state.  This
+ * is specific to an errata on e300c2/c3/c4 class parts
+ */
+#define MMU_FTR_NEED_DTLB_SW_LRU	ASM_CONST(0x00200000)
+
 #ifndef __ASSEMBLY__
 #include <asm/cputable.h>
 
@@ -56,6 +62,10 @@
 
 extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
 
+/* MMU initialization (64-bit only fo now) */
+extern void early_init_mmu(void);
+extern void early_init_mmu_secondary(void);
+
 #endif /* !__ASSEMBLY__ */
 
 
@@ -71,9 +81,9 @@
 #elif defined(CONFIG_44x)
 /* 44x-style software loaded TLB */
 #  include <asm/mmu-44x.h>
-#elif defined(CONFIG_FSL_BOOKE)
-/* Freescale Book-E software loaded TLB */
-#  include <asm/mmu-fsl-booke.h>
+#elif defined(CONFIG_PPC_BOOK3E_MMU)
+/* Freescale Book-E software loaded TLB or Book-3e (ISA 2.06+) MMU */
+#  include <asm/mmu-book3e.h>
 #elif defined (CONFIG_PPC_8xx)
 /* Motorola/Freescale 8xx software loaded TLB */
 #  include <asm/mmu-8xx.h>
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
index ab4f192..b706366 100644
--- a/arch/powerpc/include/asm/mmu_context.h
+++ b/arch/powerpc/include/asm/mmu_context.h
@@ -31,7 +31,7 @@
 			     struct task_struct *tsk)
 {
 	/* Mark this context has been used on the new CPU */
-	cpu_set(smp_processor_id(), next->cpu_vm_mask);
+	cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
 
 	/* 32-bit keeps track of the current PGDIR in the thread struct */
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h
index 81a2393..52e049c 100644
--- a/arch/powerpc/include/asm/mpc52xx.h
+++ b/arch/powerpc/include/asm/mpc52xx.h
@@ -273,6 +273,7 @@
 extern void mpc52xx_declare_of_platform_devices(void);
 extern void mpc52xx_map_common_devices(void);
 extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv);
+extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node);
 extern void mpc52xx_restart(char *cmd);
 
 /* mpc52xx_pic.c */
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 197d569..32cbf16 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -19,12 +19,14 @@
 #include <asm/kdump.h>
 
 /*
- * On regular PPC32 page size is 4K (but we support 4K/16K/64K pages
+ * On regular PPC32 page size is 4K (but we support 4K/16K/64K/256K pages
  * on PPC44x). For PPC64 we support either 4K or 64K software
  * page size. When using 64K pages however, whether we are really supporting
  * 64K pages in HW or not is irrelevant to those definitions.
  */
-#if defined(CONFIG_PPC_64K_PAGES)
+#if defined(CONFIG_PPC_256K_PAGES)
+#define PAGE_SHIFT		18
+#elif defined(CONFIG_PPC_64K_PAGES)
 #define PAGE_SHIFT		16
 #elif defined(CONFIG_PPC_16K_PAGES)
 #define PAGE_SHIFT		14
diff --git a/arch/powerpc/include/asm/page_32.h b/arch/powerpc/include/asm/page_32.h
index 1458d95..a0e3f6e 100644
--- a/arch/powerpc/include/asm/page_32.h
+++ b/arch/powerpc/include/asm/page_32.h
@@ -19,7 +19,11 @@
 #define PTE_FLAGS_OFFSET	0
 #endif
 
+#ifdef CONFIG_PPC_256K_PAGES
+#define PTE_SHIFT	(PAGE_SHIFT - PTE_T_LOG2 - 2)	/* 1/4 of a page */
+#else
 #define PTE_SHIFT	(PAGE_SHIFT - PTE_T_LOG2)	/* full page */
+#endif
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/arch/powerpc/include/asm/pgtable-4k.h b/arch/powerpc/include/asm/pgtable-4k.h
deleted file mode 100644
index 1dbca4e7..0000000
--- a/arch/powerpc/include/asm/pgtable-4k.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef _ASM_POWERPC_PGTABLE_4K_H
-#define _ASM_POWERPC_PGTABLE_4K_H
-/*
- * Entries per page directory level.  The PTE level must use a 64b record
- * for each page table entry.  The PMD and PGD level use a 32b record for
- * each entry by assuming that each entry is page aligned.
- */
-#define PTE_INDEX_SIZE  9
-#define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  7
-#define PGD_INDEX_SIZE  9
-
-#ifndef __ASSEMBLY__
-#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_INDEX_SIZE)
-#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
-#define PUD_TABLE_SIZE	(sizeof(pud_t) << PUD_INDEX_SIZE)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
-#endif	/* __ASSEMBLY__ */
-
-#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
-#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PUD	(1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
-
-/* PMD_SHIFT determines what a second-level page table entry can map */
-#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PMD_SHIFT
-
-/* PUD_SHIFT determines what a third-level page table entry can map */
-#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
-#define PUD_SIZE	(1UL << PUD_SHIFT)
-#define PUD_MASK	(~(PUD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
-#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
-
-/* PTE bits */
-#define _PAGE_HASHPTE	0x0400 /* software: pte has an associated HPTE */
-#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */
-#define _PAGE_GROUP_IX  0x7000 /* software: HPTE index within group */
-#define _PAGE_F_SECOND  _PAGE_SECONDARY
-#define _PAGE_F_GIX     _PAGE_GROUP_IX
-#define _PAGE_SPECIAL	0x10000 /* software: special page */
-#define __HAVE_ARCH_PTE_SPECIAL
-
-/* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
-			 _PAGE_SECONDARY | _PAGE_GROUP_IX)
-
-/* There is no 4K PFN hack on 4K pages */
-#define _PAGE_4K_PFN	0
-
-/* PAGE_MASK gives the right answer below, but only by accident */
-/* It should be preserving the high 48 bits and then specifically */
-/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
-                         _PAGE_HPTEFLAGS | _PAGE_SPECIAL)
-
-/* Bits to mask out from a PMD to get to the PTE page */
-#define PMD_MASKED_BITS		0
-/* Bits to mask out from a PUD to get to the PMD page */
-#define PUD_MASKED_BITS		0
-/* Bits to mask out from a PGD to get to the PUD page */
-#define PGD_MASKED_BITS		0
-
-/* shift to put page number into pte */
-#define PTE_RPN_SHIFT	(17)
-
-#ifdef STRICT_MM_TYPECHECKS
-#define __real_pte(e,p)		((real_pte_t){(e)})
-#define __rpte_to_pte(r)	((r).pte)
-#else
-#define __real_pte(e,p)		(e)
-#define __rpte_to_pte(r)	(__pte(r))
-#endif
-#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >> 12)
-
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
-	do {							         \
-		index = 0;					         \
-		shift = mmu_psize_defs[psize].shift;		         \
-
-#define pte_iterate_hashed_end() } while(0)
-
-#ifdef CONFIG_PPC_HAS_HASH_64K
-#define pte_pagesize_index(mm, addr, pte)	get_slice_psize(mm, addr)
-#else
-#define pte_pagesize_index(mm, addr, pte)	MMU_PAGE_4K
-#endif
-
-/*
- * 4-level page tables related bits
- */
-
-#define pgd_none(pgd)		(!pgd_val(pgd))
-#define pgd_bad(pgd)		(pgd_val(pgd) == 0)
-#define pgd_present(pgd)	(pgd_val(pgd) != 0)
-#define pgd_clear(pgdp)		(pgd_val(*(pgdp)) = 0)
-#define pgd_page_vaddr(pgd)	(pgd_val(pgd) & ~PGD_MASKED_BITS)
-#define pgd_page(pgd)		virt_to_page(pgd_page_vaddr(pgd))
-
-#define pud_offset(pgdp, addr)	\
-  (((pud_t *) pgd_page_vaddr(*(pgdp))) + \
-    (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
-
-#define pud_ERROR(e) \
-	printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
-
-#define remap_4k_pfn(vma, addr, pfn, prot)	\
-	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
-#endif /* _ASM_POWERPC_PGTABLE_4K_H */
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
index 820b5f0..ba45c99 100644
--- a/arch/powerpc/include/asm/pgtable-ppc32.h
+++ b/arch/powerpc/include/asm/pgtable-ppc32.h
@@ -19,55 +19,6 @@
 #endif /* __ASSEMBLY__ */
 
 /*
- * The PowerPC MMU uses a hash table containing PTEs, together with
- * a set of 16 segment registers (on 32-bit implementations), to define
- * the virtual to physical address mapping.
- *
- * We use the hash table as an extended TLB, i.e. a cache of currently
- * active mappings.  We maintain a two-level page table tree, much
- * like that used by the i386, for the sake of the Linux memory
- * management code.  Low-level assembler code in hashtable.S
- * (procedure hash_page) is responsible for extracting ptes from the
- * tree and putting them into the hash table when necessary, and
- * updating the accessed and modified bits in the page table tree.
- */
-
-/*
- * The PowerPC MPC8xx uses a TLB with hardware assisted, software tablewalk.
- * We also use the two level tables, but we can put the real bits in them
- * needed for the TLB and tablewalk.  These definitions require Mx_CTR.PPM = 0,
- * Mx_CTR.PPCS = 0, and MD_CTR.TWAM = 1.  The level 2 descriptor has
- * additional page protection (when Mx_CTR.PPCS = 1) that allows TLB hit
- * based upon user/super access.  The TLB does not have accessed nor write
- * protect.  We assume that if the TLB get loaded with an entry it is
- * accessed, and overload the changed bit for write protect.  We use
- * two bits in the software pte that are supposed to be set to zero in
- * the TLB entry (24 and 25) for these indicators.  Although the level 1
- * descriptor contains the guarded and writethrough/copyback bits, we can
- * set these at the page level since they get copied from the Mx_TWC
- * register when the TLB entry is loaded.  We will use bit 27 for guard, since
- * that is where it exists in the MD_TWC, and bit 26 for writethrough.
- * These will get masked from the level 2 descriptor at TLB load time, and
- * copied to the MD_TWC before it gets loaded.
- * Large page sizes added.  We currently support two sizes, 4K and 8M.
- * This also allows a TLB hander optimization because we can directly
- * load the PMD into MD_TWC.  The 8M pages are only used for kernel
- * mapping of well known areas.  The PMD (PGD) entries contain control
- * flags in addition to the address, so care must be taken that the
- * software no longer assumes these are only pointers.
- */
-
-/*
- * At present, all PowerPC 400-class processors share a similar TLB
- * architecture. The instruction and data sides share a unified,
- * 64-entry, fully-associative TLB which is maintained totally under
- * software control. In addition, the instruction side has a
- * hardware-managed, 4-entry, fully-associative TLB which serves as a
- * first level to the shared TLB. These two TLBs are known as the UTLB
- * and ITLB, respectively (see "mmu.h" for definitions).
- */
-
-/*
  * The normal case is that PTEs are 32-bits and we have a 1-page
  * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
  *
@@ -135,409 +86,22 @@
  */
 
 #if defined(CONFIG_40x)
-
-/* There are several potential gotchas here.  The 40x hardware TLBLO
-   field looks like this:
-
-   0  1  2  3  4  ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-   RPN.....................  0  0 EX WR ZSEL.......  W  I  M  G
-
-   Where possible we make the Linux PTE bits match up with this
-
-   - bits 20 and 21 must be cleared, because we use 4k pages (40x can
-     support down to 1k pages), this is done in the TLBMiss exception
-     handler.
-   - We use only zones 0 (for kernel pages) and 1 (for user pages)
-     of the 16 available.  Bit 24-26 of the TLB are cleared in the TLB
-     miss handler.  Bit 27 is PAGE_USER, thus selecting the correct
-     zone.
-   - PRESENT *must* be in the bottom two bits because swap cache
-     entries use the top 30 bits.  Because 40x doesn't support SMP
-     anyway, M is irrelevant so we borrow it for PAGE_PRESENT.  Bit 30
-     is cleared in the TLB miss handler before the TLB entry is loaded.
-   - All other bits of the PTE are loaded into TLBLO without
-     modification, leaving us only the bits 20, 21, 24, 25, 26, 30 for
-     software PTE bits.  We actually use use bits 21, 24, 25, and
-     30 respectively for the software bits: ACCESSED, DIRTY, RW, and
-     PRESENT.
-*/
-
-/* Definitions for 40x embedded chips. */
-#define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
-#define _PAGE_FILE	0x001	/* when !present: nonlinear file mapping */
-#define _PAGE_PRESENT	0x002	/* software: PTE contains a translation */
-#define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
-#define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
-#define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
-#define	_PAGE_RW	0x040	/* software: Writes permitted */
-#define	_PAGE_DIRTY	0x080	/* software: dirty page */
-#define _PAGE_HWWRITE	0x100	/* hardware: Dirty & RW, set in exception */
-#define _PAGE_HWEXEC	0x200	/* hardware: EX permission */
-#define _PAGE_ACCESSED	0x400	/* software: R: page referenced */
-
-#define _PMD_PRESENT	0x400	/* PMD points to page of PTEs */
-#define _PMD_BAD	0x802
-#define _PMD_SIZE	0x0e0	/* size field, != 0 for large-page PMD entry */
-#define _PMD_SIZE_4M	0x0c0
-#define _PMD_SIZE_16M	0x0e0
-#define PMD_PAGE_SIZE(pmdval)	(1024 << (((pmdval) & _PMD_SIZE) >> 4))
-
-/* Until my rework is finished, 40x still needs atomic PTE updates */
-#define PTE_ATOMIC_UPDATES	1
-
+#include <asm/pte-40x.h>
 #elif defined(CONFIG_44x)
-/*
- * Definitions for PPC440
- *
- * Because of the 3 word TLB entries to support 36-bit addressing,
- * the attribute are difficult to map in such a fashion that they
- * are easily loaded during exception processing.  I decided to
- * organize the entry so the ERPN is the only portion in the
- * upper word of the PTE and the attribute bits below are packed
- * in as sensibly as they can be in the area below a 4KB page size
- * oriented RPN.  This at least makes it easy to load the RPN and
- * ERPN fields in the TLB. -Matt
- *
- * Note that these bits preclude future use of a page size
- * less than 4KB.
- *
- *
- * PPC 440 core has following TLB attribute fields;
- *
- *   TLB1:
- *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- *   RPN.................................  -  -  -  -  -  - ERPN.......
- *
- *   TLB2:
- *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- *   -  -  -  -  -    - U0 U1 U2 U3 W  I  M  G  E   - UX UW UR SX SW SR
- *
- * Newer 440 cores (440x6 as used on AMCC 460EX/460GT) have additional
- * TLB2 storage attibute fields. Those are:
- *
- *   TLB2:
- *   0...10    11   12   13   14   15   16...31
- *   no change WL1  IL1I IL1D IL2I IL2D no change
- *
- * There are some constrains and options, to decide mapping software bits
- * into TLB entry.
- *
- *   - PRESENT *must* be in the bottom three bits because swap cache
- *     entries use the top 29 bits for TLB2.
- *
- *   - FILE *must* be in the bottom three bits because swap cache
- *     entries use the top 29 bits for TLB2.
- *
- *   - CACHE COHERENT bit (M) has no effect on original PPC440 cores,
- *     because it doesn't support SMP. However, some later 460 variants
- *     have -some- form of SMP support and so I keep the bit there for
- *     future use
- *
- * With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used
- * for memory protection related functions (see PTE structure in
- * include/asm-ppc/mmu.h).  The _PAGE_XXX definitions in this file map to the
- * above bits.  Note that the bit values are CPU specific, not architecture
- * specific.
- *
- * The kernel PTE entry holds an arch-dependent swp_entry structure under
- * certain situations. In other words, in such situations some portion of
- * the PTE bits are used as a swp_entry. In the PPC implementation, the
- * 3-24th LSB are shared with swp_entry, however the 0-2nd three LSB still
- * hold protection values. That means the three protection bits are
- * reserved for both PTE and SWAP entry at the most significant three
- * LSBs.
- *
- * There are three protection bits available for SWAP entry:
- *	_PAGE_PRESENT
- *	_PAGE_FILE
- *	_PAGE_HASHPTE (if HW has)
- *
- * So those three bits have to be inside of 0-2nd LSB of PTE.
- *
- */
-
-#define _PAGE_PRESENT	0x00000001		/* S: PTE valid */
-#define _PAGE_RW	0x00000002		/* S: Write permission */
-#define _PAGE_FILE	0x00000004		/* S: nonlinear file mapping */
-#define _PAGE_HWEXEC	0x00000004		/* H: Execute permission */
-#define _PAGE_ACCESSED	0x00000008		/* S: Page referenced */
-#define _PAGE_DIRTY	0x00000010		/* S: Page dirty */
-#define _PAGE_SPECIAL	0x00000020		/* S: Special page */
-#define _PAGE_USER	0x00000040		/* S: User page */
-#define _PAGE_ENDIAN	0x00000080		/* H: E bit */
-#define _PAGE_GUARDED	0x00000100		/* H: G bit */
-#define _PAGE_COHERENT	0x00000200		/* H: M bit */
-#define _PAGE_NO_CACHE	0x00000400		/* H: I bit */
-#define _PAGE_WRITETHRU	0x00000800		/* H: W bit */
-
-/* TODO: Add large page lowmem mapping support */
-#define _PMD_PRESENT	0
-#define _PMD_PRESENT_MASK (PAGE_MASK)
-#define _PMD_BAD	(~PAGE_MASK)
-
-/* ERPN in a PTE never gets cleared, ignore it */
-#define _PTE_NONE_MASK	0xffffffff00000000ULL
-
-#define __HAVE_ARCH_PTE_SPECIAL
-
+#include <asm/pte-44x.h>
 #elif defined(CONFIG_FSL_BOOKE)
-/*
-   MMU Assist Register 3:
-
-   32 33 34 35 36  ... 50 51 52 53 54 55 56 57 58 59 60 61 62 63
-   RPN......................  0  0 U0 U1 U2 U3 UX SX UW SW UR SR
-
-   - PRESENT *must* be in the bottom three bits because swap cache
-     entries use the top 29 bits.
-
-   - FILE *must* be in the bottom three bits because swap cache
-     entries use the top 29 bits.
-*/
-
-/* Definitions for FSL Book-E Cores */
-#define _PAGE_PRESENT	0x00001	/* S: PTE contains a translation */
-#define _PAGE_USER	0x00002	/* S: User page (maps to UR) */
-#define _PAGE_FILE	0x00002	/* S: when !present: nonlinear file mapping */
-#define _PAGE_RW	0x00004	/* S: Write permission (SW) */
-#define _PAGE_DIRTY	0x00008	/* S: Page dirty */
-#define _PAGE_HWEXEC	0x00010	/* H: SX permission */
-#define _PAGE_ACCESSED	0x00020	/* S: Page referenced */
-
-#define _PAGE_ENDIAN	0x00040	/* H: E bit */
-#define _PAGE_GUARDED	0x00080	/* H: G bit */
-#define _PAGE_COHERENT	0x00100	/* H: M bit */
-#define _PAGE_NO_CACHE	0x00200	/* H: I bit */
-#define _PAGE_WRITETHRU	0x00400	/* H: W bit */
-#define _PAGE_SPECIAL	0x00800 /* S: Special page */
-
-#ifdef CONFIG_PTE_64BIT
-/* ERPN in a PTE never gets cleared, ignore it */
-#define _PTE_NONE_MASK	0xffffffffffff0000ULL
-#endif
-
-#define _PMD_PRESENT	0
-#define _PMD_PRESENT_MASK (PAGE_MASK)
-#define _PMD_BAD	(~PAGE_MASK)
-
-#define __HAVE_ARCH_PTE_SPECIAL
-
+#include <asm/pte-fsl-booke.h>
 #elif defined(CONFIG_8xx)
-/* Definitions for 8xx embedded chips. */
-#define _PAGE_PRESENT	0x0001	/* Page is valid */
-#define _PAGE_FILE	0x0002	/* when !present: nonlinear file mapping */
-#define _PAGE_NO_CACHE	0x0002	/* I: cache inhibit */
-#define _PAGE_SHARED	0x0004	/* No ASID (context) compare */
-
-/* These five software bits must be masked out when the entry is loaded
- * into the TLB.
- */
-#define _PAGE_EXEC	0x0008	/* software: i-cache coherency required */
-#define _PAGE_GUARDED	0x0010	/* software: guarded access */
-#define _PAGE_DIRTY	0x0020	/* software: page changed */
-#define _PAGE_RW	0x0040	/* software: user write access allowed */
-#define _PAGE_ACCESSED	0x0080	/* software: page referenced */
-
-/* Setting any bits in the nibble with the follow two controls will
- * require a TLB exception handler change.  It is assumed unused bits
- * are always zero.
- */
-#define _PAGE_HWWRITE	0x0100	/* h/w write enable: never set in Linux PTE */
-#define _PAGE_USER	0x0800	/* One of the PP bits, the other is USER&~RW */
-
-#define _PMD_PRESENT	0x0001
-#define _PMD_BAD	0x0ff0
-#define _PMD_PAGE_MASK	0x000c
-#define _PMD_PAGE_8M	0x000c
-
-#define _PTE_NONE_MASK _PAGE_ACCESSED
-
-/* Until my rework is finished, 8xx still needs atomic PTE updates */
-#define PTE_ATOMIC_UPDATES	1
-
+#include <asm/pte-8xx.h>
 #else /* CONFIG_6xx */
-/* Definitions for 60x, 740/750, etc. */
-#define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
-#define _PAGE_HASHPTE	0x002	/* hash_page has made an HPTE for this pte */
-#define _PAGE_FILE	0x004	/* when !present: nonlinear file mapping */
-#define _PAGE_USER	0x004	/* usermode access allowed */
-#define _PAGE_GUARDED	0x008	/* G: prohibit speculative access */
-#define _PAGE_COHERENT	0x010	/* M: enforce memory coherence (SMP systems) */
-#define _PAGE_NO_CACHE	0x020	/* I: cache inhibit */
-#define _PAGE_WRITETHRU	0x040	/* W: cache write-through */
-#define _PAGE_DIRTY	0x080	/* C: page changed */
-#define _PAGE_ACCESSED	0x100	/* R: page referenced */
-#define _PAGE_EXEC	0x200	/* software: i-cache coherency required */
-#define _PAGE_RW	0x400	/* software: user write access allowed */
-#define _PAGE_SPECIAL	0x800	/* software: Special page */
-
-#ifdef CONFIG_PTE_64BIT
-/* We never clear the high word of the pte */
-#define _PTE_NONE_MASK	(0xffffffff00000000ULL | _PAGE_HASHPTE)
-#else
-#define _PTE_NONE_MASK	_PAGE_HASHPTE
+#include <asm/pte-hash32.h>
 #endif
 
-#define _PMD_PRESENT	0
-#define _PMD_PRESENT_MASK (PAGE_MASK)
-#define _PMD_BAD	(~PAGE_MASK)
-
-/* Hash table based platforms need atomic updates of the linux PTE */
-#define PTE_ATOMIC_UPDATES	1
-
-#define __HAVE_ARCH_PTE_SPECIAL
-
-#endif
-
-/*
- * Some bits are only used on some cpu families...
- */
-#ifndef _PAGE_HASHPTE
-#define _PAGE_HASHPTE	0
-#endif
-#ifndef _PTE_NONE_MASK
-#define _PTE_NONE_MASK 0
-#endif
-#ifndef _PAGE_SHARED
-#define _PAGE_SHARED	0
-#endif
-#ifndef _PAGE_HWWRITE
-#define _PAGE_HWWRITE	0
-#endif
-#ifndef _PAGE_HWEXEC
-#define _PAGE_HWEXEC	0
-#endif
-#ifndef _PAGE_EXEC
-#define _PAGE_EXEC	0
-#endif
-#ifndef _PAGE_ENDIAN
-#define _PAGE_ENDIAN	0
-#endif
-#ifndef _PAGE_COHERENT
-#define _PAGE_COHERENT	0
-#endif
-#ifndef _PAGE_WRITETHRU
-#define _PAGE_WRITETHRU	0
-#endif
-#ifndef _PAGE_SPECIAL
-#define _PAGE_SPECIAL	0
-#endif
-#ifndef _PMD_PRESENT_MASK
-#define _PMD_PRESENT_MASK	_PMD_PRESENT
-#endif
-#ifndef _PMD_SIZE
-#define _PMD_SIZE	0
-#define PMD_PAGE_SIZE(pmd)	bad_call_to_PMD_PAGE_SIZE()
-#endif
-
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
-			 _PAGE_SPECIAL)
-
-
-#define PAGE_PROT_BITS	(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
-			 _PAGE_WRITETHRU | _PAGE_ENDIAN | \
-			 _PAGE_USER | _PAGE_ACCESSED | \
-			 _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
-			 _PAGE_EXEC | _PAGE_HWEXEC)
-
-/*
- * We define 2 sets of base prot bits, one for basic pages (ie,
- * cacheable kernel and user pages) and one for non cacheable
- * pages. We always set _PAGE_COHERENT when SMP is enabled or
- * the processor might need it for DMA coherency.
- */
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
-#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
-#else
-#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED)
-#endif
-#define _PAGE_BASE_NC	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE)
-
-#define _PAGE_WRENABLE	(_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE)
-#define _PAGE_KERNEL	(_PAGE_BASE | _PAGE_SHARED | _PAGE_WRENABLE)
-#define _PAGE_KERNEL_NC	(_PAGE_BASE_NC | _PAGE_SHARED | _PAGE_WRENABLE)
-
-#ifdef CONFIG_PPC_STD_MMU
-/* On standard PPC MMU, no user access implies kernel read/write access,
- * so to write-protect kernel memory we must turn on user access */
-#define _PAGE_KERNEL_RO	(_PAGE_BASE | _PAGE_SHARED | _PAGE_USER)
-#else
-#define _PAGE_KERNEL_RO	(_PAGE_BASE | _PAGE_SHARED)
-#endif
-
-#define _PAGE_IO	(_PAGE_KERNEL_NC | _PAGE_GUARDED)
-#define _PAGE_RAM	(_PAGE_KERNEL | _PAGE_HWEXEC)
-
-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
-	defined(CONFIG_KPROBES)
-/* We want the debuggers to be able to set breakpoints anywhere, so
- * don't write protect the kernel text */
-#define _PAGE_RAM_TEXT	_PAGE_RAM
-#else
-#define _PAGE_RAM_TEXT	(_PAGE_KERNEL_RO | _PAGE_HWEXEC)
-#endif
-
-#define PAGE_NONE	__pgprot(_PAGE_BASE)
-#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
-#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-
-#define PAGE_KERNEL		__pgprot(_PAGE_RAM)
-#define PAGE_KERNEL_NOCACHE	__pgprot(_PAGE_IO)
-
-/*
- * The PowerPC can only do execute protection on a segment (256MB) basis,
- * not on a page basis.  So we consider execute permission the same as read.
- * Also, write permissions imply read permissions.
- * This is the closest we can get..
- */
-#define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY_X
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY_X
-#define __P100	PAGE_READONLY
-#define __P101	PAGE_READONLY_X
-#define __P110	PAGE_COPY
-#define __P111	PAGE_COPY_X
-
-#define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY_X
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED_X
-#define __S100	PAGE_READONLY
-#define __S101	PAGE_READONLY_X
-#define __S110	PAGE_SHARED
-#define __S111	PAGE_SHARED_X
+/* And here we include common definitions */
+#include <asm/pte-common.h>
 
 #ifndef __ASSEMBLY__
-/* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a
- * kernel without large page PMD support */
-extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
 
-/*
- * Conversions between PTE values and page frame numbers.
- */
-
-/* in some case we want to additionaly adjust where the pfn is in the pte to
- * allow room for more flags */
-#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_PTE_64BIT)
-#define PFN_SHIFT_OFFSET	(PAGE_SHIFT + 8)
-#else
-#define PFN_SHIFT_OFFSET	(PAGE_SHIFT)
-#endif
-
-#define pte_pfn(x)		(pte_val(x) >> PFN_SHIFT_OFFSET)
-#define pte_page(x)		pfn_to_page(pte_pfn(x))
-
-#define pfn_pte(pfn, prot)	__pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\
-					pgprot_val(prot))
-#define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
-#endif /* __ASSEMBLY__ */
-
-#define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
-#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
 #define pte_clear(mm, addr, ptep) \
 	do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0)
 
@@ -546,43 +110,6 @@
 #define	pmd_present(pmd)	(pmd_val(pmd) & _PMD_PRESENT_MASK)
 #define	pmd_clear(pmdp)		do { pmd_val(*(pmdp)) = 0; } while (0)
 
-#ifndef __ASSEMBLY__
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
-static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
-static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
-static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
-static inline int pte_special(pte_t pte)	{ return pte_val(pte) & _PAGE_SPECIAL; }
-
-static inline pte_t pte_wrprotect(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_mkclean(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
-static inline pte_t pte_mkold(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-
-static inline pte_t pte_mkwrite(pte_t pte) {
-	pte_val(pte) |= _PAGE_RW; return pte; }
-static inline pte_t pte_mkdirty(pte_t pte) {
-	pte_val(pte) |= _PAGE_DIRTY; return pte; }
-static inline pte_t pte_mkyoung(pte_t pte) {
-	pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkspecial(pte_t pte) {
-	pte_val(pte) |= _PAGE_SPECIAL; return pte; }
-static inline pgprot_t pte_pgprot(pte_t pte)
-{
-	return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
-}
-
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-	return pte;
-}
-
 /*
  * When flushing the tlb entry for a page, we also need to flush the hash
  * table entry.  flush_hash_pages is assembler (for speed) in hashtable.S.
@@ -599,11 +126,19 @@
 			     unsigned long address);
 
 /*
- * Atomic PTE updates.
+ * PTE updates. This function is called whenever an existing
+ * valid PTE is updated. This does -not- include set_pte_at()
+ * which nowadays only sets a new PTE.
  *
- * pte_update clears and sets bit atomically, and returns
- * the old pte value.  In the 64-bit PTE case we lock around the
- * low PTE word since we expect ALL flag bits to be there
+ * Depending on the type of MMU, we may need to use atomic updates
+ * and the PTE may be either 32 or 64 bit wide. In the later case,
+ * when using atomic updates, only the low part of the PTE is
+ * accessed atomically.
+ *
+ * In addition, on 44x, we also maintain a global flag indicating
+ * that an executable user mapping was modified, which is needed
+ * to properly flush the virtually tagged instruction cache of
+ * those implementations.
  */
 #ifndef CONFIG_PTE_64BIT
 static inline unsigned long pte_update(pte_t *p,
@@ -668,44 +203,6 @@
 #endif /* CONFIG_PTE_64BIT */
 
 /*
- * set_pte stores a linux PTE into the linux page table.
- * On machines which use an MMU hash table we avoid changing the
- * _PAGE_HASHPTE bit.
- */
-
-static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep, pte_t pte)
-{
-#if (_PAGE_HASHPTE != 0) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
-	pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
-#elif defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
-#if _PAGE_HASHPTE != 0
-	if (pte_val(*ptep) & _PAGE_HASHPTE)
-		flush_hash_entry(mm, ptep, addr);
-#endif
-	__asm__ __volatile__("\
-		stw%U0%X0 %2,%0\n\
-		eieio\n\
-		stw%U0%X0 %L2,%1"
-	: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
-	: "r" (pte) : "memory");
-#else
-	*ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
-		      | (pte_val(pte) & ~_PAGE_HASHPTE));
-#endif
-}
-
-
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep, pte_t pte)
-{
-#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) && defined(CONFIG_DEBUG_VM)
-	WARN_ON(pte_present(*ptep));
-#endif
-	__set_pte_at(mm, addr, ptep, pte);
-}
-
-/*
  * 2.6 calls this without flushing the TLB entry; this is wrong
  * for our hash-based implementation, we fix that up here.
  */
@@ -745,24 +242,14 @@
 }
 
 
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
 {
 	unsigned long bits = pte_val(entry) &
-		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW);
+		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW |
+		 _PAGE_HWEXEC | _PAGE_EXEC);
 	pte_update(ptep, 0, bits);
 }
 
-#define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({									   \
-	int __changed = !pte_same(*(__ptep), __entry);			   \
-	if (__changed) {						   \
-		__ptep_set_access_flags(__ptep, __entry, __dirty);         \
-		flush_tlb_page_nohash(__vma, __address);		   \
-	}								   \
-	__changed;							   \
-})
-
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
 
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-4k.h b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
new file mode 100644
index 0000000..6eefdcf
--- /dev/null
+++ b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
@@ -0,0 +1,74 @@
+#ifndef _ASM_POWERPC_PGTABLE_PPC64_4K_H
+#define _ASM_POWERPC_PGTABLE_PPC64_4K_H
+/*
+ * Entries per page directory level.  The PTE level must use a 64b record
+ * for each page table entry.  The PMD and PGD level use a 32b record for
+ * each entry by assuming that each entry is page aligned.
+ */
+#define PTE_INDEX_SIZE  9
+#define PMD_INDEX_SIZE  7
+#define PUD_INDEX_SIZE  7
+#define PGD_INDEX_SIZE  9
+
+#ifndef __ASSEMBLY__
+#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_INDEX_SIZE)
+#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
+#define PUD_TABLE_SIZE	(sizeof(pud_t) << PUD_INDEX_SIZE)
+#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
+#endif	/* __ASSEMBLY__ */
+
+#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD	(1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+
+/* PMD_SHIFT determines what a second-level page table entry can map */
+#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* With 4k base page size, hugepage PTEs go at the PMD level */
+#define MIN_HUGEPTE_SHIFT	PMD_SHIFT
+
+/* PUD_SHIFT determines what a third-level page table entry can map */
+#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
+#define PUD_SIZE	(1UL << PUD_SHIFT)
+#define PUD_MASK	(~(PUD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
+#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/* Bits to mask out from a PMD to get to the PTE page */
+#define PMD_MASKED_BITS		0
+/* Bits to mask out from a PUD to get to the PMD page */
+#define PUD_MASKED_BITS		0
+/* Bits to mask out from a PGD to get to the PUD page */
+#define PGD_MASKED_BITS		0
+
+
+/*
+ * 4-level page tables related bits
+ */
+
+#define pgd_none(pgd)		(!pgd_val(pgd))
+#define pgd_bad(pgd)		(pgd_val(pgd) == 0)
+#define pgd_present(pgd)	(pgd_val(pgd) != 0)
+#define pgd_clear(pgdp)		(pgd_val(*(pgdp)) = 0)
+#define pgd_page_vaddr(pgd)	(pgd_val(pgd) & ~PGD_MASKED_BITS)
+#define pgd_page(pgd)		virt_to_page(pgd_page_vaddr(pgd))
+
+#define pud_offset(pgdp, addr)	\
+  (((pud_t *) pgd_page_vaddr(*(pgdp))) + \
+    (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
+
+#define pud_ERROR(e) \
+	printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
+
+/*
+ * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range() */
+#define remap_4k_pfn(vma, addr, pfn, prot)	\
+	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
+
+#endif /* _ASM_POWERPC_PGTABLE_PPC64_4K_H */
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
new file mode 100644
index 0000000..6cc085b
--- /dev/null
+++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_POWERPC_PGTABLE_PPC64_64K_H
+#define _ASM_POWERPC_PGTABLE_PPC64_64K_H
+
+#include <asm-generic/pgtable-nopud.h>
+
+
+#define PTE_INDEX_SIZE  12
+#define PMD_INDEX_SIZE  12
+#define PUD_INDEX_SIZE	0
+#define PGD_INDEX_SIZE  4
+
+#ifndef __ASSEMBLY__
+
+#define PTE_TABLE_SIZE	(sizeof(real_pte_t) << PTE_INDEX_SIZE)
+#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
+#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
+
+#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+
+/* With 4k base page size, hugepage PTEs go at the PMD level */
+#define MIN_HUGEPTE_SHIFT	PAGE_SHIFT
+
+/* PMD_SHIFT determines what a second-level page table entry can map */
+#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+#endif	/* __ASSEMBLY__ */
+
+/* Bits to mask out from a PMD to get to the PTE page */
+#define PMD_MASKED_BITS		0x1ff
+/* Bits to mask out from a PGD/PUD to get to the PMD page */
+#define PUD_MASKED_BITS		0x1ff
+
+#endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index b0f18be..c40db05 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -11,9 +11,9 @@
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_PPC_64K_PAGES
-#include <asm/pgtable-64k.h>
+#include <asm/pgtable-ppc64-64k.h>
 #else
-#include <asm/pgtable-4k.h>
+#include <asm/pgtable-ppc64-4k.h>
 #endif
 
 #define FIRST_USER_ADDRESS	0
@@ -25,6 +25,8 @@
                 	    PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
 #define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
 
+
+/* Some sanity checking */
 #if TASK_SIZE_USER64 > PGTABLE_RANGE
 #error TASK_SIZE_USER64 exceeds pagetable range
 #endif
@@ -33,7 +35,6 @@
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 
-
 /*
  * Define the address range of the vmalloc VM area.
  */
@@ -76,82 +77,11 @@
 
 
 /*
- * Common bits in a linux-style PTE.  These match the bits in the
- * (hardware-defined) PowerPC PTE as closely as possible. Additional
- * bits may be defined in pgtable-*.h
+ * Include the PTE bits definitions
  */
-#define _PAGE_PRESENT	0x0001 /* software: pte contains a translation */
-#define _PAGE_USER	0x0002 /* matches one of the PP bits */
-#define _PAGE_FILE	0x0002 /* (!present only) software: pte holds file offset */
-#define _PAGE_EXEC	0x0004 /* No execute on POWER4 and newer (we invert) */
-#define _PAGE_GUARDED	0x0008
-#define _PAGE_COHERENT	0x0010 /* M: enforce memory coherence (SMP systems) */
-#define _PAGE_NO_CACHE	0x0020 /* I: cache inhibit */
-#define _PAGE_WRITETHRU	0x0040 /* W: cache write-through */
-#define _PAGE_DIRTY	0x0080 /* C: page changed */
-#define _PAGE_ACCESSED	0x0100 /* R: page referenced */
-#define _PAGE_RW	0x0200 /* software: user write access allowed */
-#define _PAGE_BUSY	0x0800 /* software: PTE & hash are busy */
+#include <asm/pte-hash64.h>
+#include <asm/pte-common.h>
 
-/* Strong Access Ordering */
-#define _PAGE_SAO	(_PAGE_WRITETHRU | _PAGE_NO_CACHE | _PAGE_COHERENT)
-
-#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
-
-#define _PAGE_WRENABLE	(_PAGE_RW | _PAGE_DIRTY)
-
-/* __pgprot defined in arch/powerpc/include/asm/page.h */
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-
-#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER)
-#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_WRENABLE)
-#define PAGE_KERNEL_CI	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
-			       _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
-#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC)
-
-#define PAGE_AGP	__pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
-#define HAVE_PAGE_AGP
-
-#define PAGE_PROT_BITS	(_PAGE_GUARDED | _PAGE_COHERENT | \
-			 _PAGE_NO_CACHE | _PAGE_WRITETHRU |		\
-			 _PAGE_4K_PFN | _PAGE_RW | _PAGE_USER |		\
-			 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
-/* PTEIDX nibble */
-#define _PTEIDX_SECONDARY	0x8
-#define _PTEIDX_GROUP_IX	0x7
-
-
-/*
- * POWER4 and newer have per page execute protection, older chips can only
- * do this on a segment (256MB) basis.
- *
- * Also, write permissions imply read permissions.
- * This is the closest we can get..
- *
- * Note due to the way vm flags are laid out, the bits are XWR
- */
-#define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
-#define __P100	PAGE_READONLY_X
-#define __P101	PAGE_READONLY_X
-#define __P110	PAGE_COPY_X
-#define __P111	PAGE_COPY_X
-
-#define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
-#define __S100	PAGE_READONLY_X
-#define __S101	PAGE_READONLY_X
-#define __S110	PAGE_SHARED_X
-#define __S111	PAGE_SHARED_X
 
 #ifdef CONFIG_PPC_MM_SLICES
 #define HAVE_ARCH_UNMAPPED_AREA
@@ -161,33 +91,39 @@
 #ifndef __ASSEMBLY__
 
 /*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- *
- * mk_pte takes a (struct page *) as input
+ * This is the default implementation of various PTE accessors, it's
+ * used in all cases except Book3S with 64K pages where we have a
+ * concept of sub-pages
  */
-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+#ifndef __real_pte
 
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
-{
-	pte_t pte;
+#ifdef STRICT_MM_TYPECHECKS
+#define __real_pte(e,p)		((real_pte_t){(e)})
+#define __rpte_to_pte(r)	((r).pte)
+#else
+#define __real_pte(e,p)		(e)
+#define __rpte_to_pte(r)	(__pte(r))
+#endif
+#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >> 12)
 
+#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
+	do {							         \
+		index = 0;					         \
+		shift = mmu_psize_defs[psize].shift;		         \
 
-	pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot);
-	return pte;
-}
+#define pte_iterate_hashed_end() } while(0)
 
-#define pte_modify(_pte, newprot) \
-  (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
+#ifdef CONFIG_PPC_HAS_HASH_64K
+#define pte_pagesize_index(mm, addr, pte)	get_slice_psize(mm, addr)
+#else
+#define pte_pagesize_index(mm, addr, pte)	MMU_PAGE_4K
+#endif
 
-#define pte_none(pte)		((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0)
-#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
+#endif /* __real_pte */
+
 
 /* pte_clear moved to later in this file */
 
-#define pte_pfn(x)		((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT)))
-#define pte_page(x)		pfn_to_page(pte_pfn(x))
-
 #define PMD_BAD_BITS		(PTE_TABLE_SIZE-1)
 #define PUD_BAD_BITS		(PMD_TABLE_SIZE-1)
 
@@ -235,36 +171,6 @@
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
-static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
-static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
-static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
-static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
-
-static inline pte_t pte_wrprotect(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_RW); return pte; }
-static inline pte_t pte_mkclean(pte_t pte) {
-	pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
-static inline pte_t pte_mkold(pte_t pte) {
-	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkwrite(pte_t pte) {
-	pte_val(pte) |= _PAGE_RW; return pte; }
-static inline pte_t pte_mkdirty(pte_t pte) {
-	pte_val(pte) |= _PAGE_DIRTY; return pte; }
-static inline pte_t pte_mkyoung(pte_t pte) {
-	pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-static inline pte_t pte_mkhuge(pte_t pte) {
-	return pte; }
-static inline pte_t pte_mkspecial(pte_t pte) {
-	pte_val(pte) |= _PAGE_SPECIAL; return pte; }
-static inline pgprot_t pte_pgprot(pte_t pte)
-{
-	return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
-}
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(struct mm_struct *mm,
@@ -272,6 +178,7 @@
 				       pte_t *ptep, unsigned long clr,
 				       int huge)
 {
+#ifdef PTE_ATOMIC_UPDATES
 	unsigned long old, tmp;
 
 	__asm__ __volatile__(
@@ -284,6 +191,13 @@
 	: "=&r" (old), "=&r" (tmp), "=m" (*ptep)
 	: "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
 	: "cc" );
+#else
+	unsigned long old = pte_val(*ptep);
+	*ptep = __pte(old & ~clr);
+#endif
+	/* huge pages use the old page table lock */
+	if (!huge)
+		assert_pte_locked(mm, addr);
 
 	if (old & _PAGE_HASHPTE)
 		hpte_need_flush(mm, addr, ptep, old, huge);
@@ -359,26 +273,17 @@
 	pte_update(mm, addr, ptep, ~0UL, 0);
 }
 
-/*
- * set_pte stores a linux PTE into the linux page table.
- */
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep, pte_t pte)
-{
-	if (pte_present(*ptep))
-		pte_clear(mm, addr, ptep);
-	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
-	*ptep = pte;
-}
 
 /* Set the dirty and/or accessed bits atomically in a linux PTE, this
  * function doesn't need to flush the hash entry
  */
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
 {
 	unsigned long bits = pte_val(entry) &
-		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
+		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW |
+		 _PAGE_EXEC | _PAGE_HWEXEC);
+
+#ifdef PTE_ATOMIC_UPDATES
 	unsigned long old, tmp;
 
 	__asm__ __volatile__(
@@ -391,16 +296,11 @@
 	:"=&r" (old), "=&r" (tmp), "=m" (*ptep)
 	:"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
 	:"cc");
+#else
+	unsigned long old = pte_val(*ptep);
+	*ptep = __pte(old | bits);
+#endif
 }
-#define  ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({									   \
-	int __changed = !pte_same(*(__ptep), __entry);			   \
-	if (__changed) {						   \
-		__ptep_set_access_flags(__ptep, __entry, __dirty);    	   \
-		flush_tlb_page_nohash(__vma, __address);		   \
-	}								   \
-	__changed;							   \
-})
 
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 07f55e6..eb17da7 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -6,7 +6,17 @@
 #include <asm/processor.h>		/* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
+
 struct mm_struct;
+
+#ifdef CONFIG_DEBUG_VM
+extern void assert_pte_locked(struct mm_struct *mm, unsigned long addr);
+#else /* CONFIG_DEBUG_VM */
+static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
+{
+}
+#endif /* !CONFIG_DEBUG_VM */
+
 #endif /* !__ASSEMBLY__ */
 
 #if defined(CONFIG_PPC64)
@@ -17,6 +27,130 @@
 
 #ifndef __ASSEMBLY__
 
+/* Generic accessors to PTE bits */
+static inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
+static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte)		{ return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte)	{ return pte_val(pte) & _PAGE_SPECIAL; }
+static inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
+static inline int pte_none(pte_t pte)		{ return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
+static inline pgprot_t pte_pgprot(pte_t pte)	{ return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
+
+/* Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ *
+ * Even if PTEs can be unsigned long long, a PFN is always an unsigned
+ * long for now.
+ */
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) {
+	return __pte(((pte_basic_t)(pfn) << PTE_RPN_SHIFT) |
+		     pgprot_val(pgprot)); }
+static inline unsigned long pte_pfn(pte_t pte)	{
+	return pte_val(pte) >> PTE_RPN_SHIFT; }
+
+/* Keep these as a macros to avoid include dependency mess */
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+
+/* Generic modifiers for PTE bits */
+static inline pte_t pte_wrprotect(pte_t pte) {
+	pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_mkclean(pte_t pte) {
+	pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
+static inline pte_t pte_mkold(pte_t pte) {
+	pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) {
+	pte_val(pte) |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) {
+	pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) {
+	pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkspecial(pte_t pte) {
+	pte_val(pte) |= _PAGE_SPECIAL; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) {
+	return pte; }
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	return pte;
+}
+
+
+/* Insert a PTE, top-level function is out of line. It uses an inline
+ * low level function in the respective pgtable-* files
+ */
+extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
+		       pte_t pte);
+
+/* This low level function performs the actual PTE insertion
+ * Setting the PTE depends on the MMU type and other factors. It's
+ * an horrible mess that I'm not going to try to clean up now but
+ * I'm keeping it in one place rather than spread around
+ */
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
+				pte_t *ptep, pte_t pte, int percpu)
+{
+#if defined(CONFIG_PPC_STD_MMU_32) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
+	/* First case is 32-bit Hash MMU in SMP mode with 32-bit PTEs. We use the
+	 * helper pte_update() which does an atomic update. We need to do that
+	 * because a concurrent invalidation can clear _PAGE_HASHPTE. If it's a
+	 * per-CPU PTE such as a kmap_atomic, we do a simple update preserving
+	 * the hash bits instead (ie, same as the non-SMP case)
+	 */
+	if (percpu)
+		*ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+			      | (pte_val(pte) & ~_PAGE_HASHPTE));
+	else
+		pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte));
+
+#elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
+	/* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we
+	 * can just store as long as we do the two halves in the right order
+	 * with a barrier in between. This is possible because we take care,
+	 * in the hash code, to pre-invalidate if the PTE was already hashed,
+	 * which synchronizes us with any concurrent invalidation.
+	 * In the percpu case, we also fallback to the simple update preserving
+	 * the hash bits
+	 */
+	if (percpu) {
+		*ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+			      | (pte_val(pte) & ~_PAGE_HASHPTE));
+		return;
+	}
+#if _PAGE_HASHPTE != 0
+	if (pte_val(*ptep) & _PAGE_HASHPTE)
+		flush_hash_entry(mm, ptep, addr);
+#endif
+	__asm__ __volatile__("\
+		stw%U0%X0 %2,%0\n\
+		eieio\n\
+		stw%U0%X0 %L2,%1"
+	: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
+	: "r" (pte) : "memory");
+
+#elif defined(CONFIG_PPC_STD_MMU_32)
+	/* Third case is 32-bit hash table in UP mode, we need to preserve
+	 * the _PAGE_HASHPTE bit since we may not have invalidated the previous
+	 * translation in the hash yet (done in a subsequent flush_tlb_xxx())
+	 * and see we need to keep track that this PTE needs invalidating
+	 */
+	*ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+		      | (pte_val(pte) & ~_PAGE_HASHPTE));
+
+#else
+	/* Anything else just stores the PTE normally. That covers all 64-bit
+	 * cases, and 32-bit non-hash with 64-bit PTEs in UP mode
+	 */
+	*ptep = pte;
+#endif
+}
+
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+				 pte_t *ptep, pte_t entry, int dirty);
+
 /*
  * Macro to mark a page protection value as "uncacheable".
  */
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
new file mode 100644
index 0000000..f4a4db8
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Freescale Semicondutor, 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.
+ *
+ * provides masks and opcode images for use by code generation, emulation
+ * and for instructions that older assemblers might not know about
+ */
+#ifndef _ASM_POWERPC_PPC_OPCODE_H
+#define _ASM_POWERPC_PPC_OPCODE_H
+
+#include <linux/stringify.h>
+#include <asm/asm-compat.h>
+
+/* sorted alphabetically */
+#define PPC_INST_DCBA			0x7c0005ec
+#define PPC_INST_DCBA_MASK		0xfc0007fe
+#define PPC_INST_DCBAL			0x7c2005ec
+#define PPC_INST_DCBZL			0x7c2007ec
+#define PPC_INST_ISEL			0x7c00001e
+#define PPC_INST_ISEL_MASK		0xfc00003e
+#define PPC_INST_LSWI			0x7c0004aa
+#define PPC_INST_LSWX			0x7c00042a
+#define PPC_INST_LWSYNC			0x7c2004ac
+#define PPC_INST_MCRXR			0x7c000400
+#define PPC_INST_MCRXR_MASK		0xfc0007fe
+#define PPC_INST_MFSPR_PVR		0x7c1f42a6
+#define PPC_INST_MFSPR_PVR_MASK		0xfc1fffff
+#define PPC_INST_MSGSND			0x7c00019c
+#define PPC_INST_NOP			0x60000000
+#define PPC_INST_POPCNTB		0x7c0000f4
+#define PPC_INST_POPCNTB_MASK		0xfc0007fe
+#define PPC_INST_RFCI			0x4c000066
+#define PPC_INST_RFDI			0x4c00004e
+#define PPC_INST_RFMCI			0x4c00004c
+
+#define PPC_INST_STRING			0x7c00042a
+#define PPC_INST_STRING_MASK		0xfc0007fe
+#define PPC_INST_STRING_GEN_MASK	0xfc00067e
+
+#define PPC_INST_STSWI			0x7c0005aa
+#define PPC_INST_STSWX			0x7c00052a
+#define PPC_INST_TLBILX			0x7c000626
+#define PPC_INST_WAIT			0x7c00007c
+
+/* macros to insert fields into opcodes */
+#define __PPC_RA(a)	((a & 0x1f) << 16)
+#define __PPC_RB(b)	((b & 0x1f) << 11)
+#define __PPC_T_TLB(t)	((t & 0x3) << 21)
+#define __PPC_WC(w)	((w & 0x3) << 21)
+
+/* Deal with instructions that older assemblers aren't aware of */
+#define	PPC_DCBAL(a, b)		stringify_in_c(.long PPC_INST_DCBAL | \
+					__PPC_RA(a) | __PPC_RB(b))
+#define	PPC_DCBZL(a, b)		stringify_in_c(.long PPC_INST_DCBZL | \
+					__PPC_RA(a) | __PPC_RB(b))
+#define PPC_MSGSND(b)		stringify_in_c(.long PPC_INST_MSGSND | \
+					__PPC_RB(b))
+#define PPC_RFCI		stringify_in_c(.long PPC_INST_RFCI)
+#define PPC_RFDI		stringify_in_c(.long PPC_INST_RFDI)
+#define PPC_RFMCI		stringify_in_c(.long PPC_INST_RFMCI)
+#define PPC_TLBILX(t, a, b)	stringify_in_c(.long PPC_INST_TLBILX | \
+					__PPC_T_TLB(t) | __PPC_RA(a) | __PPC_RB(b))
+#define PPC_TLBILX_ALL(a, b)	PPC_TLBILX(0, a, b)
+#define PPC_TLBILX_PID(a, b)	PPC_TLBILX(1, a, b)
+#define PPC_TLBILX_VA(a, b)	PPC_TLBILX(3, a, b)
+#define PPC_WAIT(w)		stringify_in_c(.long PPC_INST_WAIT | \
+					__PPC_WC(w))
+
+#endif /* _ASM_POWERPC_PPC_OPCODE_H */
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 1a0d628..f59a666 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -7,6 +7,7 @@
 #include <linux/stringify.h>
 #include <asm/asm-compat.h>
 #include <asm/processor.h>
+#include <asm/ppc-opcode.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -167,11 +168,6 @@
 #define HMT_MEDIUM_HIGH or	5,5,5		# medium high priority
 #define HMT_HIGH	or	3,3,3
 
-/* handle instructions that older assemblers may not know */
-#define RFCI		.long 0x4c000066	/* rfci instruction */
-#define RFDI		.long 0x4c00004e	/* rfdi instruction */
-#define RFMCI		.long 0x4c00004c	/* rfmci instruction */
-
 #ifdef __KERNEL__
 #ifdef CONFIG_PPC64
 
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index d346649..9eed29e 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -313,6 +313,25 @@
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 #endif
 
+#ifdef CONFIG_PPC64
+static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+{
+	unsigned long sp;
+
+	if (is_32)
+		sp = regs->gpr[1] & 0x0ffffffffUL;
+	else
+		sp = regs->gpr[1];
+
+	return sp;
+}
+#else
+static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+{
+	return regs->gpr[1];
+}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PROCESSOR_H */
diff --git a/arch/powerpc/include/asm/ps3av.h b/arch/powerpc/include/asm/ps3av.h
index cd24ac1..0427b0b 100644
--- a/arch/powerpc/include/asm/ps3av.h
+++ b/arch/powerpc/include/asm/ps3av.h
@@ -730,7 +730,7 @@
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
 					    u32);
 
-extern int ps3av_set_video_mode(u32);
+extern int ps3av_set_video_mode(int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(void);
 extern int ps3av_get_mode(void);
diff --git a/arch/powerpc/include/asm/ps3fb.h b/arch/powerpc/include/asm/ps3fb.h
index e7233a8..90dbefb 100644
--- a/arch/powerpc/include/asm/ps3fb.h
+++ b/arch/powerpc/include/asm/ps3fb.h
@@ -21,6 +21,7 @@
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
+#include <linux/types.h>
 
 /* ioctl */
 #define PS3FB_IOCTL_SETMODE       _IOW('r',  1, int) /* set video mode */
diff --git a/arch/powerpc/include/asm/pte-40x.h b/arch/powerpc/include/asm/pte-40x.h
new file mode 100644
index 0000000..07630fa
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-40x.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_POWERPC_PTE_40x_H
+#define _ASM_POWERPC_PTE_40x_H
+#ifdef __KERNEL__
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully-associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively (see "mmu.h" for definitions).
+ *
+ * There are several potential gotchas here.  The 40x hardware TLBLO
+ * field looks like this:
+ *
+ * 0  1  2  3  4  ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ * RPN.....................  0  0 EX WR ZSEL.......  W  I  M  G
+ *
+ * Where possible we make the Linux PTE bits match up with this
+ *
+ * - bits 20 and 21 must be cleared, because we use 4k pages (40x can
+ *   support down to 1k pages), this is done in the TLBMiss exception
+ *   handler.
+ * - We use only zones 0 (for kernel pages) and 1 (for user pages)
+ *   of the 16 available.  Bit 24-26 of the TLB are cleared in the TLB
+ *   miss handler.  Bit 27 is PAGE_USER, thus selecting the correct
+ *   zone.
+ * - PRESENT *must* be in the bottom two bits because swap cache
+ *   entries use the top 30 bits.  Because 40x doesn't support SMP
+ *   anyway, M is irrelevant so we borrow it for PAGE_PRESENT.  Bit 30
+ *   is cleared in the TLB miss handler before the TLB entry is loaded.
+ * - All other bits of the PTE are loaded into TLBLO without
+ *   modification, leaving us only the bits 20, 21, 24, 25, 26, 30 for
+ *   software PTE bits.  We actually use use bits 21, 24, 25, and
+ *   30 respectively for the software bits: ACCESSED, DIRTY, RW, and
+ *   PRESENT.
+ */
+
+#define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
+#define _PAGE_FILE	0x001	/* when !present: nonlinear file mapping */
+#define _PAGE_PRESENT	0x002	/* software: PTE contains a translation */
+#define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
+#define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
+#define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
+#define	_PAGE_RW	0x040	/* software: Writes permitted */
+#define	_PAGE_DIRTY	0x080	/* software: dirty page */
+#define _PAGE_HWWRITE	0x100	/* hardware: Dirty & RW, set in exception */
+#define _PAGE_HWEXEC	0x200	/* hardware: EX permission */
+#define _PAGE_ACCESSED	0x400	/* software: R: page referenced */
+
+#define _PMD_PRESENT	0x400	/* PMD points to page of PTEs */
+#define _PMD_BAD	0x802
+#define _PMD_SIZE	0x0e0	/* size field, != 0 for large-page PMD entry */
+#define _PMD_SIZE_4M	0x0c0
+#define _PMD_SIZE_16M	0x0e0
+
+#define PMD_PAGE_SIZE(pmdval)	(1024 << (((pmdval) & _PMD_SIZE) >> 4))
+
+/* Until my rework is finished, 40x still needs atomic PTE updates */
+#define PTE_ATOMIC_UPDATES	1
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_40x_H */
diff --git a/arch/powerpc/include/asm/pte-44x.h b/arch/powerpc/include/asm/pte-44x.h
new file mode 100644
index 0000000..37e98bc
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-44x.h
@@ -0,0 +1,102 @@
+#ifndef _ASM_POWERPC_PTE_44x_H
+#define _ASM_POWERPC_PTE_44x_H
+#ifdef __KERNEL__
+
+/*
+ * Definitions for PPC440
+ *
+ * Because of the 3 word TLB entries to support 36-bit addressing,
+ * the attribute are difficult to map in such a fashion that they
+ * are easily loaded during exception processing.  I decided to
+ * organize the entry so the ERPN is the only portion in the
+ * upper word of the PTE and the attribute bits below are packed
+ * in as sensibly as they can be in the area below a 4KB page size
+ * oriented RPN.  This at least makes it easy to load the RPN and
+ * ERPN fields in the TLB. -Matt
+ *
+ * This isn't entirely true anymore, at least some bits are now
+ * easier to move into the TLB from the PTE. -BenH.
+ *
+ * Note that these bits preclude future use of a page size
+ * less than 4KB.
+ *
+ *
+ * PPC 440 core has following TLB attribute fields;
+ *
+ *   TLB1:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   RPN.................................  -  -  -  -  -  - ERPN.......
+ *
+ *   TLB2:
+ *   0  1  2  3  4  ... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ *   -  -  -  -  -    - U0 U1 U2 U3 W  I  M  G  E   - UX UW UR SX SW SR
+ *
+ * Newer 440 cores (440x6 as used on AMCC 460EX/460GT) have additional
+ * TLB2 storage attibute fields. Those are:
+ *
+ *   TLB2:
+ *   0...10    11   12   13   14   15   16...31
+ *   no change WL1  IL1I IL1D IL2I IL2D no change
+ *
+ * There are some constrains and options, to decide mapping software bits
+ * into TLB entry.
+ *
+ *   - PRESENT *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - FILE *must* be in the bottom three bits because swap cache
+ *     entries use the top 29 bits for TLB2.
+ *
+ *   - CACHE COHERENT bit (M) has no effect on original PPC440 cores,
+ *     because it doesn't support SMP. However, some later 460 variants
+ *     have -some- form of SMP support and so I keep the bit there for
+ *     future use
+ *
+ * With the PPC 44x Linux implementation, the 0-11th LSBs of the PTE are used
+ * for memory protection related functions (see PTE structure in
+ * include/asm-ppc/mmu.h).  The _PAGE_XXX definitions in this file map to the
+ * above bits.  Note that the bit values are CPU specific, not architecture
+ * specific.
+ *
+ * The kernel PTE entry holds an arch-dependent swp_entry structure under
+ * certain situations. In other words, in such situations some portion of
+ * the PTE bits are used as a swp_entry. In the PPC implementation, the
+ * 3-24th LSB are shared with swp_entry, however the 0-2nd three LSB still
+ * hold protection values. That means the three protection bits are
+ * reserved for both PTE and SWAP entry at the most significant three
+ * LSBs.
+ *
+ * There are three protection bits available for SWAP entry:
+ *	_PAGE_PRESENT
+ *	_PAGE_FILE
+ *	_PAGE_HASHPTE (if HW has)
+ *
+ * So those three bits have to be inside of 0-2nd LSB of PTE.
+ *
+ */
+
+#define _PAGE_PRESENT	0x00000001		/* S: PTE valid */
+#define _PAGE_RW	0x00000002		/* S: Write permission */
+#define _PAGE_FILE	0x00000004		/* S: nonlinear file mapping */
+#define _PAGE_HWEXEC	0x00000004		/* H: Execute permission */
+#define _PAGE_ACCESSED	0x00000008		/* S: Page referenced */
+#define _PAGE_DIRTY	0x00000010		/* S: Page dirty */
+#define _PAGE_SPECIAL	0x00000020		/* S: Special page */
+#define _PAGE_USER	0x00000040		/* S: User page */
+#define _PAGE_ENDIAN	0x00000080		/* H: E bit */
+#define _PAGE_GUARDED	0x00000100		/* H: G bit */
+#define _PAGE_COHERENT	0x00000200		/* H: M bit */
+#define _PAGE_NO_CACHE	0x00000400		/* H: I bit */
+#define _PAGE_WRITETHRU	0x00000800		/* H: W bit */
+
+/* TODO: Add large page lowmem mapping support */
+#define _PMD_PRESENT	0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD	(~PAGE_MASK)
+
+/* ERPN in a PTE never gets cleared, ignore it */
+#define _PTE_NONE_MASK	0xffffffff00000000ULL
+
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_44x_H */
diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
new file mode 100644
index 0000000..8c6e312
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-8xx.h
@@ -0,0 +1,67 @@
+#ifndef _ASM_POWERPC_PTE_8xx_H
+#define _ASM_POWERPC_PTE_8xx_H
+#ifdef __KERNEL__
+
+/*
+ * The PowerPC MPC8xx uses a TLB with hardware assisted, software tablewalk.
+ * We also use the two level tables, but we can put the real bits in them
+ * needed for the TLB and tablewalk.  These definitions require Mx_CTR.PPM = 0,
+ * Mx_CTR.PPCS = 0, and MD_CTR.TWAM = 1.  The level 2 descriptor has
+ * additional page protection (when Mx_CTR.PPCS = 1) that allows TLB hit
+ * based upon user/super access.  The TLB does not have accessed nor write
+ * protect.  We assume that if the TLB get loaded with an entry it is
+ * accessed, and overload the changed bit for write protect.  We use
+ * two bits in the software pte that are supposed to be set to zero in
+ * the TLB entry (24 and 25) for these indicators.  Although the level 1
+ * descriptor contains the guarded and writethrough/copyback bits, we can
+ * set these at the page level since they get copied from the Mx_TWC
+ * register when the TLB entry is loaded.  We will use bit 27 for guard, since
+ * that is where it exists in the MD_TWC, and bit 26 for writethrough.
+ * These will get masked from the level 2 descriptor at TLB load time, and
+ * copied to the MD_TWC before it gets loaded.
+ * Large page sizes added.  We currently support two sizes, 4K and 8M.
+ * This also allows a TLB hander optimization because we can directly
+ * load the PMD into MD_TWC.  The 8M pages are only used for kernel
+ * mapping of well known areas.  The PMD (PGD) entries contain control
+ * flags in addition to the address, so care must be taken that the
+ * software no longer assumes these are only pointers.
+ */
+
+/* Definitions for 8xx embedded chips. */
+#define _PAGE_PRESENT	0x0001	/* Page is valid */
+#define _PAGE_FILE	0x0002	/* when !present: nonlinear file mapping */
+#define _PAGE_NO_CACHE	0x0002	/* I: cache inhibit */
+#define _PAGE_SHARED	0x0004	/* No ASID (context) compare */
+
+/* These five software bits must be masked out when the entry is loaded
+ * into the TLB.
+ */
+#define _PAGE_EXEC	0x0008	/* software: i-cache coherency required */
+#define _PAGE_GUARDED	0x0010	/* software: guarded access */
+#define _PAGE_DIRTY	0x0020	/* software: page changed */
+#define _PAGE_RW	0x0040	/* software: user write access allowed */
+#define _PAGE_ACCESSED	0x0080	/* software: page referenced */
+
+/* Setting any bits in the nibble with the follow two controls will
+ * require a TLB exception handler change.  It is assumed unused bits
+ * are always zero.
+ */
+#define _PAGE_HWWRITE	0x0100	/* h/w write enable: never set in Linux PTE */
+#define _PAGE_USER	0x0800	/* One of the PP bits, the other is USER&~RW */
+
+#define _PMD_PRESENT	0x0001
+#define _PMD_BAD	0x0ff0
+#define _PMD_PAGE_MASK	0x000c
+#define _PMD_PAGE_8M	0x000c
+
+#define _PTE_NONE_MASK _PAGE_ACCESSED
+
+/* Until my rework is finished, 8xx still needs atomic PTE updates */
+#define PTE_ATOMIC_UPDATES	1
+
+/* We need to add _PAGE_SHARED to kernel pages */
+#define _PAGE_KERNEL_RO	(_PAGE_SHARED)
+#define _PAGE_KERNEL_RW	(_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_8xx_H */
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h
new file mode 100644
index 0000000..d9740e8
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -0,0 +1,180 @@
+/* Included from asm/pgtable-*.h only ! */
+
+/*
+ * Some bits are only used on some cpu families... Make sure that all
+ * the undefined gets a sensible default
+ */
+#ifndef _PAGE_HASHPTE
+#define _PAGE_HASHPTE	0
+#endif
+#ifndef _PAGE_SHARED
+#define _PAGE_SHARED	0
+#endif
+#ifndef _PAGE_HWWRITE
+#define _PAGE_HWWRITE	0
+#endif
+#ifndef _PAGE_HWEXEC
+#define _PAGE_HWEXEC	0
+#endif
+#ifndef _PAGE_EXEC
+#define _PAGE_EXEC	0
+#endif
+#ifndef _PAGE_ENDIAN
+#define _PAGE_ENDIAN	0
+#endif
+#ifndef _PAGE_COHERENT
+#define _PAGE_COHERENT	0
+#endif
+#ifndef _PAGE_WRITETHRU
+#define _PAGE_WRITETHRU	0
+#endif
+#ifndef _PAGE_SPECIAL
+#define _PAGE_SPECIAL	0
+#endif
+#ifndef _PAGE_4K_PFN
+#define _PAGE_4K_PFN		0
+#endif
+#ifndef _PAGE_PSIZE
+#define _PAGE_PSIZE		0
+#endif
+#ifndef _PMD_PRESENT_MASK
+#define _PMD_PRESENT_MASK	_PMD_PRESENT
+#endif
+#ifndef _PMD_SIZE
+#define _PMD_SIZE	0
+#define PMD_PAGE_SIZE(pmd)	bad_call_to_PMD_PAGE_SIZE()
+#endif
+#ifndef _PAGE_KERNEL_RO
+#define _PAGE_KERNEL_RO	0
+#endif
+#ifndef _PAGE_KERNEL_RW
+#define _PAGE_KERNEL_RW	(_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
+#endif
+#ifndef _PAGE_HPTEFLAGS
+#define _PAGE_HPTEFLAGS _PAGE_HASHPTE
+#endif
+#ifndef _PTE_NONE_MASK
+#define _PTE_NONE_MASK	_PAGE_HPTEFLAGS
+#endif
+
+/* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a
+ * kernel without large page PMD support
+ */
+#ifndef __ASSEMBLY__
+extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
+#endif /* __ASSEMBLY__ */
+
+/* Location of the PFN in the PTE. Most 32-bit platforms use the same
+ * as _PAGE_SHIFT here (ie, naturally aligned).
+ * Platform who don't just pre-define the value so we don't override it here
+ */
+#ifndef PTE_RPN_SHIFT
+#define PTE_RPN_SHIFT	(PAGE_SHIFT)
+#endif
+
+/* The mask convered by the RPN must be a ULL on 32-bit platforms with
+ * 64-bit PTEs
+ */
+#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)
+#define PTE_RPN_MAX	(1ULL << (64 - PTE_RPN_SHIFT))
+#define PTE_RPN_MASK	(~((1ULL<<PTE_RPN_SHIFT)-1))
+#else
+#define PTE_RPN_MAX	(1UL << (32 - PTE_RPN_SHIFT))
+#define PTE_RPN_MASK	(~((1UL<<PTE_RPN_SHIFT)-1))
+#endif
+
+/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
+ * pgprot changes
+ */
+#define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
+                         _PAGE_ACCESSED | _PAGE_SPECIAL)
+
+/* Mask of bits returned by pte_pgprot() */
+#define PAGE_PROT_BITS	(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
+			 _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \
+			 _PAGE_USER | _PAGE_ACCESSED | \
+			 _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
+			 _PAGE_EXEC | _PAGE_HWEXEC)
+
+/*
+ * We define 2 sets of base prot bits, one for basic pages (ie,
+ * cacheable kernel and user pages) and one for non cacheable
+ * pages. We always set _PAGE_COHERENT when SMP is enabled or
+ * the processor might need it for DMA coherency.
+ */
+#define _PAGE_BASE_NC	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
+#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
+#define _PAGE_BASE	(_PAGE_BASE_NC | _PAGE_COHERENT)
+#else
+#define _PAGE_BASE	(_PAGE_BASE_NC)
+#endif
+
+/* Permission masks used to generate the __P and __S table,
+ *
+ * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
+ *
+ * Write permissions imply read permissions for now (we could make write-only
+ * pages on BookE but we don't bother for now). Execute permission control is
+ * possible on platforms that define _PAGE_EXEC
+ *
+ * Note due to the way vm flags are laid out, the bits are XWR
+ */
+#define PAGE_NONE	__pgprot(_PAGE_BASE)
+#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
+#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY_X
+#define __P101	PAGE_READONLY_X
+#define __P110	PAGE_COPY_X
+#define __P111	PAGE_COPY_X
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY_X
+#define __S101	PAGE_READONLY_X
+#define __S110	PAGE_SHARED_X
+#define __S111	PAGE_SHARED_X
+
+/* Permission masks used for kernel mappings */
+#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
+#define PAGE_KERNEL_NC	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
+				 _PAGE_NO_CACHE)
+#define PAGE_KERNEL_NCG	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
+				 _PAGE_NO_CACHE | _PAGE_GUARDED)
+#define PAGE_KERNEL_X	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
+#define PAGE_KERNEL_ROX	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC)
+
+/* Protection used for kernel text. We want the debuggers to be able to
+ * set breakpoints anywhere, so don't write protect the kernel text
+ * on platforms where such control is possible.
+ */
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
+	defined(CONFIG_KPROBES)
+#define PAGE_KERNEL_TEXT	PAGE_KERNEL_X
+#else
+#define PAGE_KERNEL_TEXT	PAGE_KERNEL_ROX
+#endif
+
+/* Make modules code happy. We don't set RO yet */
+#define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
+
+/* Advertise special mapping type for AGP */
+#define PAGE_AGP		(PAGE_KERNEL_NC)
+#define HAVE_PAGE_AGP
+
+/* Advertise support for _PAGE_SPECIAL */
+#ifdef _PAGE_SPECIAL
+#define __HAVE_ARCH_PTE_SPECIAL
+#endif
+
diff --git a/arch/powerpc/include/asm/pte-fsl-booke.h b/arch/powerpc/include/asm/pte-fsl-booke.h
new file mode 100644
index 0000000..10820f5
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-fsl-booke.h
@@ -0,0 +1,48 @@
+#ifndef _ASM_POWERPC_PTE_FSL_BOOKE_H
+#define _ASM_POWERPC_PTE_FSL_BOOKE_H
+#ifdef __KERNEL__
+
+/* PTE bit definitions for Freescale BookE SW loaded TLB MMU based
+ * processors
+ *
+   MMU Assist Register 3:
+
+   32 33 34 35 36  ... 50 51 52 53 54 55 56 57 58 59 60 61 62 63
+   RPN......................  0  0 U0 U1 U2 U3 UX SX UW SW UR SR
+
+   - PRESENT *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+
+   - FILE *must* be in the bottom three bits because swap cache
+     entries use the top 29 bits.
+*/
+
+/* Definitions for FSL Book-E Cores */
+#define _PAGE_PRESENT	0x00001	/* S: PTE contains a translation */
+#define _PAGE_USER	0x00002	/* S: User page (maps to UR) */
+#define _PAGE_FILE	0x00002	/* S: when !present: nonlinear file mapping */
+#define _PAGE_RW	0x00004	/* S: Write permission (SW) */
+#define _PAGE_DIRTY	0x00008	/* S: Page dirty */
+#define _PAGE_HWEXEC	0x00010	/* H: SX permission */
+#define _PAGE_ACCESSED	0x00020	/* S: Page referenced */
+
+#define _PAGE_ENDIAN	0x00040	/* H: E bit */
+#define _PAGE_GUARDED	0x00080	/* H: G bit */
+#define _PAGE_COHERENT	0x00100	/* H: M bit */
+#define _PAGE_NO_CACHE	0x00200	/* H: I bit */
+#define _PAGE_WRITETHRU	0x00400	/* H: W bit */
+#define _PAGE_SPECIAL	0x00800 /* S: Special page */
+
+#ifdef CONFIG_PTE_64BIT
+/* ERPN in a PTE never gets cleared, ignore it */
+#define _PTE_NONE_MASK	0xffffffffffff0000ULL
+/* We extend the size of the PTE flags area when using 64-bit PTEs */
+#define PTE_RPN_SHIFT	(PAGE_SHIFT + 8)
+#endif
+
+#define _PMD_PRESENT	0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD	(~PAGE_MASK)
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_FSL_BOOKE_H */
diff --git a/arch/powerpc/include/asm/pte-hash32.h b/arch/powerpc/include/asm/pte-hash32.h
new file mode 100644
index 0000000..16e571c
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-hash32.h
@@ -0,0 +1,48 @@
+#ifndef _ASM_POWERPC_PTE_HASH32_H
+#define _ASM_POWERPC_PTE_HASH32_H
+#ifdef __KERNEL__
+
+/*
+ * The "classic" 32-bit implementation of the PowerPC MMU uses a hash
+ * table containing PTEs, together with a set of 16 segment registers,
+ * to define the virtual to physical address mapping.
+ *
+ * We use the hash table as an extended TLB, i.e. a cache of currently
+ * active mappings.  We maintain a two-level page table tree, much
+ * like that used by the i386, for the sake of the Linux memory
+ * management code.  Low-level assembler code in hash_low_32.S
+ * (procedure hash_page) is responsible for extracting ptes from the
+ * tree and putting them into the hash table when necessary, and
+ * updating the accessed and modified bits in the page table tree.
+ */
+
+#define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
+#define _PAGE_HASHPTE	0x002	/* hash_page has made an HPTE for this pte */
+#define _PAGE_FILE	0x004	/* when !present: nonlinear file mapping */
+#define _PAGE_USER	0x004	/* usermode access allowed */
+#define _PAGE_GUARDED	0x008	/* G: prohibit speculative access */
+#define _PAGE_COHERENT	0x010	/* M: enforce memory coherence (SMP systems) */
+#define _PAGE_NO_CACHE	0x020	/* I: cache inhibit */
+#define _PAGE_WRITETHRU	0x040	/* W: cache write-through */
+#define _PAGE_DIRTY	0x080	/* C: page changed */
+#define _PAGE_ACCESSED	0x100	/* R: page referenced */
+#define _PAGE_EXEC	0x200	/* software: i-cache coherency required */
+#define _PAGE_RW	0x400	/* software: user write access allowed */
+#define _PAGE_SPECIAL	0x800	/* software: Special page */
+
+#ifdef CONFIG_PTE_64BIT
+/* We never clear the high word of the pte */
+#define _PTE_NONE_MASK	(0xffffffff00000000ULL | _PAGE_HASHPTE)
+#else
+#define _PTE_NONE_MASK	_PAGE_HASHPTE
+#endif
+
+#define _PMD_PRESENT	0
+#define _PMD_PRESENT_MASK (PAGE_MASK)
+#define _PMD_BAD	(~PAGE_MASK)
+
+/* Hash table based platforms need atomic updates of the linux PTE */
+#define PTE_ATOMIC_UPDATES	1
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_HASH32_H */
diff --git a/arch/powerpc/include/asm/pte-hash64-4k.h b/arch/powerpc/include/asm/pte-hash64-4k.h
new file mode 100644
index 0000000..c134e809
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-hash64-4k.h
@@ -0,0 +1,17 @@
+/* To be include by pgtable-hash64.h only */
+
+/* PTE bits */
+#define _PAGE_HASHPTE	0x0400 /* software: pte has an associated HPTE */
+#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */
+#define _PAGE_GROUP_IX  0x7000 /* software: HPTE index within group */
+#define _PAGE_F_SECOND  _PAGE_SECONDARY
+#define _PAGE_F_GIX     _PAGE_GROUP_IX
+#define _PAGE_SPECIAL	0x10000 /* software: special page */
+
+/* PTE flags to conserve for HPTE identification */
+#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
+			 _PAGE_SECONDARY | _PAGE_GROUP_IX)
+
+/* shift to put page number into pte */
+#define PTE_RPN_SHIFT	(17)
+
diff --git a/arch/powerpc/include/asm/pgtable-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h
similarity index 73%
rename from arch/powerpc/include/asm/pgtable-64k.h
rename to arch/powerpc/include/asm/pte-hash64-64k.h
index 7389003..e05d26f 100644
--- a/arch/powerpc/include/asm/pgtable-64k.h
+++ b/arch/powerpc/include/asm/pte-hash64-64k.h
@@ -1,22 +1,80 @@
-#ifndef _ASM_POWERPC_PGTABLE_64K_H
-#define _ASM_POWERPC_PGTABLE_64K_H
+/* To be include by pgtable-hash64.h only */
 
-#include <asm-generic/pgtable-nopud.h>
+/* Additional PTE bits (don't change without checking asm in hash_low.S) */
+#define _PAGE_SPECIAL	0x00000400 /* software: special page */
+#define _PAGE_HPTE_SUB	0x0ffff000 /* combo only: sub pages HPTE bits */
+#define _PAGE_HPTE_SUB0	0x08000000 /* combo only: first sub page */
+#define _PAGE_COMBO	0x10000000 /* this is a combo 4k page */
+#define _PAGE_4K_PFN	0x20000000 /* PFN is for a single 4k page */
 
+/* For 64K page, we don't have a separate _PAGE_HASHPTE bit. Instead,
+ * we set that to be the whole sub-bits mask. The C code will only
+ * test this, so a multi-bit mask will work. For combo pages, this
+ * is equivalent as effectively, the old _PAGE_HASHPTE was an OR of
+ * all the sub bits. For real 64k pages, we now have the assembly set
+ * _PAGE_HPTE_SUB0 in addition to setting the HIDX bits which overlap
+ * that mask. This is fine as long as the HIDX bits are never set on
+ * a PTE that isn't hashed, which is the case today.
+ *
+ * A little nit is for the huge page C code, which does the hashing
+ * in C, we need to provide which bit to use.
+ */
+#define _PAGE_HASHPTE	_PAGE_HPTE_SUB
 
-#define PTE_INDEX_SIZE  12
-#define PMD_INDEX_SIZE  12
-#define PUD_INDEX_SIZE	0
-#define PGD_INDEX_SIZE  4
+/* Note the full page bits must be in the same location as for normal
+ * 4k pages as the same asssembly will be used to insert 64K pages
+ * wether the kernel has CONFIG_PPC_64K_PAGES or not
+ */
+#define _PAGE_F_SECOND  0x00008000 /* full page: hidx bits */
+#define _PAGE_F_GIX     0x00007000 /* full page: hidx bits */
+
+/* PTE flags to conserve for HPTE identification */
+#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_COMBO)
+
+/* Shift to put page number into pte.
+ *
+ * That gives us a max RPN of 34 bits, which means a max of 50 bits
+ * of addressable physical space, or 46 bits for the special 4k PFNs.
+ */
+#define PTE_RPN_SHIFT	(30)
 
 #ifndef __ASSEMBLY__
-#define PTE_TABLE_SIZE	(sizeof(real_pte_t) << PTE_INDEX_SIZE)
-#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
 
-#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
-#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+/*
+ * With 64K pages on hash table, we have a special PTE format that
+ * uses a second "half" of the page table to encode sub-page information
+ * in order to deal with 64K made of 4K HW pages. Thus we override the
+ * generic accessors and iterators here
+ */
+#define __real_pte(e,p) 	((real_pte_t) { \
+	(e), pte_val(*((p) + PTRS_PER_PTE)) })
+#define __rpte_to_hidx(r,index)	((pte_val((r).pte) & _PAGE_COMBO) ? \
+        (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
+#define __rpte_to_pte(r)	((r).pte)
+#define __rpte_sub_valid(rpte, index) \
+	(pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index)))
+
+/* Trick: we set __end to va + 64k, which happens works for
+ * a 16M page as well as we want only one iteration
+ */
+#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)	    \
+        do {                                                                \
+                unsigned long __end = va + PAGE_SIZE;                       \
+                unsigned __split = (psize == MMU_PAGE_4K ||                 \
+				    psize == MMU_PAGE_64K_AP);              \
+                shift = mmu_psize_defs[psize].shift;                        \
+		for (index = 0; va < __end; index++, va += (1L << shift)) { \
+		        if (!__split || __rpte_sub_valid(rpte, index)) do { \
+
+#define pte_iterate_hashed_end() } while(0); } } while(0)
+
+#define pte_pagesize_index(mm, addr, pte)	\
+	(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
+
+#define remap_4k_pfn(vma, addr, pfn, prot)				\
+	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,		\
+			__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
+
 
 #ifdef CONFIG_PPC_SUBPAGE_PROT
 /*
@@ -55,101 +113,3 @@
 }
 #endif /* CONFIG_PPC_SUBPAGE_PROT */
 #endif	/* __ASSEMBLY__ */
-
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PAGE_SHIFT
-
-/* PMD_SHIFT determines what a second-level page table entry can map */
-#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
-
-/* Additional PTE bits (don't change without checking asm in hash_low.S) */
-#define __HAVE_ARCH_PTE_SPECIAL
-#define _PAGE_SPECIAL	0x00000400 /* software: special page */
-#define _PAGE_HPTE_SUB	0x0ffff000 /* combo only: sub pages HPTE bits */
-#define _PAGE_HPTE_SUB0	0x08000000 /* combo only: first sub page */
-#define _PAGE_COMBO	0x10000000 /* this is a combo 4k page */
-#define _PAGE_4K_PFN	0x20000000 /* PFN is for a single 4k page */
-
-/* For 64K page, we don't have a separate _PAGE_HASHPTE bit. Instead,
- * we set that to be the whole sub-bits mask. The C code will only
- * test this, so a multi-bit mask will work. For combo pages, this
- * is equivalent as effectively, the old _PAGE_HASHPTE was an OR of
- * all the sub bits. For real 64k pages, we now have the assembly set
- * _PAGE_HPTE_SUB0 in addition to setting the HIDX bits which overlap
- * that mask. This is fine as long as the HIDX bits are never set on
- * a PTE that isn't hashed, which is the case today.
- *
- * A little nit is for the huge page C code, which does the hashing
- * in C, we need to provide which bit to use.
- */
-#define _PAGE_HASHPTE	_PAGE_HPTE_SUB
-
-/* Note the full page bits must be in the same location as for normal
- * 4k pages as the same asssembly will be used to insert 64K pages
- * wether the kernel has CONFIG_PPC_64K_PAGES or not
- */
-#define _PAGE_F_SECOND  0x00008000 /* full page: hidx bits */
-#define _PAGE_F_GIX     0x00007000 /* full page: hidx bits */
-
-/* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_COMBO)
-
-/* Shift to put page number into pte.
- *
- * That gives us a max RPN of 34 bits, which means a max of 50 bits
- * of addressable physical space, or 46 bits for the special 4k PFNs.
- */
-#define PTE_RPN_SHIFT	(30)
-#define PTE_RPN_MAX	(1UL << (64 - PTE_RPN_SHIFT))
-#define PTE_RPN_MASK	(~((1UL<<PTE_RPN_SHIFT)-1))
-
-/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
- * pgprot changes
- */
-#define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
-                         _PAGE_ACCESSED | _PAGE_SPECIAL)
-
-/* Bits to mask out from a PMD to get to the PTE page */
-#define PMD_MASKED_BITS		0x1ff
-/* Bits to mask out from a PGD/PUD to get to the PMD page */
-#define PUD_MASKED_BITS		0x1ff
-
-/* Manipulate "rpte" values */
-#define __real_pte(e,p) 	((real_pte_t) { \
-	(e), pte_val(*((p) + PTRS_PER_PTE)) })
-#define __rpte_to_hidx(r,index)	((pte_val((r).pte) & _PAGE_COMBO) ? \
-        (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
-#define __rpte_to_pte(r)	((r).pte)
-#define __rpte_sub_valid(rpte, index) \
-	(pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index)))
-
-
-/* Trick: we set __end to va + 64k, which happens works for
- * a 16M page as well as we want only one iteration
- */
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)	    \
-        do {                                                                \
-                unsigned long __end = va + PAGE_SIZE;                       \
-                unsigned __split = (psize == MMU_PAGE_4K ||                 \
-				    psize == MMU_PAGE_64K_AP);              \
-                shift = mmu_psize_defs[psize].shift;                        \
-		for (index = 0; va < __end; index++, va += (1L << shift)) { \
-		        if (!__split || __rpte_sub_valid(rpte, index)) do { \
-
-#define pte_iterate_hashed_end() } while(0); } } while(0)
-
-#define pte_pagesize_index(mm, addr, pte)	\
-	(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
-
-#define remap_4k_pfn(vma, addr, pfn, prot)				\
-	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,		\
-			__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))
-
-#endif /* _ASM_POWERPC_PGTABLE_64K_H */
diff --git a/arch/powerpc/include/asm/pte-hash64.h b/arch/powerpc/include/asm/pte-hash64.h
new file mode 100644
index 0000000..0419eeb
--- /dev/null
+++ b/arch/powerpc/include/asm/pte-hash64.h
@@ -0,0 +1,54 @@
+#ifndef _ASM_POWERPC_PTE_HASH64_H
+#define _ASM_POWERPC_PTE_HASH64_H
+#ifdef __KERNEL__
+
+/*
+ * Common bits between 4K and 64K pages in a linux-style PTE.
+ * These match the bits in the (hardware-defined) PowerPC PTE as closely
+ * as possible. Additional bits may be defined in pgtable-hash64-*.h
+ *
+ * Note: We only support user read/write permissions. Supervisor always
+ * have full read/write to pages above PAGE_OFFSET (pages below that
+ * always use the user access permissions).
+ *
+ * We could create separate kernel read-only if we used the 3 PP bits
+ * combinations that newer processors provide but we currently don't.
+ */
+#define _PAGE_PRESENT		0x0001 /* software: pte contains a translation */
+#define _PAGE_USER		0x0002 /* matches one of the PP bits */
+#define _PAGE_FILE		0x0002 /* (!present only) software: pte holds file offset */
+#define _PAGE_EXEC		0x0004 /* No execute on POWER4 and newer (we invert) */
+#define _PAGE_GUARDED		0x0008
+#define _PAGE_COHERENT		0x0010 /* M: enforce memory coherence (SMP systems) */
+#define _PAGE_NO_CACHE		0x0020 /* I: cache inhibit */
+#define _PAGE_WRITETHRU		0x0040 /* W: cache write-through */
+#define _PAGE_DIRTY		0x0080 /* C: page changed */
+#define _PAGE_ACCESSED		0x0100 /* R: page referenced */
+#define _PAGE_RW		0x0200 /* software: user write access allowed */
+#define _PAGE_BUSY		0x0800 /* software: PTE & hash are busy */
+
+/* No separate kernel read-only */
+#define _PAGE_KERNEL_RW		(_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
+#define _PAGE_KERNEL_RO		 _PAGE_KERNEL_RW
+
+/* Strong Access Ordering */
+#define _PAGE_SAO		(_PAGE_WRITETHRU | _PAGE_NO_CACHE | _PAGE_COHERENT)
+
+/* No page size encoding in the linux PTE */
+#define _PAGE_PSIZE		0
+
+/* PTEIDX nibble */
+#define _PTEIDX_SECONDARY	0x8
+#define _PTEIDX_GROUP_IX	0x7
+
+/* Hash table based platforms need atomic updates of the linux PTE */
+#define PTE_ATOMIC_UPDATES	1
+
+#ifdef CONFIG_PPC_64K_PAGES
+#include <asm/pte-hash64-64k.h>
+#else
+#include <asm/pte-hash64-4k.h>
+#endif
+
+#endif /* __KERNEL__ */
+#endif /*  _ASM_POWERPC_PTE_HASH64_H */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index f484a34..c9ff1ec 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -155,6 +155,8 @@
 #define   CTRL_RUNLATCH	0x1
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
 #define   DABR_TRANSLATION	(1UL << 2)
+#define   DABR_DATA_WRITE	(1UL << 1)
+#define   DABR_DATA_READ	(1UL << 0)
 #define SPRN_DABR2	0x13D	/* e300 */
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 6745376..a56f4d61 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -10,6 +10,7 @@
 #define __ASM_POWERPC_REG_BOOKE_H__
 
 /* Machine State Register (MSR) Fields */
+#define MSR_GS		(1<<28) /* Guest state */
 #define MSR_UCLE	(1<<26)	/* User-mode cache lock enable */
 #define MSR_SPE		(1<<25)	/* Enable SPE */
 #define MSR_DWE		(1<<10)	/* Debug Wait Enable */
@@ -110,6 +111,7 @@
 #define SPRN_L1CSR0	0x3F2	/* L1 Cache Control and Status Register 0 */
 #define SPRN_L1CSR1	0x3F3	/* L1 Cache Control and Status Register 1 */
 #define SPRN_MMUCSR0	0x3F4	/* MMU Control and Status Register 0 */
+#define SPRN_MMUCFG	0x3F7	/* MMU Configuration Register */
 #define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
 #define SPRN_BUCSR	0x3F5	/* Branch Unit Control and Status */
 #define SPRN_L2CSR0	0x3F9	/* L2 Data Cache Control and Status Register 0 */
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index 2a4be19..f612798 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -531,7 +531,7 @@
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 #endif
 
-#define arch_align_stack(x) (x)
+extern unsigned long arch_align_stack(unsigned long sp);
 
 /* Used in very early kernel initialization. */
 extern unsigned long reloc_offset(void);
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 9665a26..9aba5a3 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -12,8 +12,10 @@
 
 /* We have 8k stacks on ppc32 and 16k on ppc64 */
 
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PPC64)
 #define THREAD_SHIFT		14
+#elif defined(CONFIG_PPC_256K_PAGES)
+#define THREAD_SHIFT		15
 #else
 #define THREAD_SHIFT		13
 #endif
@@ -154,6 +156,13 @@
 	ti->local_flags |= _TLF_RESTORE_SIGMASK;
 	set_bit(TIF_SIGPENDING, &ti->flags);
 }
+
+#ifdef CONFIG_PPC64
+#define is_32bit_task()	(test_thread_flag(TIF_32BIT))
+#else
+#define is_32bit_task()	(1)
+#endif
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 6418cee..cd21e5e 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 
 extern void (*udbg_putc)(char c);
+extern void (*udbg_flush)(void);
 extern int (*udbg_getc)(void);
 extern int (*udbg_getc_poll)(void);
 
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 8d1a419..71901fb 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -18,12 +18,10 @@
 CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog
 CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog
 CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog
-
-ifdef CONFIG_DYNAMIC_FTRACE
-# dynamic ftrace setup.
+# do not trace tracer code
 CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog
-endif
-
+# timers used by tracing
+CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog
 endif
 
 obj-y				:= cputable.o ptrace.o syscalls.o \
@@ -61,6 +59,7 @@
 obj64-$(CONFIG_HIBERNATION)	+= swsusp_asm64.o
 obj-$(CONFIG_MODULES)		+= module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)		+= cpu_setup_44x.o
+obj-$(CONFIG_FSL_BOOKE)		+= cpu_setup_fsl_booke.o dbell.o
 
 extra-$(CONFIG_PPC_STD_MMU)	:= head_32.o
 extra-$(CONFIG_PPC64)		:= head_64.o
@@ -76,7 +75,7 @@
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)		+= dma-iommu.o iommu.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
-obj-$(CONFIG_PPC_MULTIPLATFORM)	+= prom_init.o
+obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE)	+= prom_init.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_SMP)		+= smp.o
@@ -94,6 +93,7 @@
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 
 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
 
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 73cb6a3..5ffcfaa 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -187,7 +187,7 @@
 	{ 4, ST+F+S+U },	/* 11 1 1010: stfsux */
 	{ 8, ST+F+U },		/* 11 1 1011: stfdux */
 	INVALID,		/* 11 1 1100 */
-	INVALID,		/* 11 1 1101 */
+	{ 4, LD+F },		/* 11 1 1101: lfiwzx */
 	INVALID,		/* 11 1 1110 */
 	INVALID,		/* 11 1 1111 */
 };
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 42fe4da..1e40bc0 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -284,9 +284,6 @@
 #endif /* ! CONFIG_PPC64 */
 
 	/* About the CPU features table */
-	DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec));
-	DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask));
-	DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
 	DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
 	DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S
index 10b4ab1..7d606f8 100644
--- a/arch/powerpc/kernel/cpu_setup_44x.S
+++ b/arch/powerpc/kernel/cpu_setup_44x.S
@@ -34,6 +34,7 @@
 	blr
 _GLOBAL(__setup_cpu_460ex)
 _GLOBAL(__setup_cpu_460gt)
+_GLOBAL(__setup_cpu_460sx)
 	mflr	r4
 	bl	__init_fpu_44x
 	bl	__fixup_440A_mcheck
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 72d1d73..54f767e 100644
--- a/arch/powerpc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -15,9 +15,14 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
+#include <asm/mmu.h>
 
 _GLOBAL(__setup_cpu_603)
 	mflr	r4
+BEGIN_MMU_FTR_SECTION
+	li	r10,0
+	mtspr	SPRN_SPRG4,r10		/* init SW LRU tracking */
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 BEGIN_FTR_SECTION
 	bl	__init_fpu_registers
 END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
new file mode 100644
index 0000000..eb4b9ad
--- /dev/null
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -0,0 +1,31 @@
+/*
+ * This file contains low level CPU setup functions.
+ * Kumar Gala <galak@kernel.crashing.org>
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Based on cpu_setup_6xx code by
+ * Benjamin Herrenschmidt <benh@kernel.crashing.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 <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+
+_GLOBAL(__setup_cpu_e200)
+	/* enable dedicated debug exception handling resources (Debug APU) */
+	mfspr	r3,SPRN_HID0
+	ori	r3,r3,HID0_DAPUEN@l
+	mtspr	SPRN_HID0,r3
+	b	__setup_e200_ivors
+_GLOBAL(__setup_cpu_e500v1)
+_GLOBAL(__setup_cpu_e500v2)
+	b	__setup_e500_ivors
+_GLOBAL(__setup_cpu_e500mc)
+	b	__setup_e500mc_ivors
+
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 923f87a..cd1b687 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -35,6 +35,10 @@
  * and ppc64
  */
 #ifdef CONFIG_PPC32
+extern void __setup_cpu_e200(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_e500mc(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
@@ -43,6 +47,7 @@
 extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec);
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -726,6 +731,8 @@
 		.cpu_setup		= __setup_cpu_750,
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc750",
+		.oprofile_cpu_type      = "ppc/750",
+		.oprofile_type		= PPC_OPROFILE_G4,
 	},
 	{	/* 750FX rev 2.0 must disable HID0[DPM] */
 		.pvr_mask		= 0xffffffff,
@@ -741,6 +748,8 @@
 		.cpu_setup		= __setup_cpu_750,
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc750",
+		.oprofile_cpu_type      = "ppc/750",
+		.oprofile_type		= PPC_OPROFILE_G4,
 	},
 	{	/* 750FX (All revs except 2.0) */
 		.pvr_mask		= 0xffff0000,
@@ -756,6 +765,8 @@
 		.cpu_setup		= __setup_cpu_750fx,
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc750",
+		.oprofile_cpu_type      = "ppc/750",
+		.oprofile_type		= PPC_OPROFILE_G4,
 	},
 	{	/* 750GX */
 		.pvr_mask		= 0xffff0000,
@@ -771,6 +782,8 @@
 		.cpu_setup		= __setup_cpu_750fx,
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc750",
+		.oprofile_cpu_type      = "ppc/750",
+		.oprofile_type		= PPC_OPROFILE_G4,
 	},
 	{	/* 740/750 (L2CR bit need fixup for 740) */
 		.pvr_mask		= 0xffff0000,
@@ -1077,7 +1090,8 @@
 		.cpu_name		= "e300c2",
 		.cpu_features		= CPU_FTRS_E300C2,
 		.cpu_user_features	= PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
-		.mmu_features		= MMU_FTR_USE_HIGH_BATS,
+		.mmu_features		= MMU_FTR_USE_HIGH_BATS |
+			MMU_FTR_NEED_DTLB_SW_LRU,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -1090,7 +1104,8 @@
 		.cpu_name		= "e300c3",
 		.cpu_features		= CPU_FTRS_E300,
 		.cpu_user_features	= COMMON_USER,
-		.mmu_features		= MMU_FTR_USE_HIGH_BATS,
+		.mmu_features		= MMU_FTR_USE_HIGH_BATS |
+			MMU_FTR_NEED_DTLB_SW_LRU,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -1105,7 +1120,8 @@
 		.cpu_name		= "e300c4",
 		.cpu_features		= CPU_FTRS_E300,
 		.cpu_user_features	= COMMON_USER,
-		.mmu_features		= MMU_FTR_USE_HIGH_BATS,
+		.mmu_features		= MMU_FTR_USE_HIGH_BATS |
+			MMU_FTR_NEED_DTLB_SW_LRU,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -1634,6 +1650,19 @@
 		.machine_check		= machine_check_440A,
 		.platform		= "ppc440",
 	},
+	{ /* 460SX */
+		.pvr_mask		= 0xffffff00,
+		.pvr_value		= 0x13541800,
+		.cpu_name		= "460SX",
+		.cpu_features		= CPU_FTRS_44X,
+		.cpu_user_features	= COMMON_USER_BOOKE,
+		.mmu_features		= MMU_FTR_TYPE_44x,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_460sx,
+		.machine_check		= machine_check_440A,
+		.platform		= "ppc440",
+	},
 	{	/* default match */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
@@ -1687,6 +1716,7 @@
 			PPC_FEATURE_UNIFIED_CACHE,
 		.mmu_features		= MMU_FTR_TYPE_FSL_E,
 		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_e200,
 		.machine_check		= machine_check_e200,
 		.platform		= "ppc5554",
 	}
@@ -1706,6 +1736,7 @@
 		.num_pmcs		= 4,
 		.oprofile_cpu_type	= "ppc/e500",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
+		.cpu_setup		= __setup_cpu_e500v1,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8540",
 	},
@@ -1724,6 +1755,7 @@
 		.num_pmcs		= 4,
 		.oprofile_cpu_type	= "ppc/e500",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
+		.cpu_setup		= __setup_cpu_e500v2,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppc8548",
 	},
@@ -1733,12 +1765,14 @@
 		.cpu_name		= "e500mc",
 		.cpu_features		= CPU_FTRS_E500MC,
 		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
-		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS,
+		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
+			MMU_FTR_USE_TLBILX,
 		.icache_bsize		= 64,
 		.dcache_bsize		= 64,
 		.num_pmcs		= 4,
 		.oprofile_cpu_type	= "ppc/e500", /* xxx - galak, e500mc? */
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
+		.cpu_setup		= __setup_cpu_e500mc,
 		.machine_check		= machine_check_e500,
 		.platform		= "ppce500mc",
 	},
@@ -1762,74 +1796,84 @@
 
 static struct cpu_spec the_cpu_spec;
 
+static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
+{
+	struct cpu_spec *t = &the_cpu_spec;
+	struct cpu_spec old;
+
+	t = PTRRELOC(t);
+	old = *t;
+
+	/* Copy everything, then do fixups */
+	*t = *s;
+
+	/*
+	 * If we are overriding a previous value derived from the real
+	 * PVR with a new value obtained using a logical PVR value,
+	 * don't modify the performance monitor fields.
+	 */
+	if (old.num_pmcs && !s->num_pmcs) {
+		t->num_pmcs = old.num_pmcs;
+		t->pmc_type = old.pmc_type;
+		t->oprofile_type = old.oprofile_type;
+		t->oprofile_mmcra_sihv = old.oprofile_mmcra_sihv;
+		t->oprofile_mmcra_sipr = old.oprofile_mmcra_sipr;
+		t->oprofile_mmcra_clear = old.oprofile_mmcra_clear;
+
+		/*
+		 * If we have passed through this logic once before and
+		 * have pulled the default case because the real PVR was
+		 * not found inside cpu_specs[], then we are possibly
+		 * running in compatibility mode. In that case, let the
+		 * oprofiler know which set of compatibility counters to
+		 * pull from by making sure the oprofile_cpu_type string
+		 * is set to that of compatibility mode. If the
+		 * oprofile_cpu_type already has a value, then we are
+		 * possibly overriding a real PVR with a logical one,
+		 * and, in that case, keep the current value for
+		 * oprofile_cpu_type.
+		 */
+		if (old.oprofile_cpu_type == NULL)
+			t->oprofile_cpu_type = s->oprofile_cpu_type;
+	}
+
+	*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+
+	/*
+	 * Set the base platform string once; assumes
+	 * we're called with real pvr first.
+	 */
+	if (*PTRRELOC(&powerpc_base_platform) == NULL)
+		*PTRRELOC(&powerpc_base_platform) = t->platform;
+
+#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
+	/* ppc64 and booke expect identify_cpu to also call setup_cpu for
+	 * that processor. I will consolidate that at a later time, for now,
+	 * just use #ifdef. We also don't need to PTRRELOC the function
+	 * pointer on ppc64 and booke as we are running at 0 in real mode
+	 * on ppc64 and reloc_offset is always 0 on booke.
+	 */
+	if (s->cpu_setup) {
+		s->cpu_setup(offset, s);
+	}
+#endif /* CONFIG_PPC64 || CONFIG_BOOKE */
+}
+
 struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
 {
 	struct cpu_spec *s = cpu_specs;
-	struct cpu_spec *t = &the_cpu_spec;
 	int i;
 
 	s = PTRRELOC(s);
-	t = PTRRELOC(t);
 
-	for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
+	for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) {
 		if ((pvr & s->pvr_mask) == s->pvr_value) {
-			/*
-			 * If we are overriding a previous value derived
-			 * from the real PVR with a new value obtained
-			 * using a logical PVR value, don't modify the
-			 * performance monitor fields.
-			 */
-			if (t->num_pmcs && !s->num_pmcs) {
-				t->cpu_name = s->cpu_name;
-				t->cpu_features = s->cpu_features;
-				t->cpu_user_features = s->cpu_user_features;
-				t->icache_bsize = s->icache_bsize;
-				t->dcache_bsize = s->dcache_bsize;
-				t->cpu_setup = s->cpu_setup;
-				t->cpu_restore = s->cpu_restore;
-				t->platform = s->platform;
-				/*
-				 * If we have passed through this logic once
-				 * before and have pulled the default case
-				 * because the real PVR was not found inside
-				 * cpu_specs[], then we are possibly running in
-				 * compatibility mode. In that case, let the
-				 * oprofiler know which set of compatibility
-				 * counters to pull from by making sure the
-				 * oprofile_cpu_type string is set to that of
-				 * compatibility mode. If the oprofile_cpu_type
-				 * already has a value, then we are possibly
-				 * overriding a real PVR with a logical one, and,
-				 * in that case, keep the current value for
-				 * oprofile_cpu_type.
-				 */
-				if (t->oprofile_cpu_type == NULL)
-					t->oprofile_cpu_type = s->oprofile_cpu_type;
-			} else
-				*t = *s;
-			*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
-
-			/*
-			 * Set the base platform string once; assumes
-			 * we're called with real pvr first.
-			 */
-			if (*PTRRELOC(&powerpc_base_platform) == NULL)
-				*PTRRELOC(&powerpc_base_platform) = t->platform;
-
-#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
-			/* ppc64 and booke expect identify_cpu to also call
-			 * setup_cpu for that processor. I will consolidate
-			 * that at a later time, for now, just use #ifdef.
-			 * we also don't need to PTRRELOC the function pointer
-			 * on ppc64 and booke as we are running at 0 in real
-			 * mode on ppc64 and reloc_offset is always 0 on booke.
-			 */
-			if (s->cpu_setup) {
-				s->cpu_setup(offset, s);
-			}
-#endif /* CONFIG_PPC64 || CONFIG_BOOKE */
+			setup_cpu_spec(offset, s);
 			return s;
 		}
+	}
+
 	BUG();
+
 	return NULL;
 }
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 19671ac..5fb667a 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -48,7 +48,7 @@
 	 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
 	 * two instructions it doesn't require any registers.
 	 */
-	patch_instruction(p, PPC_NOP_INSTR);
+	patch_instruction(p, PPC_INST_NOP);
 	patch_branch(++p, addr + PHYSICAL_START, 0);
 }
 
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
new file mode 100644
index 0000000..1493734
--- /dev/null
+++ b/arch/powerpc/kernel/dbell.c
@@ -0,0 +1,44 @@
+/*
+ * Author: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 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.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+
+#include <asm/dbell.h>
+
+#ifdef CONFIG_SMP
+unsigned long dbell_smp_message[NR_CPUS];
+
+void smp_dbell_message_pass(int target, int msg)
+{
+	int i;
+
+	if(target < NR_CPUS) {
+		set_bit(msg, &dbell_smp_message[target]);
+		ppc_msgsnd(PPC_DBELL, 0, target);
+	}
+	else if(target == MSG_ALL_BUT_SELF) {
+		for_each_online_cpu(i) {
+			if (i == smp_processor_id())
+				continue;
+			set_bit(msg, &dbell_smp_message[i]);
+			ppc_msgsnd(PPC_DBELL, 0, i);
+		}
+	}
+	else { /* target == MSG_ALL */
+		for_each_online_cpu(i)
+			set_bit(msg, &dbell_smp_message[i]);
+		ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0);
+	}
+}
+#endif
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 6f7eb7e..4dd38f1 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -63,7 +63,7 @@
 
 	.globl	crit_transfer_to_handler
 crit_transfer_to_handler:
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_BOOK3E_MMU
 	mfspr	r0,SPRN_MAS0
 	stw	r0,MAS0(r11)
 	mfspr	r0,SPRN_MAS1
@@ -78,7 +78,7 @@
 	mfspr	r0,SPRN_MAS7
 	stw	r0,MAS7(r11)
 #endif /* CONFIG_PHYS_64BIT */
-#endif /* CONFIG_FSL_BOOKE */
+#endif /* CONFIG_PPC_BOOK3E_MMU */
 #ifdef CONFIG_44x
 	mfspr	r0,SPRN_MMUCR
 	stw	r0,MMUCR(r11)
@@ -914,7 +914,7 @@
 	mtspr	SPRN_##exc_lvl_srr0,r9;					\
 	mtspr	SPRN_##exc_lvl_srr1,r10;
 
-#if defined(CONFIG_FSL_BOOKE)
+#if defined(CONFIG_PPC_BOOK3E_MMU)
 #ifdef CONFIG_PHYS_64BIT
 #define	RESTORE_MAS7							\
 	lwz	r11,MAS7(r1);						\
@@ -956,7 +956,7 @@
 	lwz	r10,crit_srr1@l(r10);
 	mtspr	SPRN_SRR0,r9;
 	mtspr	SPRN_SRR1,r10;
-	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI)
 #endif /* CONFIG_40x */
 
 #ifdef CONFIG_BOOKE
@@ -967,7 +967,7 @@
 	stw	r10,KSP_LIMIT(r9)
 	RESTORE_xSRR(SRR0,SRR1);
 	RESTORE_MMU_REGS;
-	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
+	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI)
 
 	.globl	ret_from_debug_exc
 ret_from_debug_exc:
@@ -981,7 +981,7 @@
 	RESTORE_xSRR(SRR0,SRR1);
 	RESTORE_xSRR(CSRR0,CSRR1);
 	RESTORE_MMU_REGS;
-	RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
+	RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, PPC_RFDI)
 
 	.globl	ret_from_mcheck_exc
 ret_from_mcheck_exc:
@@ -992,7 +992,7 @@
 	RESTORE_xSRR(CSRR0,CSRR1);
 	RESTORE_xSRR(DSRR0,DSRR1);
 	RESTORE_MMU_REGS;
-	RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
+	RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, PPC_RFMCI)
 #endif /* CONFIG_BOOKE */
 
 /*
@@ -1176,59 +1176,27 @@
 	bctr
 
 _GLOBAL(ftrace_caller)
-	/* Based off of objdump optput from glibc */
-	stwu	r1,-48(r1)
-	stw	r3, 12(r1)
-	stw	r4, 16(r1)
-	stw	r5, 20(r1)
-	stw	r6, 24(r1)
-	mflr	r3
-	lwz	r4, 52(r1)
-	mfcr	r5
-	stw	r7, 28(r1)
-	stw	r8, 32(r1)
-	stw	r9, 36(r1)
-	stw	r10,40(r1)
-	stw	r3, 44(r1)
-	stw	r5, 8(r1)
+	MCOUNT_SAVE_FRAME
+	/* r3 ends up with link register */
 	subi	r3, r3, MCOUNT_INSN_SIZE
 .globl ftrace_call
 ftrace_call:
 	bl	ftrace_stub
 	nop
-	lwz	r6, 8(r1)
-	lwz	r0, 44(r1)
-	lwz	r3, 12(r1)
-	mtctr	r0
-	lwz	r4, 16(r1)
-	mtcr	r6
-	lwz	r5, 20(r1)
-	lwz	r6, 24(r1)
-	lwz	r0, 52(r1)
-	lwz	r7, 28(r1)
-	lwz	r8, 32(r1)
-	mtlr	r0
-	lwz	r9, 36(r1)
-	lwz	r10,40(r1)
-	addi	r1, r1, 48
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+.globl ftrace_graph_call
+ftrace_graph_call:
+	b	ftrace_graph_stub
+_GLOBAL(ftrace_graph_stub)
+#endif
+	MCOUNT_RESTORE_FRAME
+	/* old link register ends up in ctr reg */
 	bctr
 #else
 _GLOBAL(mcount)
 _GLOBAL(_mcount)
-	stwu	r1,-48(r1)
-	stw	r3, 12(r1)
-	stw	r4, 16(r1)
-	stw	r5, 20(r1)
-	stw	r6, 24(r1)
-	mflr	r3
-	lwz	r4, 52(r1)
-	mfcr	r5
-	stw	r7, 28(r1)
-	stw	r8, 32(r1)
-	stw	r9, 36(r1)
-	stw	r10,40(r1)
-	stw	r3, 44(r1)
-	stw	r5, 8(r1)
+
+	MCOUNT_SAVE_FRAME
 
 	subi	r3, r3, MCOUNT_INSN_SIZE
 	LOAD_REG_ADDR(r5, ftrace_trace_function)
@@ -1236,28 +1204,55 @@
 
 	mtctr	r5
 	bctrl
-
 	nop
 
-	lwz	r6, 8(r1)
-	lwz	r0, 44(r1)
-	lwz	r3, 12(r1)
-	mtctr	r0
-	lwz	r4, 16(r1)
-	mtcr	r6
-	lwz	r5, 20(r1)
-	lwz	r6, 24(r1)
-	lwz	r0, 52(r1)
-	lwz	r7, 28(r1)
-	lwz	r8, 32(r1)
-	mtlr	r0
-	lwz	r9, 36(r1)
-	lwz	r10,40(r1)
-	addi	r1, r1, 48
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	b	ftrace_graph_caller
+#endif
+	MCOUNT_RESTORE_FRAME
 	bctr
 #endif
 
 _GLOBAL(ftrace_stub)
 	blr
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+_GLOBAL(ftrace_graph_caller)
+	/* load r4 with local address */
+	lwz	r4, 44(r1)
+	subi	r4, r4, MCOUNT_INSN_SIZE
+
+	/* get the parent address */
+	addi	r3, r1, 52
+
+	bl	prepare_ftrace_return
+	nop
+
+	MCOUNT_RESTORE_FRAME
+	/* old link register ends up in ctr reg */
+	bctr
+
+_GLOBAL(return_to_handler)
+	/* need to save return values */
+	stwu	r1, -32(r1)
+	stw	r3, 20(r1)
+	stw	r4, 16(r1)
+	stw	r31, 12(r1)
+	mr	r31, r1
+
+	bl	ftrace_return_to_handler
+	nop
+
+	/* return value has real return address */
+	mtlr	r3
+
+	lwz	r3, 20(r1)
+	lwz	r4, 16(r1)
+	lwz	r31,12(r1)
+	lwz	r1, 0(r1)
+
+	/* Jump back to real return address */
+	blr
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 #endif /* CONFIG_MCOUNT */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 383ed6e..abfc323 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -908,6 +908,12 @@
 ftrace_call:
 	bl	ftrace_stub
 	nop
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+.globl ftrace_graph_call
+ftrace_graph_call:
+	b	ftrace_graph_stub
+_GLOBAL(ftrace_graph_stub)
+#endif
 	ld	r0, 128(r1)
 	mtlr	r0
 	addi	r1, r1, 112
@@ -931,13 +937,90 @@
 	ld	r5,0(r5)
 	mtctr	r5
 	bctrl
-
 	nop
+
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	b	ftrace_graph_caller
+#endif
 	ld	r0, 128(r1)
 	mtlr	r0
 	addi	r1, r1, 112
 _GLOBAL(ftrace_stub)
 	blr
 
-#endif
-#endif
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+_GLOBAL(ftrace_graph_caller)
+	/* load r4 with local address */
+	ld	r4, 128(r1)
+	subi	r4, r4, MCOUNT_INSN_SIZE
+
+	/* get the parent address */
+	ld	r11, 112(r1)
+	addi	r3, r11, 16
+
+	bl	.prepare_ftrace_return
+	nop
+
+	ld	r0, 128(r1)
+	mtlr	r0
+	addi	r1, r1, 112
+	blr
+
+_GLOBAL(return_to_handler)
+	/* need to save return values */
+	std	r4,  -24(r1)
+	std	r3,  -16(r1)
+	std	r31, -8(r1)
+	mr	r31, r1
+	stdu	r1, -112(r1)
+
+	bl	.ftrace_return_to_handler
+	nop
+
+	/* return value has real return address */
+	mtlr	r3
+
+	ld	r1, 0(r1)
+	ld	r4,  -24(r1)
+	ld	r3,  -16(r1)
+	ld	r31, -8(r1)
+
+	/* Jump back to real return address */
+	blr
+
+_GLOBAL(mod_return_to_handler)
+	/* need to save return values */
+	std	r4,  -32(r1)
+	std	r3,  -24(r1)
+	/* save TOC */
+	std	r2,  -16(r1)
+	std	r31, -8(r1)
+	mr	r31, r1
+	stdu	r1, -112(r1)
+
+	/*
+	 * We are in a module using the module's TOC.
+	 * Switch to our TOC to run inside the core kernel.
+	 */
+	LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler)
+	ld	r2, 8(r4)
+
+	bl	.ftrace_return_to_handler
+	nop
+
+	/* return value has real return address */
+	mtlr	r3
+
+	ld	r1, 0(r1)
+	ld	r4,  -32(r1)
+	ld	r3,  -24(r1)
+	ld	r2,  -16(r1)
+	ld	r31, -8(r1)
+
+	/* Jump back to real return address */
+	blr
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 60c60cc..5b5d16b 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -5,6 +5,9 @@
  *
  * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
  *
+ * Added function graph tracer code, taken from x86 that was written
+ * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
+ *
  */
 
 #include <linux/spinlock.h>
@@ -20,14 +23,6 @@
 #include <asm/code-patching.h>
 #include <asm/ftrace.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt , ...)	do { } while (0)
-#endif
-
-static unsigned int ftrace_nop = PPC_NOP_INSTR;
-
 #ifdef CONFIG_PPC32
 # define GET_ADDR(addr) addr
 #else
@@ -35,37 +30,23 @@
 # define GET_ADDR(addr) (*(unsigned long *)addr)
 #endif
 
-
-static unsigned int ftrace_calc_offset(long ip, long addr)
+#ifdef CONFIG_DYNAMIC_FTRACE
+static unsigned int ftrace_nop_replace(void)
 {
-	return (int)(addr - ip);
+	return PPC_INST_NOP;
 }
 
-static unsigned char *ftrace_nop_replace(void)
+static unsigned int
+ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
 {
-	return (char *)&ftrace_nop;
-}
+	unsigned int op;
 
-static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
-{
-	static unsigned int op;
-
-	/*
-	 * It would be nice to just use create_function_call, but that will
-	 * update the code itself. Here we need to just return the
-	 * instruction that is going to be modified, without modifying the
-	 * code.
-	 */
 	addr = GET_ADDR(addr);
 
-	/* Set to "bl addr" */
-	op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
+	/* if (link) set op to 'bl' else 'b' */
+	op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
 
-	/*
-	 * No locking needed, this must be called via kstop_machine
-	 * which in essence is like running on a uniprocessor machine.
-	 */
-	return (unsigned char *)&op;
+	return op;
 }
 
 #ifdef CONFIG_PPC64
@@ -77,10 +58,9 @@
 #endif
 
 static int
-ftrace_modify_code(unsigned long ip, unsigned char *old_code,
-		   unsigned char *new_code)
+ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
 {
-	unsigned char replaced[MCOUNT_INSN_SIZE];
+	unsigned int replaced;
 
 	/*
 	 * Note: Due to modules and __init, code can
@@ -93,15 +73,15 @@
 	 */
 
 	/* read the text we want to modify */
-	if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
+	if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
 		return -EFAULT;
 
 	/* Make sure it is what we expect it to be */
-	if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
+	if (replaced != old)
 		return -EINVAL;
 
 	/* replace the text with the new text */
-	if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
+	if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE))
 		return -EPERM;
 
 	flush_icache_range(ip, ip + 8);
@@ -119,6 +99,8 @@
 	return create_branch((unsigned int *)ip, addr, 0);
 }
 
+#ifdef CONFIG_MODULES
+
 static int is_bl_op(unsigned int op)
 {
 	return (op & 0xfc000003) == 0x48000001;
@@ -175,7 +157,7 @@
 	 * 0xe8, 0x4c, 0x00, 0x28,    ld      r2,40(r12)
 	 */
 
-	DEBUGP("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc);
+	pr_debug("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc);
 
 	/* Find where the trampoline jumps to */
 	if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
@@ -183,7 +165,7 @@
 		return -EFAULT;
 	}
 
-	DEBUGP(" %08x %08x", jmp[0], jmp[1]);
+	pr_debug(" %08x %08x", jmp[0], jmp[1]);
 
 	/* verify that this is what we expect it to be */
 	if (((jmp[0] & 0xffff0000) != 0x3d820000) ||
@@ -199,18 +181,18 @@
 	offset = ((unsigned)((unsigned short)jmp[0]) << 16) +
 		(int)((short)jmp[1]);
 
-	DEBUGP(" %x ", offset);
+	pr_debug(" %x ", offset);
 
 	/* get the address this jumps too */
 	tramp = mod->arch.toc + offset + 32;
-	DEBUGP("toc: %lx", tramp);
+	pr_debug("toc: %lx", tramp);
 
 	if (probe_kernel_read(jmp, (void *)tramp, 8)) {
 		printk(KERN_ERR "Failed to read %lx\n", tramp);
 		return -EFAULT;
 	}
 
-	DEBUGP(" %08x %08x\n", jmp[0], jmp[1]);
+	pr_debug(" %08x %08x\n", jmp[0], jmp[1]);
 
 	ptr = ((unsigned long)jmp[0] << 32) + jmp[1];
 
@@ -287,7 +269,7 @@
 	 *  0x4e, 0x80, 0x04, 0x20  bctr
 	 */
 
-	DEBUGP("ip:%lx jumps to %lx", ip, tramp);
+	pr_debug("ip:%lx jumps to %lx", ip, tramp);
 
 	/* Find where the trampoline jumps to */
 	if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
@@ -295,7 +277,7 @@
 		return -EFAULT;
 	}
 
-	DEBUGP(" %08x %08x ", jmp[0], jmp[1]);
+	pr_debug(" %08x %08x ", jmp[0], jmp[1]);
 
 	/* verify that this is what we expect it to be */
 	if (((jmp[0] & 0xffff0000) != 0x3d600000) ||
@@ -311,7 +293,7 @@
 	if (tramp & 0x8000)
 		tramp -= 0x10000;
 
-	DEBUGP(" %x ", tramp);
+	pr_debug(" %x ", tramp);
 
 	if (tramp != addr) {
 		printk(KERN_ERR
@@ -320,7 +302,7 @@
 		return -EINVAL;
 	}
 
-	op = PPC_NOP_INSTR;
+	op = PPC_INST_NOP;
 
 	if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
 		return -EPERM;
@@ -330,12 +312,13 @@
 	return 0;
 }
 #endif /* PPC64 */
+#endif /* CONFIG_MODULES */
 
 int ftrace_make_nop(struct module *mod,
 		    struct dyn_ftrace *rec, unsigned long addr)
 {
-	unsigned char *old, *new;
 	unsigned long ip = rec->ip;
+	unsigned int old, new;
 
 	/*
 	 * If the calling address is more that 24 bits away,
@@ -344,11 +327,12 @@
 	 */
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
-		old = ftrace_call_replace(ip, addr);
+		old = ftrace_call_replace(ip, addr, 1);
 		new = ftrace_nop_replace();
 		return ftrace_modify_code(ip, old, new);
 	}
 
+#ifdef CONFIG_MODULES
 	/*
 	 * Out of range jumps are called from modules.
 	 * We should either already have a pointer to the module
@@ -373,9 +357,13 @@
 		mod = rec->arch.mod;
 
 	return __ftrace_make_nop(mod, rec, addr);
-
+#else
+	/* We should not get here without modules */
+	return -EINVAL;
+#endif /* CONFIG_MODULES */
 }
 
+#ifdef CONFIG_MODULES
 #ifdef CONFIG_PPC64
 static int
 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
@@ -392,7 +380,7 @@
 	 *  b +8; ld r2,40(r1)
 	 */
 	if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) &&
-	    ((op[0] != PPC_NOP_INSTR) || (op[1] != PPC_NOP_INSTR))) {
+	    ((op[0] != PPC_INST_NOP) || (op[1] != PPC_INST_NOP))) {
 		printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]);
 		return -EINVAL;
 	}
@@ -414,7 +402,7 @@
 	/* ld r2,40(r1) */
 	op[1] = 0xe8410028;
 
-	DEBUGP("write to %lx\n", rec->ip);
+	pr_debug("write to %lx\n", rec->ip);
 
 	if (probe_kernel_write((void *)ip, op, MCOUNT_INSN_SIZE * 2))
 		return -EPERM;
@@ -435,7 +423,7 @@
 		return -EFAULT;
 
 	/* It should be pointing to a nop */
-	if (op != PPC_NOP_INSTR) {
+	if (op != PPC_INST_NOP) {
 		printk(KERN_ERR "Expected NOP but have %x\n", op);
 		return -EINVAL;
 	}
@@ -454,7 +442,7 @@
 		return -EINVAL;
 	}
 
-	DEBUGP("write to %lx\n", rec->ip);
+	pr_debug("write to %lx\n", rec->ip);
 
 	if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
 		return -EPERM;
@@ -464,11 +452,12 @@
 	return 0;
 }
 #endif /* CONFIG_PPC64 */
+#endif /* CONFIG_MODULES */
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
-	unsigned char *old, *new;
 	unsigned long ip = rec->ip;
+	unsigned int old, new;
 
 	/*
 	 * If the calling address is more that 24 bits away,
@@ -478,10 +467,11 @@
 	if (test_24bit_addr(ip, addr)) {
 		/* within range */
 		old = ftrace_nop_replace();
-		new = ftrace_call_replace(ip, addr);
+		new = ftrace_call_replace(ip, addr, 1);
 		return ftrace_modify_code(ip, old, new);
 	}
 
+#ifdef CONFIG_MODULES
 	/*
 	 * Out of range jumps are called from modules.
 	 * Being that we are converting from nop, it had better
@@ -493,16 +483,20 @@
 	}
 
 	return __ftrace_make_call(rec, addr);
+#else
+	/* We should not get here without modules */
+	return -EINVAL;
+#endif /* CONFIG_MODULES */
 }
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
 	unsigned long ip = (unsigned long)(&ftrace_call);
-	unsigned char old[MCOUNT_INSN_SIZE], *new;
+	unsigned int old, new;
 	int ret;
 
-	memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
-	new = ftrace_call_replace(ip, (unsigned long)func);
+	old = *(unsigned int *)&ftrace_call;
+	new = ftrace_call_replace(ip, (unsigned long)func, 1);
 	ret = ftrace_modify_code(ip, old, new);
 
 	return ret;
@@ -517,3 +511,115 @@
 
 	return 0;
 }
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_graph_call(void);
+extern void ftrace_graph_stub(void);
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	unsigned long ip = (unsigned long)(&ftrace_graph_call);
+	unsigned long addr = (unsigned long)(&ftrace_graph_caller);
+	unsigned long stub = (unsigned long)(&ftrace_graph_stub);
+	unsigned int old, new;
+
+	old = ftrace_call_replace(ip, stub, 0);
+	new = ftrace_call_replace(ip, addr, 0);
+
+	return ftrace_modify_code(ip, old, new);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	unsigned long ip = (unsigned long)(&ftrace_graph_call);
+	unsigned long addr = (unsigned long)(&ftrace_graph_caller);
+	unsigned long stub = (unsigned long)(&ftrace_graph_stub);
+	unsigned int old, new;
+
+	old = ftrace_call_replace(ip, addr, 0);
+	new = ftrace_call_replace(ip, stub, 0);
+
+	return ftrace_modify_code(ip, old, new);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_PPC64
+extern void mod_return_to_handler(void);
+#endif
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+	unsigned long old;
+	unsigned long long calltime;
+	int faulted;
+	struct ftrace_graph_ent trace;
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+#if CONFIG_PPC64
+	/* non core kernel code needs to save and restore the TOC */
+	if (REGION_ID(self_addr) != KERNEL_REGION_ID)
+		return_hooker = (unsigned long)&mod_return_to_handler;
+#endif
+
+	return_hooker = GET_ADDR(return_hooker);
+
+	/*
+	 * Protect against fault, even if it shouldn't
+	 * happen. This tool is too much intrusive to
+	 * ignore such a protection.
+	 */
+	asm volatile(
+		"1: " PPC_LL "%[old], 0(%[parent])\n"
+		"2: " PPC_STL "%[return_hooker], 0(%[parent])\n"
+		"   li %[faulted], 0\n"
+		"3:\n"
+
+		".section .fixup, \"ax\"\n"
+		"4: li %[faulted], 1\n"
+		"   b 3b\n"
+		".previous\n"
+
+		".section __ex_table,\"a\"\n"
+			PPC_LONG_ALIGN "\n"
+			PPC_LONG "1b,4b\n"
+			PPC_LONG "2b,4b\n"
+		".previous"
+
+		: [old] "=r" (old), [faulted] "=r" (faulted)
+		: [parent] "r" (parent), [return_hooker] "r" (return_hooker)
+		: "memory"
+	);
+
+	if (unlikely(faulted)) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		return;
+	}
+
+	calltime = cpu_clock(raw_smp_processor_id());
+
+	if (ftrace_push_return_trace(old, calltime,
+				self_addr, &trace.depth) == -EBUSY) {
+		*parent = old;
+		return;
+	}
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		*parent = old;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index d794a63..54e68c1 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -108,18 +108,21 @@
  * because OF may have I/O devices mapped into that area
  * (particularly on CHRP).
  */
-#ifdef CONFIG_PPC_MULTIPLATFORM
 	cmpwi	0,r5,0
 	beq	1f
 
+#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
 	/* find out where we are now */
 	bcl	20,31,$+4
 0:	mflr	r8			/* r8 = runtime addr here */
 	addis	r8,r8,(_stext - 0b)@ha
 	addi	r8,r8,(_stext - 0b)@l	/* current runtime base addr */
 	bl	prom_init
+#endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */
+
+	/* We never return. We also hit that trap if trying to boot
+	 * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */
 	trap
-#endif
 
 /*
  * Check for BootX signature when supporting PowerMac and branch to
@@ -472,12 +475,11 @@
 	. = 0x1000
 InstructionTLBMiss:
 /*
- * r0:	stored ctr
+ * r0:	scratch
  * r1:	linux style pte ( later becomes ppc hardware pte )
  * r2:	ptr to linux-style pte
  * r3:	scratch
  */
-	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r3,SPRN_IMISS
 	lis	r1,PAGE_OFFSET@h		/* check if kernel address */
@@ -496,28 +498,27 @@
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	InstructionAddressInvalid	/* return if no mapping */
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r3,0(r2)		/* get linux-style pte */
-	andc.	r1,r1,r3		/* check access & ~permission */
+	lwz	r0,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r0		/* check access & ~permission */
 	bne-	InstructionAddressInvalid /* return if access not permitted */
-	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	ori	r0,r0,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
 	/*
 	 * NOTE! We are assuming this is not an SMP system, otherwise
 	 * we would need to update the pte atomically with lwarx/stwcx.
 	 */
-	stw	r3,0(r2)		/* update PTE (accessed bit) */
+	stw	r0,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
-	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	rlwinm	r1,r0,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r0,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
 	and	r1,r1,r2		/* writable if _RW and _DIRTY */
-	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
-	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	rlwimi	r0,r0,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r0,r0,32-1,31,31	/* _PAGE_USER -> PP lsb */
 	ori	r1,r1,0xe04		/* clear out reserved bits */
-	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+	andc	r1,r0,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 BEGIN_FTR_SECTION
 	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
-	mfspr	r3,SPRN_IMISS
 	tlbli	r3
 	mfspr	r3,SPRN_SRR1		/* Need to restore CR0 */
 	mtcrf	0x80,r3
@@ -528,7 +529,6 @@
 
 	addis	r1,r1,0x2000
 	mtspr	SPRN_DSISR,r1	/* (shouldn't be needed) */
-	mtctr	r0		/* Restore CTR */
 	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
 	or	r2,r2,r1
 	mtspr	SPRN_SRR1,r2
@@ -549,12 +549,11 @@
 	. = 0x1100
 DataLoadTLBMiss:
 /*
- * r0:	stored ctr
+ * r0:	scratch
  * r1:	linux style pte ( later becomes ppc hardware pte )
  * r2:	ptr to linux-style pte
  * r3:	scratch
  */
-	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r3,SPRN_DMISS
 	lis	r1,PAGE_OFFSET@h		/* check if kernel address */
@@ -573,38 +572,48 @@
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	DataAddressInvalid	/* return if no mapping */
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r3,0(r2)		/* get linux-style pte */
-	andc.	r1,r1,r3		/* check access & ~permission */
+	lwz	r0,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r0		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	ori	r0,r0,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
 	/*
 	 * NOTE! We are assuming this is not an SMP system, otherwise
 	 * we would need to update the pte atomically with lwarx/stwcx.
 	 */
-	stw	r3,0(r2)		/* update PTE (accessed bit) */
+	stw	r0,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
-	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	rlwinm	r1,r0,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r0,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
 	and	r1,r1,r2		/* writable if _RW and _DIRTY */
-	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
-	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	rlwimi	r0,r0,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r0,r0,32-1,31,31	/* _PAGE_USER -> PP lsb */
 	ori	r1,r1,0xe04		/* clear out reserved bits */
-	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
+	andc	r1,r0,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 BEGIN_FTR_SECTION
 	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
-	mfspr	r3,SPRN_DMISS
+	mfspr	r2,SPRN_SRR1		/* Need to restore CR0 */
+	mtcrf	0x80,r2
+BEGIN_MMU_FTR_SECTION
+	li	r0,1
+	mfspr	r1,SPRN_SPRG4
+	rlwinm	r2,r3,20,27,31		/* Get Address bits 15:19 */
+	slw	r0,r0,r2
+	xor	r1,r0,r1
+	srw	r0,r1,r2
+	mtspr   SPRN_SPRG4,r1
+	mfspr	r2,SPRN_SRR1
+	rlwimi	r2,r0,31-14,14,14
+	mtspr   SPRN_SRR1,r2
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 	tlbld	r3
-	mfspr	r3,SPRN_SRR1		/* Need to restore CR0 */
-	mtcrf	0x80,r3
 	rfi
 DataAddressInvalid:
 	mfspr	r3,SPRN_SRR1
 	rlwinm	r1,r3,9,6,6	/* Get load/store bit */
 	addis	r1,r1,0x2000
 	mtspr	SPRN_DSISR,r1
-	mtctr	r0		/* Restore CTR */
 	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
 	mtspr	SPRN_SRR1,r2
 	mfspr	r1,SPRN_DMISS	/* Get failing address */
@@ -624,12 +633,11 @@
 	. = 0x1200
 DataStoreTLBMiss:
 /*
- * r0:	stored ctr
+ * r0:	scratch
  * r1:	linux style pte ( later becomes ppc hardware pte )
  * r2:	ptr to linux-style pte
  * r3:	scratch
  */
-	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r3,SPRN_DMISS
 	lis	r1,PAGE_OFFSET@h		/* check if kernel address */
@@ -648,27 +656,38 @@
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	DataAddressInvalid	/* return if no mapping */
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r3,0(r2)		/* get linux-style pte */
-	andc.	r1,r1,r3		/* check access & ~permission */
+	lwz	r0,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r0		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
+	ori	r0,r0,_PAGE_ACCESSED|_PAGE_DIRTY
 	/*
 	 * NOTE! We are assuming this is not an SMP system, otherwise
 	 * we would need to update the pte atomically with lwarx/stwcx.
 	 */
-	stw	r3,0(r2)		/* update PTE (accessed/dirty bits) */
+	stw	r0,0(r2)		/* update PTE (accessed/dirty bits) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r0,r0,32-1,30,30	/* _PAGE_USER -> PP msb */
 	li	r1,0xe05		/* clear out reserved bits & PP lsb */
-	andc	r1,r3,r1		/* PP = user? 2: 0 */
+	andc	r1,r0,r1		/* PP = user? 2: 0 */
 BEGIN_FTR_SECTION
 	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
 END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
 	mtspr	SPRN_RPA,r1
-	mfspr	r3,SPRN_DMISS
+	mfspr	r2,SPRN_SRR1		/* Need to restore CR0 */
+	mtcrf	0x80,r2
+BEGIN_MMU_FTR_SECTION
+	li	r0,1
+	mfspr	r1,SPRN_SPRG4
+	rlwinm	r2,r3,20,27,31		/* Get Address bits 15:19 */
+	slw	r0,r0,r2
+	xor	r1,r0,r1
+	srw	r0,r1,r2
+	mtspr   SPRN_SPRG4,r1
+	mfspr	r2,SPRN_SRR1
+	rlwimi	r2,r0,31-14,14,14
+	mtspr   SPRN_SRR1,r2
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 	tlbld	r3
-	mfspr	r3,SPRN_SRR1		/* Need to restore CR0 */
-	mtcrf	0x80,r3
 	rfi
 
 #ifndef CONFIG_ALTIVEC
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index ebaedaf..50ef505 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1360,6 +1360,7 @@
 	b	.__after_prom_start
 
 _INIT_STATIC(__boot_from_prom)
+#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
 	/* Save parameters */
 	mr	r31,r3
 	mr	r30,r4
@@ -1390,7 +1391,10 @@
 	/* Do all of the interaction with OF client interface */
 	mr	r8,r26
 	bl	.prom_init
-	/* We never return */
+#endif /* #CONFIG_PPC_OF_BOOT_TRAMPOLINE */
+
+	/* We never return. We also hit that trap if trying to boot
+	 * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */
 	trap
 
 _STATIC(__after_prom_start)
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index fce2df9..95f39f1 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -10,6 +10,15 @@
 		mtspr	SPRN_IVOR##vector_number,r26;	\
 		sync
 
+#if (THREAD_SHIFT < 15)
+#define ALLOC_STACK_FRAME(reg, val)			\
+	addi reg,reg,val
+#else
+#define ALLOC_STACK_FRAME(reg, val)			\
+	addis	reg,reg,val@ha;				\
+	addi	reg,reg,val@l
+#endif
+
 #define NORMAL_EXCEPTION_PROLOG						     \
 	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
 	mtspr	SPRN_SPRG1,r11;						     \
@@ -20,7 +29,7 @@
 	beq	1f;							     \
 	mfspr	r1,SPRN_SPRG3;		/* if from user, start at top of   */\
 	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	addi	r1,r1,THREAD_SIZE;					     \
+	ALLOC_STACK_FRAME(r1, THREAD_SIZE);				     \
 1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
 	mr	r11,r1;							     \
 	stw	r10,_CCR(r11);          /* save various registers	   */\
@@ -70,10 +79,10 @@
 
 /* only on e500mc/e200 */
 #define DEBUG_STACK_BASE	dbgirq_ctx
-#ifdef CONFIG_PPC_E500MC
-#define DEBUG_SPRG		SPRN_SPRG9
-#else
+#ifdef CONFIG_E200
 #define DEBUG_SPRG		SPRN_SPRG6W
+#else
+#define DEBUG_SPRG		SPRN_SPRG9
 #endif
 
 #define EXC_LVL_FRAME_OVERHEAD	(THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
@@ -279,7 +288,7 @@
 	lwz	r11,GPR11(r8);						      \
 	mfspr	r8,DEBUG_SPRG;						      \
 									      \
-	RFDI;								      \
+	PPC_RFDI;								      \
 	b	.;							      \
 									      \
 	/* continue normal handling for a debug exception... */		      \
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 36ffb35..4c22620 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -103,10 +103,15 @@
 	or	r7,r7,r4
 	mtspr	SPRN_MAS6,r7
 	tlbsx	0,r6				/* search MSR[IS], SPID=PID0 */
-#ifndef CONFIG_E200
 	mfspr	r7,SPRN_MAS1
 	andis.	r7,r7,MAS1_VALID@h
 	bne	match_TLB
+
+	mfspr	r7,SPRN_MMUCFG
+	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
+	cmpwi	r7,3
+	bne	match_TLB			/* skip if NPIDS != 3 */
+
 	mfspr	r7,SPRN_PID1
 	slwi	r7,r7,16
 	or	r7,r7,r4
@@ -120,7 +125,7 @@
 	or	r7,r7,r4
 	mtspr	SPRN_MAS6,r7
 	tlbsx	0,r6				/* Fall through, we had to match */
-#endif
+
 match_TLB:
 	mfspr	r7,SPRN_MAS0
 	rlwinm	r3,r7,16,20,31			/* Extract MAS0(Entry) */
@@ -168,7 +173,7 @@
 
 	/* grab and fixup the RPN */
 	mfspr	r6,SPRN_MAS1	/* extract MAS1[SIZE] */
-	rlwinm	r6,r6,25,27,30
+	rlwinm	r6,r6,25,27,31
 	li	r8,-1
 	addi	r6,r6,10
 	slw	r6,r8,r6	/* convert to mask */
@@ -194,7 +199,7 @@
 	xori	r6,r4,1		/* Setup TMP mapping in the other Address space */
 	slwi	r6,r6,12
 	oris	r6,r6,(MAS1_VALID|MAS1_IPROT)@h
-	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
 	mtspr	SPRN_MAS1,r6
 	mfspr	r6,SPRN_MAS2
 	li	r7,0		/* temp EPN = 0 */
@@ -215,14 +220,19 @@
 
 /* 4. Clear out PIDs & Search info */
 	li	r6,0
+	mtspr   SPRN_MAS6,r6
 	mtspr	SPRN_PID0,r6
-#ifndef CONFIG_E200
+
+	mfspr	r7,SPRN_MMUCFG
+	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
+	cmpwi	r7,3
+	bne	2f				/* skip if NPIDS != 3 */
+
 	mtspr	SPRN_PID1,r6
 	mtspr	SPRN_PID2,r6
-#endif
-	mtspr	SPRN_MAS6,r6
 
 /* 5. Invalidate mapping we started in */
+2:
 	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
 	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
 	mtspr	SPRN_MAS0,r7
@@ -247,10 +257,10 @@
 	lis	r6,0x1000		/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
 	mtspr	SPRN_MAS0,r6
 	lis	r6,(MAS1_VALID|MAS1_IPROT)@h
-	ori	r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
+	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
 	mtspr	SPRN_MAS1,r6
-	lis	r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@h
-	ori	r6,r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@l
+	lis	r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
+	ori	r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
 	mtspr	SPRN_MAS2,r6
 	mtspr	SPRN_MAS3,r8
 	tlbwe
@@ -298,26 +308,14 @@
 	SET_IVOR(12, WatchdogTimer);
 	SET_IVOR(13, DataTLBError);
 	SET_IVOR(14, InstructionTLBError);
-	SET_IVOR(15, DebugDebug);
-#if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC)
 	SET_IVOR(15, DebugCrit);
-#endif
-	SET_IVOR(32, SPEUnavailable);
-	SET_IVOR(33, SPEFloatingPointData);
-	SET_IVOR(34, SPEFloatingPointRound);
-#ifndef CONFIG_E200
-	SET_IVOR(35, PerformanceMonitor);
-#endif
-#ifdef CONFIG_PPC_E500MC
-	SET_IVOR(36, Doorbell);
-#endif
 
 	/* Establish the interrupt vector base */
 	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
 	mtspr	SPRN_IVPR,r4
 
 	/* Setup the defaults for TLB entries */
-	li	r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+	li	r2,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l
 #ifdef CONFIG_E200
 	oris	r2,r2,MAS4_TLBSELD(1)@h
 #endif
@@ -329,12 +327,6 @@
 	oris	r2,r2,HID0_DOZE@h
 	mtspr	SPRN_HID0, r2
 #endif
-#ifdef CONFIG_E200
-	/* enable dedicated debug exception handling resources (Debug APU) */
-	mfspr	r2,SPRN_HID0
-	ori	r2,r2,HID0_DAPUEN@l
-	mtspr	SPRN_HID0,r2
-#endif
 
 #if !defined(CONFIG_BDI_SWITCH)
 	/*
@@ -706,15 +698,13 @@
 	/* Performance Monitor */
 	EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
 
-#ifdef CONFIG_PPC_E500MC
-	EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD)
-#endif
+	EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD)
+
+	CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception)
 
 	/* Debug Interrupt */
 	DEBUG_DEBUG_EXCEPTION
-#if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC)
 	DEBUG_CRIT_EXCEPTION
-#endif
 
 /*
  * Local functions
@@ -897,6 +887,47 @@
  * Global functions
  */
 
+/* Adjust or setup IVORs for e200 */
+_GLOBAL(__setup_e200_ivors)
+	li	r3,DebugDebug@l
+	mtspr	SPRN_IVOR15,r3
+	li	r3,SPEUnavailable@l
+	mtspr	SPRN_IVOR32,r3
+	li	r3,SPEFloatingPointData@l
+	mtspr	SPRN_IVOR33,r3
+	li	r3,SPEFloatingPointRound@l
+	mtspr	SPRN_IVOR34,r3
+	sync
+	blr
+
+/* Adjust or setup IVORs for e500v1/v2 */
+_GLOBAL(__setup_e500_ivors)
+	li	r3,DebugCrit@l
+	mtspr	SPRN_IVOR15,r3
+	li	r3,SPEUnavailable@l
+	mtspr	SPRN_IVOR32,r3
+	li	r3,SPEFloatingPointData@l
+	mtspr	SPRN_IVOR33,r3
+	li	r3,SPEFloatingPointRound@l
+	mtspr	SPRN_IVOR34,r3
+	li	r3,PerformanceMonitor@l
+	mtspr	SPRN_IVOR35,r3
+	sync
+	blr
+
+/* Adjust or setup IVORs for e500mc */
+_GLOBAL(__setup_e500mc_ivors)
+	li	r3,DebugDebug@l
+	mtspr	SPRN_IVOR15,r3
+	li	r3,PerformanceMonitor@l
+	mtspr	SPRN_IVOR35,r3
+	li	r3,Doorbell@l
+	mtspr	SPRN_IVOR36,r3
+	li	r3,CriticalDoorbell@l
+	mtspr	SPRN_IVOR37,r3
+	sync
+	blr
+
 /*
  * extern void loadcam_entry(unsigned int index)
  *
@@ -1089,7 +1120,7 @@
 	mtspr	SPRN_SPRG3,r4
 
 	/* Setup the defaults for TLB entries */
-	li	r4,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+	li	r4,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l
 	mtspr	SPRN_MAS4,r4
 
 	/* Jump to start_secondary */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 1b55ffd..5576147 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -171,7 +171,7 @@
 {
 	int i = *(loff_t *)v, j;
 	struct irqaction *action;
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	unsigned long flags;
 
 	if (i == 0) {
@@ -1038,7 +1038,7 @@
 static int virq_debug_show(struct seq_file *m, void *private)
 {
 	unsigned long flags;
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	const char *p;
 	char none[] = "none";
 	int i;
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 8992b03..8fbb125 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -329,7 +329,7 @@
    restore r2. */
 static int restore_r2(u32 *instruction, struct module *me)
 {
-	if (*instruction != PPC_NOP_INSTR) {
+	if (*instruction != PPC_INST_NOP) {
 		printk("%s: Expect noop after relocate, got %08x\n",
 		       me->name, *instruction);
 		return 0;
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0f41812..9c69e7e 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -38,6 +38,7 @@
 #include <asm/eeh.h>
 
 static DEFINE_SPINLOCK(hose_spinlock);
+LIST_HEAD(hose_list);
 
 /* XXX kill that some day ... */
 static int global_phb_number;		/* Global phb counter */
@@ -49,7 +50,7 @@
 unsigned int ppc_pci_flags = 0;
 
 
-static struct dma_mapping_ops *pci_dma_ops;
+static struct dma_mapping_ops *pci_dma_ops = &dma_direct_ops;
 
 void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
 {
@@ -113,19 +114,24 @@
 		kfree(phb);
 }
 
+static resource_size_t pcibios_io_size(const struct pci_controller *hose)
+{
+#ifdef CONFIG_PPC64
+	return hose->pci_io_size;
+#else
+	return hose->io_resource.end - hose->io_resource.start + 1;
+#endif
+}
+
 int pcibios_vaddr_is_ioport(void __iomem *address)
 {
 	int ret = 0;
 	struct pci_controller *hose;
-	unsigned long size;
+	resource_size_t size;
 
 	spin_lock(&hose_spinlock);
 	list_for_each_entry(hose, &hose_list, list_node) {
-#ifdef CONFIG_PPC64
-		size = hose->pci_io_size;
-#else
-		size = hose->io_resource.end - hose->io_resource.start + 1;
-#endif
+		size = pcibios_io_size(hose);
 		if (address >= hose->io_base_virt &&
 		    address < (hose->io_base_virt + size)) {
 			ret = 1;
@@ -136,6 +142,29 @@
 	return ret;
 }
 
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+	struct pci_controller *hose;
+	resource_size_t size;
+	unsigned long ret = ~0;
+
+	spin_lock(&hose_spinlock);
+	list_for_each_entry(hose, &hose_list, list_node) {
+		size = pcibios_io_size(hose);
+		if (address >= hose->io_base_phys &&
+		    address < (hose->io_base_phys + size)) {
+			unsigned long base =
+				(unsigned long)hose->io_base_virt - _IO_BASE;
+			ret = base + (address - hose->io_base_phys);
+			break;
+		}
+	}
+	spin_unlock(&hose_spinlock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
 /*
  * Return the domain number for this bus.
  */
@@ -1453,7 +1482,7 @@
 	 * we proceed to assigning things that were left unassigned
 	 */
 	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
-		pr_debug("PCI: Assigning unassigned resouces...\n");
+		pr_debug("PCI: Assigning unassigned resources...\n");
 		pci_assign_unassigned_resources();
 	}
 
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 132cd80..d473634 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -20,6 +20,7 @@
 #include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
@@ -43,8 +44,6 @@
  */
 static int pci_assign_all_buses;
 
-LIST_HEAD(hose_list);
-
 static int pci_bus_count;
 
 /* This will remain NULL for now, until isa-bridge.c is made common
@@ -219,16 +218,23 @@
 static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,
 					       unsigned int devfn)
 {
-	struct device_node *np;
+	struct device_node *np, *cnp;
 	const u32 *reg;
 	unsigned int psize;
 
 	for_each_child_of_node(parent, np) {
 		reg = of_get_property(np, "reg", &psize);
-		if (reg == NULL || psize < 4)
-			continue;
-		if (((reg[0] >> 8) & 0xff) == devfn)
+                if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn)
 			return np;
+
+		/* Note: some OFs create a parent node "multifunc-device" as
+		 * a fake root for all functions of a multi-function device,
+		 * we go down them as well. */
+                if (!strcmp(np->name, "multifunc-device")) {
+                        cnp = scan_OF_for_pci_dev(np, devfn);
+                        if (cnp)
+                                return cnp;
+                }
 	}
 	return NULL;
 }
@@ -491,24 +497,6 @@
 	return result;
 }
 
-unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		unsigned int size = hose->io_resource.end -
-			hose->io_resource.start + 1;
-		if (address >= hose->io_base_phys &&
-		    address < (hose->io_base_phys + size)) {
-			unsigned long base =
-				(unsigned long)hose->io_base_virt - _IO_BASE;
-			return base + (address - hose->io_base_phys);
-		}
-	}
-	return (unsigned int)-1;
-}
-EXPORT_SYMBOL(pci_address_to_pio);
-
 /*
  * Null PCI config access functions, for the case when we can't
  * find a hose.
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index ea8eda8..be574fc 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -43,8 +43,6 @@
 unsigned long pci_io_base = ISA_IO_BASE;
 EXPORT_SYMBOL(pci_io_base);
 
-LIST_HEAD(hose_list);
-
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
 	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -524,23 +522,6 @@
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		if (address >= hose->io_base_phys &&
-		    address < (hose->io_base_phys + hose->pci_io_size)) {
-			unsigned long base =
-				(unsigned long)hose->io_base_virt - _IO_BASE;
-			return base + (address - hose->io_base_phys);
-		}
-	}
-	return (unsigned int)-1;
-}
-EXPORT_SYMBOL_GPL(pci_address_to_pio);
-
-
 #define IOBASE_BRIDGE_NUMBER	0
 #define IOBASE_MEMORY		1
 #define IOBASE_IO		2
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index fb7049c..eac0649 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -33,7 +33,10 @@
 #include <linux/mqueue.h>
 #include <linux/hardirq.h>
 #include <linux/utsname.h>
+#include <linux/ftrace.h>
 #include <linux/kernel_stat.h>
+#include <linux/personality.h>
+#include <linux/random.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -1008,6 +1011,14 @@
 	unsigned long sp, ip, lr, newsp;
 	int count = 0;
 	int firstframe = 1;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	int curr_frame = current->curr_ret_stack;
+	extern void return_to_handler(void);
+	unsigned long addr = (unsigned long)return_to_handler;
+#ifdef CONFIG_PPC64
+	addr = *(unsigned long*)addr;
+#endif
+#endif
 
 	sp = (unsigned long) stack;
 	if (tsk == NULL)
@@ -1030,6 +1041,13 @@
 		ip = stack[STACK_FRAME_LR_SAVE];
 		if (!firstframe || ip != lr) {
 			printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+			if (ip == addr && curr_frame >= 0) {
+				printk(" (%pS)",
+				       (void *)current->ret_stack[curr_frame].ret);
+				curr_frame--;
+			}
+#endif
 			if (firstframe)
 				printk(" (unreliable)");
 			printk("\n");
@@ -1122,3 +1140,43 @@
 }
 
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+		sp -= get_random_int() & ~PAGE_MASK;
+	return sp & ~0xf;
+}
+
+static inline unsigned long brk_rnd(void)
+{
+        unsigned long rnd = 0;
+
+	/* 8MB for 32bit, 1GB for 64bit */
+	if (is_32bit_task())
+		rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
+	else
+		rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
+
+	return rnd << PAGE_SHIFT;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
+
+	if (ret < mm->brk)
+		return mm->brk;
+
+	return ret;
+}
+
+unsigned long randomize_et_dyn(unsigned long base)
+{
+	unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+
+	if (ret < base)
+		return base;
+
+	return ret;
+}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f00f831..5ec6a9e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1075,11 +1075,6 @@
 		DBG("reserving: %llx -> %llx\n", base, size);
 		lmb_reserve(base, size);
 	}
-
-#if 0
-	DBG("memory reserved, lmbs :\n");
-      	lmb_dump_all();
-#endif
 }
 
 #ifdef CONFIG_PHYP_DUMP
@@ -1221,6 +1216,7 @@
 	lmb_enforce_memory_limit(limit);
 
 	lmb_analyze();
+	lmb_dump_all();
 
 	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
 
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7f1b33d..2e026c0 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2283,6 +2283,8 @@
 	 */
 	prom_init_stdout();
 
+	prom_printf("Preparing to boot %s", RELOC(linux_banner));
+
 	/*
 	 * Get default machine type. At this point, we do not differentiate
 	 * between pSeries SMP and pSeries LPAR
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index ea3a2ec..1ac136b 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -20,7 +20,7 @@
 _end enter_prom memcpy memset reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
-reloc_got2 kernstart_addr memstart_addr"
+reloc_got2 kernstart_addr memstart_addr linux_banner"
 
 NM="$1"
 OBJ="$2"
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index fdfe14c..ee4c760 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -46,6 +46,7 @@
 
 struct rtas_suspend_me_data {
 	atomic_t working; /* number of cpus accessing this struct */
+	atomic_t done;
 	int token; /* ibm,suspend-me */
 	int error;
 	struct completion *complete; /* wait on this until working == 0 */
@@ -689,7 +690,7 @@
 #ifdef CONFIG_PPC_PSERIES
 static void rtas_percpu_suspend_me(void *info)
 {
-	long rc;
+	long rc = H_SUCCESS;
 	unsigned long msr_save;
 	int cpu;
 	struct rtas_suspend_me_data *data =
@@ -701,7 +702,8 @@
 	msr_save = mfmsr();
 	mtmsr(msr_save & ~(MSR_EE));
 
-	rc = plpar_hcall_norets(H_JOIN);
+	while (rc == H_SUCCESS && !atomic_read(&data->done))
+		rc = plpar_hcall_norets(H_JOIN);
 
 	mtmsr(msr_save);
 
@@ -724,6 +726,9 @@
 		       smp_processor_id(), rc);
 		data->error = rc;
 	}
+
+	atomic_set(&data->done, 1);
+
 	/* This cpu did the suspend or got an error; in either case,
 	 * we need to prod all other other cpus out of join state.
 	 * Extra prods are harmless.
@@ -766,6 +771,7 @@
 	}
 
 	atomic_set(&data.working, 0);
+	atomic_set(&data.done, 0);
 	data.token = rtas_token("ibm,suspend-me");
 	data.error = 0;
 	data.complete = &done;
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 705fc4b..9774f9f 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -35,6 +35,8 @@
 #include <linux/debugfs.h>
 #include <linux/percpu.h>
 #include <linux/lmb.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -669,3 +671,37 @@
 }
 arch_initcall(powerpc_debugfs_init);
 #endif
+
+static int ppc_dflt_bus_notify(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct device *dev = data;
+
+	/* We are only intereted in device addition */
+	if (action != BUS_NOTIFY_ADD_DEVICE)
+		return 0;
+
+	set_dma_ops(dev, &dma_direct_ops);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_dflt_plat_bus_notifier = {
+	.notifier_call = ppc_dflt_bus_notify,
+	.priority = INT_MAX,
+};
+
+static struct notifier_block ppc_dflt_of_bus_notifier = {
+	.notifier_call = ppc_dflt_bus_notify,
+	.priority = INT_MAX,
+};
+
+static int __init setup_bus_notifier(void)
+{
+	bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier);
+	bus_register_notifier(&of_platform_bus_type, &ppc_dflt_of_bus_notifier);
+
+	return 0;
+}
+
+arch_initcall(setup_bus_notifier);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 2d34196..c410c60 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -202,8 +202,6 @@
 
 	/* Fix up paca fields required for the boot cpu */
 	get_paca()->cpu_start = 1;
-	get_paca()->stab_real = __pa((u64)&initial_stab);
-	get_paca()->stab_addr = (u64)&initial_stab;
 
 	/* Probe the machine type */
 	probe_machine();
@@ -212,20 +210,8 @@
 
 	DBG("Found, Initializing memory management...\n");
 
-	/*
-	 * Initialize the MMU Hash table and create the linear mapping
-	 * of memory. Has to be done before stab/slb initialization as
-	 * this is currently where the page size encoding is obtained
-	 */
-	htab_initialize();
-
-	/*
-	 * Initialize stab / SLB management except on iSeries
-	 */
-	if (cpu_has_feature(CPU_FTR_SLB))
-		slb_initialize();
-	else if (!firmware_has_feature(FW_FEATURE_ISERIES))
-		stab_initialize(get_paca()->stab_real);
+	/* Initialize the hash table or TLB handling */
+	early_init_mmu();
 
 	DBG(" <- early_setup()\n");
 }
@@ -233,22 +219,11 @@
 #ifdef CONFIG_SMP
 void early_setup_secondary(void)
 {
-	struct paca_struct *lpaca = get_paca();
-
 	/* Mark interrupts enabled in PACA */
-	lpaca->soft_enabled = 0;
+	get_paca()->soft_enabled = 0;
 
-	/* Initialize hash table for that CPU */
-	htab_initialize_secondary();
-
-	/* Initialize STAB/SLB. We use a virtual address as it works
-	 * in real mode on pSeries and we want a virutal address on
-	 * iSeries anyway
-	 */
-	if (cpu_has_feature(CPU_FTR_SLB))
-		slb_initialize();
-	else
-		stab_initialize(lpaca->stab_addr);
+	/* Initialize the hash table or TLB handling */
+	early_init_mmu_secondary();
 }
 
 #endif /* CONFIG_SMP */
@@ -578,13 +553,6 @@
 	printk("[boot]%04x %s\n", src, msg);
 }
 
-/* Print a termination message (print only -- does not stop the kernel) */
-void ppc64_terminate_msg(unsigned int src, const char *msg)
-{
-	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);
-	printk("[terminate]%04x %s\n", src, msg);
-}
-
 void cpu_die(void)
 {
 	if (ppc_md.cpu_die)
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index a54405e..00b5078 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -26,12 +26,12 @@
  * Allocate space for the signal frame
  */
 void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-			   size_t frame_size)
+			   size_t frame_size, int is_32)
 {
         unsigned long oldsp, newsp;
 
         /* Default to using normal stack */
-        oldsp = regs->gpr[1];
+        oldsp = get_clean_sp(regs, is_32);
 
 	/* Check for alt stack */
 	if ((ka->sa.sa_flags & SA_ONSTACK) &&
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index b427bf8..6c0ddfc 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -15,7 +15,7 @@
 extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags);
 
 extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-				  size_t frame_size);
+				  size_t frame_size, int is_32);
 extern void restore_sigmask(sigset_t *set);
 
 extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
@@ -39,22 +39,12 @@
 
 #ifdef CONFIG_PPC64
 
-static inline int is_32bit_task(void)
-{
-	return test_thread_flag(TIF_32BIT);
-}
-
 extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
 			      siginfo_t *info, sigset_t *set,
 			      struct pt_regs *regs);
 
 #else /* CONFIG_PPC64 */
 
-static inline int is_32bit_task(void)
-{
-	return 1;
-}
-
 static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
 				     siginfo_t *info, sigset_t *set,
 				     struct pt_regs *regs)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index b13abf3..d670429 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -836,7 +836,7 @@
 
 	/* Set up Signal Frame */
 	/* Put a Real Time Context onto stack */
-	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+	rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1);
 	addr = rt_sf;
 	if (unlikely(rt_sf == NULL))
 		goto badframe;
@@ -1182,7 +1182,7 @@
 	unsigned long newsp = 0;
 
 	/* Set up Signal Frame */
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ka, regs, sizeof(*frame), 1);
 	if (unlikely(frame == NULL))
 		goto badframe;
 	sc = (struct sigcontext __user *) &frame->sctx;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index e132891..2fe6fc6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -402,7 +402,7 @@
 	unsigned long newsp = 0;
 	long err = 0;
 
-	frame = get_sigframe(ka, regs, sizeof(*frame));
+	frame = get_sigframe(ka, regs, sizeof(*frame), 0);
 	if (unlikely(frame == NULL))
 		goto badframe;
 
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 4a2ee08..f41aec8 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -134,44 +134,23 @@
 }
 EXPORT_SYMBOL(ppc_enable_pmcs);
 
-#if defined(CONFIG_6xx) || defined(CONFIG_PPC64)
-/* XXX convert to rusty's on_one_cpu */
-static unsigned long run_on_cpu(unsigned long cpu,
-			        unsigned long (*func)(unsigned long),
-				unsigned long arg)
-{
-	cpumask_t old_affinity = current->cpus_allowed;
-	unsigned long ret;
-
-	/* should return -EINVAL to userspace */
-	if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
-		return 0;
-
-	ret = func(arg);
-
-	set_cpus_allowed(current, old_affinity);
-
-	return ret;
-}
-#endif
-
 #define SYSFS_PMCSETUP(NAME, ADDRESS) \
-static unsigned long read_##NAME(unsigned long junk) \
+static void read_##NAME(void *val) \
 { \
-	return mfspr(ADDRESS); \
+	*(unsigned long *)val = mfspr(ADDRESS);	\
 } \
-static unsigned long write_##NAME(unsigned long val) \
+static void write_##NAME(void *val) \
 { \
 	ppc_enable_pmcs(); \
-	mtspr(ADDRESS, val); \
-	return 0; \
+	mtspr(ADDRESS, *(unsigned long *)val);	\
 } \
 static ssize_t show_##NAME(struct sys_device *dev, \
 			struct sysdev_attribute *attr, \
 			char *buf) \
 { \
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
-	unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \
+	unsigned long val; \
+	smp_call_function_single(cpu->sysdev.id, read_##NAME, &val, 1);	\
 	return sprintf(buf, "%lx\n", val); \
 } \
 static ssize_t __used \
@@ -183,7 +162,7 @@
 	int ret = sscanf(buf, "%lx", &val); \
 	if (ret != 1) \
 		return -EINVAL; \
-	run_on_cpu(cpu->sysdev.id, write_##NAME, val); \
+	smp_call_function_single(cpu->sysdev.id, write_##NAME, &val, 1); \
 	return count; \
 }
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5457e95..678fbff 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -52,6 +52,10 @@
 #include <asm/processor.h>
 #endif
 #include <asm/kexec.h>
+#include <asm/ppc-opcode.h>
+#ifdef CONFIG_FSL_BOOKE
+#include <asm/dbell.h>
+#endif
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 int (*__debugger)(struct pt_regs *regs);
@@ -637,29 +641,6 @@
  * bits is faster and easier.
  *
  */
-#define INST_MFSPR_PVR		0x7c1f42a6
-#define INST_MFSPR_PVR_MASK	0xfc1fffff
-
-#define INST_DCBA		0x7c0005ec
-#define INST_DCBA_MASK		0xfc0007fe
-
-#define INST_MCRXR		0x7c000400
-#define INST_MCRXR_MASK		0xfc0007fe
-
-#define INST_STRING		0x7c00042a
-#define INST_STRING_MASK	0xfc0007fe
-#define INST_STRING_GEN_MASK	0xfc00067e
-#define INST_LSWI		0x7c0004aa
-#define INST_LSWX		0x7c00042a
-#define INST_STSWI		0x7c0005aa
-#define INST_STSWX		0x7c00052a
-
-#define INST_POPCNTB		0x7c0000f4
-#define INST_POPCNTB_MASK	0xfc0007fe
-
-#define INST_ISEL		0x7c00001e
-#define INST_ISEL_MASK		0xfc00003e
-
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -670,20 +651,20 @@
 	int pos = 0;
 
 	/* Early out if we are an invalid form of lswx */
-	if ((instword & INST_STRING_MASK) == INST_LSWX)
+	if ((instword & PPC_INST_STRING_MASK) == PPC_INST_LSWX)
 		if ((rT == rA) || (rT == NB_RB))
 			return -EINVAL;
 
 	EA = (rA == 0) ? 0 : regs->gpr[rA];
 
-	switch (instword & INST_STRING_MASK) {
-		case INST_LSWX:
-		case INST_STSWX:
+	switch (instword & PPC_INST_STRING_MASK) {
+		case PPC_INST_LSWX:
+		case PPC_INST_STSWX:
 			EA += NB_RB;
 			num_bytes = regs->xer & 0x7f;
 			break;
-		case INST_LSWI:
-		case INST_STSWI:
+		case PPC_INST_LSWI:
+		case PPC_INST_STSWI:
 			num_bytes = (NB_RB == 0) ? 32 : NB_RB;
 			break;
 		default:
@@ -695,9 +676,9 @@
 		u8 val;
 		u32 shift = 8 * (3 - (pos & 0x3));
 
-		switch ((instword & INST_STRING_MASK)) {
-			case INST_LSWX:
-			case INST_LSWI:
+		switch ((instword & PPC_INST_STRING_MASK)) {
+			case PPC_INST_LSWX:
+			case PPC_INST_LSWI:
 				if (get_user(val, (u8 __user *)EA))
 					return -EFAULT;
 				/* first time updating this reg,
@@ -706,8 +687,8 @@
 					regs->gpr[rT] = 0;
 				regs->gpr[rT] |= val << shift;
 				break;
-			case INST_STSWI:
-			case INST_STSWX:
+			case PPC_INST_STSWI:
+			case PPC_INST_STSWX:
 				val = regs->gpr[rT] >> shift;
 				if (put_user(val, (u8 __user *)EA))
 					return -EFAULT;
@@ -775,18 +756,18 @@
 		return -EFAULT;
 
 	/* Emulate the mfspr rD, PVR. */
-	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+	if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) {
 		rd = (instword >> 21) & 0x1f;
 		regs->gpr[rd] = mfspr(SPRN_PVR);
 		return 0;
 	}
 
 	/* Emulating the dcba insn is just a no-op.  */
-	if ((instword & INST_DCBA_MASK) == INST_DCBA)
+	if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA)
 		return 0;
 
 	/* Emulate the mcrxr insn.  */
-	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+	if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) {
 		int shift = (instword >> 21) & 0x1c;
 		unsigned long msk = 0xf0000000UL >> shift;
 
@@ -796,16 +777,16 @@
 	}
 
 	/* Emulate load/store string insn. */
-	if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
+	if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING)
 		return emulate_string_inst(regs, instword);
 
 	/* Emulate the popcntb (Population Count Bytes) instruction. */
-	if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
+	if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) {
 		return emulate_popcntb_inst(regs, instword);
 	}
 
 	/* Emulate isel (Integer Select) instruction */
-	if ((instword & INST_ISEL_MASK) == INST_ISEL) {
+	if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) {
 		return emulate_isel(regs, instword);
 	}
 
@@ -1144,6 +1125,24 @@
 #endif /* CONFIG_VSX */
 
 #ifdef CONFIG_FSL_BOOKE
+
+void doorbell_exception(struct pt_regs *regs)
+{
+#ifdef CONFIG_SMP
+	int cpu = smp_processor_id();
+	int msg;
+
+	if (num_online_cpus() < 2)
+		return;
+
+	for (msg = 0; msg < 4; msg++)
+		if (test_and_clear_bit(msg, &dbell_smp_message[cpu]))
+			smp_message_recv(msg);
+#else
+	printk(KERN_WARNING "Received doorbell on non-smp system\n");
+#endif
+}
+
 void CacheLockingException(struct pt_regs *regs, unsigned long address,
 			   unsigned long error_code)
 {
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 7d6c9bb..fc9af47 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -18,6 +18,7 @@
 #include <asm/udbg.h>
 
 void (*udbg_putc)(char c);
+void (*udbg_flush)(void);
 int (*udbg_getc)(void);
 int (*udbg_getc_poll)(void);
 
@@ -76,6 +77,9 @@
 			while ((c = *s++) != '\0')
 				udbg_putc(c);
 		}
+
+		if (udbg_flush)
+			udbg_flush();
 	}
 #if 0
 	else {
@@ -98,6 +102,9 @@
 		}
 	}
 
+	if (udbg_flush)
+		udbg_flush();
+
 	return n - remain;
 }
 
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 7b7da8c..0362a89 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -48,14 +48,21 @@
 
 static struct NS16550 __iomem *udbg_comport;
 
-static void udbg_550_putc(char c)
+static void udbg_550_flush(void)
 {
 	if (udbg_comport) {
 		while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		out_8(&udbg_comport->thr, c);
+	}
+}
+
+static void udbg_550_putc(char c)
+{
+	if (udbg_comport) {
 		if (c == '\n')
 			udbg_550_putc('\r');
+		udbg_550_flush();
+		out_8(&udbg_comport->thr, c);
 	}
 }
 
@@ -108,6 +115,7 @@
 		/* Clear & enable FIFOs */
 		out_8(&udbg_comport->fcr ,0x07);
 		udbg_putc = udbg_550_putc;
+		udbg_flush = udbg_550_flush;
 		udbg_getc = udbg_550_getc;
 		udbg_getc_poll = udbg_550_getc_poll;
 	}
@@ -149,14 +157,21 @@
 }
 
 #ifdef CONFIG_PPC_MAPLE
-void udbg_maple_real_putc(char c)
+void udbg_maple_real_flush(void)
 {
 	if (udbg_comport) {
 		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		real_writeb(c, &udbg_comport->thr); eieio();
+	}
+}
+
+void udbg_maple_real_putc(char c)
+{
+	if (udbg_comport) {
 		if (c == '\n')
 			udbg_maple_real_putc('\r');
+		udbg_maple_real_flush();
+		real_writeb(c, &udbg_comport->thr); eieio();
 	}
 }
 
@@ -165,20 +180,28 @@
 	udbg_comport = (struct NS16550 __iomem *)0xf40003f8;
 
 	udbg_putc = udbg_maple_real_putc;
+	udbg_flush = udbg_maple_real_flush;
 	udbg_getc = NULL;
 	udbg_getc_poll = NULL;
 }
 #endif /* CONFIG_PPC_MAPLE */
 
 #ifdef CONFIG_PPC_PASEMI
-void udbg_pas_real_putc(char c)
+void udbg_pas_real_flush(void)
 {
 	if (udbg_comport) {
 		while ((real_205_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		real_205_writeb(c, &udbg_comport->thr); eieio();
+	}
+}
+
+void udbg_pas_real_putc(char c)
+{
+	if (udbg_comport) {
 		if (c == '\n')
 			udbg_pas_real_putc('\r');
+		udbg_pas_real_flush();
+		real_205_writeb(c, &udbg_comport->thr); eieio();
 	}
 }
 
@@ -187,6 +210,7 @@
 	udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL;
 
 	udbg_putc = udbg_pas_real_putc;
+	udbg_flush = udbg_pas_real_flush;
 	udbg_getc = NULL;
 	udbg_getc_poll = NULL;
 }
@@ -195,14 +219,21 @@
 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
 #include <platforms/44x/44x.h>
 
-static void udbg_44x_as1_putc(char c)
+static int udbg_44x_as1_flush(void)
 {
 	if (udbg_comport) {
 		while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		as1_writeb(c, &udbg_comport->thr); eieio();
+	}
+}
+
+static void udbg_44x_as1_putc(char c)
+{
+	if (udbg_comport) {
 		if (c == '\n')
 			udbg_44x_as1_putc('\r');
+		udbg_44x_as1_flush();
+		as1_writeb(c, &udbg_comport->thr); eieio();
 	}
 }
 
@@ -222,19 +253,27 @@
 		(struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
 
 	udbg_putc = udbg_44x_as1_putc;
+	udbg_flush = udbg_44x_as1_flush;
 	udbg_getc = udbg_44x_as1_getc;
 }
 #endif /* CONFIG_PPC_EARLY_DEBUG_44x */
 
 #ifdef CONFIG_PPC_EARLY_DEBUG_40x
-static void udbg_40x_real_putc(char c)
+static void udbg_40x_real_flush(void)
 {
 	if (udbg_comport) {
 		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		real_writeb(c, &udbg_comport->thr); eieio();
+	}
+}
+
+static void udbg_40x_real_putc(char c)
+{
+	if (udbg_comport) {
 		if (c == '\n')
 			udbg_40x_real_putc('\r');
+		udbg_40x_real_flush();
+		real_writeb(c, &udbg_comport->thr); eieio();
 	}
 }
 
@@ -254,6 +293,7 @@
 		CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR;
 
 	udbg_putc = udbg_40x_real_putc;
+	udbg_flush = udbg_40x_real_flush;
 	udbg_getc = udbg_40x_real_getc;
 	udbg_getc_poll = NULL;
 }
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 67f07f4..b9ef164 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -58,6 +58,7 @@
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 
 #ifdef CONFIG_PPC32
 		*(.got1)
diff --git a/arch/powerpc/lib/dma-noncoherent.c b/arch/powerpc/lib/dma-noncoherent.c
index b7dc4c1..005a28d 100644
--- a/arch/powerpc/lib/dma-noncoherent.c
+++ b/arch/powerpc/lib/dma-noncoherent.c
@@ -29,121 +29,11 @@
 #include <linux/types.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
 
 #include <asm/tlbflush.h>
 
 /*
- * This address range defaults to a value that is safe for all
- * platforms which currently set CONFIG_NOT_COHERENT_CACHE. It
- * can be further configured for specific applications under
- * the "Advanced Setup" menu. -Matt
- */
-#define CONSISTENT_BASE	(CONFIG_CONSISTENT_START)
-#define CONSISTENT_END	(CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
-#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
-
-/*
- * This is the page table (2MB) covering uncached, DMA consistent allocations
- */
-static pte_t *consistent_pte;
-static DEFINE_SPINLOCK(consistent_lock);
-
-/*
- * VM region handling support.
- *
- * This should become something generic, handling VM region allocations for
- * vmalloc and similar (ioremap, module space, etc).
- *
- * I envisage vmalloc()'s supporting vm_struct becoming:
- *
- *  struct vm_struct {
- *    struct vm_region	region;
- *    unsigned long	flags;
- *    struct page	**pages;
- *    unsigned int	nr_pages;
- *    unsigned long	phys_addr;
- *  };
- *
- * get_vm_area() would then call vm_region_alloc with an appropriate
- * struct vm_region head (eg):
- *
- *  struct vm_region vmalloc_head = {
- *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
- *	.vm_start	= VMALLOC_START,
- *	.vm_end		= VMALLOC_END,
- *  };
- *
- * However, vmalloc_head.vm_start is variable (typically, it is dependent on
- * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
- * would have to initialise this each time prior to calling vm_region_alloc().
- */
-struct ppc_vm_region {
-	struct list_head	vm_list;
-	unsigned long		vm_start;
-	unsigned long		vm_end;
-};
-
-static struct ppc_vm_region consistent_head = {
-	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
-	.vm_start	= CONSISTENT_BASE,
-	.vm_end		= CONSISTENT_END,
-};
-
-static struct ppc_vm_region *
-ppc_vm_region_alloc(struct ppc_vm_region *head, size_t size, gfp_t gfp)
-{
-	unsigned long addr = head->vm_start, end = head->vm_end - size;
-	unsigned long flags;
-	struct ppc_vm_region *c, *new;
-
-	new = kmalloc(sizeof(struct ppc_vm_region), gfp);
-	if (!new)
-		goto out;
-
-	spin_lock_irqsave(&consistent_lock, flags);
-
-	list_for_each_entry(c, &head->vm_list, vm_list) {
-		if ((addr + size) < addr)
-			goto nospc;
-		if ((addr + size) <= c->vm_start)
-			goto found;
-		addr = c->vm_end;
-		if (addr > end)
-			goto nospc;
-	}
-
- found:
-	/*
-	 * Insert this entry _before_ the one we found.
-	 */
-	list_add_tail(&new->vm_list, &c->vm_list);
-	new->vm_start = addr;
-	new->vm_end = addr + size;
-
-	spin_unlock_irqrestore(&consistent_lock, flags);
-	return new;
-
- nospc:
-	spin_unlock_irqrestore(&consistent_lock, flags);
-	kfree(new);
- out:
-	return NULL;
-}
-
-static struct ppc_vm_region *ppc_vm_region_find(struct ppc_vm_region *head, unsigned long addr)
-{
-	struct ppc_vm_region *c;
-
-	list_for_each_entry(c, &head->vm_list, vm_list) {
-		if (c->vm_start == addr)
-			goto out;
-	}
-	c = NULL;
- out:
-	return c;
-}
-
-/*
  * Allocate DMA-coherent memory space and return both the kernel remapped
  * virtual and bus address for that space.
  */
@@ -151,21 +41,21 @@
 __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
 {
 	struct page *page;
-	struct ppc_vm_region *c;
 	unsigned long order;
+	int i;
+	unsigned int nr_pages = PAGE_ALIGN(size)>>PAGE_SHIFT;
+	unsigned int array_size = nr_pages * sizeof(struct page *);
+	struct page **pages;
+	struct page *end;
 	u64 mask = 0x00ffffff, limit; /* ISA default */
+	struct vm_struct *area;
 
-	if (!consistent_pte) {
-		printk(KERN_ERR "%s: not initialised\n", __func__);
-		dump_stack();
-		return NULL;
-	}
-
+	BUG_ON(!mem_init_done);
 	size = PAGE_ALIGN(size);
 	limit = (mask + 1) & ~mask;
-	if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
-		printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
-		       size, mask);
+	if (limit && size >= limit) {
+		printk(KERN_WARNING "coherent allocation too big (requested "
+				"%#x mask %#Lx)\n", size, mask);
 		return NULL;
 	}
 
@@ -178,6 +68,8 @@
 	if (!page)
 		goto no_page;
 
+	end = page + (1 << order);
+
 	/*
 	 * Invalidate any data that might be lurking in the
 	 * kernel direct-mapped region for device DMA.
@@ -188,48 +80,59 @@
 		flush_dcache_range(kaddr, kaddr + size);
 	}
 
+	split_page(page, order);
+
 	/*
-	 * Allocate a virtual address in the consistent mapping region.
+	 * Set the "dma handle"
 	 */
-	c = ppc_vm_region_alloc(&consistent_head, size,
-			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
-	if (c) {
-		unsigned long vaddr = c->vm_start;
-		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
-		struct page *end = page + (1 << order);
+	*handle = page_to_phys(page);
 
-		split_page(page, order);
+	area = get_vm_area_caller(size, VM_IOREMAP,
+			__builtin_return_address(1));
+	if (!area)
+		goto out_free_pages;
 
-		/*
-		 * Set the "dma handle"
-		 */
-		*handle = page_to_phys(page);
+	if (array_size > PAGE_SIZE) {
+		pages = vmalloc(array_size);
+		area->flags |= VM_VPAGES;
+	} else {
+		pages = kmalloc(array_size, GFP_KERNEL);
+	}
+	if (!pages)
+		goto out_free_area;
 
-		do {
-			BUG_ON(!pte_none(*pte));
+	area->pages = pages;
+	area->nr_pages = nr_pages;
 
-			SetPageReserved(page);
-			set_pte_at(&init_mm, vaddr,
-				   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
-			page++;
-			pte++;
-			vaddr += PAGE_SIZE;
-		} while (size -= PAGE_SIZE);
+	for (i = 0; i < nr_pages; i++)
+		pages[i] = page + i;
 
-		/*
-		 * Free the otherwise unused pages.
-		 */
-		while (page < end) {
-			__free_page(page);
-			page++;
-		}
+	if (map_vm_area(area, pgprot_noncached(PAGE_KERNEL), &pages))
+		goto out_unmap;
 
-		return (void *)c->vm_start;
+	/*
+	 * Free the otherwise unused pages.
+	 */
+	page += nr_pages;
+	while (page < end) {
+		__free_page(page);
+		page++;
 	}
 
+	return area->addr;
+out_unmap:
+	vunmap(area->addr);
+	if (array_size > PAGE_SIZE)
+		vfree(pages);
+	else
+		kfree(pages);
+	goto out_free_pages;
+out_free_area:
+	free_vm_area(area);
+out_free_pages:
 	if (page)
 		__free_pages(page, order);
- no_page:
+no_page:
 	return NULL;
 }
 EXPORT_SYMBOL(__dma_alloc_coherent);
@@ -239,104 +142,12 @@
  */
 void __dma_free_coherent(size_t size, void *vaddr)
 {
-	struct ppc_vm_region *c;
-	unsigned long flags, addr;
-	pte_t *ptep;
+	vfree(vaddr);
 
-	size = PAGE_ALIGN(size);
-
-	spin_lock_irqsave(&consistent_lock, flags);
-
-	c = ppc_vm_region_find(&consistent_head, (unsigned long)vaddr);
-	if (!c)
-		goto no_area;
-
-	if ((c->vm_end - c->vm_start) != size) {
-		printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
-		       __func__, c->vm_end - c->vm_start, size);
-		dump_stack();
-		size = c->vm_end - c->vm_start;
-	}
-
-	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
-	addr = c->vm_start;
-	do {
-		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
-		unsigned long pfn;
-
-		ptep++;
-		addr += PAGE_SIZE;
-
-		if (!pte_none(pte) && pte_present(pte)) {
-			pfn = pte_pfn(pte);
-
-			if (pfn_valid(pfn)) {
-				struct page *page = pfn_to_page(pfn);
-				ClearPageReserved(page);
-
-				__free_page(page);
-				continue;
-			}
-		}
-
-		printk(KERN_CRIT "%s: bad page in kernel page table\n",
-		       __func__);
-	} while (size -= PAGE_SIZE);
-
-	flush_tlb_kernel_range(c->vm_start, c->vm_end);
-
-	list_del(&c->vm_list);
-
-	spin_unlock_irqrestore(&consistent_lock, flags);
-
-	kfree(c);
-	return;
-
- no_area:
-	spin_unlock_irqrestore(&consistent_lock, flags);
-	printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
-	       __func__, vaddr);
-	dump_stack();
 }
 EXPORT_SYMBOL(__dma_free_coherent);
 
 /*
- * Initialise the consistent memory allocation.
- */
-static int __init dma_alloc_init(void)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	int ret = 0;
-
-	do {
-		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
-		pud = pud_alloc(&init_mm, pgd, CONSISTENT_BASE);
-		pmd = pmd_alloc(&init_mm, pud, CONSISTENT_BASE);
-		if (!pmd) {
-			printk(KERN_ERR "%s: no pmd tables\n", __func__);
-			ret = -ENOMEM;
-			break;
-		}
-
-		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
-		if (!pte) {
-			printk(KERN_ERR "%s: no pte tables\n", __func__);
-			ret = -ENOMEM;
-			break;
-		}
-
-		consistent_pte = pte;
-	} while (0);
-
-	return ret;
-}
-
-core_initcall(dma_alloc_init);
-
-/*
  * make an area consistent.
  */
 void __dma_sync(void *vaddr, size_t size, int direction)
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 8c5a03b..7e8865b 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -85,7 +85,7 @@
 	}
 
 	for (; dest < end; dest++)
-		patch_instruction(dest, PPC_NOP_INSTR);
+		patch_instruction(dest, PPC_INST_NOP);
 
 	return 0;
 }
@@ -122,7 +122,7 @@
 
 	for (; start < end; start++) {
 		dest = (void *)start + *start;
-		patch_instruction(dest, PPC_LWSYNC_INSTR);
+		patch_instruction(dest, PPC_INST_LWSYNC);
 	}
 }
 
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile
index f9e506a..0c16ab9 100644
--- a/arch/powerpc/math-emu/Makefile
+++ b/arch/powerpc/math-emu/Makefile
@@ -1,6 +1,4 @@
 
-obj-y				:= math.o fmr.o lfd.o stfd.o
-
 obj-$(CONFIG_MATH_EMULATION)	+= fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
 					fctiw.o fctiwz.o fdiv.o fdivs.o \
 					fmadd.o fmadds.o fmsub.o fmsubs.o \
@@ -9,7 +7,8 @@
 					fres.o frsp.o frsqrte.o fsel.o lfs.o \
 					fsqrt.o	fsqrts.o fsub.o fsubs.o \
 					mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
-					mtfsf.o mtfsfi.o stfiwx.o stfs.o
+					mtfsf.o mtfsfi.o stfiwx.o stfs.o \
+					math.o fmr.o lfd.o stfd.o
 
 obj-$(CONFIG_SPE)		+= math_efp.o
 
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 953cc4a..17290bc 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -6,7 +6,7 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 endif
 
-obj-y				:= fault.o mem.o pgtable.o \
+obj-y				:= fault.o mem.o pgtable.o gup.o \
 				   init_$(CONFIG_WORD_SIZE).o \
 				   pgtable_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC_MMU_NOHASH)	+= mmu_context_nohash.o tlb_nohash.o \
@@ -14,7 +14,7 @@
 hash-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
 obj-$(CONFIG_PPC64)		+= hash_utils_64.o \
 				   slb_low.o slb.o stab.o \
-				   gup.o mmap.o $(hash-y)
+				   mmap_64.o $(hash-y)
 obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o
 obj-$(CONFIG_PPC_STD_MMU)	+= hash_low_$(CONFIG_WORD_SIZE).o \
 				   tlb_hash$(CONFIG_WORD_SIZE).o \
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 91c7b86..7699394 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -253,45 +253,33 @@
 #endif /* CONFIG_8xx */
 
 	if (is_exec) {
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-		/* protection fault */
+#ifdef CONFIG_PPC_STD_MMU
+		/* Protection fault on exec go straight to failure on
+		 * Hash based MMUs as they either don't support per-page
+		 * execute permission, or if they do, it's handled already
+		 * at the hash level. This test would probably have to
+		 * be removed if we change the way this works to make hash
+		 * processors use the same I/D cache coherency mechanism
+		 * as embedded.
+		 */
 		if (error_code & DSISR_PROTFAULT)
 			goto bad_area;
+#endif /* CONFIG_PPC_STD_MMU */
+
 		/*
 		 * Allow execution from readable areas if the MMU does not
 		 * provide separate controls over reading and executing.
+		 *
+		 * Note: That code used to not be enabled for 4xx/BookE.
+		 * It is now as I/D cache coherency for these is done at
+		 * set_pte_at() time and I see no reason why the test
+		 * below wouldn't be valid on those processors. This -may-
+		 * break programs compiled with a really old ABI though.
 		 */
 		if (!(vma->vm_flags & VM_EXEC) &&
 		    (cpu_has_feature(CPU_FTR_NOEXECUTE) ||
 		     !(vma->vm_flags & (VM_READ | VM_WRITE))))
 			goto bad_area;
-#else
-		pte_t *ptep;
-		pmd_t *pmdp;
-
-		/* Since 4xx/Book-E supports per-page execute permission,
-		 * we lazily flush dcache to icache. */
-		ptep = NULL;
-		if (get_pteptr(mm, address, &ptep, &pmdp)) {
-			spinlock_t *ptl = pte_lockptr(mm, pmdp);
-			spin_lock(ptl);
-			if (pte_present(*ptep)) {
-				struct page *page = pte_page(*ptep);
-
-				if (!test_bit(PG_arch_1, &page->flags)) {
-					flush_dcache_icache_page(page);
-					set_bit(PG_arch_1, &page->flags);
-				}
-				pte_update(ptep, 0, _PAGE_HWEXEC |
-					   _PAGE_ACCESSED);
-				local_flush_tlb_page(vma, address);
-				pte_unmap_unlock(ptep, ptl);
-				up_read(&mm->mmap_sem);
-				return 0;
-			}
-			pte_unmap_unlock(ptep, ptl);
-		}
-#endif
 	/* a write */
 	} else if (is_write) {
 		if (!(vma->vm_flags & VM_WRITE))
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index ea6e41e..bb3d659 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -56,10 +56,14 @@
 
 extern void loadcam_entry(unsigned int index);
 unsigned int tlbcam_index;
-static unsigned long __cam0, __cam1, __cam2;
+static unsigned long cam[CONFIG_LOWMEM_CAM_NUM];
 
 #define NUM_TLBCAMS	(16)
 
+#if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
+#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
+#endif
+
 struct tlbcam TLBCAM[NUM_TLBCAMS];
 
 struct tlbcamrange {
@@ -107,7 +111,7 @@
 	unsigned int tsize, lz;
 
 	asm ("cntlzw %0,%1" : "=r" (lz) : "r" (size));
-	tsize = (21 - lz) / 2;
+	tsize = 21 - lz;
 
 #ifdef CONFIG_SMP
 	if ((flags & _PAGE_NO_CACHE) == 0)
@@ -152,19 +156,19 @@
 	loadcam_entry(index);
 }
 
-void __init cam_mapin_ram(unsigned long cam0, unsigned long cam1,
-		unsigned long cam2)
+unsigned long __init mmu_mapin_ram(void)
 {
-	settlbcam(0, PAGE_OFFSET, memstart_addr, cam0, _PAGE_KERNEL, 0);
-	tlbcam_index++;
-	if (cam1) {
+	unsigned long virt = PAGE_OFFSET;
+	phys_addr_t phys = memstart_addr;
+
+	while (cam[tlbcam_index] && tlbcam_index < ARRAY_SIZE(cam)) {
+		settlbcam(tlbcam_index, virt, phys, cam[tlbcam_index], PAGE_KERNEL_X, 0);
+		virt += cam[tlbcam_index];
+		phys += cam[tlbcam_index];
 		tlbcam_index++;
-		settlbcam(1, PAGE_OFFSET+cam0, memstart_addr+cam0, cam1, _PAGE_KERNEL, 0);
 	}
-	if (cam2) {
-		tlbcam_index++;
-		settlbcam(2, PAGE_OFFSET+cam0+cam1, memstart_addr+cam0+cam1, cam2, _PAGE_KERNEL, 0);
-	}
+
+	return virt - PAGE_OFFSET;
 }
 
 /*
@@ -175,51 +179,46 @@
 	flush_instruction_cache();
 }
 
-unsigned long __init mmu_mapin_ram(void)
-{
-	cam_mapin_ram(__cam0, __cam1, __cam2);
-
-	return __cam0 + __cam1 + __cam2;
-}
-
-
 void __init
 adjust_total_lowmem(void)
 {
-	phys_addr_t max_lowmem_size = __max_low_memory;
-	phys_addr_t cam_max_size = 0x10000000;
 	phys_addr_t ram;
+	unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xff;
+	char buf[ARRAY_SIZE(cam) * 5 + 1], *p = buf;
+	int i;
+	unsigned long virt = PAGE_OFFSET & 0xffffffffUL;
+	unsigned long phys = memstart_addr & 0xffffffffUL;
 
-	/* adjust CAM size to max_lowmem_size */
-	if (max_lowmem_size < cam_max_size)
-		cam_max_size = max_lowmem_size;
+	/* Convert (4^max) kB to (2^max) bytes */
+	max_cam = max_cam * 2 + 10;
 
-	/* adjust lowmem size to max_lowmem_size */
-	ram = min(max_lowmem_size, total_lowmem);
+	/* adjust lowmem size to __max_low_memory */
+	ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem);
 
 	/* Calculate CAM values */
-	__cam0 = 1UL << 2 * (__ilog2(ram) / 2);
-	if (__cam0 > cam_max_size)
-		__cam0 = cam_max_size;
-	ram -= __cam0;
-	if (ram) {
-		__cam1 = 1UL << 2 * (__ilog2(ram) / 2);
-		if (__cam1 > cam_max_size)
-			__cam1 = cam_max_size;
-		ram -= __cam1;
-	}
-	if (ram) {
-		__cam2 = 1UL << 2 * (__ilog2(ram) / 2);
-		if (__cam2 > cam_max_size)
-			__cam2 = cam_max_size;
-		ram -= __cam2;
-	}
+	__max_low_memory = 0;
+	for (i = 0; ram && i < ARRAY_SIZE(cam); i++) {
+		unsigned int camsize = __ilog2(ram) & ~1U;
+		unsigned int align = __ffs(virt | phys) & ~1U;
 
-	printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb,"
-			" CAM2=%ldMb residual: %ldMb\n",
-			__cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
-			(long int)((total_lowmem - __cam0 - __cam1 - __cam2)
-				   >> 20));
-	__max_low_memory = __cam0 + __cam1 + __cam2;
+		if (camsize > align)
+			camsize = align;
+		if (camsize > max_cam)
+			camsize = max_cam;
+
+		cam[i] = 1UL << camsize;
+		ram -= cam[i];
+		__max_low_memory += cam[i];
+		virt += cam[i];
+		phys += cam[i];
+
+		p += sprintf(p, "%lu/", cam[i] >> 20);
+	}
+	for (; i < ARRAY_SIZE(cam); i++)
+		p += sprintf(p, "0/");
+	p[-1] = '\0';
+
+	pr_info("Memory CAM mapping: %s Mb, residual: %dMb\n", buf,
+	        (unsigned int)((total_lowmem - __max_low_memory) >> 20));
 	__initial_memory_limit_addr = memstart_addr + __max_low_memory;
 }
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c
index 28a114d..bc400c7 100644
--- a/arch/powerpc/mm/gup.c
+++ b/arch/powerpc/mm/gup.c
@@ -14,6 +14,8 @@
 #include <linux/rwsem.h>
 #include <asm/pgtable.h>
 
+#ifdef __HAVE_ARCH_PTE_SPECIAL
+
 /*
  * The performance critical leaf functions are made noinline otherwise gcc
  * inlines everything into a single function which results in too much
@@ -151,8 +153,11 @@
 	unsigned long addr, len, end;
 	unsigned long next;
 	pgd_t *pgdp;
-	int psize, nr = 0;
+	int nr = 0;
+#ifdef CONFIG_PPC64
 	unsigned int shift;
+	int psize;
+#endif
 
 	pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
 
@@ -205,8 +210,13 @@
 	 */
 	local_irq_disable();
 
+#ifdef CONFIG_PPC64
+	/* Those bits are related to hugetlbfs implementation and only exist
+	 * on 64-bit for now
+	 */
 	psize = get_slice_psize(mm, addr);
 	shift = mmu_psize_defs[psize].shift;
+#endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_HUGETLB_PAGE
 	if (unlikely(mmu_huge_psizes[psize])) {
@@ -236,7 +246,9 @@
 		do {
 			pgd_t pgd = *pgdp;
 
+#ifdef CONFIG_PPC64
 			VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift);
+#endif
 			pr_debug("  %016lx: normal pgd %p\n", addr,
 				 (void *)pgd_val(pgd));
 			next = pgd_addr_end(addr, end);
@@ -279,3 +291,5 @@
 		return ret;
 	}
 }
+
+#endif /* __HAVE_ARCH_PTE_SPECIAL */
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 8d5b475..db556d2 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -516,7 +516,7 @@
 
 static unsigned long __init htab_get_table_size(void)
 {
-	unsigned long mem_size, rnd_mem_size, pteg_count;
+	unsigned long mem_size, rnd_mem_size, pteg_count, psize;
 
 	/* If hash size isn't already provided by the platform, we try to
 	 * retrieve it from the device-tree. If it's not there neither, we
@@ -534,7 +534,8 @@
 		rnd_mem_size <<= 1;
 
 	/* # pages / 2 */
-	pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11);
+	psize = mmu_psize_defs[mmu_virtual_psize].shift;
+	pteg_count = max(rnd_mem_size >> (psize + 1), 1UL << 11);
 
 	return pteg_count << 7;
 }
@@ -589,7 +590,7 @@
 	make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
 }
 
-void __init htab_initialize(void)
+static void __init htab_initialize(void)
 {
 	unsigned long table;
 	unsigned long pteg_count;
@@ -731,11 +732,43 @@
 #undef KB
 #undef MB
 
-void htab_initialize_secondary(void)
+void __init early_init_mmu(void)
 {
+	/* Setup initial STAB address in the PACA */
+	get_paca()->stab_real = __pa((u64)&initial_stab);
+	get_paca()->stab_addr = (u64)&initial_stab;
+
+	/* Initialize the MMU Hash table and create the linear mapping
+	 * of memory. Has to be done before stab/slb initialization as
+	 * this is currently where the page size encoding is obtained
+	 */
+	htab_initialize();
+
+	/* Initialize stab / SLB management except on iSeries
+	 */
+	if (cpu_has_feature(CPU_FTR_SLB))
+		slb_initialize();
+	else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		stab_initialize(get_paca()->stab_real);
+}
+
+#ifdef CONFIG_SMP
+void __init early_init_mmu_secondary(void)
+{
+	/* Initialize hash table for that CPU */
 	if (!firmware_has_feature(FW_FEATURE_LPAR))
 		mtspr(SPRN_SDR1, _SDR1);
+
+	/* Initialize STAB/SLB. We use a virtual address as it works
+	 * in real mode on pSeries and we want a virutal address on
+	 * iSeries anyway
+	 */
+	if (cpu_has_feature(CPU_FTR_SLB))
+		slb_initialize();
+	else
+		stab_initialize(get_paca()->stab_addr);
 }
+#endif /* CONFIG_SMP */
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
@@ -858,7 +891,7 @@
 	unsigned long vsid;
 	struct mm_struct *mm;
 	pte_t *ptep;
-	cpumask_t tmp;
+	const struct cpumask *tmp;
 	int rc, user_region = 0, local = 0;
 	int psize, ssize;
 
@@ -906,8 +939,8 @@
 		return 1;
 
 	/* Check CPU locality */
-	tmp = cpumask_of_cpu(smp_processor_id());
-	if (user_region && cpus_equal(mm->cpu_vm_mask, tmp))
+	tmp = cpumask_of(smp_processor_id());
+	if (user_region && cpumask_equal(mm_cpumask(mm), tmp))
 		local = 1;
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -1023,7 +1056,6 @@
 	unsigned long vsid;
 	void *pgdir;
 	pte_t *ptep;
-	cpumask_t mask;
 	unsigned long flags;
 	int local = 0;
 	int ssize;
@@ -1066,8 +1098,7 @@
 	local_irq_save(flags);
 
 	/* Is that local to this CPU ? */
-	mask = cpumask_of_cpu(smp_processor_id());
-	if (cpus_equal(mm->cpu_vm_mask, mask))
+	if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
 		local = 1;
 
 	/* Hash it in */
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index f00f09a..f668fa9 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -472,40 +472,7 @@
 {
 #ifdef CONFIG_PPC_STD_MMU
 	unsigned long access = 0, trap;
-#endif
-	unsigned long pfn = pte_pfn(pte);
 
-	/* handle i-cache coherency */
-	if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
-	    !cpu_has_feature(CPU_FTR_NOEXECUTE) &&
-	    pfn_valid(pfn)) {
-		struct page *page = pfn_to_page(pfn);
-#ifdef CONFIG_8xx
-		/* On 8xx, cache control instructions (particularly
-		 * "dcbst" from flush_dcache_icache) fault as write
-		 * operation if there is an unpopulated TLB entry
-		 * for the address in question. To workaround that,
-		 * we invalidate the TLB here, thus avoiding dcbst
-		 * misbehaviour.
-		 */
-		_tlbil_va(address, 0 /* 8xx doesn't care about PID */);
-#endif
-		/* The _PAGE_USER test should really be _PAGE_EXEC, but
-		 * older glibc versions execute some code from no-exec
-		 * pages, which for now we are supporting.  If exec-only
-		 * pages are ever implemented, this will have to change.
-		 */
-		if (!PageReserved(page) && (pte_val(pte) & _PAGE_USER)
-		    && !test_bit(PG_arch_1, &page->flags)) {
-			if (vma->vm_mm == current->active_mm) {
-				__flush_dcache_icache((void *) address);
-			} else
-				flush_dcache_icache_page(page);
-			set_bit(PG_arch_1, &page->flags);
-		}
-	}
-
-#ifdef CONFIG_PPC_STD_MMU
 	/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
 	if (!pte_young(pte) || address >= TASK_SIZE)
 		return;
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap_64.c
similarity index 64%
rename from arch/powerpc/mm/mmap.c
rename to arch/powerpc/mm/mmap_64.c
index 86010fc..0d957a4 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap_64.c
@@ -24,16 +24,57 @@
 
 #include <linux/personality.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 #include <linux/sched.h>
 
 /*
  * Top of mmap area (just below the process stack).
  *
- * Leave an at least ~128 MB hole.
+ * Leave at least a ~128 MB hole on 32bit applications.
+ *
+ * On 64bit applications we randomise the stack by 1GB so we need to
+ * space our mmap start address by a further 1GB, otherwise there is a
+ * chance the mmap area will end up closer to the stack than our ulimit
+ * requires.
  */
-#define MIN_GAP (128*1024*1024)
+#define MIN_GAP32 (128*1024*1024)
+#define MIN_GAP64 ((128 + 1024)*1024*1024UL)
+#define MIN_GAP ((is_32bit_task()) ? MIN_GAP32 : MIN_GAP64)
 #define MAX_GAP (TASK_SIZE/6*5)
 
+static inline int mmap_is_legacy(void)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
+		return 1;
+
+	return sysctl_legacy_va_layout;
+}
+
+/*
+ * Since get_random_int() returns the same value within a 1 jiffy window,
+ * we will almost always get the same randomisation for the stack and mmap
+ * region. This will mean the relative distance between stack and mmap will
+ * be the same.
+ *
+ * To avoid this we can shift the randomness by 1 bit.
+ */
+static unsigned long mmap_rnd(void)
+{
+	unsigned long rnd = 0;
+
+	if (current->flags & PF_RANDOMIZE) {
+		/* 8MB for 32bit, 1GB for 64bit */
+		if (is_32bit_task())
+			rnd = (long)(get_random_int() % (1<<(22-PAGE_SHIFT)));
+		else
+			rnd = (long)(get_random_int() % (1<<(29-PAGE_SHIFT)));
+	}
+	return (rnd << PAGE_SHIFT) * 2;
+}
+
 static inline unsigned long mmap_base(void)
 {
 	unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
@@ -43,24 +84,7 @@
 	else if (gap > MAX_GAP)
 		gap = MAX_GAP;
 
-	return TASK_SIZE - (gap & PAGE_MASK);
-}
-
-static inline int mmap_is_legacy(void)
-{
-	/*
-	 * Force standard allocation for 64 bit programs.
-	 */
-	if (!test_thread_flag(TIF_32BIT))
-		return 1;
-
-	if (current->personality & ADDR_COMPAT_LAYOUT)
-		return 1;
-
-	if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
-		return 1;
-
-	return sysctl_legacy_va_layout;
+	return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd());
 }
 
 /*
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index 52a0cfc..a70e311 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -97,7 +97,7 @@
 		mm->context.id = MMU_NO_CONTEXT;
 
 		/* Mark it stale on all CPUs that used this mm */
-		for_each_cpu_mask_nr(cpu, mm->cpu_vm_mask)
+		for_each_cpu(cpu, mm_cpumask(mm))
 			__set_bit(id, stale_map[cpu]);
 		return id;
 	}
@@ -380,7 +380,7 @@
 #endif
 
 	printk(KERN_INFO
-	       "MMU: Allocated %d bytes of context maps for %d contexts\n",
+	       "MMU: Allocated %zu bytes of context maps for %d contexts\n",
 	       2 * CTX_MAP_SIZE + (sizeof(void *) * (last_context + 1)),
 	       last_context - first_context + 1);
 
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 5ac08b8..9047145 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -158,35 +158,6 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
-{
-	unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
-	struct device_node *cpu_node = NULL;
-	const unsigned int *interrupt_server, *reg;
-	int len;
-
-	while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) {
-		/* Try interrupt server first */
-		interrupt_server = of_get_property(cpu_node,
-					"ibm,ppc-interrupt-server#s", &len);
-
-		len = len / sizeof(u32);
-
-		if (interrupt_server && (len > 0)) {
-			while (len--) {
-				if (interrupt_server[len] == hw_cpuid)
-					return cpu_node;
-			}
-		} else {
-			reg = of_get_property(cpu_node, "reg", &len);
-			if (reg && (len > 0) && (reg[0] == hw_cpuid))
-				return cpu_node;
-		}
-	}
-
-	return NULL;
-}
-
 /* must hold reference to node during call */
 static const int *of_get_associativity(struct device_node *dev)
 {
@@ -290,7 +261,7 @@
 	ref_points = of_get_property(rtas_root,
 			"ibm,associativity-reference-points", &len);
 
-	if ((len >= 1) && ref_points) {
+	if ((len >= 2 * sizeof(unsigned int)) && ref_points) {
 		depth = ref_points[1];
 	} else {
 		dbg("NUMA: ibm,associativity-reference-points not found.\n");
@@ -470,7 +441,7 @@
 static int __cpuinit numa_setup_cpu(unsigned long lcpu)
 {
 	int nid = 0;
-	struct device_node *cpu = find_cpu_node(lcpu);
+	struct device_node *cpu = of_get_cpu_node(lcpu, NULL);
 
 	if (!cpu) {
 		WARN_ON(1);
@@ -652,7 +623,7 @@
 	for_each_present_cpu(i) {
 		int nid;
 
-		cpu = find_cpu_node(i);
+		cpu = of_get_cpu_node(i, NULL);
 		BUG_ON(!cpu);
 		nid = of_node_to_nid_single(cpu);
 		of_node_put(cpu);
@@ -1041,57 +1012,32 @@
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
- * Validate the node associated with the memory section we are
- * trying to add.
- */
-int valid_hot_add_scn(int *nid, unsigned long start, u32 lmb_size,
-		      unsigned long scn_addr)
-{
-	nodemask_t nodes;
-
-	if (*nid < 0 || !node_online(*nid))
-		*nid = any_online_node(NODE_MASK_ALL);
-
-	if ((scn_addr >= start) && (scn_addr < (start + lmb_size))) {
-		nodes_setall(nodes);
-		while (NODE_DATA(*nid)->node_spanned_pages == 0) {
-			node_clear(*nid, nodes);
-			*nid = any_online_node(nodes);
-		}
-
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- * Find the node associated with a hot added memory section represented
- * by the ibm,dynamic-reconfiguration-memory node.
+ * Find the node associated with a hot added memory section for
+ * memory represented in the device tree by the property
+ * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory.
  */
 static int hot_add_drconf_scn_to_nid(struct device_node *memory,
 				     unsigned long scn_addr)
 {
 	const u32 *dm;
-	unsigned int n, rc;
+	unsigned int drconf_cell_cnt, rc;
 	unsigned long lmb_size;
-	int default_nid = any_online_node(NODE_MASK_ALL);
-	int nid;
 	struct assoc_arrays aa;
+	int nid = -1;
 
-	n = of_get_drconf_memory(memory, &dm);
-	if (!n)
-		return default_nid;;
+	drconf_cell_cnt = of_get_drconf_memory(memory, &dm);
+	if (!drconf_cell_cnt)
+		return -1;
 
 	lmb_size = of_get_lmb_size(memory);
 	if (!lmb_size)
-		return default_nid;
+		return -1;
 
 	rc = of_get_assoc_arrays(memory, &aa);
 	if (rc)
-		return default_nid;
+		return -1;
 
-	for (; n != 0; --n) {
+	for (; drconf_cell_cnt != 0; --drconf_cell_cnt) {
 		struct of_drconf_cell drmem;
 
 		read_drconf_cell(&drmem, &dm);
@@ -1102,36 +1048,26 @@
 		    || !(drmem.flags & DRCONF_MEM_ASSIGNED))
 			continue;
 
-		nid = of_drconf_to_nid_single(&drmem, &aa);
+		if ((scn_addr < drmem.base_addr)
+		    || (scn_addr >= (drmem.base_addr + lmb_size)))
+			continue;
 
-		if (valid_hot_add_scn(&nid, drmem.base_addr, lmb_size,
-				      scn_addr))
-			return nid;
+		nid = of_drconf_to_nid_single(&drmem, &aa);
+		break;
 	}
 
-	BUG();	/* section address should be found above */
-	return 0;
+	return nid;
 }
 
 /*
- * Find the node associated with a hot added memory section.  Section
- * corresponds to a SPARSEMEM section, not an LMB.  It is assumed that
- * sections are fully contained within a single LMB.
+ * Find the node associated with a hot added memory section for memory
+ * represented in the device tree as a node (i.e. memory@XXXX) for
+ * each lmb.
  */
-int hot_add_scn_to_nid(unsigned long scn_addr)
+int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
 	struct device_node *memory = NULL;
-	int nid;
-
-	if (!numa_enabled || (min_common_depth < 0))
-		return any_online_node(NODE_MASK_ALL);
-
-	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
-	if (memory) {
-		nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
-		of_node_put(memory);
-		return nid;
-	}
+	int nid = -1;
 
 	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
 		unsigned long start, size;
@@ -1145,20 +1081,62 @@
 
 		/* ranges in cell */
 		ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
-ha_new_range:
-		start = read_n_cells(n_mem_addr_cells, &memcell_buf);
-		size = read_n_cells(n_mem_size_cells, &memcell_buf);
-		nid = of_node_to_nid_single(memory);
 
-		if (valid_hot_add_scn(&nid, start, size, scn_addr)) {
-			of_node_put(memory);
-			return nid;
+		while (ranges--) {
+			start = read_n_cells(n_mem_addr_cells, &memcell_buf);
+			size = read_n_cells(n_mem_size_cells, &memcell_buf);
+
+			if ((scn_addr < start) || (scn_addr >= (start + size)))
+				continue;
+
+			nid = of_node_to_nid_single(memory);
+			break;
 		}
 
-		if (--ranges)		/* process all ranges in cell */
-			goto ha_new_range;
+		of_node_put(memory);
+		if (nid >= 0)
+			break;
 	}
-	BUG();	/* section address should be found above */
-	return 0;
+
+	return nid;
 }
+
+/*
+ * Find the node associated with a hot added memory section.  Section
+ * corresponds to a SPARSEMEM section, not an LMB.  It is assumed that
+ * sections are fully contained within a single LMB.
+ */
+int hot_add_scn_to_nid(unsigned long scn_addr)
+{
+	struct device_node *memory = NULL;
+	int nid, found = 0;
+
+	if (!numa_enabled || (min_common_depth < 0))
+		return any_online_node(NODE_MASK_ALL);
+
+	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (memory) {
+		nid = hot_add_drconf_scn_to_nid(memory, scn_addr);
+		of_node_put(memory);
+	} else {
+		nid = hot_add_node_scn_to_nid(scn_addr);
+	}
+
+	if (nid < 0 || !node_online(nid))
+		nid = any_online_node(NODE_MASK_ALL);
+
+	if (NODE_DATA(nid)->node_spanned_pages)
+		return nid;
+
+	for_each_online_node(nid) {
+		if (NODE_DATA(nid)->node_spanned_pages) {
+			found = 1;
+			break;
+		}
+	}
+
+	BUG_ON(!found);
+	return nid;
+}
+
 #endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 6d94116..f5c6fd4 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -1,5 +1,6 @@
 /*
  * This file contains common routines for dealing with free of page tables
+ * Along with common page table handling code
  *
  *  Derived from arch/powerpc/mm/tlb_64.c:
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -81,11 +82,10 @@
 void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
 {
 	/* This is safe since tlb_gather_mmu has disabled preemption */
-        cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
 	struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
 
 	if (atomic_read(&tlb->mm->mm_users) < 2 ||
-	    cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
+	    cpumask_equal(mm_cpumask(tlb->mm), cpumask_of(smp_processor_id()))){
 		pgtable_free(pgf);
 		return;
 	}
@@ -115,3 +115,133 @@
 	pte_free_submit(*batchp);
 	*batchp = NULL;
 }
+
+/*
+ * Handle i/d cache flushing, called from set_pte_at() or ptep_set_access_flags()
+ */
+static pte_t do_dcache_icache_coherency(pte_t pte)
+{
+	unsigned long pfn = pte_pfn(pte);
+	struct page *page;
+
+	if (unlikely(!pfn_valid(pfn)))
+		return pte;
+	page = pfn_to_page(pfn);
+
+	if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
+		pr_debug("do_dcache_icache_coherency... flushing\n");
+		flush_dcache_icache_page(page);
+		set_bit(PG_arch_1, &page->flags);
+	}
+	else
+		pr_debug("do_dcache_icache_coherency... already clean\n");
+	return __pte(pte_val(pte) | _PAGE_HWEXEC);
+}
+
+static inline int is_exec_fault(void)
+{
+	return current->thread.regs && TRAP(current->thread.regs) == 0x400;
+}
+
+/* We only try to do i/d cache coherency on stuff that looks like
+ * reasonably "normal" PTEs. We currently require a PTE to be present
+ * and we avoid _PAGE_SPECIAL and _PAGE_NO_CACHE
+ */
+static inline int pte_looks_normal(pte_t pte)
+{
+	return (pte_val(pte) &
+		(_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE)) ==
+		(_PAGE_PRESENT);
+}
+
+#if defined(CONFIG_PPC_STD_MMU)
+/* Server-style MMU handles coherency when hashing if HW exec permission
+ * is supposed per page (currently 64-bit only). Else, we always flush
+ * valid PTEs in set_pte.
+ */
+static inline int pte_need_exec_flush(pte_t pte, int set_pte)
+{
+	return set_pte && pte_looks_normal(pte) &&
+		!(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) ||
+		  cpu_has_feature(CPU_FTR_NOEXECUTE));
+}
+#elif _PAGE_HWEXEC == 0
+/* Embedded type MMU without HW exec support (8xx only so far), we flush
+ * the cache for any present PTE
+ */
+static inline int pte_need_exec_flush(pte_t pte, int set_pte)
+{
+	return set_pte && pte_looks_normal(pte);
+}
+#else
+/* Other embedded CPUs with HW exec support per-page, we flush on exec
+ * fault if HWEXEC is not set
+ */
+static inline int pte_need_exec_flush(pte_t pte, int set_pte)
+{
+	return pte_looks_normal(pte) && is_exec_fault() &&
+		!(pte_val(pte) & _PAGE_HWEXEC);
+}
+#endif
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ */
+void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+#ifdef CONFIG_DEBUG_VM
+	WARN_ON(pte_present(*ptep));
+#endif
+	/* Note: mm->context.id might not yet have been assigned as
+	 * this context might not have been activated yet when this
+	 * is called.
+	 */
+	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
+	if (pte_need_exec_flush(pte, 1))
+		pte = do_dcache_icache_coherency(pte);
+
+	/* Perform the setting of the PTE */
+	__set_pte_at(mm, addr, ptep, pte, 0);
+}
+
+/*
+ * This is called when relaxing access to a PTE. It's also called in the page
+ * fault path when we don't hit any of the major fault cases, ie, a minor
+ * update of _PAGE_ACCESSED, _PAGE_DIRTY, etc... The generic code will have
+ * handled those two for us, we additionally deal with missing execute
+ * permission here on some processors
+ */
+int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+			  pte_t *ptep, pte_t entry, int dirty)
+{
+	int changed;
+	if (!dirty && pte_need_exec_flush(entry, 0))
+		entry = do_dcache_icache_coherency(entry);
+	changed = !pte_same(*(ptep), entry);
+	if (changed) {
+		assert_pte_locked(vma->vm_mm, address);
+		__ptep_set_access_flags(ptep, entry);
+		flush_tlb_page_nohash(vma, address);
+	}
+	return changed;
+}
+
+#ifdef CONFIG_DEBUG_VM
+void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	if (mm == &init_mm)
+		return;
+	pgd = mm->pgd + pgd_index(addr);
+	BUG_ON(pgd_none(*pgd));
+	pud = pud_offset(pgd, addr);
+	BUG_ON(pud_none(*pud));
+	pmd = pmd_offset(pud, addr);
+	BUG_ON(!pmd_present(*pmd));
+	BUG_ON(!spin_is_locked(pte_lockptr(mm, pmd)));
+}
+#endif /* CONFIG_DEBUG_VM */
+
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 58bcaeb..430d090 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -129,7 +129,8 @@
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
 {
-	return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
+	return __ioremap_caller(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED,
+				__builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap);
 
@@ -143,20 +144,27 @@
 	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
 	flags &= ~(_PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC);
 
-	return __ioremap(addr, size, flags);
+	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap_flags);
 
 void __iomem *
 __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
 {
+	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
+}
+
+void __iomem *
+__ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
+		 void *caller)
+{
 	unsigned long v, i;
 	phys_addr_t p;
 	int err;
 
 	/* Make sure we have the base flags */
 	if ((flags & _PAGE_PRESENT) == 0)
-		flags |= _PAGE_KERNEL;
+		flags |= PAGE_KERNEL;
 
 	/* Non-cacheable page cannot be coherent */
 	if (flags & _PAGE_NO_CACHE)
@@ -212,7 +220,7 @@
 
 	if (mem_init_done) {
 		struct vm_struct *area;
-		area = get_vm_area(size, VM_IOREMAP);
+		area = get_vm_area_caller(size, VM_IOREMAP, caller);
 		if (area == 0)
 			return NULL;
 		v = (unsigned long) area->addr;
@@ -288,7 +296,7 @@
 	p = memstart_addr + s;
 	for (; s < total_lowmem; s += PAGE_SIZE) {
 		ktext = ((char *) v >= _stext && (char *) v < etext);
-		f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM;
+		f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
 		map_page(v, p, f);
 #ifdef CONFIG_PPC_STD_MMU_32
 		if (ktext)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 365e61a..bfa7db6 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -144,8 +144,8 @@
 	unmap_kernel_range((unsigned long)ea, size);
 }
 
-void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
-			 unsigned long flags)
+void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
+				unsigned long flags, void *caller)
 {
 	phys_addr_t paligned;
 	void __iomem *ret;
@@ -168,8 +168,9 @@
 	if (mem_init_done) {
 		struct vm_struct *area;
 
-		area = __get_vm_area(size, VM_IOREMAP,
-				     ioremap_bot, IOREMAP_END);
+		area = __get_vm_area_caller(size, VM_IOREMAP,
+					    ioremap_bot, IOREMAP_END,
+					    caller);
 		if (area == NULL)
 			return NULL;
 		ret = __ioremap_at(paligned, area->addr, size, flags);
@@ -186,19 +187,27 @@
 	return ret;
 }
 
+void __iomem * __ioremap(phys_addr_t addr, unsigned long size,
+			 unsigned long flags)
+{
+	return __ioremap_caller(addr, size, flags, __builtin_return_address(0));
+}
 
 void __iomem * ioremap(phys_addr_t addr, unsigned long size)
 {
 	unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
+	void *caller = __builtin_return_address(0);
 
 	if (ppc_md.ioremap)
-		return ppc_md.ioremap(addr, size, flags);
-	return __ioremap(addr, size, flags);
+		return ppc_md.ioremap(addr, size, flags, caller);
+	return __ioremap_caller(addr, size, flags, caller);
 }
 
 void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size,
 			     unsigned long flags)
 {
+	void *caller = __builtin_return_address(0);
+
 	/* writeable implies dirty for kernel addresses */
 	if (flags & _PAGE_RW)
 		flags |= _PAGE_DIRTY;
@@ -207,8 +216,8 @@
 	flags &= ~(_PAGE_USER | _PAGE_EXEC);
 
 	if (ppc_md.ioremap)
-		return ppc_md.ioremap(addr, size, flags);
-	return __ioremap(addr, size, flags);
+		return ppc_md.ioremap(addr, size, flags, caller);
+	return __ioremap_caller(addr, size, flags, caller);
 }
 
 
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index fe65c40..2d2a87e 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -74,9 +74,6 @@
 
 unsigned long __init mmu_mapin_ram(void)
 {
-#ifdef CONFIG_POWER4
-	return 0;
-#else
 	unsigned long tot, bl, done;
 	unsigned long max_size = (256<<20);
 
@@ -95,7 +92,7 @@
 			break;
 	}
 
-	setbat(2, PAGE_OFFSET, 0, bl, _PAGE_RAM);
+	setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
 	done = (unsigned long)bat_addrs[2].limit - PAGE_OFFSET + 1;
 	if ((done < tot) && !bat_addrs[3].limit) {
 		/* use BAT3 to cover a bit more */
@@ -103,12 +100,11 @@
 		for (bl = 128<<10; bl < max_size; bl <<= 1)
 			if (bl * 2 > tot)
 				break;
-		setbat(3, PAGE_OFFSET+done, done, bl, _PAGE_RAM);
+		setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
 		done = (unsigned long)bat_addrs[3].limit - PAGE_OFFSET + 1;
 	}
 
 	return done;
-#endif
 }
 
 /*
@@ -136,9 +132,7 @@
 		wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
 		bat[1].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
 		bat[1].batl = BAT_PHYS_ADDR(phys) | wimgxpp;
-#ifndef CONFIG_KGDB /* want user access for breakpoints */
 		if (flags & _PAGE_USER)
-#endif
 			bat[1].batu |= 1; 	/* Vp = 1 */
 		if (flags & _PAGE_GUARDED) {
 			/* G bit must be zero in IBATs */
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index c931bc7..1be1b5e 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -139,12 +139,12 @@
  */
 void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
 {
-	cpumask_t tmp;
+	const struct cpumask *tmp;
 	int i, local = 0;
 
 	i = batch->index;
-	tmp = cpumask_of_cpu(smp_processor_id());
-	if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
+	tmp = cpumask_of(smp_processor_id());
+	if (cpumask_equal(mm_cpumask(batch->mm), tmp))
 		local = 1;
 	if (i == 1)
 		flush_hash_page(batch->vaddr[0], batch->pte[0],
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 39ac22b..7af7297 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -132,11 +132,11 @@
 	pid = mm->context.id;
 	if (unlikely(pid == MMU_NO_CONTEXT))
 		goto no_context;
-	cpu_mask = mm->cpu_vm_mask;
-	cpu_clear(smp_processor_id(), cpu_mask);
-	if (!cpus_empty(cpu_mask)) {
+	if (!cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
 		struct tlb_flush_param p = { .pid = pid };
-		smp_call_function_mask(cpu_mask, do_flush_tlb_mm_ipi, &p, 1);
+		/* Ignores smp_processor_id() even if set. */
+		smp_call_function_many(mm_cpumask(mm),
+				       do_flush_tlb_mm_ipi, &p, 1);
 	}
 	_tlbil_pid(pid);
  no_context:
@@ -146,16 +146,15 @@
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
-	cpumask_t cpu_mask;
+	struct cpumask *cpu_mask;
 	unsigned int pid;
 
 	preempt_disable();
 	pid = vma ? vma->vm_mm->context.id : 0;
 	if (unlikely(pid == MMU_NO_CONTEXT))
 		goto bail;
-	cpu_mask = vma->vm_mm->cpu_vm_mask;
-	cpu_clear(smp_processor_id(), cpu_mask);
-	if (!cpus_empty(cpu_mask)) {
+	cpu_mask = mm_cpumask(vma->vm_mm);
+	if (!cpumask_equal(cpu_mask, cpumask_of(smp_processor_id()))) {
 		/* If broadcast tlbivax is supported, use it */
 		if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) {
 			int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL);
@@ -167,7 +166,8 @@
 			goto bail;
 		} else {
 			struct tlb_flush_param p = { .pid = pid, .addr = vmaddr };
-			smp_call_function_mask(cpu_mask,
+			/* Ignores smp_processor_id() even if set in cpu_mask */
+			smp_call_function_many(cpu_mask,
 					       do_flush_tlb_page_ipi, &p, 1);
 		}
 	}
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index f900a39..788b87c 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -118,25 +118,50 @@
 
 #elif defined(CONFIG_FSL_BOOKE)
 /*
- * FSL BookE implementations. Currently _pid and _all are the
- * same. This will change when tlbilx is actually supported and
- * performs invalidate-by-PID. This change will be driven by
- * mmu_features conditional
+ * FSL BookE implementations.
+ *
+ * Since feature sections are using _SECTION_ELSE we need
+ * to have the larger code path before the _SECTION_ELSE
  */
 
+#define MMUCSR0_TLBFI	(MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
+			 MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
 /*
  * Flush MMU TLB on the local processor
  */
-_GLOBAL(_tlbil_pid)
 _GLOBAL(_tlbil_all)
-#define MMUCSR0_TLBFI	(MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
-			 MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
+BEGIN_MMU_FTR_SECTION
 	li	r3,(MMUCSR0_TLBFI)@l
 	mtspr	SPRN_MMUCSR0, r3
 1:
 	mfspr	r3,SPRN_MMUCSR0
 	andi.	r3,r3,MMUCSR0_TLBFI@l
 	bne	1b
+MMU_FTR_SECTION_ELSE
+	PPC_TLBILX_ALL(0,0)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
+	msync
+	isync
+	blr
+
+_GLOBAL(_tlbil_pid)
+BEGIN_MMU_FTR_SECTION
+	slwi	r3,r3,16
+	mfmsr	r10
+	wrteei	0
+	mfspr	r4,SPRN_MAS6	/* save MAS6 */
+	mtspr	SPRN_MAS6,r3
+	PPC_TLBILX_PID(0,0)
+	mtspr	SPRN_MAS6,r4	/* restore MAS6 */
+	wrtee	r10
+MMU_FTR_SECTION_ELSE
+	li	r3,(MMUCSR0_TLBFI)@l
+	mtspr	SPRN_MMUCSR0, r3
+1:
+	mfspr	r3,SPRN_MMUCSR0
+	andi.	r3,r3,MMUCSR0_TLBFI@l
+	bne	1b
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBILX)
 	msync
 	isync
 	blr
@@ -149,7 +174,9 @@
 	mfmsr	r10
 	wrteei	0
 	slwi	r4,r4,16
+	ori	r4,r4,(MAS6_ISIZE(BOOK3E_PAGESZ_4K))@l
 	mtspr	SPRN_MAS6,r4		/* assume AS=0 for now */
+BEGIN_MMU_FTR_SECTION
 	tlbsx	0,r3
 	mfspr	r4,SPRN_MAS1		/* check valid */
 	andis.	r3,r4,MAS1_VALID@h
@@ -157,6 +184,9 @@
 	rlwinm	r4,r4,0,1,31
 	mtspr	SPRN_MAS1,r4
 	tlbwe
+MMU_FTR_SECTION_ELSE
+	PPC_TLBILX_VA(0,r3)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
 	msync
 	isync
 1:	wrtee	r10
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c
index cc599eb..f8d36f9 100644
--- a/arch/powerpc/oprofile/op_model_7450.c
+++ b/arch/powerpc/oprofile/op_model_7450.c
@@ -29,7 +29,7 @@
 static unsigned long reset_value[OP_MAX_COUNTER];
 
 static int oprofile_running;
-static u32 mmcr0_val, mmcr1_val, mmcr2_val;
+static u32 mmcr0_val, mmcr1_val, mmcr2_val, num_pmcs;
 
 #define MMCR0_PMC1_SHIFT	6
 #define MMCR0_PMC2_SHIFT	0
@@ -88,13 +88,12 @@
 
 	mtspr(SPRN_MMCR0, mmcr0_val);
 	mtspr(SPRN_MMCR1, mmcr1_val);
-	mtspr(SPRN_MMCR2, mmcr2_val);
+	if (num_pmcs > 4)
+		mtspr(SPRN_MMCR2, mmcr2_val);
 
 	return 0;
 }
 
-#define NUM_CTRS 6
-
 /* Configures the global settings for the countes on all CPUs. */
 static int fsl7450_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
@@ -102,12 +101,13 @@
 {
 	int i;
 
+	num_pmcs = num_ctrs;
 	/* Our counters count up, and "count" refers to
 	 * how much before the next interrupt, and we interrupt
 	 * on overflow.  So we calculate the starting value
 	 * which will give us "count" until overflow.
 	 * Then we set the events on the enabled counters */
-	for (i = 0; i < NUM_CTRS; ++i)
+	for (i = 0; i < num_ctrs; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
 	/* Set events for Counters 1 & 2 */
@@ -123,9 +123,10 @@
 
 	/* Set events for Counters 3-6 */
 	mmcr1_val = mmcr1_event3(ctr[2].event)
-		| mmcr1_event4(ctr[3].event)
-		| mmcr1_event5(ctr[4].event)
-		| mmcr1_event6(ctr[5].event);
+		| mmcr1_event4(ctr[3].event);
+	if (num_ctrs > 4)
+		mmcr1_val |= mmcr1_event5(ctr[4].event)
+			| mmcr1_event6(ctr[5].event);
 
 	mmcr2_val = 0;
 
@@ -139,7 +140,7 @@
 
 	mtmsr(mfmsr() | MSR_PMM);
 
-	for (i = 0; i < NUM_CTRS; ++i) {
+	for (i = 0; i < num_pmcs; ++i) {
 		if (ctr[i].enabled)
 			classic_ctr_write(i, reset_value[i]);
 		else
@@ -184,7 +185,7 @@
 	pc = mfspr(SPRN_SIAR);
 	is_kernel = is_kernel_addr(pc);
 
-	for (i = 0; i < NUM_CTRS; ++i) {
+	for (i = 0; i < num_pmcs; ++i) {
 		val = classic_ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 3496bc0..bf5c7ff 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -118,6 +118,17 @@
 	help
 	  This option enables support for the AMCC PPC460GT evaluation board.
 
+config REDWOOD
+	bool "Redwood"
+	depends on 44x
+	default n
+	select PPC44x_SIMPLE
+	select 460SX
+	select PCI
+	select PPC4xx_PCI_EXPRESS
+	help
+	  This option enables support for the AMCC PPC460SX Redwood board.
+
 config YOSEMITE
 	bool "Yosemite"
 	depends on 44x
@@ -220,6 +231,14 @@
 	select IBM_NEW_EMAC_EMAC4
 	select IBM_NEW_EMAC_TAH
 
+config 460SX
+	bool
+	select PPC_FPU
+	select IBM_NEW_EMAC_EMAC4
+	select IBM_NEW_EMAC_RGMII
+	select IBM_NEW_EMAC_ZMII
+	select IBM_NEW_EMAC_TAH
+
 # 44x errata/workaround config symbols, selected by the CPU models above
 config IBM440EP_ERR42
 	bool
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 76fdc51..5bcd441 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -57,6 +57,7 @@
 	"ibm,ebony",
 	"amcc,katmai",
 	"amcc,rainier",
+	"amcc,redwood",
 	"amcc,sequoia",
 	"amcc,taishan",
 	"amcc,yosemite"
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index 326852c..4dac9b0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -12,7 +12,7 @@
 
 config MPC5121_ADS
 	bool "Freescale MPC5121E ADS"
-	depends on PPC_MULTIPLATFORM && PPC32
+	depends on 6xx
 	select DEFAULT_UIMAGE
 	select PPC_MPC5121
 	select MPC5121_ADS_CPLD
@@ -21,7 +21,7 @@
 
 config MPC5121_GENERIC
 	bool "Generic support for simple MPC5121 based boards"
-	depends on PPC_MULTIPLATFORM && PPC32
+	depends on 6xx
 	select DEFAULT_UIMAGE
 	select PPC_MPC5121
 	help
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 696a5ee..8b8e956 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -1,6 +1,6 @@
 config PPC_MPC52xx
 	bool "52xx-based boards"
-	depends on PPC_MULTIPLATFORM && PPC32
+	depends on 6xx
 	select PPC_CLOCK
 	select PPC_PCI_CHOICE
 
@@ -21,7 +21,13 @@
 	    and if there is a PCI bus node defined in the device tree.
 
 	  Boards that are compatible with this generic platform support
-	  are: 'tqc,tqm5200', 'promess,motionpro', 'schindler,cm5200'.
+	  are:
+	     intercontrol,digsy-mtc
+	     phytec,pcm030
+	     phytec,pcm032
+	     promess,motionpro
+	     schindler,cm5200
+	     tqc,tqm5200
 
 config PPC_EFIKA
 	bool "bPlan Efika 5k2. MPC5200B based computer"
@@ -35,6 +41,11 @@
 	depends on PPC_MPC52xx
 	select DEFAULT_UIMAGE
 
+config PPC_MEDIA5200
+	bool "Freescale Media5200 Eval Board"
+	depends on PPC_MPC52xx
+	select DEFAULT_UIMAGE
+
 config PPC_MPC5200_BUGFIX
 	bool "MPC5200 (L25R) bugfix support"
 	depends on PPC_MPC52xx
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index b8a5206..bfd4f52 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -1,12 +1,13 @@
 #
 # Makefile for 52xx based boards
 #
-obj-y				+= mpc52xx_pic.o mpc52xx_common.o
+obj-y				+= mpc52xx_pic.o mpc52xx_common.o mpc52xx_gpt.o
 obj-$(CONFIG_PCI)		+= mpc52xx_pci.o
 
 obj-$(CONFIG_PPC_MPC5200_SIMPLE) += mpc5200_simple.o
 obj-$(CONFIG_PPC_EFIKA)		+= efika.o
 obj-$(CONFIG_PPC_LITE5200)	+= lite5200.o
+obj-$(CONFIG_PPC_MEDIA5200)	+= media5200.o
 
 obj-$(CONFIG_PM)		+= mpc52xx_sleep.o mpc52xx_pm.o
 ifeq ($(CONFIG_PPC_LITE5200),y)
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
new file mode 100644
index 0000000..68e4f16
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -0,0 +1,273 @@
+/*
+ * Support for 'media5200-platform' compatible boards.
+ *
+ * Copyright (C) 2008 Secret Lab Technologies 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.
+ *
+ * Description:
+ * This code implements support for the Freescape Media5200 platform
+ * (built around the MPC5200 SoC).
+ *
+ * Notable characteristic of the Media5200 is the presence of an FPGA
+ * that has all external IRQ lines routed through it.  This file implements
+ * a cascaded interrupt controller driver which attaches itself to the
+ * Virtual IRQ subsystem after the primary mpc5200 interrupt controller
+ * is initialized.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/time.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/mpc52xx.h>
+
+static struct of_device_id mpc5200_gpio_ids[] __initdata = {
+	{ .compatible = "fsl,mpc5200-gpio", },
+	{ .compatible = "mpc5200-gpio", },
+	{}
+};
+
+/* FPGA register set */
+#define MEDIA5200_IRQ_ENABLE (0x40c)
+#define MEDIA5200_IRQ_STATUS (0x410)
+#define MEDIA5200_NUM_IRQS   (6)
+#define MEDIA5200_IRQ_SHIFT  (32 - MEDIA5200_NUM_IRQS)
+
+struct media5200_irq {
+	void __iomem *regs;
+	spinlock_t lock;
+	struct irq_host *irqhost;
+};
+struct media5200_irq media5200_irq;
+
+static void media5200_irq_unmask(unsigned int virq)
+{
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&media5200_irq.lock, flags);
+	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
+	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq);
+	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
+	spin_unlock_irqrestore(&media5200_irq.lock, flags);
+}
+
+static void media5200_irq_mask(unsigned int virq)
+{
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&media5200_irq.lock, flags);
+	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
+	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq));
+	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
+	spin_unlock_irqrestore(&media5200_irq.lock, flags);
+}
+
+static struct irq_chip media5200_irq_chip = {
+	.typename = "Media5200 FPGA",
+	.unmask = media5200_irq_unmask,
+	.mask = media5200_irq_mask,
+	.mask_ack = media5200_irq_mask,
+};
+
+void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
+{
+	int sub_virq, val;
+	u32 status, enable;
+
+	/* Mask off the cascaded IRQ */
+	spin_lock(&desc->lock);
+	desc->chip->mask(virq);
+	spin_unlock(&desc->lock);
+
+	/* Ask the FPGA for IRQ status.  If 'val' is 0, then no irqs
+	 * are pending.  'ffs()' is 1 based */
+	status = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
+	enable = in_be32(media5200_irq.regs + MEDIA5200_IRQ_STATUS);
+	val = ffs((status & enable) >> MEDIA5200_IRQ_SHIFT);
+	if (val) {
+		sub_virq = irq_linear_revmap(media5200_irq.irqhost, val - 1);
+		/* pr_debug("%s: virq=%i s=%.8x e=%.8x hwirq=%i subvirq=%i\n",
+		 *          __func__, virq, status, enable, val - 1, sub_virq);
+		 */
+		generic_handle_irq(sub_virq);
+	}
+
+	/* Processing done; can reenable the cascade now */
+	spin_lock(&desc->lock);
+	desc->chip->ack(virq);
+	if (!(desc->status & IRQ_DISABLED))
+		desc->chip->unmask(virq);
+	spin_unlock(&desc->lock);
+}
+
+static int media5200_irq_map(struct irq_host *h, unsigned int virq,
+			     irq_hw_number_t hw)
+{
+	struct irq_desc *desc = get_irq_desc(virq);
+
+	pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw);
+	set_irq_chip_data(virq, &media5200_irq);
+	set_irq_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
+	set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+	desc->status |= IRQ_TYPE_LEVEL_LOW | IRQ_LEVEL;
+
+	return 0;
+}
+
+static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct,
+				 u32 *intspec, unsigned int intsize,
+				 irq_hw_number_t *out_hwirq,
+				 unsigned int *out_flags)
+{
+	if (intsize != 2)
+		return -1;
+
+	pr_debug("%s: bank=%i, number=%i\n", __func__, intspec[0], intspec[1]);
+	*out_hwirq = intspec[1];
+	*out_flags = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_host_ops media5200_irq_ops = {
+	.map = media5200_irq_map,
+	.xlate = media5200_irq_xlate,
+};
+
+/*
+ * Setup Media5200 IRQ mapping
+ */
+static void __init media5200_init_irq(void)
+{
+	struct device_node *fpga_np;
+	int cascade_virq;
+
+	/* First setup the regular MPC5200 interrupt controller */
+	mpc52xx_init_irq();
+
+	/* Now find the FPGA IRQ */
+	fpga_np = of_find_compatible_node(NULL, NULL, "fsl,media5200-fpga");
+	if (!fpga_np)
+		goto out;
+	pr_debug("%s: found fpga node: %s\n", __func__, fpga_np->full_name);
+
+	media5200_irq.regs = of_iomap(fpga_np, 0);
+	if (!media5200_irq.regs)
+		goto out;
+	pr_debug("%s: mapped to %p\n", __func__, media5200_irq.regs);
+
+	cascade_virq = irq_of_parse_and_map(fpga_np, 0);
+	if (!cascade_virq)
+		goto out;
+	pr_debug("%s: cascaded on virq=%i\n", __func__, cascade_virq);
+
+	/* Disable all FPGA IRQs */
+	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, 0);
+
+	spin_lock_init(&media5200_irq.lock);
+
+	media5200_irq.irqhost = irq_alloc_host(fpga_np, IRQ_HOST_MAP_LINEAR,
+					       MEDIA5200_NUM_IRQS,
+					       &media5200_irq_ops, -1);
+	if (!media5200_irq.irqhost)
+		goto out;
+	pr_debug("%s: allocated irqhost\n", __func__);
+
+	media5200_irq.irqhost->host_data = &media5200_irq;
+
+	set_irq_data(cascade_virq, &media5200_irq);
+	set_irq_chained_handler(cascade_virq, media5200_irq_cascade);
+
+	return;
+
+ out:
+	pr_err("Could not find Media5200 FPGA; PCI interrupts will not work\n");
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init media5200_setup_arch(void)
+{
+
+	struct device_node *np;
+	struct mpc52xx_gpio __iomem *gpio;
+	u32 port_config;
+
+	if (ppc_md.progress)
+		ppc_md.progress("media5200_setup_arch()", 0);
+
+	/* Map important registers from the internal memory map */
+	mpc52xx_map_common_devices();
+
+	/* Some mpc5200 & mpc5200b related configuration */
+	mpc5200_setup_xlb_arbiter();
+
+	mpc52xx_setup_pci();
+
+	np = of_find_matching_node(NULL, mpc5200_gpio_ids);
+	gpio = of_iomap(np, 0);
+	of_node_put(np);
+	if (!gpio) {
+		printk(KERN_ERR "%s() failed. expect abnormal behavior\n",
+		       __func__);
+		return;
+	}
+
+	/* Set port config */
+	port_config = in_be32(&gpio->port_config);
+
+	port_config &= ~0x03000000;	/* ATA CS is on csb_4/5		*/
+	port_config |=  0x01000000;
+
+	out_be32(&gpio->port_config, port_config);
+
+	/* Unmap zone */
+	iounmap(gpio);
+
+}
+
+/* list of the supported boards */
+static char *board[] __initdata = {
+	"fsl,media5200",
+	NULL
+};
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init media5200_probe(void)
+{
+	unsigned long node = of_get_flat_dt_root();
+	int i = 0;
+
+	while (board[i]) {
+		if (of_flat_dt_is_compatible(node, board[i]))
+			break;
+		i++;
+	}
+
+	return (board[i] != NULL);
+}
+
+define_machine(media5200_platform) {
+	.name		= "media5200-platform",
+	.probe		= media5200_probe,
+	.setup_arch	= media5200_setup_arch,
+	.init		= mpc52xx_declare_of_platform_devices,
+	.init_IRQ	= media5200_init_irq,
+	.get_irq	= mpc52xx_get_irq,
+	.restart	= mpc52xx_restart,
+	.calibrate_decr	= generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index a3bda0b..c31e5b5 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,8 +50,10 @@
 
 /* list of the supported boards */
 static char *board[] __initdata = {
-	"promess,motionpro",
+	"intercontrol,digsy-mtc",
 	"phytec,pcm030",
+	"phytec,pcm032",
+	"promess,motionpro",
 	"schindler,cm5200",
 	"tqc,tqm5200",
 	NULL
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 98367a0..8e3dd5a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -28,9 +28,10 @@
 static struct of_device_id mpc52xx_bus_ids[] __initdata = {
 	{ .compatible = "fsl,mpc5200-immr", },
 	{ .compatible = "fsl,mpc5200b-immr", },
-	{ .compatible = "fsl,lpb", },
+	{ .compatible = "simple-bus", },
 
 	/* depreciated matches; shouldn't be used in new device trees */
+	{ .compatible = "fsl,lpb", },
 	{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
 	{ .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
 	{}
@@ -205,6 +206,43 @@
 EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv);
 
 /**
+ * mpc52xx_get_xtal_freq - Get SYS_XTAL_IN frequency for a device
+ *
+ * @node: device node
+ *
+ * Returns the frequency of the external oscillator clock connected
+ * to the SYS_XTAL_IN pin, or 0 if it cannot be determined.
+ */
+unsigned int mpc52xx_get_xtal_freq(struct device_node *node)
+{
+	u32 val;
+	unsigned int freq;
+
+	if (!mpc52xx_cdm)
+		return 0;
+
+	freq = mpc52xx_find_ipb_freq(node);
+	if (!freq)
+		return 0;
+
+	if (in_8(&mpc52xx_cdm->ipb_clk_sel) & 0x1)
+		freq *= 2;
+
+	val  = in_be32(&mpc52xx_cdm->rstcfg);
+	if (val & (1 << 5))
+		freq *= 8;
+	else
+		freq *= 4;
+	if (val & (1 << 6))
+		freq /= 12;
+	else
+		freq /= 16;
+
+	return freq;
+}
+EXPORT_SYMBOL(mpc52xx_get_xtal_freq);
+
+/**
  * mpc52xx_restart: ppc_md->restart hook for mpc5200 using the watchdog timer
  */
 void
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
index 07f89ae..2b8d8ef 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
@@ -354,88 +354,6 @@
 	.remove = mpc52xx_gpiochip_remove,
 };
 
-/*
- * GPIO LIB API implementation for gpt GPIOs.
- *
- * Each gpt only has a single GPIO.
- */
-static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
-
-	return (in_be32(&regs->status) & (1 << (31 - 23))) ? 1 : 0;
-}
-
-static void
-mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
-
-	if (val)
-		out_be32(&regs->mode, 0x34);
-	else
-		out_be32(&regs->mode, 0x24);
-
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
-
-	out_be32(&regs->mode, 0x04);
-
-	return 0;
-}
-
-static int
-mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	mpc52xx_gpt_gpio_set(gc, gpio, val);
-	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
-	return 0;
-}
-
-static int __devinit mpc52xx_gpt_gpiochip_probe(struct of_device *ofdev,
-					const struct of_device_id *match)
-{
-	struct of_mm_gpio_chip *mmchip;
-	struct of_gpio_chip *chip;
-
-	mmchip = kzalloc(sizeof(*mmchip), GFP_KERNEL);
-	if (!mmchip)
-		return -ENOMEM;
-
-	chip = &mmchip->of_gc;
-
-	chip->gpio_cells          = 2;
-	chip->gc.ngpio            = 1;
-	chip->gc.direction_input  = mpc52xx_gpt_gpio_dir_in;
-	chip->gc.direction_output = mpc52xx_gpt_gpio_dir_out;
-	chip->gc.get              = mpc52xx_gpt_gpio_get;
-	chip->gc.set              = mpc52xx_gpt_gpio_set;
-
-	return of_mm_gpiochip_add(ofdev->node, mmchip);
-}
-
-static const struct of_device_id mpc52xx_gpt_gpiochip_match[] = {
-	{
-		.compatible = "fsl,mpc5200-gpt-gpio",
-	},
-	{}
-};
-
-static struct of_platform_driver mpc52xx_gpt_gpiochip_driver = {
-	.name = "gpio_gpt",
-	.match_table = mpc52xx_gpt_gpiochip_match,
-	.probe = mpc52xx_gpt_gpiochip_probe,
-	.remove = mpc52xx_gpiochip_remove,
-};
-
 static int __init mpc52xx_gpio_init(void)
 {
 	if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver))
@@ -444,9 +362,6 @@
 	if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver))
 		printk(KERN_ERR "Unable to register simple GPIO driver\n");
 
-	if (of_register_platform_driver(&mpc52xx_gpt_gpiochip_driver))
-		printk(KERN_ERR "Unable to register gpt GPIO driver\n");
-
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
new file mode 100644
index 0000000..bfbcd41
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -0,0 +1,396 @@
+/*
+ * MPC5200 General Purpose Timer device driver
+ *
+ * Copyright (c) 2009 Secret Lab Technologies Ltd.
+ * Copyright (c) 2008 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This file is a driver for the the General Purpose Timer (gpt) devices
+ * found on the MPC5200 SoC.  Each timer has an IO pin which can be used
+ * for GPIO or can be used to raise interrupts.  The timer function can
+ * be used independently from the IO pin, or it can be used to control
+ * output signals or measure input signals.
+ *
+ * This driver supports the GPIO and IRQ controller functions of the GPT
+ * device.  Timer functions are not yet supported, nor is the watchdog
+ * timer.
+ *
+ * To use the GPIO function, the following two properties must be added
+ * to the device tree node for the gpt device (typically in the .dts file
+ * for the board):
+ * 	gpio-controller;
+ * 	#gpio-cells = < 2 >;
+ * This driver will register the GPIO pin if it finds the gpio-controller
+ * property in the device tree.
+ *
+ * To use the IRQ controller function, the following two properties must
+ * be added to the device tree node for the gpt device:
+ * 	interrupt-controller;
+ * 	#interrupt-cells = < 1 >;
+ * The IRQ controller binding only uses one cell to specify the interrupt,
+ * and the IRQ flags are encoded in the cell.  A cell is not used to encode
+ * the IRQ number because the GPT only has a single IRQ source.  For flags,
+ * a value of '1' means rising edge sensitive and '2' means falling edge.
+ *
+ * The GPIO and the IRQ controller functions can be used at the same time,
+ * but in this use case the IO line will only work as an input.  Trying to
+ * use it as a GPIO output will not work.
+ *
+ * When using the GPIO line as an output, it can either be driven as normal
+ * IO, or it can be an Open Collector (OC) output.  At the moment it is the
+ * responsibility of either the bootloader or the platform setup code to set
+ * the output mode.  This driver does not change the output mode setting.
+ */
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/kernel.h>
+#include <asm/mpc52xx.h>
+
+MODULE_DESCRIPTION("Freescale MPC52xx gpt driver");
+MODULE_AUTHOR("Sascha Hauer, Grant Likely");
+MODULE_LICENSE("GPL");
+
+/**
+ * struct mpc52xx_gpt - Private data structure for MPC52xx GPT driver
+ * @dev: pointer to device structure
+ * @regs: virtual address of GPT registers
+ * @lock: spinlock to coordinate between different functions.
+ * @of_gc: of_gpio_chip instance structure; used when GPIO is enabled
+ * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported
+ */
+struct mpc52xx_gpt_priv {
+	struct device *dev;
+	struct mpc52xx_gpt __iomem *regs;
+	spinlock_t lock;
+	struct irq_host *irqhost;
+
+#if defined(CONFIG_GPIOLIB)
+	struct of_gpio_chip of_gc;
+#endif
+};
+
+#define MPC52xx_GPT_MODE_MS_MASK	(0x07)
+#define MPC52xx_GPT_MODE_MS_IC		(0x01)
+#define MPC52xx_GPT_MODE_MS_OC		(0x02)
+#define MPC52xx_GPT_MODE_MS_PWM		(0x03)
+#define MPC52xx_GPT_MODE_MS_GPIO	(0x04)
+
+#define MPC52xx_GPT_MODE_GPIO_MASK	(0x30)
+#define MPC52xx_GPT_MODE_GPIO_OUT_LOW	(0x20)
+#define MPC52xx_GPT_MODE_GPIO_OUT_HIGH	(0x30)
+
+#define MPC52xx_GPT_MODE_IRQ_EN		(0x0100)
+
+#define MPC52xx_GPT_MODE_ICT_MASK	(0x030000)
+#define MPC52xx_GPT_MODE_ICT_RISING	(0x010000)
+#define MPC52xx_GPT_MODE_ICT_FALLING	(0x020000)
+#define MPC52xx_GPT_MODE_ICT_TOGGLE	(0x030000)
+
+#define MPC52xx_GPT_STATUS_IRQMASK	(0x000f)
+
+/* ---------------------------------------------------------------------
+ * Cascaded interrupt controller hooks
+ */
+
+static void mpc52xx_gpt_irq_unmask(unsigned int virq)
+{
+	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpt->lock, flags);
+	setbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+}
+
+static void mpc52xx_gpt_irq_mask(unsigned int virq)
+{
+	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpt->lock, flags);
+	clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+}
+
+static void mpc52xx_gpt_irq_ack(unsigned int virq)
+{
+	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+
+	out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK);
+}
+
+static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
+{
+	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	unsigned long flags;
+	u32 reg;
+
+	dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, virq, flow_type);
+
+	spin_lock_irqsave(&gpt->lock, flags);
+	reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK;
+	if (flow_type & IRQF_TRIGGER_RISING)
+		reg |= MPC52xx_GPT_MODE_ICT_RISING;
+	if (flow_type & IRQF_TRIGGER_FALLING)
+		reg |= MPC52xx_GPT_MODE_ICT_FALLING;
+	out_be32(&gpt->regs->mode, reg);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+
+	return 0;
+}
+
+static struct irq_chip mpc52xx_gpt_irq_chip = {
+	.typename = "MPC52xx GPT",
+	.unmask = mpc52xx_gpt_irq_unmask,
+	.mask = mpc52xx_gpt_irq_mask,
+	.ack = mpc52xx_gpt_irq_ack,
+	.set_type = mpc52xx_gpt_irq_set_type,
+};
+
+void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
+{
+	struct mpc52xx_gpt_priv *gpt = get_irq_data(virq);
+	int sub_virq;
+	u32 status;
+
+	status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK;
+	if (status) {
+		sub_virq = irq_linear_revmap(gpt->irqhost, 0);
+		generic_handle_irq(sub_virq);
+	}
+}
+
+static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t hw)
+{
+	struct mpc52xx_gpt_priv *gpt = h->host_data;
+
+	dev_dbg(gpt->dev, "%s: h=%p, virq=%i\n", __func__, h, virq);
+	set_irq_chip_data(virq, gpt);
+	set_irq_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
+
+	return 0;
+}
+
+static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct,
+				 u32 *intspec, unsigned int intsize,
+				 irq_hw_number_t *out_hwirq,
+				 unsigned int *out_flags)
+{
+	struct mpc52xx_gpt_priv *gpt = h->host_data;
+
+	dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]);
+
+	if ((intsize < 1) || (intspec[0] < 1) || (intspec[0] > 3)) {
+		dev_err(gpt->dev, "bad irq specifier in %s\n", ct->full_name);
+		return -EINVAL;
+	}
+
+	*out_hwirq = 0; /* The GPT only has 1 IRQ line */
+	*out_flags = intspec[0];
+
+	return 0;
+}
+
+static struct irq_host_ops mpc52xx_gpt_irq_ops = {
+	.map = mpc52xx_gpt_irq_map,
+	.xlate = mpc52xx_gpt_irq_xlate,
+};
+
+static void
+mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
+{
+	int cascade_virq;
+	unsigned long flags;
+
+	/* Only setup cascaded IRQ if device tree claims the GPT is
+	 * an interrupt controller */
+	if (!of_find_property(node, "interrupt-controller", NULL))
+		return;
+
+	cascade_virq = irq_of_parse_and_map(node, 0);
+
+	gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1,
+				      &mpc52xx_gpt_irq_ops, -1);
+	if (!gpt->irqhost) {
+		dev_err(gpt->dev, "irq_alloc_host() failed\n");
+		return;
+	}
+
+	gpt->irqhost->host_data = gpt;
+
+	set_irq_data(cascade_virq, gpt);
+	set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
+
+	/* Set to Input Capture mode */
+	spin_lock_irqsave(&gpt->lock, flags);
+	clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
+			MPC52xx_GPT_MODE_MS_IC);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+
+	dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq);
+}
+
+
+/* ---------------------------------------------------------------------
+ * GPIOLIB hooks
+ */
+#if defined(CONFIG_GPIOLIB)
+static inline struct mpc52xx_gpt_priv *gc_to_mpc52xx_gpt(struct gpio_chip *gc)
+{
+	return container_of(to_of_gpio_chip(gc), struct mpc52xx_gpt_priv,of_gc);
+}
+
+static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+
+	return (in_be32(&gpt->regs->status) >> 8) & 1;
+}
+
+static void
+mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v)
+{
+	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+	unsigned long flags;
+	u32 r;
+
+	dev_dbg(gpt->dev, "%s: gpio:%d v:%d\n", __func__, gpio, v);
+	r = v ? MPC52xx_GPT_MODE_GPIO_OUT_HIGH : MPC52xx_GPT_MODE_GPIO_OUT_LOW;
+
+	spin_lock_irqsave(&gpt->lock, flags);
+	clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK, r);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+}
+
+static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+	unsigned long flags;
+
+	dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio);
+
+	spin_lock_irqsave(&gpt->lock, flags);
+	clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK);
+	spin_unlock_irqrestore(&gpt->lock, flags);
+
+	return 0;
+}
+
+static int
+mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	mpc52xx_gpt_gpio_set(gc, gpio, val);
+	return 0;
+}
+
+static void
+mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)
+{
+	int rc;
+
+	/* Only setup GPIO if the device tree claims the GPT is
+	 * a GPIO controller */
+	if (!of_find_property(node, "gpio-controller", NULL))
+		return;
+
+	gpt->of_gc.gc.label = kstrdup(node->full_name, GFP_KERNEL);
+	if (!gpt->of_gc.gc.label) {
+		dev_err(gpt->dev, "out of memory\n");
+		return;
+	}
+
+	gpt->of_gc.gpio_cells = 2;
+	gpt->of_gc.gc.ngpio = 1;
+	gpt->of_gc.gc.direction_input  = mpc52xx_gpt_gpio_dir_in;
+	gpt->of_gc.gc.direction_output = mpc52xx_gpt_gpio_dir_out;
+	gpt->of_gc.gc.get = mpc52xx_gpt_gpio_get;
+	gpt->of_gc.gc.set = mpc52xx_gpt_gpio_set;
+	gpt->of_gc.gc.base = -1;
+	gpt->of_gc.xlate = of_gpio_simple_xlate;
+	node->data = &gpt->of_gc;
+	of_node_get(node);
+
+	/* Setup external pin in GPIO mode */
+	clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
+			MPC52xx_GPT_MODE_MS_GPIO);
+
+	rc = gpiochip_add(&gpt->of_gc.gc);
+	if (rc)
+		dev_err(gpt->dev, "gpiochip_add() failed; rc=%i\n", rc);
+
+	dev_dbg(gpt->dev, "%s() complete.\n", __func__);
+}
+#else /* defined(CONFIG_GPIOLIB) */
+static void
+mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *p, struct device_node *np) { }
+#endif /* defined(CONFIG_GPIOLIB) */
+
+/* ---------------------------------------------------------------------
+ * of_platform bus binding code
+ */
+static int __devinit mpc52xx_gpt_probe(struct of_device *ofdev,
+				       const struct of_device_id *match)
+{
+	struct mpc52xx_gpt_priv *gpt;
+
+	gpt = kzalloc(sizeof *gpt, GFP_KERNEL);
+	if (!gpt)
+		return -ENOMEM;
+
+	spin_lock_init(&gpt->lock);
+	gpt->dev = &ofdev->dev;
+	gpt->regs = of_iomap(ofdev->node, 0);
+	if (!gpt->regs) {
+		kfree(gpt);
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(&ofdev->dev, gpt);
+
+	mpc52xx_gpt_gpio_setup(gpt, ofdev->node);
+	mpc52xx_gpt_irq_setup(gpt, ofdev->node);
+
+	return 0;
+}
+
+static int mpc52xx_gpt_remove(struct of_device *ofdev)
+{
+	return -EBUSY;
+}
+
+static const struct of_device_id mpc52xx_gpt_match[] = {
+	{ .compatible = "fsl,mpc5200-gpt", },
+
+	/* Depreciated compatible values; don't use for new dts files */
+	{ .compatible = "fsl,mpc5200-gpt-gpio", },
+	{ .compatible = "mpc5200-gpt", },
+	{}
+};
+
+static struct of_platform_driver mpc52xx_gpt_driver = {
+	.name = "mpc52xx-gpt",
+	.match_table = mpc52xx_gpt_match,
+	.probe = mpc52xx_gpt_probe,
+	.remove = mpc52xx_gpt_remove,
+};
+
+static int __init mpc52xx_gpt_init(void)
+{
+	if (of_register_platform_driver(&mpc52xx_gpt_driver))
+		pr_err("error registering MPC52xx GPT driver\n");
+
+	return 0;
+}
+
+/* Make sure GPIOs and IRQs get set up before anyone tries to use them */
+subsys_initcall(mpc52xx_gpt_init);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 0a093f0..480f806 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -163,8 +163,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_clrbit(&intr->ctrl, 11 - l2irq);
 }
 
@@ -176,8 +174,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_setbit(&intr->ctrl, 11 - l2irq);
 }
 
@@ -189,17 +185,15 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_setbit(&intr->ctrl, 27-l2irq);
 }
 
 static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
 {
-	struct irq_desc *desc = get_irq_desc(virq);
 	u32 ctrl_reg, type;
 	int irq;
 	int l2irq;
+	void *handler = handle_level_irq;
 
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
@@ -207,32 +201,21 @@
 	pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
 
 	switch (flow_type) {
-	case IRQF_TRIGGER_HIGH:
-		type = 0;
-		break;
-	case IRQF_TRIGGER_RISING:
-		type = 1;
-		break;
-	case IRQF_TRIGGER_FALLING:
-		type = 2;
-		break;
-	case IRQF_TRIGGER_LOW:
-		type = 3;
-		break;
+	case IRQF_TRIGGER_HIGH: type = 0; break;
+	case IRQF_TRIGGER_RISING: type = 1; handler = handle_edge_irq; break;
+	case IRQF_TRIGGER_FALLING: type = 2; handler = handle_edge_irq; break;
+	case IRQF_TRIGGER_LOW: type = 3; break;
 	default:
 		type = 0;
 	}
 
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		desc->status |= IRQ_LEVEL;
-
 	ctrl_reg = in_be32(&intr->ctrl);
 	ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
 	ctrl_reg |= (type << (22 - (l2irq * 2)));
 	out_be32(&intr->ctrl, ctrl_reg);
 
+	__set_irq_handler_unlocked(virq, handler);
+
 	return 0;
 }
 
@@ -247,6 +230,11 @@
 /*
  * Main interrupt irq_chip
  */
+static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
+{
+	return 0; /* Do nothing so that the sense mask will get updated */
+}
+
 static void mpc52xx_main_mask(unsigned int virq)
 {
 	int irq;
@@ -255,8 +243,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_setbit(&intr->main_mask, 16 - l2irq);
 }
 
@@ -268,8 +254,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_clrbit(&intr->main_mask, 16 - l2irq);
 }
 
@@ -278,6 +262,7 @@
 	.mask = mpc52xx_main_mask,
 	.mask_ack = mpc52xx_main_mask,
 	.unmask = mpc52xx_main_unmask,
+	.set_type = mpc52xx_null_set_type,
 };
 
 /*
@@ -291,8 +276,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_setbit(&intr->per_mask, 31 - l2irq);
 }
 
@@ -304,8 +287,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_clrbit(&intr->per_mask, 31 - l2irq);
 }
 
@@ -314,6 +295,7 @@
 	.mask = mpc52xx_periph_mask,
 	.mask_ack = mpc52xx_periph_mask,
 	.unmask = mpc52xx_periph_unmask,
+	.set_type = mpc52xx_null_set_type,
 };
 
 /*
@@ -327,8 +309,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_setbit(&sdma->IntMask, l2irq);
 }
 
@@ -340,8 +320,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	io_be_clrbit(&sdma->IntMask, l2irq);
 }
 
@@ -353,8 +331,6 @@
 	irq = irq_map[virq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
-	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
-
 	out_be32(&sdma->IntPend, 1 << l2irq);
 }
 
@@ -363,9 +339,19 @@
 	.mask = mpc52xx_sdma_mask,
 	.unmask = mpc52xx_sdma_unmask,
 	.ack = mpc52xx_sdma_ack,
+	.set_type = mpc52xx_null_set_type,
 };
 
 /**
+ * mpc52xx_is_extirq - Returns true if hwirq number is for an external IRQ
+ */
+static int mpc52xx_is_extirq(int l1, int l2)
+{
+	return ((l1 == 0) && (l2 == 0)) ||
+	       ((l1 == 1) && (l2 >= 1) && (l2 <= 3));
+}
+
+/**
  * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property
  */
 static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
@@ -383,38 +369,23 @@
 
 	intrvect_l1 = (int)intspec[0];
 	intrvect_l2 = (int)intspec[1];
-	intrvect_type = (int)intspec[2];
+	intrvect_type = (int)intspec[2] & 0x3;
 
 	intrvect_linux = (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) &
 			 MPC52xx_IRQ_L1_MASK;
 	intrvect_linux |= intrvect_l2 & MPC52xx_IRQ_L2_MASK;
 
+	*out_hwirq = intrvect_linux;
+	*out_flags = IRQ_TYPE_LEVEL_LOW;
+	if (mpc52xx_is_extirq(intrvect_l1, intrvect_l2))
+		*out_flags = mpc52xx_map_senses[intrvect_type];
+
 	pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
 		 intrvect_l2);
-
-	*out_hwirq = intrvect_linux;
-	*out_flags = mpc52xx_map_senses[intrvect_type];
-
 	return 0;
 }
 
 /**
- * mpc52xx_irqx_gettype - determine the IRQ sense type (level/edge)
- *
- * Only external IRQs need this.
- */
-static int mpc52xx_irqx_gettype(int irq)
-{
-	int type;
-	u32 ctrl_reg;
-
-	ctrl_reg = in_be32(&intr->ctrl);
-	type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
-
-	return mpc52xx_map_senses[type];
-}
-
-/**
  * mpc52xx_irqhost_map - Hook to map from virq to an irq_chip structure
  */
 static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
@@ -422,68 +393,46 @@
 {
 	int l1irq;
 	int l2irq;
-	struct irq_chip *good_irqchip;
-	void *good_handle;
+	struct irq_chip *irqchip;
+	void *hndlr;
 	int type;
+	u32 reg;
 
 	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	/*
-	 * Most of ours IRQs will be level low
-	 * Only external IRQs on some platform may be others
+	 * External IRQs are handled differently by the hardware so they are
+	 * handled by a dedicated irq_chip structure.
 	 */
-	type = IRQ_TYPE_LEVEL_LOW;
+	if (mpc52xx_is_extirq(l1irq, l2irq)) {
+		reg = in_be32(&intr->ctrl);
+		type = mpc52xx_map_senses[(reg >> (22 - l2irq * 2)) & 0x3];
+		if ((type == IRQ_TYPE_EDGE_FALLING) ||
+		    (type == IRQ_TYPE_EDGE_RISING))
+			hndlr = handle_edge_irq;
+		else
+			hndlr = handle_level_irq;
 
+		set_irq_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
+		pr_debug("%s: External IRQ%i virq=%x, hw=%x. type=%x\n",
+			 __func__, l2irq, virq, (int)irq, type);
+		return 0;
+	}
+
+	/* It is an internal SOC irq.  Choose the correct irq_chip */
 	switch (l1irq) {
-	case MPC52xx_IRQ_L1_CRIT:
-		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
-
-		BUG_ON(l2irq != 0);
-
-		type = mpc52xx_irqx_gettype(l2irq);
-		good_irqchip = &mpc52xx_extirq_irqchip;
-		break;
-
-	case MPC52xx_IRQ_L1_MAIN:
-		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
-
-		if ((l2irq >= 1) && (l2irq <= 3)) {
-			type = mpc52xx_irqx_gettype(l2irq);
-			good_irqchip = &mpc52xx_extirq_irqchip;
-		} else {
-			good_irqchip = &mpc52xx_main_irqchip;
-		}
-		break;
-
-	case MPC52xx_IRQ_L1_PERP:
-		pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
-		good_irqchip = &mpc52xx_periph_irqchip;
-		break;
-
-	case MPC52xx_IRQ_L1_SDMA:
-		pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
-		good_irqchip = &mpc52xx_sdma_irqchip;
-		break;
-
+	case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
+	case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
+	case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
 	default:
-		pr_err("%s: invalid virq requested (0x%x)\n", __func__, virq);
+		pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
+		       __func__, virq, l1irq, l2irq);
 		return -EINVAL;
 	}
 
-	switch (type) {
-	case IRQ_TYPE_EDGE_FALLING:
-	case IRQ_TYPE_EDGE_RISING:
-		good_handle = handle_edge_irq;
-		break;
-	default:
-		good_handle = handle_level_irq;
-	}
-
-	set_irq_chip_and_handler(virq, good_irqchip, good_handle);
-
-	pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
-		 (int)irq, type);
+	set_irq_chip_and_handler(virq, irqchip, handle_level_irq);
+	pr_debug("%s: virq=%x, l1=%i, l2=%i\n", __func__, virq, l1irq, l2irq);
 
 	return 0;
 }
@@ -522,6 +471,8 @@
 		panic(__FILE__	": find_and_map failed on 'mpc5200-bestcomm'. "
 				"Check node !");
 
+	pr_debug("MPC5200 IRQ controller mapped to 0x%p\n", intr);
+
 	/* Disable all interrupt sources. */
 	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
 	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
@@ -613,8 +564,5 @@
 		}
 	}
 
-	pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
-		 irq_linear_revmap(mpc52xx_irqhost, irq));
-
 	return irq_linear_revmap(mpc52xx_irqhost, irq);
 }
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 30f008b..7c7df40 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -1,6 +1,6 @@
 menuconfig PPC_82xx
 	bool "82xx-based boards (PQ II)"
-	depends on 6xx && PPC_MULTIPLATFORM
+	depends on 6xx
 
 if PPC_82xx
 
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 83c664a..437d29a 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -1,6 +1,6 @@
 menuconfig PPC_83xx
 	bool "83xx-based boards"
-	depends on 6xx && PPC_MULTIPLATFORM
+	depends on 6xx
 	select PPC_UDBG_16550
 	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
diff --git a/arch/powerpc/platforms/83xx/asp834x.c b/arch/powerpc/platforms/83xx/asp834x.c
index bb30d67..aa0d84d 100644
--- a/arch/powerpc/platforms/83xx/asp834x.c
+++ b/arch/powerpc/platforms/83xx/asp834x.c
@@ -58,6 +58,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index 91a2c80..0b4f883 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -38,6 +38,8 @@
 #ifdef CONFIG_PCI
 	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
 		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
+		mpc83xx_add_bridge(np);
 #endif
 	mpc831x_usb_cfg();
 }
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 76092d3..81e44fa 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -42,6 +42,7 @@
 static struct of_device_id __initdata mpc834x_itx_ids[] = {
 	{ .compatible = "fsl,pq2pro-localbus", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index fc3f2ed..d0a634b 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -112,6 +112,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 530ef99..51df7e7 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -84,14 +84,10 @@
 		ppc_md.progress("mpc837x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
-		if (!of_device_is_available(np)) {
-			pr_warning("%s: disabled by the firmware.\n",
-				   np->full_name);
-			continue;
-		}
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
 		mpc83xx_add_bridge(np);
-	}
+	for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
+		mpc83xx_add_bridge(np);
 #endif
 	mpc837xmds_usb_cfg();
 }
@@ -100,6 +96,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index 1d09654..76f3b32 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -38,6 +38,8 @@
 #ifdef CONFIG_PCI
 	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
 		mpc83xx_add_bridge(np);
+	for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
+		mpc83xx_add_bridge(np);
 #endif
 	mpc837x_usb_cfg();
 }
@@ -46,6 +48,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index 156c4e2..49023db 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -84,6 +84,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index cc99c28..11e1fac 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -14,6 +14,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -210,7 +211,7 @@
 	int ret = 0;
 
 	np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
-	if (!np)
+	if (!np || !of_device_is_available(np))
 		return -ENODEV;
 	prop = of_get_property(np, "phy_type", NULL);
 
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index b79dc71..7f066ad 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -51,6 +51,12 @@
 	help
 	  This option enables support for the MPC85xx DS (MPC8544 DS) board
 
+config SOCRATES
+	bool "Socrates"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the Socrates board.
+
 config KSI8560
         bool "Emerson KSI8560"
         select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index f0798c0..a857b35 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -13,4 +13,5 @@
 obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
 obj-$(CONFIG_SBC8560)     += sbc8560.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
+obj-$(CONFIG_SOCRATES)    += socrates.o socrates_fpga_pic.o
 obj-$(CONFIG_KSI8560)	  += ksi8560.o
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index 81cee7b..f4d36b5 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -106,8 +106,6 @@
 	cpm2_pic_init(np);
 	of_node_put(np);
 	set_irq_chained_handler(irq, cpm2_cascade);
-
-	setup_irq(0, NULL);
 #endif
 }
 
@@ -221,6 +219,7 @@
 	{ .type = "simple-bus", },
 	{ .name = "cpm", },
 	{ .name = "localbus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index 1bf5aef..63efca2 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -92,6 +92,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 21f0090..9438a892 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -226,6 +226,7 @@
 	{ .name = "cpm", },
 	{ .name = "localbus", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index aeb6a5b..0a9e491 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -336,6 +336,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 7326d90..de66de7 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -204,6 +204,7 @@
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 658a36f..7dd0290 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -265,6 +265,7 @@
 	{ .compatible = "simple-bus", },
 	{ .type = "qe", },
 	{ .compatible = "fsl,qe", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index 7ec77ce..ecdd8c0 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -154,6 +154,7 @@
 	{ .name = "soc", },
 	{ .type = "soc", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index 472f254..cc27807 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -213,6 +213,7 @@
 	{ .name = "cpm", },
 	{ .name = "localbus", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 79a0df1..cc0b0db 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -21,6 +21,7 @@
 #include <asm/page.h>
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
+#include <asm/dbell.h>
 
 #include <sysdev/fsl_soc.h>
 
@@ -80,10 +81,8 @@
 }
 
 static void __init
-smp_85xx_setup_cpu(int cpu_nr)
+smp_85xx_basic_setup(int cpu_nr)
 {
-	mpic_setup_this_cpu();
-
 	/* Clear any pending timer interrupts */
 	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
 
@@ -91,15 +90,43 @@
 	mtspr(SPRN_TCR, TCR_DIE);
 }
 
+static void __init
+smp_85xx_setup_cpu(int cpu_nr)
+{
+	mpic_setup_this_cpu();
+
+	smp_85xx_basic_setup(cpu_nr);
+}
+
 struct smp_ops_t smp_85xx_ops = {
-	.message_pass = smp_mpic_message_pass,
-	.probe = smp_mpic_probe,
 	.kick_cpu = smp_85xx_kick_cpu,
-	.setup_cpu = smp_85xx_setup_cpu,
 };
 
-void __init
-mpc85xx_smp_init(void)
+static int __init smp_dummy_probe(void)
 {
+	return NR_CPUS;
+}
+
+void __init mpc85xx_smp_init(void)
+{
+	struct device_node *np;
+
+	smp_85xx_ops.message_pass = NULL;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (np) {
+		smp_85xx_ops.probe = smp_mpic_probe;
+		smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
+		smp_85xx_ops.message_pass = smp_mpic_message_pass;
+	} else {
+		smp_85xx_ops.probe = smp_dummy_probe;
+		smp_85xx_ops.setup_cpu = smp_85xx_basic_setup;
+	}
+
+	if (cpu_has_feature(CPU_FTR_DBELL))
+		smp_85xx_ops.message_pass = smp_dbell_message_pass;
+
+	BUG_ON(!smp_85xx_ops.message_pass);
+
 	smp_ops = &smp_85xx_ops;
 }
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
new file mode 100644
index 0000000..d0e8443
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2008 Emcraft Systems
+ * Sergei Poselenov <sposelenov@emcraft.com>
+ *
+ * Based on MPC8560 ADS and arch/ppc tqm85xx ports
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2008 Freescale Semiconductor Inc.
+ *
+ * Copyright (c) 2005-2006 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * 	Kumar Gala <kumar.gala@freescale.com>
+ *      Copyright 2004 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.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+
+#include "socrates_fpga_pic.h"
+
+static void __init socrates_pic_init(void)
+{
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np;
+
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (!np) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Could not map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			0, 256, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_init(mpic);
+
+	np = of_find_compatible_node(NULL, NULL, "abb,socrates-fpga-pic");
+	if (!np) {
+		printk(KERN_ERR "Could not find socrates-fpga-pic node\n");
+		return;
+	}
+	socrates_fpga_pic_init(np);
+	of_node_put(np);
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init socrates_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("socrates_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
+		fsl_add_bridge(np, 1);
+#endif
+}
+
+static struct of_device_id __initdata socrates_of_bus_ids[] = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
+	{},
+};
+
+static void __init socrates_init(void)
+{
+	of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init socrates_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "abb,socrates"))
+		return 1;
+
+	return 0;
+}
+
+define_machine(socrates) {
+	.name			= "Socrates",
+	.probe			= socrates_probe,
+	.setup_arch		= socrates_setup_arch,
+	.init			= socrates_init,
+	.init_IRQ		= socrates_pic_init,
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
new file mode 100644
index 0000000..60edf63
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -0,0 +1,327 @@
+/*
+ *  Copyright (C) 2008 Ilya Yanok, Emcraft Systems
+ *
+ *
+ * This program is free software; you can 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/irq.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+
+/*
+ * The FPGA supports 9 interrupt sources, which can be routed to 3
+ * interrupt request lines of the MPIC. The line to be used can be
+ * specified through the third cell of FDT property  "interrupts".
+ */
+
+#define SOCRATES_FPGA_NUM_IRQS	9
+
+#define FPGA_PIC_IRQCFG		(0x0)
+#define FPGA_PIC_IRQMASK(n)	(0x4 + 0x4 * (n))
+
+#define SOCRATES_FPGA_IRQ_MASK	((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
+
+struct socrates_fpga_irq_info {
+	unsigned int irq_line;
+	int type;
+};
+
+/*
+ * Interrupt routing and type table
+ *
+ * IRQ_TYPE_NONE means the interrupt type is configurable,
+ * otherwise it's fixed to the specified value.
+ */
+static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
+	[0] = {0, IRQ_TYPE_NONE},
+	[1] = {0, IRQ_TYPE_LEVEL_HIGH},
+	[2] = {0, IRQ_TYPE_LEVEL_LOW},
+	[3] = {0, IRQ_TYPE_NONE},
+	[4] = {0, IRQ_TYPE_NONE},
+	[5] = {0, IRQ_TYPE_NONE},
+	[6] = {0, IRQ_TYPE_NONE},
+	[7] = {0, IRQ_TYPE_NONE},
+	[8] = {0, IRQ_TYPE_LEVEL_HIGH},
+};
+
+#define socrates_fpga_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
+
+static DEFINE_SPINLOCK(socrates_fpga_pic_lock);
+
+static void __iomem *socrates_fpga_pic_iobase;
+static struct irq_host *socrates_fpga_pic_irq_host;
+static unsigned int socrates_fpga_irqs[3];
+
+static inline uint32_t socrates_fpga_pic_read(int reg)
+{
+	return in_be32(socrates_fpga_pic_iobase + reg);
+}
+
+static inline void socrates_fpga_pic_write(int reg, uint32_t val)
+{
+	out_be32(socrates_fpga_pic_iobase + reg, val);
+}
+
+static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
+{
+	uint32_t cause;
+	unsigned long flags;
+	int i;
+
+	/* Check irq line routed to the MPIC */
+	for (i = 0; i < 3; i++) {
+		if (irq == socrates_fpga_irqs[i])
+			break;
+	}
+	if (i == 3)
+		return NO_IRQ;
+
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
+		if (cause >> (i + 16))
+			break;
+	}
+	return irq_linear_revmap(socrates_fpga_pic_irq_host,
+			(irq_hw_number_t)i);
+}
+
+void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int cascade_irq;
+
+	/*
+	 * See if we actually have an interrupt, call generic handling code if
+	 * we do.
+	 */
+	cascade_irq = socrates_fpga_pic_get_irq(irq);
+
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq);
+	desc->chip->eoi(irq);
+
+}
+
+static void socrates_fpga_pic_ack(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq, irq_line;
+	uint32_t mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	irq_line = fpga_irqs[hwirq].irq_line;
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
+		& SOCRATES_FPGA_IRQ_MASK;
+	mask |= (1 << (hwirq + 16));
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+}
+
+static void socrates_fpga_pic_mask(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	int irq_line;
+	u32 mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	irq_line = fpga_irqs[hwirq].irq_line;
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
+		& SOCRATES_FPGA_IRQ_MASK;
+	mask &= ~(1 << hwirq);
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+}
+
+static void socrates_fpga_pic_mask_ack(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	int irq_line;
+	u32 mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	irq_line = fpga_irqs[hwirq].irq_line;
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
+		& SOCRATES_FPGA_IRQ_MASK;
+	mask &= ~(1 << hwirq);
+	mask |= (1 << (hwirq + 16));
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+}
+
+static void socrates_fpga_pic_unmask(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	int irq_line;
+	u32 mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	irq_line = fpga_irqs[hwirq].irq_line;
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
+		& SOCRATES_FPGA_IRQ_MASK;
+	mask |= (1 << hwirq);
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+}
+
+static void socrates_fpga_pic_eoi(unsigned int virq)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	int irq_line;
+	u32 mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	irq_line = fpga_irqs[hwirq].irq_line;
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
+		& SOCRATES_FPGA_IRQ_MASK;
+	mask |= (1 << (hwirq + 16));
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+}
+
+static int socrates_fpga_pic_set_type(unsigned int virq,
+		unsigned int flow_type)
+{
+	unsigned long flags;
+	unsigned int hwirq;
+	int polarity;
+	u32 mask;
+
+	hwirq = socrates_fpga_irq_to_hw(virq);
+
+	if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
+		return -EINVAL;
+
+	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		polarity = 1;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		polarity = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
+	if (polarity)
+		mask |= (1 << hwirq);
+	else
+		mask &= ~(1 << hwirq);
+	socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	return 0;
+}
+
+static struct irq_chip socrates_fpga_pic_chip = {
+	.typename       = " FPGA-PIC ",
+	.ack		= socrates_fpga_pic_ack,
+	.mask           = socrates_fpga_pic_mask,
+	.mask_ack       = socrates_fpga_pic_mask_ack,
+	.unmask         = socrates_fpga_pic_unmask,
+	.eoi		= socrates_fpga_pic_eoi,
+	.set_type	= socrates_fpga_pic_set_type,
+};
+
+static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
+		irq_hw_number_t hwirq)
+{
+	/* All interrupts are LEVEL sensitive */
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
+			handle_fasteoi_irq);
+
+	return 0;
+}
+
+static int socrates_fpga_pic_host_xlate(struct irq_host *h,
+		struct device_node *ct,	u32 *intspec, unsigned int intsize,
+		irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+	struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
+
+	*out_hwirq = intspec[0];
+	if  (fpga_irq->type == IRQ_TYPE_NONE) {
+		/* type is configurable */
+		if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
+		    intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
+			pr_warning("FPGA PIC: invalid irq type, "
+				   "setting default active low\n");
+			*out_flags = IRQ_TYPE_LEVEL_LOW;
+		} else {
+			*out_flags = intspec[1];
+		}
+	} else {
+		/* type is fixed */
+		*out_flags = fpga_irq->type;
+	}
+
+	/* Use specified interrupt routing */
+	if (intspec[2] <= 2)
+		fpga_irq->irq_line = intspec[2];
+	else
+		pr_warning("FPGA PIC: invalid irq routing\n");
+
+	return 0;
+}
+
+static struct irq_host_ops socrates_fpga_pic_host_ops = {
+	.map    = socrates_fpga_pic_host_map,
+	.xlate  = socrates_fpga_pic_host_xlate,
+};
+
+void socrates_fpga_pic_init(struct device_node *pic)
+{
+	unsigned long flags;
+	int i;
+
+	/* Setup an irq_host structure */
+	socrates_fpga_pic_irq_host = irq_alloc_host(pic, IRQ_HOST_MAP_LINEAR,
+			SOCRATES_FPGA_NUM_IRQS,	&socrates_fpga_pic_host_ops,
+			SOCRATES_FPGA_NUM_IRQS);
+	if (socrates_fpga_pic_irq_host == NULL) {
+		pr_err("FPGA PIC: Unable to allocate host\n");
+		return;
+	}
+
+	for (i = 0; i < 3; i++) {
+		socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
+		if (socrates_fpga_irqs[i] == NO_IRQ) {
+			pr_warning("FPGA PIC: can't get irq%d.\n", i);
+			continue;
+		}
+		set_irq_chained_handler(socrates_fpga_irqs[i],
+				socrates_fpga_pic_cascade);
+	}
+
+	socrates_fpga_pic_iobase = of_iomap(pic, 0);
+
+	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
+			SOCRATES_FPGA_IRQ_MASK << 16);
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
+			SOCRATES_FPGA_IRQ_MASK << 16);
+	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
+			SOCRATES_FPGA_IRQ_MASK << 16);
+	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+
+	pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
+}
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.h b/arch/powerpc/platforms/85xx/socrates_fpga_pic.h
new file mode 100644
index 0000000..21d7d8e
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.h
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (C) 2008 Ilya Yanok, Emcraft Systems
+ *
+ *
+ * This program is free software; you can 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 SOCRATES_FPGA_PIC_H
+#define SOCRATES_FPGA_PIC_H
+
+void socrates_fpga_pic_init(struct device_node *pic);
+
+#endif
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index 0cca8f5..f559918 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -145,6 +145,7 @@
 
 static struct of_device_id __initdata of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 2933a8e..5b0ab99 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -153,6 +153,7 @@
 
 static struct of_device_id __initdata of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 8e56939..fdaf4dd 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,7 +1,7 @@
 config PPC_86xx
 menuconfig PPC_86xx
 	bool "86xx-based boards"
-	depends on 6xx && PPC_MULTIPLATFORM
+	depends on 6xx
 	select FSL_SOC
 	select ALTIVEC
 	help
@@ -31,6 +31,22 @@
 	help
 	  This option enables support for the MPC8610 HPCD board.
 
+config GEF_PPC9A
+	bool "GE Fanuc PPC9A"
+	select DEFAULT_UIMAGE
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  This option enables support for GE Fanuc's PPC9A.
+
+config GEF_SBC310
+	bool "GE Fanuc SBC310"
+	select DEFAULT_UIMAGE
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  This option enables support for GE Fanuc's SBC310.
+
 config GEF_SBC610
 	bool "GE Fanuc SBC610"
 	select DEFAULT_UIMAGE
@@ -48,7 +64,7 @@
 	select FSL_PCI if PCI
 	select PPC_UDBG_16550
 	select MPIC
-	default y if MPC8641_HPCN || SBC8641D || GEF_SBC610
+	default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
 
 config MPC8610
 	bool
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 31e540c..4b0d7b1 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -9,3 +9,5 @@
 obj-$(CONFIG_MPC8610_HPCD)	+= mpc8610_hpcd.o
 gef-gpio-$(CONFIG_GPIOLIB)	+= gef_gpio.o
 obj-$(CONFIG_GEF_SBC610)	+= gef_sbc610.o gef_pic.o $(gef-gpio-y)
+obj-$(CONFIG_GEF_SBC310)	+= gef_sbc310.o gef_pic.o $(gef-gpio-y)
+obj-$(CONFIG_GEF_PPC9A)		+= gef_ppc9a.o gef_pic.o $(gef-gpio-y)
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
index 85b2800..b2ea887 100644
--- a/arch/powerpc/platforms/86xx/gef_gpio.c
+++ b/arch/powerpc/platforms/86xx/gef_gpio.c
@@ -37,8 +37,6 @@
 #define GEF_GPIO_OVERRUN	0x1C
 #define GEF_GPIO_MODE		0x20
 
-#define NUM_GPIO 19
-
 static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
 {
 	unsigned int data;
@@ -103,10 +101,10 @@
 static int __init gef_gpio_init(void)
 {
 	struct device_node *np;
+	int retval;
+	struct of_mm_gpio_chip *gef_gpio_chip;
 
 	for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-		int retval;
-		struct of_mm_gpio_chip *gef_gpio_chip;
 
 		pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
 
@@ -120,7 +118,35 @@
 
 		/* Setup pointers to chip functions */
 		gef_gpio_chip->of_gc.gpio_cells = 2;
-		gef_gpio_chip->of_gc.gc.ngpio = NUM_GPIO;
+		gef_gpio_chip->of_gc.gc.ngpio = 19;
+		gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
+		gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
+		gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
+		gef_gpio_chip->of_gc.gc.set = gef_gpio_set;
+
+		/* This function adds a memory mapped GPIO chip */
+		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
+		if (retval) {
+			kfree(gef_gpio_chip);
+			pr_err("%s: Unable to add GPIO\n", np->full_name);
+		}
+	}
+
+	for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
+
+		pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
+
+		/* Allocate chip structure */
+		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
+		if (!gef_gpio_chip) {
+			pr_err("%s: Unable to allocate structure\n",
+				np->full_name);
+			continue;
+		}
+
+		/* Setup pointers to chip functions */
+		gef_gpio_chip->of_gc.gpio_cells = 2;
+		gef_gpio_chip->of_gc.gc.ngpio = 6;
 		gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
 		gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
 		gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
new file mode 100644
index 0000000..d7910466
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -0,0 +1,224 @@
+/*
+ * GE Fanuc PPC9A board support
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+#include "gef_pic.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "PPC9A: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *ppc9a_regs;
+
+static void __init gef_ppc9a_init_irq(void)
+{
+	struct device_node *cascade_node = NULL;
+
+	mpc86xx_init_irq();
+
+	/*
+	 * There is a simple interrupt handler in the main FPGA, this needs
+	 * to be cascaded into the MPIC
+	 */
+	cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic-1.00");
+	if (!cascade_node) {
+		printk(KERN_WARNING "PPC9A: No FPGA PIC\n");
+		return;
+	}
+
+	gef_pic_init(cascade_node);
+	of_node_put(cascade_node);
+}
+
+static void __init gef_ppc9a_setup_arch(void)
+{
+	struct device_node *regs;
+#ifdef CONFIG_PCI
+	struct device_node *np;
+
+	for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
+		fsl_add_bridge(np, 1);
+	}
+#endif
+
+	printk(KERN_INFO "GE Fanuc Intelligent Platforms PPC9A 6U VME SBC\n");
+
+#ifdef CONFIG_SMP
+	mpc86xx_smp_init();
+#endif
+
+	/* Remap basic board registers */
+	regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
+	if (regs) {
+		ppc9a_regs = of_iomap(regs, 0);
+		if (ppc9a_regs == NULL)
+			printk(KERN_WARNING "Unable to map board registers\n");
+		of_node_put(regs);
+	}
+}
+
+/* Return the PCB revision */
+static unsigned int gef_ppc9a_get_pcb_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(ppc9a_regs);
+	return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_ppc9a_get_board_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(ppc9a_regs);
+	return (reg >> 16) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_ppc9a_get_fpga_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(ppc9a_regs);
+	return (reg >> 24) & 0xf;
+}
+
+static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
+{
+	uint svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+
+	seq_printf(m, "Revision\t: %u%c\n", gef_ppc9a_get_pcb_rev(),
+		('A' + gef_ppc9a_get_board_rev() - 1));
+	seq_printf(m, "FPGA Revision\t: %u\n", gef_ppc9a_get_fpga_rev());
+
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+}
+
+static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+
+	/* Do not do the fixup on other platforms! */
+	if (!machine_is(gef_ppc9a))
+		return;
+
+	printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+	/* Ensure ports 1, 2, 3, 4 & 5 are enabled */
+	pci_read_config_dword(pdev, 0xe0, &val);
+	pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x5);
+
+	/* System clock is 48-MHz Oscillator and EHCI Enabled. */
+	pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+	gef_ppc9a_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_ppc9a_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "gef,ppc9a"))
+		return 1;
+
+	return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+	unsigned int temp;
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	temp = mfspr(SPRN_HID0);
+	temp |= HID0_TBEN;
+	mtspr(SPRN_HID0, temp);
+	asm volatile("isync");
+
+	return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	printk(KERN_DEBUG "Probe platform devices\n");
+	of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
+
+define_machine(gef_ppc9a) {
+	.name			= "GE Fanuc PPC9A",
+	.probe			= gef_ppc9a_probe,
+	.setup_arch		= gef_ppc9a_setup_arch,
+	.init_IRQ		= gef_ppc9a_init_irq,
+	.show_cpuinfo		= gef_ppc9a_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.time_init		= mpc86xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
new file mode 100644
index 0000000..af14f85
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -0,0 +1,235 @@
+/*
+ * GE Fanuc SBC310 board support
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+#include "gef_pic.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "SBC310: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *sbc310_regs;
+
+static void __init gef_sbc310_init_irq(void)
+{
+	struct device_node *cascade_node = NULL;
+
+	mpc86xx_init_irq();
+
+	/*
+	 * There is a simple interrupt handler in the main FPGA, this needs
+	 * to be cascaded into the MPIC
+	 */
+	cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
+	if (!cascade_node) {
+		printk(KERN_WARNING "SBC310: No FPGA PIC\n");
+		return;
+	}
+
+	gef_pic_init(cascade_node);
+	of_node_put(cascade_node);
+}
+
+static void __init gef_sbc310_setup_arch(void)
+{
+	struct device_node *regs;
+#ifdef CONFIG_PCI
+	struct device_node *np;
+
+	for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
+		fsl_add_bridge(np, 1);
+	}
+#endif
+
+	printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC310 6U VPX SBC\n");
+
+#ifdef CONFIG_SMP
+	mpc86xx_smp_init();
+#endif
+
+	/* Remap basic board registers */
+	regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
+	if (regs) {
+		sbc310_regs = of_iomap(regs, 0);
+		if (sbc310_regs == NULL)
+			printk(KERN_WARNING "Unable to map board registers\n");
+		of_node_put(regs);
+	}
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc310_get_board_id(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc310_regs);
+	return reg & 0xff;
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc310_get_pcb_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc310_regs);
+	return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_sbc310_get_board_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc310_regs);
+	return (reg >> 16) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_sbc310_get_fpga_rev(void)
+{
+	unsigned int reg;
+
+	reg = ioread32(sbc310_regs);
+	return (reg >> 24) & 0xf;
+}
+
+static void gef_sbc310_show_cpuinfo(struct seq_file *m)
+{
+	uint svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+
+	seq_printf(m, "Board ID\t: 0x%2.2x\n", gef_sbc310_get_board_id());
+	seq_printf(m, "Revision\t: %u%c\n", gef_sbc310_get_pcb_rev(),
+		('A' + gef_sbc310_get_board_rev() - 1));
+	seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc310_get_fpga_rev());
+
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+}
+
+static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+
+	/* Do not do the fixup on other platforms! */
+	if (!machine_is(gef_sbc310))
+		return;
+
+	printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+	/* Ensure only ports 1 & 2 are enabled */
+	pci_read_config_dword(pdev, 0xe0, &val);
+	pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2);
+
+	/* System clock is 48-MHz Oscillator and EHCI Enabled. */
+	pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+	gef_sbc310_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_sbc310_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "gef,sbc310"))
+		return 1;
+
+	return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+	unsigned int temp;
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	temp = mfspr(SPRN_HID0);
+	temp |= HID0_TBEN;
+	mtspr(SPRN_HID0, temp);
+	asm volatile("isync");
+
+	return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	printk(KERN_DEBUG "Probe platform devices\n");
+	of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(gef_sbc310, declare_of_platform_devices);
+
+define_machine(gef_sbc310) {
+	.name			= "GE Fanuc SBC310",
+	.probe			= gef_sbc310_probe,
+	.setup_arch		= gef_sbc310_setup_arch,
+	.init_IRQ		= gef_sbc310_init_irq,
+	.show_cpuinfo		= gef_sbc310_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.time_init		= mpc86xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index d6b772b..ea23606 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -194,6 +194,7 @@
 
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index e8d54ac..3f49a6f 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -46,6 +46,7 @@
 static struct of_device_id __initdata mpc8610_ids[] = {
 	{ .compatible = "fsl,mpc8610-immr", },
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{}
 };
 
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 27e0e68..c4ec49b 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -148,6 +148,7 @@
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "fsl,rapidio-delta", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index 5fd7ed4..2886a36 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -103,6 +103,7 @@
 
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
+	{ .compatible = "gianfar", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 200b9cb..ffa2a9f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -1,14 +1,5 @@
 menu "Platform support"
 
-config PPC_MULTIPLATFORM
-	bool
-	depends on PPC64 || 6xx
-	default y
-
-config CLASSIC32
-	def_bool y
-	depends on 6xx && PPC_MULTIPLATFORM
-
 source "arch/powerpc/platforms/pseries/Kconfig"
 source "arch/powerpc/platforms/iseries/Kconfig"
 source "arch/powerpc/platforms/chrp/Kconfig"
@@ -28,15 +19,28 @@
 source "arch/powerpc/platforms/embedded6xx/Kconfig"
 source "arch/powerpc/platforms/44x/Kconfig"
 source "arch/powerpc/platforms/40x/Kconfig"
+source "arch/powerpc/platforms/amigaone/Kconfig"
 
 config PPC_NATIVE
 	bool
-	depends on PPC_MULTIPLATFORM
+	depends on 6xx || PPC64
 	help
 	  Support for running natively on the hardware, i.e. without
 	  a hypervisor. This option is not user-selectable but should
 	  be selected by all platforms that need it.
 
+config PPC_OF_BOOT_TRAMPOLINE
+	bool "Support booting from Open Firmware or yaboot"
+	depends on 6xx || PPC64
+	default y
+	help
+	  Support from booting from Open Firmware or yaboot using an
+	  Open Firmware client interface. This enables the kernel to
+	  communicate with open firmware to retrieve system informations
+	  such as the device tree.
+
+	  In case of doubt, say Y
+
 config UDBG_RTAS_CONSOLE
 	bool "RTAS based debug console"
 	depends on PPC_RTAS
@@ -70,7 +74,7 @@
 
 config U3_DART
 	bool
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64
 	default n
 
 config PPC_RTAS
@@ -91,15 +95,6 @@
 	tristate "Firmware flash interface"
 	depends on PPC64 && RTAS_PROC
 
-config PPC_PMI
-	tristate "Support for PMI"
-	depends on PPC_IBM_CELL_BLADE
-	help
-	  PMI (Platform Management Interrupt) is a way to
-	  communicate with the BMC (Baseboard Management Controller).
-	  It is used in some IBM Cell blades.
-	default m
-
 config MMIO_NVRAM
 	bool
 	default n
@@ -196,7 +191,7 @@
 
 config TAU
 	bool "On-chip CPU temperature sensor support"
-	depends on CLASSIC32
+	depends on 6xx
 	help
 	  G3 and G4 processors have an on-chip temperature sensor called the
 	  'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
@@ -274,7 +269,7 @@
 
 config AXON_RAM
 	tristate "Axon DDR2 memory device driver"
-	depends on PPC_IBM_CELL_BLADE
+	depends on PPC_IBM_CELL_BLADE && BLOCK
 	default m
 	help
 	  It registers one block device per Axon's DDR2 memory bank found
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index e868b5c..9da795e 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -57,9 +57,17 @@
 
 endchoice
 
+# Until we have a choice of exclusive CPU types on 64-bit, we always
+# use PPC_BOOK3S. On 32-bit, this is equivalent to 6xx which is
+# "classic" MMU
+
+config PPC_BOOK3S
+       def_bool y
+       depends on PPC64 || 6xx
+
 config POWER4_ONLY
 	bool "Optimize for POWER4"
-	depends on PPC64
+	depends on PPC64 && PPC_BOOK3S
 	default n
 	---help---
 	  Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
@@ -68,16 +76,16 @@
 
 config POWER3
 	bool
-	depends on PPC64
+	depends on PPC64 && PPC_BOOK3S
 	default y if !POWER4_ONLY
 
 config POWER4
-	depends on PPC64
+	depends on PPC64 && PPC_BOOK3S
 	def_bool y
 
 config TUNE_CELL
 	bool "Optimize for Cell Broadband Engine"
-	depends on PPC64
+	depends on PPC64 && PPC_BOOK3S
 	help
 	  Cause the compiler to optimize for the PPE of the Cell Broadband
 	  Engine. This will make the code run considerably faster on Cell
@@ -147,7 +155,7 @@
 
 config ALTIVEC
 	bool "AltiVec Support"
-	depends on CLASSIC32 || POWER4
+	depends on 6xx || POWER4
 	---help---
 	  This option enables kernel support for the Altivec extensions to the
 	  PowerPC processor. The kernel currently supports saving and restoring
@@ -210,6 +218,10 @@
 	def_bool y
 	depends on !PPC_STD_MMU
 
+config PPC_BOOK3E_MMU
+	def_bool y
+	depends on FSL_BOOKE
+
 config PPC_MM_SLICES
 	bool
 	default y if HUGETLB_PAGE || (PPC_STD_MMU_64 && PPC_64K_PAGES)
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 8079e0b..f741919 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -19,3 +19,4 @@
 obj-$(CONFIG_PPC_CELL)		+= cell/
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/
+obj-$(CONFIG_AMIGAONE)		+= amigaone/
diff --git a/arch/powerpc/platforms/amigaone/Kconfig b/arch/powerpc/platforms/amigaone/Kconfig
new file mode 100644
index 0000000..0224767
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Kconfig
@@ -0,0 +1,18 @@
+config AMIGAONE
+	bool "Eyetech AmigaOne/MAI Teron"
+	depends on 6xx && BROKEN_ON_SMP
+	select PPC_I8259
+	select PPC_INDIRECT_PCI
+	select PPC_UDBG_16550
+	select PCI
+	select NOT_COHERENT_CACHE
+	select CHECK_CACHE_COHERENCY
+	select DEFAULT_UIMAGE
+	select PCSPKR_PLATFORM
+	help
+	Select AmigaOne for the following machines:
+	- AmigaOne SE/Teron CX (G3 only)
+	- AmigaOne XE/Teron PX
+	- uA1/Teron mini
+	  More information is available at:
+	  <http://amigaone-linux.sourceforge.net/>.
diff --git a/arch/powerpc/platforms/amigaone/Makefile b/arch/powerpc/platforms/amigaone/Makefile
new file mode 100644
index 0000000..e6885b3
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/Makefile
@@ -0,0 +1 @@
+obj-y	+= setup.o
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
new file mode 100644
index 0000000..4430353
--- /dev/null
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -0,0 +1,170 @@
+/*
+ * AmigaOne platform setup
+ *
+ * Copyright 2008 Gerhard Pircher (gerhard_pircher@gmx.net)
+ *
+ *   Based on original amigaone_setup.c source code
+ * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/seq_file.h>
+#include <linux/utsrelease.h>
+
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/i8259.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+extern void __flush_disable_L1(void);
+
+void amigaone_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Eyetech Ltd.\n");
+}
+
+static int __init amigaone_add_bridge(struct device_node *dev)
+{
+	const u32 *cfg_addr, *cfg_data;
+	int len;
+	const int *bus_range;
+	struct pci_controller *hose;
+
+	printk(KERN_INFO "Adding PCI host bridge %s\n", dev->full_name);
+
+	cfg_addr = of_get_address(dev, 0, NULL, NULL);
+	cfg_data = of_get_address(dev, 1, NULL, NULL);
+	if ((cfg_addr == NULL) || (cfg_data == NULL))
+		return -ENODEV;
+
+	bus_range = of_get_property(dev, "bus-range", &len);
+	if ((bus_range == NULL) || (len < 2 * sizeof(int)))
+		printk(KERN_WARNING "Can't get bus-range for %s, assume"
+		       " bus 0\n", dev->full_name);
+
+	hose = pcibios_alloc_controller(dev);
+	if (hose == NULL)
+		return -ENOMEM;
+
+	hose->first_busno = bus_range ? bus_range[0] : 0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+	setup_indirect_pci(hose, cfg_addr[0], cfg_data[0], 0);
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(hose, dev, 1);
+
+	return 0;
+}
+
+void __init amigaone_setup_arch(void)
+{
+	struct device_node *np;
+	int phb = -ENODEV;
+
+	/* Lookup PCI host bridges. */
+	for_each_compatible_node(np, "pci", "mai-logic,articia-s")
+		phb = amigaone_add_bridge(np);
+
+	BUG_ON(phb != 0);
+
+	if (ppc_md.progress)
+		ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0);
+}
+
+void __init amigaone_init_IRQ(void)
+{
+	struct device_node *pic, *np = NULL;
+	const unsigned long *prop = NULL;
+	unsigned long int_ack = 0;
+
+	/* Search for ISA interrupt controller. */
+	pic = of_find_compatible_node(NULL, "interrupt-controller",
+	                              "pnpPNP,000");
+	BUG_ON(pic == NULL);
+
+	/* Look for interrupt acknowledge address in the PCI root node. */
+	np = of_find_compatible_node(NULL, "pci", "mai-logic,articia-s");
+	if (np) {
+		prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
+		if (prop)
+			int_ack = prop[0];
+		of_node_put(np);
+	}
+
+	if (int_ack == 0)
+		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
+		       " address, polling\n");
+
+	i8259_init(pic, int_ack);
+	ppc_md.get_irq = i8259_irq;
+	irq_set_default_host(i8259_get_host());
+}
+
+void __init amigaone_init(void)
+{
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xc0, 0x20, "dma2");
+}
+
+void amigaone_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* Flush and disable caches. */
+	__flush_disable_L1();
+
+        /* Set SRR0 to the reset vector and turn on MSR_IP. */
+	mtspr(SPRN_SRR0, 0xfff00100);
+	mtspr(SPRN_SRR1, MSR_IP);
+
+	/* Do an rfi to jump back to firmware. */
+	__asm__ __volatile__("rfi" : : : "memory");
+
+	/* Not reached. */
+	while (1);
+}
+
+static int __init amigaone_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "eyetech,amigaone")) {
+		/*
+		 * Coherent memory access cause complete system lockup! Thus
+		 * disable this CPU feature, even if the CPU needs it.
+		 */
+		cur_cpu_spec->cpu_features &= ~CPU_FTR_NEED_COHERENT;
+
+		ISA_DMA_THRESHOLD = 0x00ffffff;
+		DMA_MODE_READ = 0x44;
+		DMA_MODE_WRITE = 0x48;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(amigaone) {
+	.name			= "AmigaOne",
+	.probe			= amigaone_probe,
+	.setup_arch		= amigaone_setup_arch,
+	.init			= amigaone_init,
+	.show_cpuinfo		= amigaone_show_cpuinfo,
+	.init_IRQ		= amigaone_init_IRQ,
+	.restart		= amigaone_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 5cc3279..40e24c3 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -23,7 +23,7 @@
 
 config PPC_IBM_CELL_BLADE
 	bool "IBM Cell Blade"
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	select PPC_CELL_NATIVE
 	select MMIO_NVRAM
 	select PPC_UDBG_16550
@@ -31,7 +31,7 @@
 
 config PPC_CELLEB
 	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	select PPC_CELL_NATIVE
 	select HAS_TXX9_SERIAL
 	select PPC_UDBG_BEAT
@@ -40,9 +40,14 @@
 
 config PPC_CELL_QPACE
 	bool "IBM Cell - QPACE"
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	select PPC_CELL_COMMON
 
+config AXON_MSI
+	bool
+	depends on PPC_IBM_CELL_BLADE && PCI_MSI
+	default y
+
 menu "Cell Broadband Engine options"
 	depends on PPC_CELL
 
@@ -98,7 +103,7 @@
 
 config PPC_IBM_CELL_POWERBUTTON
 	tristate "IBM Cell Blade power button"
-	depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV
+	depends on PPC_IBM_CELL_BLADE && INPUT_EVDEV
 	default y
 	help
 	  Support Powerbutton on IBM Cell blades.
@@ -118,9 +123,9 @@
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 	  If you don't have such processor, say N
 
-config CBE_CPUFREQ_PMI
-	tristate "CBE frequency scaling using PMI interface"
-	depends on CBE_CPUFREQ && PPC_PMI && EXPERIMENTAL
+config CBE_CPUFREQ_PMI_ENABLE
+	bool "CBE frequency scaling using PMI interface"
+	depends on CBE_CPUFREQ && EXPERIMENTAL
 	default n
 	help
 	  Select this, if you want to use the PMI interface
@@ -128,6 +133,20 @@
 	  processor will not only be able to run at lower speed,
 	  but also at lower core voltage.
 
+config CBE_CPUFREQ_PMI
+	tristate
+	depends on CBE_CPUFREQ_PMI_ENABLE
+	default CBE_CPUFREQ
+
+config PPC_PMI
+	tristate
+	default y
+	depends on CBE_CPUFREQ_PMI || PPC_IBM_CELL_POWERBUTTON
+	help
+	  PMI (Platform Management Interrupt) is a way to
+	  communicate with the BMC (Baseboard Management Controller).
+	  It is used in some IBM Cell blades.
+
 config CBE_CPUFREQ_SPU_GOVERNOR
 	tristate "CBE frequency scaling based on SPU usage"
 	depends on SPU_FS && CPU_FREQ
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 43eccb2..83fafe9 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -28,7 +28,7 @@
 					   $(spu-manage-y) \
 					   spufs/
 
-obj-$(CONFIG_PCI_MSI)			+= axon_msi.o
+obj-$(CONFIG_AXON_MSI)			+= axon_msi.o
 
 # qpace setup
 obj-$(CONFIG_PPC_CELL_QPACE)		+= qpace_setup.o
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 059cad6..5c1118e 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -131,10 +131,10 @@
 };
 
 static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
-						unsigned long flags)
+				  unsigned long flags, void *caller)
 {
 	struct iowa_bus *bus;
-	void __iomem *res = __ioremap(addr, size, flags);
+	void __iomem *res = __ioremap_caller(addr, size, flags, caller);
 	int busno;
 
 	bus = iowa_pci_find(0, (unsigned long)addr);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index ee5033e..5744527 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -74,7 +74,7 @@
 #define IOC_IO_ExcpStat_V		0x8000000000000000ul
 #define IOC_IO_ExcpStat_SPF_Mask	0x6000000000000000ul
 #define IOC_IO_ExcpStat_SPF_S		0x6000000000000000ul
-#define IOC_IO_ExcpStat_SPF_P		0x4000000000000000ul
+#define IOC_IO_ExcpStat_SPF_P		0x2000000000000000ul
 #define IOC_IO_ExcpStat_ADDR_Mask	0x00000007fffff000ul
 #define IOC_IO_ExcpStat_RW_Mask		0x0000000000000800ul
 #define IOC_IO_ExcpStat_IOID_Mask	0x00000000000007fful
@@ -247,17 +247,18 @@
 
 static irqreturn_t ioc_interrupt(int irq, void *data)
 {
-	unsigned long stat;
+	unsigned long stat, spf;
 	struct cbe_iommu *iommu = data;
 
 	stat = in_be64(iommu->xlate_regs + IOC_IO_ExcpStat);
+	spf = stat & IOC_IO_ExcpStat_SPF_Mask;
 
 	/* Might want to rate limit it */
 	printk(KERN_ERR "iommu: DMA exception 0x%016lx\n", stat);
 	printk(KERN_ERR "  V=%d, SPF=[%c%c], RW=%s, IOID=0x%04x\n",
 	       !!(stat & IOC_IO_ExcpStat_V),
-	       (stat & IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ',
-	       (stat & IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ',
+	       (spf == IOC_IO_ExcpStat_SPF_S) ? 'S' : ' ',
+	       (spf == IOC_IO_ExcpStat_SPF_P) ? 'P' : ' ',
 	       (stat & IOC_IO_ExcpStat_RW_Mask) ? "Read" : "Write",
 	       (unsigned int)(stat & IOC_IO_ExcpStat_IOID_Mask));
 	printk(KERN_ERR "  page=0x%016lx\n",
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c
index be84e6a..c5ce02e 100644
--- a/arch/powerpc/platforms/cell/qpace_setup.c
+++ b/arch/powerpc/platforms/cell/qpace_setup.c
@@ -81,16 +81,6 @@
 }
 machine_subsys_initcall(qpace, qpace_publish_devices);
 
-extern int qpace_notify(struct device *dev)
-{
-	/* set dma_ops for of_platform bus */
-	if (dev->bus && dev->bus->name
-			&& !strcmp(dev->bus->name, "of_platform"))
-		set_dma_ops(dev, &dma_direct_ops);
-
-	return 0;
-}
-
 static void __init qpace_setup_arch(void)
 {
 #ifdef CONFIG_SPU_BASE
@@ -115,9 +105,6 @@
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
-
-	/* set notifier function */
-	platform_notify = &qpace_notify;
 }
 
 static int __init qpace_probe(void)
@@ -141,6 +128,8 @@
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.get_boot_time		= rtas_get_boot_time,
+	.get_rtc_time		= rtas_get_rtc_time,
+	.set_rtc_time		= rtas_set_rtc_time,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= qpace_progress,
 	.init_IRQ		= iic_init_IRQ,
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index e487ad6..9abd210 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -114,7 +114,7 @@
 	int nr = (NR_CPUS > 1) ? NR_CPUS : NR_CPUS + 1;
 
 	/* Global TLBIE broadcast required with SPEs. */
-	__cpus_setall(&mm->cpu_vm_mask, nr);
+	bitmap_fill(cpumask_bits(mm_cpumask(mm)), nr);
 }
 
 void spu_associate_mm(struct spu *spu, struct mm_struct *mm)
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
index c8b1cd4..95d8dad 100644
--- a/arch/powerpc/platforms/cell/spu_fault.c
+++ b/arch/powerpc/platforms/cell/spu_fault.c
@@ -39,60 +39,56 @@
 	unsigned long is_write;
 	int ret;
 
-#if 0
-	if (!IS_VALID_EA(ea)) {
+	if (mm == NULL)
 		return -EFAULT;
-	}
-#endif /* XXX */
-	if (mm == NULL) {
+
+	if (mm->pgd == NULL)
 		return -EFAULT;
-	}
-	if (mm->pgd == NULL) {
-		return -EFAULT;
-	}
 
 	down_read(&mm->mmap_sem);
+	ret = -EFAULT;
 	vma = find_vma(mm, ea);
 	if (!vma)
-		goto bad_area;
-	if (vma->vm_start <= ea)
-		goto good_area;
-	if (!(vma->vm_flags & VM_GROWSDOWN))
-		goto bad_area;
-	if (expand_stack(vma, ea))
-		goto bad_area;
-good_area:
+		goto out_unlock;
+
+	if (ea < vma->vm_start) {
+		if (!(vma->vm_flags & VM_GROWSDOWN))
+			goto out_unlock;
+		if (expand_stack(vma, ea))
+			goto out_unlock;
+	}
+
 	is_write = dsisr & MFC_DSISR_ACCESS_PUT;
 	if (is_write) {
 		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;
+			goto out_unlock;
 	} else {
 		if (dsisr & MFC_DSISR_ACCESS_DENIED)
-			goto bad_area;
+			goto out_unlock;
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-			goto bad_area;
+			goto out_unlock;
 	}
+
 	ret = 0;
 	*flt = handle_mm_fault(mm, vma, ea, is_write);
 	if (unlikely(*flt & VM_FAULT_ERROR)) {
 		if (*flt & VM_FAULT_OOM) {
 			ret = -ENOMEM;
-			goto bad_area;
+			goto out_unlock;
 		} else if (*flt & VM_FAULT_SIGBUS) {
 			ret = -EFAULT;
-			goto bad_area;
+			goto out_unlock;
 		}
 		BUG();
 	}
+
 	if (*flt & VM_FAULT_MAJOR)
 		current->maj_flt++;
 	else
 		current->min_flt++;
+
+out_unlock:
 	up_read(&mm->mmap_sem);
 	return ret;
-
-bad_area:
-	up_read(&mm->mmap_sem);
-	return -EFAULT;
 }
 EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 6653ddb..db5398c 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -35,6 +35,8 @@
 struct spu_context *alloc_spu_context(struct spu_gang *gang)
 {
 	struct spu_context *ctx;
+	struct timespec ts;
+
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
 		goto out;
@@ -64,6 +66,8 @@
 	__spu_update_sched_info(ctx);
 	spu_set_timeslice(ctx);
 	ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
+	ktime_get_ts(&ts);
+	ctx->stats.tstamp = timespec_to_ns(&ts);
 
 	atomic_inc(&nr_spu_contexts);
 	goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 0da7f2b..d6a519e 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -568,16 +568,17 @@
 	struct spu_lscsa *lscsa = ctx->csa.lscsa;
 	int ret;
 
-	size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
-	if (size <= 0)
+	if (*pos >= sizeof(lscsa->gprs))
 		return -EFBIG;
+
+	size = min_t(ssize_t, sizeof(lscsa->gprs) - *pos, size);
 	*pos += size;
 
 	ret = spu_acquire_saved(ctx);
 	if (ret)
 		return ret;
 
-	ret = copy_from_user(lscsa->gprs + *pos - size,
+	ret = copy_from_user((char *)lscsa->gprs + *pos - size,
 			     buffer, size) ? -EFAULT : size;
 
 	spu_release_saved(ctx);
@@ -623,10 +624,11 @@
 	struct spu_lscsa *lscsa = ctx->csa.lscsa;
 	int ret;
 
-	size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
-	if (size <= 0)
+	if (*pos >= sizeof(lscsa->fpcr))
 		return -EFBIG;
 
+	size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
+
 	ret = spu_acquire_saved(ctx);
 	if (ret)
 		return ret;
@@ -2665,7 +2667,7 @@
 	.release        = single_release,
 };
 
-struct spufs_tree_descr spufs_dir_contents[] = {
+const struct spufs_tree_descr spufs_dir_contents[] = {
 	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, LS_SIZE, },
 	{ "regs", &spufs_regs_fops,  0666, sizeof(struct spu_reg128[128]), },
@@ -2706,7 +2708,7 @@
 	{},
 };
 
-struct spufs_tree_descr spufs_dir_nosched_contents[] = {
+const struct spufs_tree_descr spufs_dir_nosched_contents[] = {
 	{ "capabilities", &spufs_caps_fops, 0444, },
 	{ "mem",  &spufs_mem_fops,  0666, LS_SIZE, },
 	{ "mbox", &spufs_mbox_fops, 0444, },
@@ -2731,12 +2733,12 @@
 	{},
 };
 
-struct spufs_tree_descr spufs_dir_debug_contents[] = {
+const struct spufs_tree_descr spufs_dir_debug_contents[] = {
 	{ ".ctx", &spufs_ctx_fops, 0444, },
 	{},
 };
 
-struct spufs_coredump_reader spufs_coredump_read[] = {
+const struct spufs_coredump_reader spufs_coredump_read[] = {
 	{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
 	{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
 	{ "lslr", NULL, spufs_lslr_get, 19 },
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e309ef7..64f0685 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -186,8 +186,9 @@
 	return simple_rmdir(parent, dir);
 }
 
-static int spufs_fill_dir(struct dentry *dir, struct spufs_tree_descr *files,
-			  int mode, struct spu_context *ctx)
+static int spufs_fill_dir(struct dentry *dir,
+		const struct spufs_tree_descr *files, int mode,
+		struct spu_context *ctx)
 {
 	struct dentry *dentry, *tmp;
 	int ret;
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c58bd36..4ddf769 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -117,6 +117,9 @@
 		cond_resched();
 	}
 
+	/* clear purge status */
+	out_be64(mfc_cntl, 0);
+
 	/* put the SPE in kernel mode to allow access to the loader */
 	sr1 = spu_mfc_sr1_get(ctx->spu);
 	sr1 &= ~MFC_STATE1_PROBLEM_STATE_MASK;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 3bf908e..ae31573 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -241,9 +241,9 @@
 	size_t size;
 };
 
-extern struct spufs_tree_descr spufs_dir_contents[];
-extern struct spufs_tree_descr spufs_dir_nosched_contents[];
-extern struct spufs_tree_descr spufs_dir_debug_contents[];
+extern const struct spufs_tree_descr spufs_dir_contents[];
+extern const struct spufs_tree_descr spufs_dir_nosched_contents[];
+extern const struct spufs_tree_descr spufs_dir_debug_contents[];
 
 /* system call implementation */
 extern struct spufs_calls spufs_calls;
@@ -358,7 +358,7 @@
 	u64 (*get)(struct spu_context *ctx);
 	size_t size;
 };
-extern struct spufs_coredump_reader spufs_coredump_read[];
+extern const struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
 extern int spu_init_csa(struct spu_state *csa);
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig
index 22b4b4e..37d438b 100644
--- a/arch/powerpc/platforms/chrp/Kconfig
+++ b/arch/powerpc/platforms/chrp/Kconfig
@@ -1,6 +1,6 @@
 config PPC_CHRP
 	bool "Common Hardware Reference Platform (CHRP) based machines"
-	depends on PPC_MULTIPLATFORM && PPC32
+	depends on 6xx
 	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c
index 130ff72..039fc8e 100644
--- a/arch/powerpc/platforms/chrp/pegasos_eth.c
+++ b/arch/powerpc/platforms/chrp/pegasos_eth.c
@@ -21,8 +21,8 @@
 #define PEGASOS2_SRAM_BASE 			(0xf2000000)
 #define PEGASOS2_SRAM_SIZE			(256*1024)
 
-#define PEGASOS2_SRAM_BASE_ETH0			(PEGASOS2_SRAM_BASE)
-#define PEGASOS2_SRAM_BASE_ETH1			(PEGASOS2_SRAM_BASE_ETH0 + (PEGASOS2_SRAM_SIZE / 2) )
+#define PEGASOS2_SRAM_BASE_ETH_PORT0			(PEGASOS2_SRAM_BASE)
+#define PEGASOS2_SRAM_BASE_ETH_PORT1			(PEGASOS2_SRAM_BASE_ETH_PORT0 + (PEGASOS2_SRAM_SIZE / 2) )
 
 
 #define PEGASOS2_SRAM_RXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
@@ -47,75 +47,42 @@
 	.resource	= mv643xx_eth_shared_resources,
 };
 
-static struct resource mv643xx_eth0_resources[] = {
+static struct resource mv643xx_eth_port1_resources[] = {
 	[0] = {
-		.name	= "eth0 irq",
+		.name	= "eth port1 irq",
 		.start	= 9,
 		.end	= 9,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
 
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.shared		= &mv643xx_eth_shared_device,
-	.port_number	= 0,
-
-	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH0,
-	.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
-	.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
-
-	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH0 + PEGASOS2_SRAM_TXRING_SIZE,
-	.rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
-	.rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth0_resources),
-	.resource	= mv643xx_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv643xx_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= 9,
-		.end	= 9,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
+static struct mv643xx_eth_platform_data eth_port1_pd = {
 	.shared		= &mv643xx_eth_shared_device,
 	.port_number	= 1,
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(7),
 
-	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH1,
+	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1,
 	.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
 	.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
 
-	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH1 + PEGASOS2_SRAM_TXRING_SIZE,
+	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1 + PEGASOS2_SRAM_TXRING_SIZE,
 	.rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
 	.rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
 };
 
-static struct platform_device eth1_device = {
+static struct platform_device eth_port1_device = {
 	.name		= MV643XX_ETH_NAME,
 	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth1_resources),
-	.resource	= mv643xx_eth1_resources,
+	.num_resources	= ARRAY_SIZE(mv643xx_eth_port1_resources),
+	.resource	= mv643xx_eth_port1_resources,
 	.dev = {
-		.platform_data = &eth1_pd,
+		.platform_data = &eth_port1_pd,
 	},
 };
 
 static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
 	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
+	&eth_port1_device,
 };
 
 /***********/
@@ -191,15 +158,10 @@
 
 		if ( Enable_SRAM() < 0)
 		{
-			eth0_pd.tx_sram_addr = 0;
-			eth0_pd.tx_sram_size = 0;
-			eth0_pd.rx_sram_addr = 0;
-			eth0_pd.rx_sram_size = 0;
-
-			eth1_pd.tx_sram_addr = 0;
-			eth1_pd.tx_sram_size = 0;
-			eth1_pd.rx_sram_addr = 0;
-			eth1_pd.rx_sram_size = 0;
+			eth_port1_pd.tx_sram_addr = 0;
+			eth_port1_pd.tx_sram_size = 0;
+			eth_port1_pd.rx_sram_addr = 0;
+			eth_port1_pd.rx_sram_size = 0;
 
 #ifdef BE_VERBOSE
 			printk("Pegasos II/Marvell MV64361: Can't enable the "
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 4f9f818..291ac9d 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -1,6 +1,6 @@
 config EMBEDDED6xx
 	bool "Embedded 6xx/7xx/7xxx-based boards"
-	depends on PPC32 && BROKEN_ON_SMP && PPC_MULTIPLATFORM
+	depends on 6xx && BROKEN_ON_SMP
 
 config LINKSTATION
 	bool "Linkstation / Kurobox(HG) from Buffalo"
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 7ddd0a2..647e877 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -1,6 +1,6 @@
 config PPC_ISERIES
 	bool "IBM Legacy iSeries"
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	select PPC_INDIRECT_IO
 	select PPC_PCI_CHOICE if EMBEDDED
 
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 701d929..94f4447 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -214,7 +214,7 @@
 	unsigned long flags;
 
 	for_each_irq (irq) {
-		irq_desc_t *desc = get_irq_desc(irq);
+		struct irq_desc *desc = get_irq_desc(irq);
 
 		if (desc && desc->chip && desc->chip->startup) {
 			spin_lock_irqsave(&desc->lock, flags);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 24519b9..a6cd339 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -617,7 +617,7 @@
 }
 
 static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size,
-				     unsigned long flags)
+				     unsigned long flags, void *caller)
 {
 	return (void __iomem *)address;
 }
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
index a6467a5..1ea621a 100644
--- a/arch/powerpc/platforms/maple/Kconfig
+++ b/arch/powerpc/platforms/maple/Kconfig
@@ -1,5 +1,5 @@
 config PPC_MAPLE
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	bool "Maple 970FX Evaluation Board"
 	select PCI
 	select MPIC
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 348e061..a2aeb32 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -1,5 +1,5 @@
 config PPC_PASEMI
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	bool "PA Semi SoC-based platforms"
 	default n
 	select MPIC
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
index 055990c..1e1a087 100644
--- a/arch/powerpc/platforms/powermac/Kconfig
+++ b/arch/powerpc/platforms/powermac/Kconfig
@@ -1,6 +1,6 @@
 config PPC_PMAC
 	bool "Apple PowerMac based machines"
-	depends on PPC_MULTIPLATFORM
+	depends on PPC_BOOK3S
 	select MPIC
 	select PCI
 	select PPC_INDIRECT_PCI if PPC32
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index beb3833..22ecfbe 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -86,6 +86,7 @@
 
 static DEFINE_MUTEX(g5_switch_mutex);
 
+static unsigned long transition_latency;
 
 #ifdef CONFIG_PMAC_SMU
 
@@ -357,7 +358,7 @@
 
 static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	policy->cpuinfo.transition_latency = transition_latency;
 	policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
 	/* secondary CPUs are tied to the primary one by the
 	 * cpufreq core if in the secondary policy we tell it that
@@ -500,6 +501,7 @@
 	g5_cpu_freqs[1].frequency = max_freq/2;
 
 	/* Set callbacks */
+	transition_latency = 12000;
 	g5_switch_freq = g5_scom_switch_freq;
 	g5_query_freq = g5_scom_query_freq;
 	freq_method = "SCOM";
@@ -675,6 +677,7 @@
 	g5_cpu_freqs[1].frequency = min_freq;
 
 	/* Set callbacks */
+	transition_latency = CPUFREQ_ETERNAL;
 	g5_switch_volt = g5_pfunc_switch_volt;
 	g5_switch_freq = g5_pfunc_switch_freq;
 	g5_query_freq = g5_pfunc_query_freq;
diff --git a/arch/powerpc/platforms/powermac/pic.h b/arch/powerpc/platforms/powermac/pic.h
index c44c89f..d622a83 100644
--- a/arch/powerpc/platforms/powermac/pic.h
+++ b/arch/powerpc/platforms/powermac/pic.h
@@ -3,7 +3,7 @@
 
 #include <linux/irq.h>
 
-extern struct hw_interrupt_type pmac_pic;
+extern struct irq_chip pmac_pic;
 
 extern void pmac_pic_init(void);
 extern int pmac_get_irq(void);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 9b78f53..45936c9 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -746,4 +746,7 @@
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64)
 	.cpu_die		= pmac_cpu_die,
 #endif
+#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+	.cpu_die		= generic_mach_cpu_die,
+#endif
 };
diff --git a/arch/powerpc/platforms/prep/Kconfig b/arch/powerpc/platforms/prep/Kconfig
index 29d4112..bf8330e 100644
--- a/arch/powerpc/platforms/prep/Kconfig
+++ b/arch/powerpc/platforms/prep/Kconfig
@@ -1,6 +1,6 @@
 config PPC_PREP
 	bool "PowerPC Reference Platform (PReP) based machines"
-	depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
+	depends on 6xx && BROKEN
 	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 740ef56..dfe316b 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -1,6 +1,6 @@
 config PPC_PS3
 	bool "Sony PS3"
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	select PPC_CELL
 	select USB_ARCH_HAS_OHCI
 	select USB_OHCI_LITTLE_ENDIAN
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index d281cc0..9a2b6d9 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -311,7 +311,7 @@
 	result = add_memory(0, start_addr, map.r1.size);
 
 	if (result) {
-		DBG("%s:%d: add_memory failed: (%d)\n",
+		pr_err("%s:%d: add_memory failed: (%d)\n",
 			__func__, __LINE__, result);
 		return result;
 	}
@@ -322,7 +322,7 @@
 	result = online_pages(start_pfn, nr_pages);
 
 	if (result)
-		DBG("%s:%d: online_pages failed: (%d)\n",
+		pr_err("%s:%d: online_pages failed: (%d)\n",
 			__func__, __LINE__, result);
 
 	return result;
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index ddc2a30..f0e6f28 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -1,5 +1,5 @@
 config PPC_PSERIES
-	depends on PPC_MULTIPLATFORM && PPC64
+	depends on PPC64 && PPC_BOOK3S
 	bool "IBM pSeries & new (POWER5-based) iSeries"
 	select MPIC
 	select PPC_I8259
@@ -25,6 +25,11 @@
 	depends on PPC_PSERIES && PCI
 	default y if !EMBEDDED
 
+config PSERIES_MSI
+       bool
+       depends on PCI_MSI && EEH
+       default y
+
 config SCANLOG
 	tristate "Scanlog dump interface"
 	depends on RTAS_PROC && PPC_PSERIES
@@ -63,3 +68,13 @@
 	  makes sense for a system running in an LPAR where the unused pages
 	  will be reused for other LPARs. The interface allows firmware to
 	  balance memory across many LPARs.
+
+config DTL
+	bool "Dispatch Trace Log"
+	depends on PPC_SPLPAR && DEBUG_FS
+	help
+	  SPLPAR machines can log hypervisor preempt & dispatch events to a
+	  kernel buffer. Saying Y here will enable logging these events,
+	  which are accessible through a debugfs file.
+
+	  Say N if you are unsure.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index dfe574a..790c0b8 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_KEXEC)	+= kexec.o
 obj-$(CONFIG_PCI)	+= pci.o pci_dlpar.o
-obj-$(CONFIG_PCI_MSI)	+= msi.o
+obj-$(CONFIG_PSERIES_MSI)	+= msi.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
 obj-$(CONFIG_MEMORY_HOTPLUG)	+= hotplug-memory.o
@@ -25,3 +25,4 @@
 obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
 obj-$(CONFIG_PHYP_DUMP)	+= phyp_dump.o
 obj-$(CONFIG_CMM)		+= cmm.o
+obj-$(CONFIG_DTL)		+= dtl.o
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
new file mode 100644
index 0000000..fafcaa0
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/dtl.c
@@ -0,0 +1,278 @@
+/*
+ * Virtual Processor Dispatch Trace Log
+ *
+ * (C) Copyright IBM Corporation 2009
+ *
+ * Author: Jeremy Kerr <jk@ozlabs.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, 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/init.h>
+#include <linux/debugfs.h>
+#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "plpar_wrappers.h"
+
+/*
+ * Layout of entries in the hypervisor's DTL buffer. Although we don't
+ * actually access the internals of an entry (we only need to know the size),
+ * we might as well define it here for reference.
+ */
+struct dtl_entry {
+	u8	dispatch_reason;
+	u8	preempt_reason;
+	u16	processor_id;
+	u32	enqueue_to_dispatch_time;
+	u32	ready_to_enqueue_time;
+	u32	waiting_to_ready_time;
+	u64	timebase;
+	u64	fault_addr;
+	u64	srr0;
+	u64	srr1;
+};
+
+struct dtl {
+	struct dtl_entry	*buf;
+	struct dentry		*file;
+	int			cpu;
+	int			buf_entries;
+	u64			last_idx;
+};
+static DEFINE_PER_CPU(struct dtl, dtl);
+
+/*
+ * Dispatch trace log event mask:
+ * 0x7: 0x1: voluntary virtual processor waits
+ *      0x2: time-slice preempts
+ *      0x4: virtual partition memory page faults
+ */
+static u8 dtl_event_mask = 0x7;
+
+
+/*
+ * Size of per-cpu log buffers. Default is just under 16 pages worth.
+ */
+static int dtl_buf_entries = (16 * 85);
+
+
+static int dtl_enable(struct dtl *dtl)
+{
+	unsigned long addr;
+	int ret, hwcpu;
+
+	/* only allow one reader */
+	if (dtl->buf)
+		return -EBUSY;
+
+	/* we need to store the original allocation size for use during read */
+	dtl->buf_entries = dtl_buf_entries;
+
+	dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry),
+			GFP_KERNEL, cpu_to_node(dtl->cpu));
+	if (!dtl->buf) {
+		printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
+				__func__, dtl->cpu);
+		return -ENOMEM;
+	}
+
+	/* Register our dtl buffer with the hypervisor. The HV expects the
+	 * buffer size to be passed in the second word of the buffer */
+	((u32 *)dtl->buf)[1] = dtl->buf_entries * sizeof(struct dtl_entry);
+
+	hwcpu = get_hard_smp_processor_id(dtl->cpu);
+	addr = __pa(dtl->buf);
+	ret = register_dtl(hwcpu, addr);
+	if (ret) {
+		printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
+		       "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
+		kfree(dtl->buf);
+		return -EIO;
+	}
+
+	/* set our initial buffer indices */
+	dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0;
+
+	/* ensure that our updates to the lppaca fields have occurred before
+	 * we actually enable the logging */
+	smp_wmb();
+
+	/* enable event logging */
+	lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask;
+
+	return 0;
+}
+
+static void dtl_disable(struct dtl *dtl)
+{
+	int hwcpu = get_hard_smp_processor_id(dtl->cpu);
+
+	lppaca[dtl->cpu].dtl_enable_mask = 0x0;
+
+	unregister_dtl(hwcpu, __pa(dtl->buf));
+
+	kfree(dtl->buf);
+	dtl->buf = NULL;
+	dtl->buf_entries = 0;
+}
+
+/* file interface */
+
+static int dtl_file_open(struct inode *inode, struct file *filp)
+{
+	struct dtl *dtl = inode->i_private;
+	int rc;
+
+	rc = dtl_enable(dtl);
+	if (rc)
+		return rc;
+
+	filp->private_data = dtl;
+	return 0;
+}
+
+static int dtl_file_release(struct inode *inode, struct file *filp)
+{
+	struct dtl *dtl = inode->i_private;
+	dtl_disable(dtl);
+	return 0;
+}
+
+static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
+		loff_t *pos)
+{
+	int rc, cur_idx, last_idx, n_read, n_req, read_size;
+	struct dtl *dtl;
+
+	if ((len % sizeof(struct dtl_entry)) != 0)
+		return -EINVAL;
+
+	dtl = filp->private_data;
+
+	/* requested number of entries to read */
+	n_req = len / sizeof(struct dtl_entry);
+
+	/* actual number of entries read */
+	n_read = 0;
+
+	cur_idx = lppaca[dtl->cpu].dtl_idx;
+	last_idx = dtl->last_idx;
+
+	if (cur_idx - last_idx > dtl->buf_entries) {
+		pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n",
+				__func__, dtl->cpu);
+	}
+
+	cur_idx  %= dtl->buf_entries;
+	last_idx %= dtl->buf_entries;
+
+	/* read the tail of the buffer if we've wrapped */
+	if (last_idx > cur_idx) {
+		read_size = min(n_req, dtl->buf_entries - last_idx);
+
+		rc = copy_to_user(buf, &dtl->buf[last_idx],
+				read_size * sizeof(struct dtl_entry));
+		if (rc)
+			return -EFAULT;
+
+		last_idx = 0;
+		n_req -= read_size;
+		n_read += read_size;
+		buf += read_size * sizeof(struct dtl_entry);
+	}
+
+	/* .. and now the head */
+	read_size = min(n_req, cur_idx - last_idx);
+	rc = copy_to_user(buf, &dtl->buf[last_idx],
+			read_size * sizeof(struct dtl_entry));
+	if (rc)
+		return -EFAULT;
+
+	n_read += read_size;
+	dtl->last_idx += n_read;
+
+	return n_read * sizeof(struct dtl_entry);
+}
+
+static struct file_operations dtl_fops = {
+	.open		= dtl_file_open,
+	.release	= dtl_file_release,
+	.read		= dtl_file_read,
+	.llseek		= no_llseek,
+};
+
+static struct dentry *dtl_dir;
+
+static int dtl_setup_file(struct dtl *dtl)
+{
+	char name[10];
+
+	sprintf(name, "cpu-%d", dtl->cpu);
+
+	dtl->file = debugfs_create_file(name, 0400, dtl_dir, dtl, &dtl_fops);
+	if (!dtl->file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int dtl_init(void)
+{
+	struct dentry *event_mask_file, *buf_entries_file;
+	int rc, i;
+
+	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+		return -ENODEV;
+
+	/* set up common debugfs structure */
+
+	rc = -ENOMEM;
+	dtl_dir = debugfs_create_dir("dtl", powerpc_debugfs_root);
+	if (!dtl_dir) {
+		printk(KERN_WARNING "%s: can't create dtl root dir\n",
+				__func__);
+		goto err;
+	}
+
+	event_mask_file = debugfs_create_x8("dtl_event_mask", 0600,
+				dtl_dir, &dtl_event_mask);
+	buf_entries_file = debugfs_create_u32("dtl_buf_entries", 0600,
+				dtl_dir, &dtl_buf_entries);
+
+	if (!event_mask_file || !buf_entries_file) {
+		printk(KERN_WARNING "%s: can't create dtl files\n", __func__);
+		goto err_remove_dir;
+	}
+
+	/* set up the per-cpu log structures */
+	for_each_possible_cpu(i) {
+		struct dtl *dtl = &per_cpu(dtl, i);
+		dtl->cpu = i;
+
+		rc = dtl_setup_file(dtl);
+		if (rc)
+			goto err_remove_dir;
+	}
+
+	return 0;
+
+err_remove_dir:
+	debugfs_remove_recursive(dtl_dir);
+err:
+	return rc;
+}
+arch_initcall(dtl_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 0ad56ff..380420f 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -79,6 +79,40 @@
 	return rc;
 }
 
+/**
+ * eeh_disable_irq - disable interrupt for the recovering device
+ */
+static void eeh_disable_irq(struct pci_dev *dev)
+{
+	struct device_node *dn = pci_device_to_OF_node(dev);
+
+	/* Don't disable MSI and MSI-X interrupts. They are
+	 * effectively disabled by the DMA Stopped state
+	 * when an EEH error occurs.
+	*/
+	if (dev->msi_enabled || dev->msix_enabled)
+		return;
+
+	if (!irq_in_use(dev->irq))
+		return;
+
+	PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+	disable_irq_nosync(dev->irq);
+}
+
+/**
+ * eeh_enable_irq - enable interrupt for the recovering device
+ */
+static void eeh_enable_irq(struct pci_dev *dev)
+{
+	struct device_node *dn = pci_device_to_OF_node(dev);
+
+	if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+		enable_irq(dev->irq);
+	}
+}
+
 /* ------------------------------------------------------- */
 /**
  * eeh_report_error - report pci error to each device driver
@@ -98,11 +132,8 @@
 	if (!driver)
 		return;
 
-	if (irq_in_use (dev->irq)) {
-		struct device_node *dn = pci_device_to_OF_node(dev);
-		PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
-		disable_irq_nosync(dev->irq);
-	}
+	eeh_disable_irq(dev);
+
 	if (!driver->err_handler ||
 	    !driver->err_handler->error_detected)
 		return;
@@ -147,15 +178,12 @@
 {
 	enum pci_ers_result rc, *res = userdata;
 	struct pci_driver *driver = dev->driver;
-	struct device_node *dn = pci_device_to_OF_node(dev);
 
 	if (!driver)
 		return;
 
-	if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
-		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
-		enable_irq(dev->irq);
-	}
+	eeh_enable_irq(dev);
+
 	if (!driver->err_handler ||
 	    !driver->err_handler->slot_reset)
 		return;
@@ -174,17 +202,14 @@
 static void eeh_report_resume(struct pci_dev *dev, void *userdata)
 {
 	struct pci_driver *driver = dev->driver;
-	struct device_node *dn = pci_device_to_OF_node(dev);
 
 	dev->error_state = pci_channel_io_normal;
 
 	if (!driver)
 		return;
 
-	if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
-		PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
-		enable_irq(dev->irq);
-	}
+	eeh_enable_irq(dev);
+
 	if (!driver->err_handler ||
 	    !driver->err_handler->resume)
 		return;
@@ -208,15 +233,12 @@
 	if (!driver)
 		return;
 
-	if (irq_in_use (dev->irq)) {
-		struct device_node *dn = pci_device_to_OF_node(dev);
-		PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
-		disable_irq_nosync(dev->irq);
-	}
-	if (!driver->err_handler)
+	eeh_disable_irq(dev);
+
+	if (!driver->err_handler ||
+	    !driver->err_handler->error_detected)
 		return;
-	if (!driver->err_handler->error_detected)
-		return;
+
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 }
 
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index f15222b..bf2e1ac 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -71,11 +71,13 @@
 	} while (rtas_busy_delay(rc));
 
 	/*
-	 * If the RTAS call succeeded, check the number of irqs is actually
-	 * what we asked for. If not, return an error.
+	 * If the RTAS call succeeded, return the number of irqs allocated.
+	 * If not, make sure we return a negative error code.
 	 */
-	if (rc == 0 && rtas_ret[0] != num_irqs)
-		rc = -ENOSPC;
+	if (rc == 0)
+		rc = rtas_ret[0];
+	else if (rc > 0)
+		rc = -rc;
 
 	pr_debug("rtas_msi: ibm,change_msi(func=%d,num=%d), got %d rc = %d\n",
 		 func, num_irqs, rtas_ret[0], rc);
@@ -91,7 +93,7 @@
 	if (!pdn)
 		return;
 
-	if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0))
+	if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
 		pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
 }
 
@@ -132,7 +134,7 @@
 	rtas_disable_msi(pdev);
 }
 
-static int check_req_msi(struct pci_dev *pdev, int nvec)
+static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 {
 	struct device_node *dn;
 	struct pci_dn *pdn;
@@ -144,26 +146,235 @@
 
 	dn = pdn->node;
 
-	req_msi = of_get_property(dn, "ibm,req#msi", NULL);
+	req_msi = of_get_property(dn, prop_name, NULL);
 	if (!req_msi) {
-		pr_debug("rtas_msi: No ibm,req#msi on %s\n", dn->full_name);
+		pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
 		return -ENOENT;
 	}
 
 	if (*req_msi < nvec) {
-		pr_debug("rtas_msi: ibm,req#msi requests < %d MSIs\n", nvec);
-		return -ENOSPC;
+		pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
+
+		if (*req_msi == 0) /* Be paranoid */
+			return -ENOSPC;
+
+		return *req_msi;
 	}
 
 	return 0;
 }
 
+static int check_req_msi(struct pci_dev *pdev, int nvec)
+{
+	return check_req(pdev, nvec, "ibm,req#msi");
+}
+
+static int check_req_msix(struct pci_dev *pdev, int nvec)
+{
+	return check_req(pdev, nvec, "ibm,req#msi-x");
+}
+
+/* Quota calculation */
+
+static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
+{
+	struct device_node *dn;
+	const u32 *p;
+
+	dn = of_node_get(pci_device_to_OF_node(dev));
+	while (dn) {
+		p = of_get_property(dn, "ibm,pe-total-#msi", NULL);
+		if (p) {
+			pr_debug("rtas_msi: found prop on dn %s\n",
+				dn->full_name);
+			*total = *p;
+			return dn;
+		}
+
+		dn = of_get_next_parent(dn);
+	}
+
+	return NULL;
+}
+
+static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
+{
+	struct device_node *dn;
+
+	/* Found our PE and assume 8 at that point. */
+
+	dn = pci_device_to_OF_node(dev);
+	if (!dn)
+		return NULL;
+
+	dn = find_device_pe(dn);
+	if (!dn)
+		return NULL;
+
+	/* We actually want the parent */
+	dn = of_get_parent(dn);
+	if (!dn)
+		return NULL;
+
+	/* Hardcode of 8 for old firmwares */
+	*total = 8;
+	pr_debug("rtas_msi: using PE dn %s\n", dn->full_name);
+
+	return dn;
+}
+
+struct msi_counts {
+	struct device_node *requestor;
+	int num_devices;
+	int request;
+	int quota;
+	int spare;
+	int over_quota;
+};
+
+static void *count_non_bridge_devices(struct device_node *dn, void *data)
+{
+	struct msi_counts *counts = data;
+	const u32 *p;
+	u32 class;
+
+	pr_debug("rtas_msi: counting %s\n", dn->full_name);
+
+	p = of_get_property(dn, "class-code", NULL);
+	class = p ? *p : 0;
+
+	if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
+		counts->num_devices++;
+
+	return NULL;
+}
+
+static void *count_spare_msis(struct device_node *dn, void *data)
+{
+	struct msi_counts *counts = data;
+	const u32 *p;
+	int req;
+
+	if (dn == counts->requestor)
+		req = counts->request;
+	else {
+		/* We don't know if a driver will try to use MSI or MSI-X,
+		 * so we just have to punt and use the larger of the two. */
+		req = 0;
+		p = of_get_property(dn, "ibm,req#msi", NULL);
+		if (p)
+			req = *p;
+
+		p = of_get_property(dn, "ibm,req#msi-x", NULL);
+		if (p)
+			req = max(req, (int)*p);
+	}
+
+	if (req < counts->quota)
+		counts->spare += counts->quota - req;
+	else if (req > counts->quota)
+		counts->over_quota++;
+
+	return NULL;
+}
+
+static int msi_quota_for_device(struct pci_dev *dev, int request)
+{
+	struct device_node *pe_dn;
+	struct msi_counts counts;
+	int total;
+
+	pr_debug("rtas_msi: calc quota for %s, request %d\n", pci_name(dev),
+		  request);
+
+	pe_dn = find_pe_total_msi(dev, &total);
+	if (!pe_dn)
+		pe_dn = find_pe_dn(dev, &total);
+
+	if (!pe_dn) {
+		pr_err("rtas_msi: couldn't find PE for %s\n", pci_name(dev));
+		goto out;
+	}
+
+	pr_debug("rtas_msi: found PE %s\n", pe_dn->full_name);
+
+	memset(&counts, 0, sizeof(struct msi_counts));
+
+	/* Work out how many devices we have below this PE */
+	traverse_pci_devices(pe_dn, count_non_bridge_devices, &counts);
+
+	if (counts.num_devices == 0) {
+		pr_err("rtas_msi: found 0 devices under PE for %s\n",
+			pci_name(dev));
+		goto out;
+	}
+
+	counts.quota = total / counts.num_devices;
+	if (request <= counts.quota)
+		goto out;
+
+	/* else, we have some more calculating to do */
+	counts.requestor = pci_device_to_OF_node(dev);
+	counts.request = request;
+	traverse_pci_devices(pe_dn, count_spare_msis, &counts);
+
+	/* If the quota isn't an integer multiple of the total, we can
+	 * use the remainder as spare MSIs for anyone that wants them. */
+	counts.spare += total % counts.num_devices;
+
+	/* Divide any spare by the number of over-quota requestors */
+	if (counts.over_quota)
+		counts.quota += counts.spare / counts.over_quota;
+
+	/* And finally clamp the request to the possibly adjusted quota */
+	request = min(counts.quota, request);
+
+	pr_debug("rtas_msi: request clamped to quota %d\n", request);
+out:
+	of_node_put(pe_dn);
+
+	return request;
+}
+
 static int rtas_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 {
-	if (type == PCI_CAP_ID_MSIX)
-		pr_debug("rtas_msi: MSI-X untested, trying anyway.\n");
+	int quota, rc;
 
-	return check_req_msi(pdev, nvec);
+	if (type == PCI_CAP_ID_MSIX)
+		rc = check_req_msix(pdev, nvec);
+	else
+		rc = check_req_msi(pdev, nvec);
+
+	if (rc)
+		return rc;
+
+	quota = msi_quota_for_device(pdev, nvec);
+
+	if (quota && quota < nvec)
+		return quota;
+
+	return 0;
+}
+
+static int check_msix_entries(struct pci_dev *pdev)
+{
+	struct msi_desc *entry;
+	int expected;
+
+	/* There's no way for us to express to firmware that we want
+	 * a discontiguous, or non-zero based, range of MSI-X entries.
+	 * So we must reject such requests. */
+
+	expected = 0;
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (entry->msi_attrib.entry_nr != expected) {
+			pr_debug("rtas_msi: bad MSI-X entries.\n");
+			return -EINVAL;
+		}
+		expected++;
+	}
+
+	return 0;
 }
 
 static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
@@ -177,6 +388,9 @@
 	if (!pdn)
 		return -ENODEV;
 
+	if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
+		return -EINVAL;
+
 	/*
 	 * Try the new more explicit firmware interface, if that fails fall
 	 * back to the old interface. The old interface is known to never
@@ -185,21 +399,21 @@
 	if (type == PCI_CAP_ID_MSI) {
 		rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
 
-		if (rc) {
+		if (rc < 0) {
 			pr_debug("rtas_msi: trying the old firmware call.\n");
 			rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec);
 		}
 	} else
 		rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
 
-	if (rc) {
+	if (rc != nvec) {
 		pr_debug("rtas_msi: rtas_change_msi() failed\n");
 		return rc;
 	}
 
 	i = 0;
 	list_for_each_entry(entry, &pdev->msi_list, list) {
-		hwirq = rtas_query_irq_number(pdn, i);
+		hwirq = rtas_query_irq_number(pdn, i++);
 		if (hwirq < 0) {
 			pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
 			return hwirq;
@@ -234,8 +448,8 @@
 	}
 
 	/* No MSI -> MSIs can't have been assigned by fw, leave LSI */
-	if (check_req_msi(pdev, 1)) {
-		dev_dbg(&pdev->dev, "rtas_msi: no req#msi, nothing to do.\n");
+	if (check_req_msi(pdev, 1) && check_req_msix(pdev, 1)) {
+		dev_dbg(&pdev->dev, "rtas_msi: no req#msi/x, nothing to do.\n");
 		return;
 	}
 
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 5e1ed3d..ad152a0 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -137,11 +137,9 @@
 struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
 {
 	struct pci_controller *phb;
-	int primary;
 
 	pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name);
 
-	primary = list_empty(&hose_list);
 	phb = pcibios_alloc_controller(dn);
 	if (!phb)
 		return NULL;
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d967c18..a24a6b23 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -43,6 +43,16 @@
 	return vpa_call(0x3, cpu, vpa);
 }
 
+static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
+{
+	return vpa_call(0x6, cpu, vpa);
+}
+
+static inline long register_dtl(unsigned long cpu, unsigned long vpa)
+{
+	return vpa_call(0x2, cpu, vpa);
+}
+
 static inline long plpar_page_set_loaned(unsigned long vpa)
 {
 	unsigned long cmo_page_sz = cmo_get_page_size();
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index c591a25..b6f1b13 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -468,9 +468,13 @@
 
 		rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
 						  action, value);
+		if (rc == NOTIFY_BAD) {
+			rc = prom_update_property(np, oldprop, newprop);
+			return -ENOMEM;
+		}
 	}
 
-	return rc;
+	return 0;
 }
 
 /**
diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c
index f1c3395..fd969f0 100644
--- a/arch/powerpc/sysdev/cpm2.c
+++ b/arch/powerpc/sysdev/cpm2.c
@@ -52,6 +52,7 @@
  * the communication processor devices.
  */
 cpm2_map_t __iomem *cpm2_immr;
+EXPORT_SYMBOL(cpm2_immr);
 
 #define CPM_MAP_SIZE	(0x40000)	/* 256k - the PQ3 reserve this amount
 					   of space for CPM as it is larger
@@ -129,7 +130,8 @@
 		brg -= 4;
 	}
 	bp += brg;
-	val = (((clk / rate) - 1) << 1) | CPM_BRG_EN | src;
+	/* Round the clock divider to the nearest integer. */
+	val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src;
 	if (div16)
 		val |= CPM_BRG_DIV16;
 
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 00d3d17..e4b6d66 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -56,7 +56,7 @@
 {
 	if (cpm_udbg_txdesc) {
 #ifdef CONFIG_CPM2
-		setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO);
+		setbat(1, 0xf0000000, 0xf0000000, 1024*1024, PAGE_KERNEL_NCG);
 #endif
 		udbg_putc = udbg_putc_cpm;
 	}
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 9817f63..78021d8 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -1,12 +1,16 @@
 /*
  * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007,2008 Freescale Semiconductor, Inc
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
  * Recode: ZHANG WEI <wei.zhang@freescale.com>
  * Rewrite the routing for Frescale PCI and PCI Express
  * 	Roy Zang <tie-fei.zang@freescale.com>
+ * MPC83xx PCI-Express support:
+ * 	Tony Li <tony.li@freescale.com>
+ * 	Anton Vorontsov <avorontsov@ru.mvista.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
@@ -27,6 +31,29 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
+static int fsl_pcie_bus_fixup;
+
+static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
+{
+	/* if we aren't a PCIe don't bother */
+	if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+		return;
+
+	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+	fsl_pcie_bus_fixup = 1;
+	return;
+}
+
+static int __init fsl_pcie_check_link(struct pci_controller *hose)
+{
+	u32 val;
+
+	early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+	if (val < PCIE_LTSSM_L0)
+		return 1;
+	return 0;
+}
+
 #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
 static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
 	unsigned int index, const struct resource *res,
@@ -159,28 +186,6 @@
 #endif
 }
 
-static int fsl_pcie_bus_fixup;
-
-static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
-{
-	/* if we aren't a PCIe don't bother */
-	if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
-		return ;
-
-	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
-	fsl_pcie_bus_fixup = 1;
-	return ;
-}
-
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
-{
-	u32 val;
-	early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
-	if (val < PCIE_LTSSM_L0)
-		return 1;
-	return 0;
-}
-
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -294,8 +299,184 @@
 #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header);
+
+struct mpc83xx_pcie_priv {
+	void __iomem *cfg_type0;
+	void __iomem *cfg_type1;
+	u32 dev_base;
+};
+
+/*
+ * With the convention of u-boot, the PCIE outbound window 0 serves
+ * as configuration transactions outbound.
+ */
+#define PEX_OUTWIN0_BAR		0xCA4
+#define PEX_OUTWIN0_TAL		0xCA8
+#define PEX_OUTWIN0_TAH		0xCAC
+
+static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
+{
+	struct pci_controller *hose = bus->sysdata;
+
+	if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Workaround for the HW bug: for Type 0 configure transactions the
+	 * PCI-E controller does not check the device number bits and just
+	 * assumes that the device number bits are 0.
+	 */
+	if (bus->number == hose->first_busno ||
+			bus->primary == hose->first_busno) {
+		if (devfn & 0xf8)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (ppc_md.pci_exclude_device) {
+		if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
+					    unsigned int devfn, int offset)
+{
+	struct pci_controller *hose = bus->sysdata;
+	struct mpc83xx_pcie_priv *pcie = hose->dn->data;
+	u8 bus_no = bus->number - hose->first_busno;
+	u32 dev_base = bus_no << 24 | devfn << 16;
+	int ret;
+
+	ret = mpc83xx_pcie_exclude_device(bus, devfn);
+	if (ret)
+		return NULL;
+
+	offset &= 0xfff;
+
+	/* Type 0 */
+	if (bus->number == hose->first_busno)
+		return pcie->cfg_type0 + offset;
+
+	if (pcie->dev_base == dev_base)
+		goto mapped;
+
+	out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, dev_base);
+
+	pcie->dev_base = dev_base;
+mapped:
+	return pcie->cfg_type1 + offset;
+}
+
+static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+				    int offset, int len, u32 *val)
+{
+	void __iomem *cfg_addr;
+
+	cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
+	if (!cfg_addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 1:
+		*val = in_8(cfg_addr);
+		break;
+	case 2:
+		*val = in_le16(cfg_addr);
+		break;
+	default:
+		*val = in_le32(cfg_addr);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				     int offset, int len, u32 val)
+{
+	void __iomem *cfg_addr;
+
+	cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
+	if (!cfg_addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	switch (len) {
+	case 1:
+		out_8(cfg_addr, val);
+		break;
+	case 2:
+		out_le16(cfg_addr, val);
+		break;
+	default:
+		out_le32(cfg_addr, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc83xx_pcie_ops = {
+	.read = mpc83xx_pcie_read_config,
+	.write = mpc83xx_pcie_write_config,
+};
+
+static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
+				     struct resource *reg)
+{
+	struct mpc83xx_pcie_priv *pcie;
+	u32 cfg_bar;
+	int ret = -ENOMEM;
+
+	pcie = zalloc_maybe_bootmem(sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return ret;
+
+	pcie->cfg_type0 = ioremap(reg->start, resource_size(reg));
+	if (!pcie->cfg_type0)
+		goto err0;
+
+	cfg_bar = in_le32(pcie->cfg_type0 + PEX_OUTWIN0_BAR);
+	if (!cfg_bar) {
+		/* PCI-E isn't configured. */
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	pcie->cfg_type1 = ioremap(cfg_bar, 0x1000);
+	if (!pcie->cfg_type1)
+		goto err1;
+
+	WARN_ON(hose->dn->data);
+	hose->dn->data = pcie;
+	hose->ops = &mpc83xx_pcie_ops;
+
+	out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
+	out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
+
+	if (fsl_pcie_check_link(hose))
+		hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+	return 0;
+err1:
+	iounmap(pcie->cfg_type0);
+err0:
+	kfree(pcie);
+	return ret;
+
+}
+
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
+	int ret;
 	int len;
 	struct pci_controller *hose;
 	struct resource rsrc_reg;
@@ -303,6 +484,11 @@
 	const int *bus_range;
 	int primary;
 
+	if (!of_device_is_available(dev)) {
+		pr_warning("%s: disabled by the firmware.\n",
+			   dev->full_name);
+		return -ENODEV;
+	}
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
 	/* Fetch host bridge registers address */
@@ -350,7 +536,14 @@
 	hose->first_busno = bus_range ? bus_range[0] : 0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-	setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0);
+	if (of_device_is_compatible(dev, "fsl,mpc8314-pcie")) {
+		ret = mpc83xx_pcie_setup(hose, &rsrc_reg);
+		if (ret)
+			goto err0;
+	} else {
+		setup_indirect_pci(hose, rsrc_cfg.start,
+				   rsrc_cfg.start + 4, 0);
+	}
 
 	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
 	       "Firmware bus number: %d->%d\n",
@@ -365,5 +558,8 @@
 	pci_process_bridge_OF_ranges(hose, dev, primary);
 
 	return 0;
+err0:
+	pcibios_free_controller(hose);
+	return ret;
 }
 #endif /* CONFIG_PPC_83xx */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 115cb16..a01c89d 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
@@ -328,6 +329,9 @@
 		struct fsl_usb2_platform_data usb_data;
 		const unsigned char *prop = NULL;
 
+		if (!of_device_is_available(np))
+			continue;
+
 		memset(&r, 0, sizeof(r));
 		memset(&usb_data, 0, sizeof(usb_data));
 
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 9a89cd3..a86d3ce 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -568,8 +568,7 @@
 
 	spin_lock_irqsave(&ipic_lock, flags);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].ack);
-	temp |= (1 << (31 - ipic_info[src].bit));
+	temp = 1 << (31 - ipic_info[src].bit);
 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
 
 	/* mb() can't guarantee that ack is finished.  But it does finish
@@ -592,8 +591,7 @@
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].ack);
-	temp |= (1 << (31 - ipic_info[src].bit));
+	temp = 1 << (31 - ipic_info[src].bit);
 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
 
 	/* mb() can't guarantee that ack is finished.  But it does finish
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index f84217b..5a32cbe 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -141,7 +141,7 @@
 #define check(x)	\
 	if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
 
-void test_basics(void)
+void __init test_basics(void)
 {
 	struct msi_bitmap bmp;
 	int i, size = 512;
@@ -186,7 +186,7 @@
 	kfree(bmp.bitmap);
 }
 
-void test_of_node(void)
+void __init test_of_node(void)
 {
 	u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 };
 	const char *expected_str = "0-9,20-24,28-39,41-99,220-255";
@@ -234,7 +234,7 @@
 	kfree(bmp.bitmap);
 }
 
-int msi_bitmap_selftest(void)
+int __init msi_bitmap_selftest(void)
 {
 	printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n");
 
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index c858749..aaa9159 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -50,7 +50,7 @@
 
 static struct pmi_data *data;
 
-static int pmi_irq_handler(int irq, void *dev_id)
+static irqreturn_t pmi_irq_handler(int irq, void *dev_id)
 {
 	u8 type;
 	int rc;
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 5558d93..6a2d473 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1839,6 +1839,8 @@
 {
 	struct device_node *np;
 
+	ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+
 #ifdef CONFIG_PPC4xx_PCI_EXPRESS
 	for_each_compatible_node(np, NULL, "ibm,plb-pciex")
 		ppc4xx_probe_pciex_bridge(np);
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index a64e388..e27655b 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -310,7 +310,8 @@
 
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
 	.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
+	SOCAM_DATAWIDTH_8,
 };
 
 static struct resource ceu_resources[] = {
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 94c0296..6f94f17 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -229,7 +229,7 @@
 static struct i2c_pca9564_pf_platform_data i2c_platform_data = {
 	.gpio			= 0,
 	.i2c_clock_speed	= I2C_PCA_CON_330kHz,
-	.timeout		= 100,
+	.timeout		= HZ,
 };
 
 static struct platform_device i2c_device = {
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index bc35b4c..4fd6a72 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -352,8 +352,9 @@
 }
 
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
-	.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
-	| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
+	.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING
+	| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH
+	| SOCAM_DATA_ACTIVE_HIGH,
 };
 
 static struct resource migor_ceu_resources[] = {
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c9012b9..45161b8 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -787,6 +787,11 @@
 	   Additional support for AMD specific MCE features such as
 	   the DRAM Error Threshold.
 
+config X86_MCE_THRESHOLD
+	depends on X86_MCE_AMD || X86_MCE_INTEL
+	bool
+	default y
+
 config X86_MCE_NONFATAL
 	tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
 	depends on X86_32 && X86_MCE
@@ -930,6 +935,12 @@
 	  with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
 	  /dev/cpu/31/cpuid.
 
+config X86_CPU_DEBUG
+	tristate "/sys/kernel/debug/x86/cpu/* - CPU Debug support"
+	---help---
+	  If you select this option, this will provide various x86 CPUs
+	  information through debugfs.
+
 choice
 	prompt "High Memory Support"
 	default HIGHMEM4G if !X86_NUMAQ
@@ -1122,7 +1133,7 @@
 
 config NODES_SHIFT
 	int "Maximum NUMA Nodes (as a power of 2)" if !MAXSMP
-	range 1 9   if X86_64
+	range 1 9
 	default "9" if MAXSMP
 	default "6" if X86_64
 	default "4" if X86_NUMAQ
@@ -1430,7 +1441,7 @@
 config KEXEC_JUMP
 	bool "kexec jump (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	depends on KEXEC && HIBERNATION && X86_32
+	depends on KEXEC && HIBERNATION
 	---help---
 	  Jump between original kernel and kexeced kernel and invoke
 	  code in physical address mode via KEXEC
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index a95eaf0..924e156 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -456,24 +456,9 @@
 
 	  If unsure, say N.
 
-config CPU_SUP_CENTAUR_32
+config CPU_SUP_CENTAUR
 	default y
 	bool "Support Centaur processors" if PROCESSOR_SELECT
-	depends on !64BIT
-	---help---
-	  This enables detection, tunings and quirks for Centaur processors
-
-	  You need this enabled if you want your kernel to run on a
-	  Centaur CPU. Disabling this option on other types of CPUs
-	  makes the kernel a tiny bit smaller. Disabling it on a Centaur
-	  CPU might render the kernel unbootable.
-
-	  If unsure, say N.
-
-config CPU_SUP_CENTAUR_64
-	default y
-	bool "Support Centaur processors" if PROCESSOR_SELECT
-	depends on 64BIT
 	---help---
 	  This enables detection, tunings and quirks for Centaur processors
 
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 1836191..f05d8c9 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -153,34 +153,23 @@
 
 boot := arch/x86/boot
 
-PHONY += zImage bzImage compressed zlilo bzlilo \
-         zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
+BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage install
+
+PHONY += bzImage $(BOOT_TARGETS)
 
 # Default kernel to build
 all: bzImage
 
 # KBUILD_IMAGE specify target image being built
-                    KBUILD_IMAGE := $(boot)/bzImage
-zImage zlilo zdisk: KBUILD_IMAGE := $(boot)/zImage
+KBUILD_IMAGE := $(boot)/bzImage
 
-zImage bzImage: vmlinux
+bzImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
 	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
 	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@
 
-compressed: zImage
-
-zlilo bzlilo: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
-
-zdisk bzdisk: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
-
-fdimage fdimage144 fdimage288 isoimage: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
-
-install:
-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
+$(BOOT_TARGETS): vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $@
 
 PHONY += vdso_install
 vdso_install:
@@ -205,7 +194,3 @@
   echo  '                  FDARGS="..."  arguments for the booted kernel'
   echo  '                  FDINITRD=file initrd for the booted kernel'
 endef
-
-CLEAN_FILES += arch/x86/boot/fdimage \
-	       arch/x86/boot/image.iso \
-	       arch/x86/boot/mtools.conf
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index c70eff6..fb737ce 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -6,26 +6,24 @@
 # for more details.
 #
 # Copyright (C) 1994 by Linus Torvalds
+# Changed by many, many contributors over the years.
 #
 
 # ROOT_DEV specifies the default root-device when making the image.
 # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
 # the default of FLOPPY is used by 'build'.
 
-ROOT_DEV := CURRENT
+ROOT_DEV	:= CURRENT
 
 # If you want to preset the SVGA mode, uncomment the next line and
 # set SVGA_MODE to whatever number you want.
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
 # The number is the same as you would ordinarily press at bootup.
 
-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
+SVGA_MODE	:= -DSVGA_MODE=NORMAL_VGA
 
-# If you want the RAM disk device, define this to be the size in blocks.
-
-#RAMDISK := -DRAMDISK=512
-
-targets		:= vmlinux.bin setup.bin setup.elf zImage bzImage
+targets		:= vmlinux.bin setup.bin setup.elf bzImage
+targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-		:= compressed
 
 setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
@@ -71,17 +69,13 @@
 KBUILD_CFLAGS +=   $(call cc-option,-m32)
 KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
 
-$(obj)/zImage:  asflags-y := $(SVGA_MODE) $(RAMDISK)
-$(obj)/bzImage: ccflags-y := -D__BIG_KERNEL__
-$(obj)/bzImage: asflags-y := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
-$(obj)/bzImage: BUILDFLAGS   := -b
+$(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \
-	    $(obj)/vmlinux.bin $(ROOT_DEV) > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
+	$(ROOT_DEV) > $@
 
-$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \
-			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
+$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
 	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
@@ -116,9 +110,11 @@
 $(obj)/compressed/vmlinux: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
-# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
+# Set this if you want to pass append arguments to the
+# bzdisk/fdimage/isoimage kernel
 FDARGS =
-# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
+# Set this if you want an initrd included with the
+# bzdisk/fdimage/isoimage kernel
 FDINITRD =
 
 image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
@@ -127,7 +123,7 @@
 	sed -e 's|@OBJ@|$(obj)|g' < $< > $@
 
 # This requires write access to /dev/fd0
-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+bzdisk: $(obj)/bzImage $(obj)/mtools.conf
 	MTOOLSRC=$(obj)/mtools.conf mformat a:			; sync
 	syslinux /dev/fd0					; sync
 	echo '$(image_cmdline)' | \
@@ -135,10 +131,10 @@
 	if [ -f '$(FDINITRD)' ] ; then \
 		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
 	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux	; sync
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(obj)/bzImage a:linux	; sync
 
 # These require being root or having syslinux 2.02 or higher installed
-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+fdimage fdimage144: $(obj)/bzImage $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
 	MTOOLSRC=$(obj)/mtools.conf mformat v:			; sync
 	syslinux $(obj)/fdimage					; sync
@@ -147,9 +143,9 @@
 	if [ -f '$(FDINITRD)' ] ; then \
 		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
 	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux	; sync
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(obj)/bzImage v:linux	; sync
 
-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+fdimage288: $(obj)/bzImage $(obj)/mtools.conf
 	dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
 	MTOOLSRC=$(obj)/mtools.conf mformat w:			; sync
 	syslinux $(obj)/fdimage					; sync
@@ -158,9 +154,9 @@
 	if [ -f '$(FDINITRD)' ] ; then \
 		MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
 	fi
-	MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux	; sync
+	MTOOLSRC=$(obj)/mtools.conf mcopy $(obj)/bzImage w:linux	; sync
 
-isoimage: $(BOOTIMAGE)
+isoimage: $(obj)/bzImage
 	-rm -rf $(obj)/isoimage
 	mkdir $(obj)/isoimage
 	for i in lib lib64 share end ; do \
@@ -170,7 +166,7 @@
 		fi ; \
 		if [ $$i = end ] ; then exit 1 ; fi ; \
 	done
-	cp $(BOOTIMAGE) $(obj)/isoimage/linux
+	cp $(obj)/bzImage $(obj)/isoimage/linux
 	echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
 	if [ -f '$(FDINITRD)' ] ; then \
 		cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
@@ -181,12 +177,13 @@
 	isohybrid $(obj)/image.iso 2>/dev/null || true
 	rm -rf $(obj)/isoimage
 
-zlilo: $(BOOTIMAGE)
+bzlilo: $(obj)/bzImage
 	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
 	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-	cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
+	cat $(obj)/bzImage > $(INSTALL_PATH)/vmlinuz
 	cp System.map $(INSTALL_PATH)/
 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
 install:
-	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
+	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
+		System.map "$(INSTALL_PATH)"
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 7ccff48..5d84d1c 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -24,12 +24,8 @@
 #include "boot.h"
 #include "offsets.h"
 
-SETUPSECTS	= 4			/* default nr of setup-sectors */
 BOOTSEG		= 0x07C0		/* original address of boot-sector */
-SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
-SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
-					/* to be loaded */
-ROOT_DEV	= 0			/* ROOT_DEV is now written by "build" */
+SYSSEG		= 0x1000		/* historical load address >> 4 */
 
 #ifndef SVGA_MODE
 #define SVGA_MODE ASK_VGA
@@ -97,12 +93,12 @@
 	.section ".header", "a"
 	.globl	hdr
 hdr:
-setup_sects:	.byte SETUPSECTS
+setup_sects:	.byte 0			/* Filled in by build.c */
 root_flags:	.word ROOT_RDONLY
-syssize:	.long SYSSIZE
-ram_size:	.word RAMDISK
+syssize:	.long 0			/* Filled in by build.c */
+ram_size:	.word 0			/* Obsolete */
 vid_mode:	.word SVGA_MODE
-root_dev:	.word ROOT_DEV
+root_dev:	.word 0			/* Filled in by build.c */
 boot_flag:	.word 0xAA55
 
 	# offset 512, entry point
@@ -123,14 +119,15 @@
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
-start_sys_seg:	.word	SYSSEG
+start_sys_seg:	.word	SYSSEG		# obsolete and meaningless, but just
+					# in case something decided to "use" it
 		.word	kernel_version-512 # pointing to kernel version string
 					# above section of header is compatible
 					# with loadlin-1.5 (header v1.5). Don't
 					# change it.
 
-type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
-					#      Bootlin, SYSLX, bootsect...)
+type_of_loader:	.byte	0		# 0 means ancient bootloader, newer
+					# bootloaders know to change this.
 					# See Documentation/i386/boot.txt for
 					# assigned ids
 
@@ -142,11 +139,7 @@
 					# space behind setup.S can be used for
 					# heap purposes.
 					# Only the loader knows what is free
-#ifndef __BIG_KERNEL__
-		.byte	0
-#else
 		.byte	LOADED_HIGH
-#endif
 
 setup_move_size: .word  0x8000		# size to move, when setup is not
 					# loaded at 0x90000. We will move setup
@@ -157,11 +150,7 @@
 
 code32_start:				# here loaders can put a different
 					# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
-		.long	0x1000		#   0x1000 = default for zImage
-#else
 		.long	0x100000	# 0x100000 = default for big kernel
-#endif
 
 ramdisk_image:	.long	0		# address of loaded ramdisk image
 					# Here the loader puts the 32-bit
diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
index 85a1cd8..8062f89 100644
--- a/arch/x86/boot/pm.c
+++ b/arch/x86/boot/pm.c
@@ -33,47 +33,6 @@
 }
 
 /*
- * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000.
- * A bzImage kernel is loaded and runs at 0x100000.
- */
-static void move_kernel_around(void)
-{
-	/* Note: rely on the compile-time option here rather than
-	   the LOADED_HIGH flag.  The Qemu kernel loader unconditionally
-	   sets the loadflags to zero. */
-#ifndef __BIG_KERNEL__
-	u16 dst_seg, src_seg;
-	u32 syssize;
-
-	dst_seg =  0x1000 >> 4;
-	src_seg = 0x10000 >> 4;
-	syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */
-
-	while (syssize) {
-		int paras  = (syssize >= 0x1000) ? 0x1000 : syssize;
-		int dwords = paras << 2;
-
-		asm volatile("pushw %%es ; "
-			     "pushw %%ds ; "
-			     "movw %1,%%es ; "
-			     "movw %2,%%ds ; "
-			     "xorw %%di,%%di ; "
-			     "xorw %%si,%%si ; "
-			     "rep;movsl ; "
-			     "popw %%ds ; "
-			     "popw %%es"
-			     : "+c" (dwords)
-			     : "r" (dst_seg), "r" (src_seg)
-			     : "esi", "edi");
-
-		syssize -= paras;
-		dst_seg += paras;
-		src_seg += paras;
-	}
-#endif
-}
-
-/*
  * Disable all interrupts at the legacy PIC.
  */
 static void mask_all_interrupts(void)
@@ -147,9 +106,6 @@
 	/* Hook before leaving real mode, also disables interrupts */
 	realmode_switch_hook();
 
-	/* Move the kernel/setup to their final resting places */
-	move_kernel_around();
-
 	/* Enable the A20 gate */
 	if (enable_a20()) {
 		puts("A20 gate not responding, unable to boot...\n");
diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
index 019c17a..3e0edc6 100644
--- a/arch/x86/boot/pmjump.S
+++ b/arch/x86/boot/pmjump.S
@@ -47,6 +47,7 @@
 ENDPROC(protected_mode_jump)
 
 	.code32
+	.section ".text32","ax"
 GLOBAL(in_pm32)
 	# Set up data segments for flat 32-bit mode
 	movl	%ecx, %ds
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
index df9234b..bb8dc2d 100644
--- a/arch/x86/boot/setup.ld
+++ b/arch/x86/boot/setup.ld
@@ -17,7 +17,8 @@
 	.header		: { *(.header) }
 	.inittext	: { *(.inittext) }
 	.initdata	: { *(.initdata) }
-	.text		: { *(.text*) }
+	.text		: { *(.text) }
+	.text32		: { *(.text32) }
 
 	. = ALIGN(16);
 	.rodata		: { *(.rodata*) }
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 44dc192..ee3a4ea 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -130,7 +130,7 @@
 
 static void usage(void)
 {
-	die("Usage: build [-b] setup system [rootdev] [> image]");
+	die("Usage: build setup system [rootdev] [> image]");
 }
 
 int main(int argc, char ** argv)
@@ -145,11 +145,6 @@
 	void *kernel;
 	u32 crc = 0xffffffffUL;
 
-	if (argc > 2 && !strcmp(argv[1], "-b"))
-	  {
-	    is_big_kernel = 1;
-	    argc--, argv++;
-	  }
 	if ((argc < 3) || (argc > 4))
 		usage();
 	if (argc > 3) {
@@ -216,8 +211,6 @@
 		die("Unable to mmap '%s': %m", argv[2]);
 	/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
 	sys_size = (sz + 15 + 4) / 16;
-	if (!is_big_kernel && sys_size > DEF_SYSSIZE)
-		die("System is too big. Try using bzImage or modules.");
 
 	/* Patch the setup code with the appropriate size parameters */
 	buf[0x1f1] = setup_sectors-1;
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index 5d4742e..95d86ce 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -129,41 +129,45 @@
 	return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
 }
 
-static void vga_set_480_scanlines(int end)
+static void vga_set_480_scanlines(int lines)
 {
-	u16 crtc;
-	u8  csel;
+	u16 crtc;		/* CRTC base address */
+	u8  csel;		/* CRTC miscellaneous output register */
+	u8  ovfw;		/* CRTC overflow register */
+	int end = lines-1;
 
 	crtc = vga_crtc();
 
+	ovfw = 0x3c | ((end >> (8-1)) & 0x02) | ((end >> (9-6)) & 0x40);
+
 	out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
 	out_idx(0x0b, crtc, 0x06); /* Vertical total */
-	out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
+	out_idx(ovfw, crtc, 0x07); /* Vertical overflow */
 	out_idx(0xea, crtc, 0x10); /* Vertical sync start */
-	out_idx(end, crtc, 0x12); /* Vertical display end */
+	out_idx(end,  crtc, 0x12); /* Vertical display end */
 	out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
 	out_idx(0x04, crtc, 0x16); /* Vertical blank end */
 	csel = inb(0x3cc);
 	csel &= 0x0d;
 	csel |= 0xe2;
-	outb(csel, 0x3cc);
+	outb(csel, 0x3c2);
 }
 
 static void vga_set_80x30(void)
 {
-	vga_set_480_scanlines(0xdf);
+	vga_set_480_scanlines(30*16);
 }
 
 static void vga_set_80x34(void)
 {
 	vga_set_14font();
-	vga_set_480_scanlines(0xdb);
+	vga_set_480_scanlines(34*14);
 }
 
 static void vga_set_80x60(void)
 {
 	vga_set_8font();
-	vga_set_480_scanlines(0xdf);
+	vga_set_480_scanlines(60*8);
 }
 
 static int vga_set_mode(struct mode_info *mode)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 4ef949c..df8a300 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -75,7 +75,7 @@
 #define setup_secondary_clock setup_secondary_APIC_clock
 #endif
 
-#ifdef CONFIG_X86_VSMP
+#ifdef CONFIG_X86_64
 extern int is_vsmp_box(void);
 #else
 static inline int is_vsmp_box(void)
@@ -108,6 +108,16 @@
 extern u64 native_apic_icr_read(void);
 
 #ifdef CONFIG_X86_X2APIC
+/*
+ * Make previous memory operations globally visible before
+ * sending the IPI through x2apic wrmsr. We need a serializing instruction or
+ * mfence for this.
+ */
+static inline void x2apic_wrmsr_fence(void)
+{
+	asm volatile("mfence" : : : "memory");
+}
+
 static inline void native_apic_msr_write(u32 reg, u32 v)
 {
 	if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
@@ -184,6 +194,9 @@
 {
 	return 0;
 }
+
+#define	x2apic	0
+
 #endif
 
 extern int get_physical_broadcast(void);
@@ -379,6 +392,7 @@
 
 static inline void ack_APIC_irq(void)
 {
+#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	 * ack_APIC_irq() actually gets compiled as a single instruction
 	 * ... yummie.
@@ -386,6 +400,7 @@
 
 	/* Docs say use 0 for future compatibility */
 	apic_write(APIC_EOI, 0);
+#endif
 }
 
 static inline unsigned default_get_apic_id(unsigned long x)
@@ -474,10 +489,19 @@
 	return physid_isset(read_apic_id(), phys_cpu_present_map);
 }
 
+static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
+{
+	return cpuid_apic >> index_msb;
+}
+
+extern int default_apicid_to_node(int logical_apicid);
+
+#endif
+
 static inline unsigned int
 default_cpu_mask_to_apicid(const struct cpumask *cpumask)
 {
-	return cpumask_bits(cpumask)[0];
+	return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
 }
 
 static inline unsigned int
@@ -491,15 +515,6 @@
 	return (unsigned int)(mask1 & mask2 & mask3);
 }
 
-static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
-{
-	return cpuid_apic >> index_msb;
-}
-
-extern int default_apicid_to_node(int logical_apicid);
-
-#endif
-
 static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid)
 {
 	return physid_isset(apicid, bitmap);
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 63134e3..bc9514f 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -53,6 +53,7 @@
 #define		APIC_ESR_SENDILL	0x00020
 #define		APIC_ESR_RECVILL	0x00040
 #define		APIC_ESR_ILLREGA	0x00080
+#define 	APIC_LVTCMCI	0x2f0
 #define	APIC_ICR	0x300
 #define		APIC_DEST_SELF		0x40000
 #define		APIC_DEST_ALLINC	0x80000
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index 6526cf0..6ba23dd 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -1,10 +1,6 @@
 #ifndef _ASM_X86_BOOT_H
 #define _ASM_X86_BOOT_H
 
-/* Don't touch these, unless you really know what you're doing. */
-#define DEF_SYSSEG	0x1000
-#define DEF_SYSSIZE	0x7F00
-
 /* Internal svga startup constants */
 #define NORMAL_VGA	0xffff		/* 80x25 mode */
 #define EXTENDED_VGA	0xfffe		/* 80x50 mode */
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 5b301b7..b3894bf 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -90,6 +90,9 @@
 int set_memory_array_uc(unsigned long *addr, int addrinarray);
 int set_memory_array_wb(unsigned long *addr, int addrinarray);
 
+int set_pages_array_uc(struct page **pages, int addrinarray);
+int set_pages_array_wb(struct page **pages, int addrinarray);
+
 /*
  * For legacy compatibility with the old APIs, a few functions
  * are provided that work on a "struct page".
diff --git a/arch/x86/include/asm/cpu_debug.h b/arch/x86/include/asm/cpu_debug.h
new file mode 100755
index 0000000..2228020
--- /dev/null
+++ b/arch/x86/include/asm/cpu_debug.h
@@ -0,0 +1,226 @@
+#ifndef _ASM_X86_CPU_DEBUG_H
+#define _ASM_X86_CPU_DEBUG_H
+
+/*
+ * CPU x86 architecture debug
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ */
+
+/* Register flags */
+enum cpu_debug_bit {
+/* Model Specific Registers (MSRs)					*/
+	CPU_MC_BIT,				/* Machine Check	*/
+	CPU_MONITOR_BIT,			/* Monitor		*/
+	CPU_TIME_BIT,				/* Time			*/
+	CPU_PMC_BIT,				/* Performance Monitor	*/
+	CPU_PLATFORM_BIT,			/* Platform		*/
+	CPU_APIC_BIT,				/* APIC			*/
+	CPU_POWERON_BIT,			/* Power-on		*/
+	CPU_CONTROL_BIT,			/* Control		*/
+	CPU_FEATURES_BIT,			/* Features control	*/
+	CPU_LBRANCH_BIT,			/* Last Branch		*/
+	CPU_BIOS_BIT,				/* BIOS			*/
+	CPU_FREQ_BIT,				/* Frequency		*/
+	CPU_MTTR_BIT,				/* MTRR			*/
+	CPU_PERF_BIT,				/* Performance		*/
+	CPU_CACHE_BIT,				/* Cache		*/
+	CPU_SYSENTER_BIT,			/* Sysenter		*/
+	CPU_THERM_BIT,				/* Thermal		*/
+	CPU_MISC_BIT,				/* Miscellaneous	*/
+	CPU_DEBUG_BIT,				/* Debug		*/
+	CPU_PAT_BIT,				/* PAT			*/
+	CPU_VMX_BIT,				/* VMX			*/
+	CPU_CALL_BIT,				/* System Call		*/
+	CPU_BASE_BIT,				/* BASE Address		*/
+	CPU_VER_BIT,				/* Version ID		*/
+	CPU_CONF_BIT,				/* Configuration	*/
+	CPU_SMM_BIT,				/* System mgmt mode	*/
+	CPU_SVM_BIT,				/*Secure Virtual Machine*/
+	CPU_OSVM_BIT,				/* OS-Visible Workaround*/
+/* Standard Registers							*/
+	CPU_TSS_BIT,				/* Task Stack Segment	*/
+	CPU_CR_BIT,				/* Control Registers	*/
+	CPU_DT_BIT,				/* Descriptor Table	*/
+/* End of Registers flags						*/
+	CPU_REG_ALL_BIT,			/* Select all Registers	*/
+};
+
+#define	CPU_REG_ALL		(~0)		/* Select all Registers	*/
+
+#define	CPU_MC			(1 << CPU_MC_BIT)
+#define	CPU_MONITOR		(1 << CPU_MONITOR_BIT)
+#define	CPU_TIME		(1 << CPU_TIME_BIT)
+#define	CPU_PMC			(1 << CPU_PMC_BIT)
+#define	CPU_PLATFORM		(1 << CPU_PLATFORM_BIT)
+#define	CPU_APIC		(1 << CPU_APIC_BIT)
+#define	CPU_POWERON		(1 << CPU_POWERON_BIT)
+#define	CPU_CONTROL		(1 << CPU_CONTROL_BIT)
+#define	CPU_FEATURES		(1 << CPU_FEATURES_BIT)
+#define	CPU_LBRANCH		(1 << CPU_LBRANCH_BIT)
+#define	CPU_BIOS		(1 << CPU_BIOS_BIT)
+#define	CPU_FREQ		(1 << CPU_FREQ_BIT)
+#define	CPU_MTRR		(1 << CPU_MTTR_BIT)
+#define	CPU_PERF		(1 << CPU_PERF_BIT)
+#define	CPU_CACHE		(1 << CPU_CACHE_BIT)
+#define	CPU_SYSENTER		(1 << CPU_SYSENTER_BIT)
+#define	CPU_THERM		(1 << CPU_THERM_BIT)
+#define	CPU_MISC		(1 << CPU_MISC_BIT)
+#define	CPU_DEBUG		(1 << CPU_DEBUG_BIT)
+#define	CPU_PAT			(1 << CPU_PAT_BIT)
+#define	CPU_VMX			(1 << CPU_VMX_BIT)
+#define	CPU_CALL		(1 << CPU_CALL_BIT)
+#define	CPU_BASE		(1 << CPU_BASE_BIT)
+#define	CPU_VER			(1 << CPU_VER_BIT)
+#define	CPU_CONF		(1 << CPU_CONF_BIT)
+#define	CPU_SMM			(1 << CPU_SMM_BIT)
+#define	CPU_SVM			(1 << CPU_SVM_BIT)
+#define	CPU_OSVM		(1 << CPU_OSVM_BIT)
+#define	CPU_TSS			(1 << CPU_TSS_BIT)
+#define	CPU_CR			(1 << CPU_CR_BIT)
+#define	CPU_DT			(1 << CPU_DT_BIT)
+
+/* Register file flags */
+enum cpu_file_bit {
+	CPU_INDEX_BIT,				/* index		*/
+	CPU_VALUE_BIT,				/* value		*/
+};
+
+#define	CPU_FILE_VALUE			(1 << CPU_VALUE_BIT)
+
+/*
+ * DisplayFamily_DisplayModel	Processor Families/Processor Number Series
+ * --------------------------	------------------------------------------
+ * 05_01, 05_02, 05_04		Pentium, Pentium with MMX
+ *
+ * 06_01			Pentium Pro
+ * 06_03, 06_05			Pentium II Xeon, Pentium II
+ * 06_07, 06_08, 06_0A, 06_0B	Pentium III Xeon, Pentum III
+ *
+ * 06_09, 060D			Pentium M
+ *
+ * 06_0E			Core Duo, Core Solo
+ *
+ * 06_0F			Xeon 3000, 3200, 5100, 5300, 7300 series,
+ *				Core 2 Quad, Core 2 Extreme, Core 2 Duo,
+ *				Pentium dual-core
+ * 06_17			Xeon 5200, 5400 series, Core 2 Quad Q9650
+ *
+ * 06_1C			Atom
+ *
+ * 0F_00, 0F_01, 0F_02		Xeon, Xeon MP, Pentium 4
+ * 0F_03, 0F_04			Xeon, Xeon MP, Pentium 4, Pentium D
+ *
+ * 0F_06			Xeon 7100, 5000 Series, Xeon MP,
+ *				Pentium 4, Pentium D
+ */
+
+/* Register processors bits */
+enum cpu_processor_bit {
+	CPU_NONE,
+/* Intel */
+	CPU_INTEL_PENTIUM_BIT,
+	CPU_INTEL_P6_BIT,
+	CPU_INTEL_PENTIUM_M_BIT,
+	CPU_INTEL_CORE_BIT,
+	CPU_INTEL_CORE2_BIT,
+	CPU_INTEL_ATOM_BIT,
+	CPU_INTEL_XEON_P4_BIT,
+	CPU_INTEL_XEON_MP_BIT,
+/* AMD */
+	CPU_AMD_K6_BIT,
+	CPU_AMD_K7_BIT,
+	CPU_AMD_K8_BIT,
+	CPU_AMD_0F_BIT,
+	CPU_AMD_10_BIT,
+	CPU_AMD_11_BIT,
+};
+
+#define	CPU_INTEL_PENTIUM	(1 << CPU_INTEL_PENTIUM_BIT)
+#define	CPU_INTEL_P6		(1 << CPU_INTEL_P6_BIT)
+#define	CPU_INTEL_PENTIUM_M	(1 << CPU_INTEL_PENTIUM_M_BIT)
+#define	CPU_INTEL_CORE		(1 << CPU_INTEL_CORE_BIT)
+#define	CPU_INTEL_CORE2		(1 << CPU_INTEL_CORE2_BIT)
+#define	CPU_INTEL_ATOM		(1 << CPU_INTEL_ATOM_BIT)
+#define	CPU_INTEL_XEON_P4	(1 << CPU_INTEL_XEON_P4_BIT)
+#define	CPU_INTEL_XEON_MP	(1 << CPU_INTEL_XEON_MP_BIT)
+
+#define	CPU_INTEL_PX		(CPU_INTEL_P6 | CPU_INTEL_PENTIUM_M)
+#define	CPU_INTEL_COREX		(CPU_INTEL_CORE | CPU_INTEL_CORE2)
+#define	CPU_INTEL_XEON		(CPU_INTEL_XEON_P4 | CPU_INTEL_XEON_MP)
+#define	CPU_CO_AT		(CPU_INTEL_CORE | CPU_INTEL_ATOM)
+#define	CPU_C2_AT		(CPU_INTEL_CORE2 | CPU_INTEL_ATOM)
+#define	CPU_CX_AT		(CPU_INTEL_COREX | CPU_INTEL_ATOM)
+#define	CPU_CX_XE		(CPU_INTEL_COREX | CPU_INTEL_XEON)
+#define	CPU_P6_XE		(CPU_INTEL_P6 | CPU_INTEL_XEON)
+#define	CPU_PM_CO_AT		(CPU_INTEL_PENTIUM_M | CPU_CO_AT)
+#define	CPU_C2_AT_XE		(CPU_C2_AT | CPU_INTEL_XEON)
+#define	CPU_CX_AT_XE		(CPU_CX_AT | CPU_INTEL_XEON)
+#define	CPU_P6_CX_AT		(CPU_INTEL_P6 | CPU_CX_AT)
+#define	CPU_P6_CX_XE		(CPU_P6_XE | CPU_INTEL_COREX)
+#define	CPU_P6_CX_AT_XE		(CPU_INTEL_P6 | CPU_CX_AT_XE)
+#define	CPU_PM_CX_AT_XE		(CPU_INTEL_PENTIUM_M | CPU_CX_AT_XE)
+#define	CPU_PM_CX_AT		(CPU_INTEL_PENTIUM_M | CPU_CX_AT)
+#define	CPU_PM_CX_XE		(CPU_INTEL_PENTIUM_M | CPU_CX_XE)
+#define	CPU_PX_CX_AT		(CPU_INTEL_PX | CPU_CX_AT)
+#define	CPU_PX_CX_AT_XE		(CPU_INTEL_PX | CPU_CX_AT_XE)
+
+/* Select all supported Intel CPUs */
+#define	CPU_INTEL_ALL		(CPU_INTEL_PENTIUM | CPU_PX_CX_AT_XE)
+
+#define	CPU_AMD_K6		(1 << CPU_AMD_K6_BIT)
+#define	CPU_AMD_K7		(1 << CPU_AMD_K7_BIT)
+#define	CPU_AMD_K8		(1 << CPU_AMD_K8_BIT)
+#define	CPU_AMD_0F		(1 << CPU_AMD_0F_BIT)
+#define	CPU_AMD_10		(1 << CPU_AMD_10_BIT)
+#define	CPU_AMD_11		(1 << CPU_AMD_11_BIT)
+
+#define	CPU_K10_PLUS		(CPU_AMD_10 | CPU_AMD_11)
+#define	CPU_K0F_PLUS		(CPU_AMD_0F | CPU_K10_PLUS)
+#define	CPU_K8_PLUS		(CPU_AMD_K8 | CPU_K0F_PLUS)
+#define	CPU_K7_PLUS		(CPU_AMD_K7 | CPU_K8_PLUS)
+
+/* Select all supported AMD CPUs */
+#define	CPU_AMD_ALL		(CPU_AMD_K6 | CPU_K7_PLUS)
+
+/* Select all supported CPUs */
+#define	CPU_ALL			(CPU_INTEL_ALL | CPU_AMD_ALL)
+
+#define MAX_CPU_FILES		512
+
+struct cpu_private {
+	unsigned		cpu;
+	unsigned		type;
+	unsigned		reg;
+	unsigned		file;
+};
+
+struct cpu_debug_base {
+	char			*name;		/* Register name	*/
+	unsigned		flag;		/* Register flag	*/
+	unsigned		write;		/* Register write flag	*/
+};
+
+/*
+ * Currently it looks similar to cpu_debug_base but once we add more files
+ * cpu_file_base will go in different direction
+ */
+struct cpu_file_base {
+	char			*name;		/* Register file name	*/
+	unsigned		flag;		/* Register file flag	*/
+	unsigned		write;		/* Register write flag	*/
+};
+
+struct cpu_cpuX_base {
+	struct dentry		*dentry;	/* Register dentry	*/
+	int			init;		/* Register index file	*/
+};
+
+struct cpu_debug_range {
+	unsigned		min;		/* Register range min	*/
+	unsigned		max;		/* Register range max	*/
+	unsigned		flag;		/* Supported flags	*/
+	unsigned		model;		/* Supported models	*/
+};
+
+#endif /* _ASM_X86_CPU_DEBUG_H */
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index dc27705..5623c50 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -91,7 +91,6 @@
 #define store_gdt(dtr) native_store_gdt(dtr)
 #define store_idt(dtr) native_store_idt(dtr)
 #define store_tr(tr) (tr = native_store_tr())
-#define store_ldt(ldt) asm("sldt %0":"=m" (ldt))
 
 #define load_TLS(t, cpu) native_load_tls(t, cpu)
 #define set_ldt native_set_ldt
@@ -112,6 +111,8 @@
 }
 #endif	/* CONFIG_PARAVIRT */
 
+#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
+
 static inline void native_write_idt_entry(gate_desc *idt, int entry,
 					  const gate_desc *gate)
 {
diff --git a/arch/x86/include/asm/dmi.h b/arch/x86/include/asm/dmi.h
index bc68212..fd8f9e2 100644
--- a/arch/x86/include/asm/dmi.h
+++ b/arch/x86/include/asm/dmi.h
@@ -1,22 +1,15 @@
 #ifndef _ASM_X86_DMI_H
 #define _ASM_X86_DMI_H
 
+#include <linux/compiler.h>
+#include <linux/init.h>
+
 #include <asm/io.h>
+#include <asm/setup.h>
 
-#define DMI_MAX_DATA 2048
-
-extern int dmi_alloc_index;
-extern char dmi_alloc_data[DMI_MAX_DATA];
-
-/* This is so early that there is no good way to allocate dynamic memory.
-   Allocate data in an BSS array. */
-static inline void *dmi_alloc(unsigned len)
+static __always_inline __init void *dmi_alloc(unsigned len)
 {
-	int idx = dmi_alloc_index;
-	if ((dmi_alloc_index + len) > DMI_MAX_DATA)
-		return NULL;
-	dmi_alloc_index += len;
-	return dmi_alloc_data + idx;
+	return extend_brk(len, sizeof(int));
 }
 
 /* Use early IO mappings for DMI because it's initialized early */
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 00d41ce..7ecba4d 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -72,7 +72,7 @@
 extern void e820_add_region(u64 start, u64 size, int type);
 extern void e820_print_map(char *who);
 extern int
-sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, int *pnr_map);
+sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
 extern u64 e820_update_range(u64 start, u64 size, unsigned old_type,
 			       unsigned new_type);
 extern u64 e820_remove_range(u64 start, u64 size, unsigned old_type,
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 854d538..c2e6bed 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -33,6 +33,8 @@
 		 smp_invalidate_interrupt)
 #endif
 
+BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR)
+
 /*
  * every pentium local APIC has two 'local interrupts', with a
  * soft-definable vector attached to both interrupts, one of
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index b55b4a7..db24c22 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -55,29 +55,4 @@
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-
-#ifndef __ASSEMBLY__
-
-/*
- * Stack of return addresses for functions
- * of a thread.
- * Used in struct thread_info
- */
-struct ftrace_ret_stack {
-	unsigned long ret;
-	unsigned long func;
-	unsigned long long calltime;
-};
-
-/*
- * Primary handler of a function return.
- * It relays on ftrace_return_to_handler.
- * Defined in entry_32/64.S
- */
-extern void return_to_handler(void);
-
-#endif /* __ASSEMBLY__ */
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-
 #endif /* _ASM_X86_FTRACE_H */
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 176f058..039db6a 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -12,6 +12,7 @@
 	unsigned int apic_timer_irqs;	/* arch dependent */
 	unsigned int irq_spurious_count;
 #endif
+	unsigned int generic_irqs;	/* arch dependent */
 #ifdef CONFIG_SMP
 	unsigned int irq_resched_count;
 	unsigned int irq_call_count;
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h
index bf9276b..014c2b8 100644
--- a/arch/x86/include/asm/highmem.h
+++ b/arch/x86/include/asm/highmem.h
@@ -63,6 +63,7 @@
 void *kmap_atomic(struct page *page, enum km_type type);
 void kunmap_atomic(void *kvaddr, enum km_type type);
 void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
 
 #ifndef CONFIG_PARAVIRT
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 370e1c8..b762ea4 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -27,6 +27,7 @@
 
 /* Interrupt handlers registered during init_IRQ */
 extern void apic_timer_interrupt(void);
+extern void generic_interrupt(void);
 extern void error_interrupt(void);
 extern void spurious_interrupt(void);
 extern void thermal_interrupt(void);
diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h
new file mode 100644
index 0000000..36fb1a6
--- /dev/null
+++ b/arch/x86/include/asm/init.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_X86_INIT_32_H
+#define _ASM_X86_INIT_32_H
+
+#ifdef CONFIG_X86_32
+extern void __init early_ioremap_page_table_range_init(void);
+#endif
+
+extern unsigned long __init
+kernel_physical_mapping_init(unsigned long start,
+			     unsigned long end,
+			     unsigned long page_size_mask);
+
+
+extern unsigned long __initdata e820_table_start;
+extern unsigned long __meminitdata e820_table_end;
+extern unsigned long __meminitdata e820_table_top;
+
+#endif /* _ASM_X86_INIT_32_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 59cb4a1..373cc2b 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -162,7 +162,8 @@
 extern void ioapic_init_mappings(void);
 
 #ifdef CONFIG_X86_64
-extern int save_mask_IO_APIC_setup(void);
+extern int save_IO_APIC_setup(void);
+extern void mask_IO_APIC_setup(void);
 extern void restore_IO_APIC_setup(void);
 extern void reinit_intr_remapped_IO_APIC(int);
 #endif
@@ -172,7 +173,7 @@
 extern int setup_ioapic_entry(int apic, int irq,
 			      struct IO_APIC_route_entry *entry,
 			      unsigned int destination, int trigger,
-			      int polarity, int vector);
+			      int polarity, int vector, int pin);
 extern void ioapic_write_entry(int apic, int pin,
 			       struct IO_APIC_route_entry e);
 #else  /* !CONFIG_X86_IO_APIC */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 107eb21..f38481b 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -36,6 +36,7 @@
 extern void fixup_irqs(void);
 #endif
 
+extern void (*generic_interrupt_extension)(void);
 extern void init_IRQ(void);
 extern void native_init_IRQ(void);
 extern bool handle_irq(unsigned irq, struct pt_regs *regs);
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 20e1fd5..0396760 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -1,8 +1,6 @@
 #ifndef _ASM_X86_IRQ_REMAPPING_H
 #define _ASM_X86_IRQ_REMAPPING_H
 
-extern int x2apic;
-
 #define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
 
 #endif	/* _ASM_X86_IRQ_REMAPPING_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 8a285f3..3cbd79b 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -112,6 +112,11 @@
 #define LOCAL_PERF_VECTOR		0xee
 
 /*
+ * Generic system vector for platform specific use
+ */
+#define GENERIC_INTERRUPT_VECTOR	0xed
+
+/*
  * First APIC vector available to drivers: (vectors 0x30-0xee) we
  * start at 0x31(0x41) to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
index 0ceb6d1..317ff17 100644
--- a/arch/x86/include/asm/kexec.h
+++ b/arch/x86/include/asm/kexec.h
@@ -9,13 +9,13 @@
 # define PAGES_NR		4
 #else
 # define PA_CONTROL_PAGE	0
-# define PA_TABLE_PAGE		1
-# define PAGES_NR		2
+# define VA_CONTROL_PAGE	1
+# define PA_TABLE_PAGE		2
+# define PA_SWAP_PAGE		3
+# define PAGES_NR		4
 #endif
 
-#ifdef CONFIG_X86_32
 # define KEXEC_CONTROL_CODE_MAX_SIZE	2048
-#endif
 
 #ifndef __ASSEMBLY__
 
@@ -136,10 +136,11 @@
 		unsigned int has_pae,
 		unsigned int preserve_context);
 #else
-NORET_TYPE void
+unsigned long
 relocate_kernel(unsigned long indirection_page,
 		unsigned long page_list,
-		unsigned long start_address) ATTRIB_NORET;
+		unsigned long start_address,
+		unsigned int preserve_context);
 #endif
 
 #define ARCH_HAS_KIMAGE_ARCH
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
index 9320e2a..12d55e7 100644
--- a/arch/x86/include/asm/linkage.h
+++ b/arch/x86/include/asm/linkage.h
@@ -1,14 +1,11 @@
 #ifndef _ASM_X86_LINKAGE_H
 #define _ASM_X86_LINKAGE_H
 
+#include <linux/stringify.h>
+
 #undef notrace
 #define notrace __attribute__((no_instrument_function))
 
-#ifdef CONFIG_X86_64
-#define __ALIGN .p2align 4,,15
-#define __ALIGN_STR ".p2align 4,,15"
-#endif
-
 #ifdef CONFIG_X86_32
 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
 /*
@@ -50,16 +47,20 @@
 	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
 			      "g" (arg4), "g" (arg5), "g" (arg6))
 
-#endif
+#endif /* CONFIG_X86_32 */
+
+#ifdef __ASSEMBLY__
 
 #define GLOBAL(name)	\
 	.globl name;	\
 	name:
 
-#ifdef CONFIG_X86_ALIGNMENT_16
-#define __ALIGN .align 16,0x90
-#define __ALIGN_STR ".align 16,0x90"
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_ALIGNMENT_16)
+#define __ALIGN		.p2align 4, 0x90
+#define __ALIGN_STR	__stringify(__ALIGN)
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_X86_LINKAGE_H */
 
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 32c6e17..563933e 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -11,6 +11,8 @@
  */
 
 #define MCG_CTL_P	 (1UL<<8)   /* MCG_CAP register available */
+#define MCG_EXT_P	 (1ULL<<9)   /* Extended registers available */
+#define MCG_CMCI_P	 (1ULL<<10)  /* CMCI supported */
 
 #define MCG_STATUS_RIPV  (1UL<<0)   /* restart ip valid */
 #define MCG_STATUS_EIPV  (1UL<<1)   /* ip points to correct instruction */
@@ -90,14 +92,29 @@
 
 #include <asm/atomic.h>
 
+void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
 DECLARE_PER_CPU(struct sys_device, device_mce);
 extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
 
+/*
+ * To support more than 128 would need to escape the predefined
+ * Linux defined extended banks first.
+ */
+#define MAX_NR_BANKS (MCE_EXTENDED_BANK - 1)
+
 #ifdef CONFIG_X86_MCE_INTEL
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
+void cmci_clear(void);
+void cmci_reenable(void);
+void cmci_rediscover(int dying);
+void cmci_recheck(void);
 #else
 static inline void mce_intel_feature_init(struct cpuinfo_x86 *c) { }
+static inline void cmci_clear(void) {}
+static inline void cmci_reenable(void) {}
+static inline void cmci_rediscover(int dying) {}
+static inline void cmci_recheck(void) {}
 #endif
 
 #ifdef CONFIG_X86_MCE_AMD
@@ -106,11 +123,23 @@
 static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
 #endif
 
-void mce_log_therm_throt_event(unsigned int cpu, __u64 status);
+extern int mce_available(struct cpuinfo_x86 *c);
+
+void mce_log_therm_throt_event(__u64 status);
 
 extern atomic_t mce_entry;
 
 extern void do_machine_check(struct pt_regs *, long);
+
+typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS);
+DECLARE_PER_CPU(mce_banks_t, mce_poll_banks);
+
+enum mcp_flags {
+	MCP_TIMESTAMP = (1 << 0),	/* log time stamp */
+	MCP_UC = (1 << 1),		/* log uncorrected errors */
+};
+extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
+
 extern int mce_notify_user(void);
 
 #endif /* !CONFIG_X86_32 */
@@ -120,8 +149,8 @@
 #else
 #define mcheck_init(c) do { } while (0)
 #endif
-extern void stop_mce(void);
-extern void restart_mce(void);
+
+extern void (*mce_threshold_vector)(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/include/asm/msidef.h b/arch/x86/include/asm/msidef.h
index 6706b30..4cc48af 100644
--- a/arch/x86/include/asm/msidef.h
+++ b/arch/x86/include/asm/msidef.h
@@ -47,6 +47,7 @@
 #define	 MSI_ADDR_DEST_ID_MASK		0x00ffff0
 #define  MSI_ADDR_DEST_ID(dest)		(((dest) << MSI_ADDR_DEST_ID_SHIFT) & \
 					 MSI_ADDR_DEST_ID_MASK)
+#define MSI_ADDR_EXT_DEST_ID(dest)	((dest) & 0xffffff00)
 
 #define MSI_ADDR_IR_EXT_INT		(1 << 4)
 #define MSI_ADDR_IR_SHV			(1 << 3)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index f4e505f..ec41fc1 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -81,6 +81,11 @@
 #define MSR_IA32_MC0_ADDR		0x00000402
 #define MSR_IA32_MC0_MISC		0x00000403
 
+/* These are consecutive and not in the normal 4er MCE bank block */
+#define MSR_IA32_MC0_CTL2		0x00000280
+#define CMCI_EN			(1ULL << 30)
+#define CMCI_THRESHOLD_MASK		0xffffULL
+
 #define MSR_P6_PERFCTR0			0x000000c1
 #define MSR_P6_PERFCTR1			0x000000c2
 #define MSR_P6_EVNTSEL0			0x00000186
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index f1e4a79..0f915ae 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -39,6 +39,11 @@
 #define __VIRTUAL_MASK_SHIFT	32
 #endif	/* CONFIG_X86_PAE */
 
+/*
+ * Kernel image size is limited to 512 MB (see in arch/x86/kernel/head_32.S)
+ */
+#define KERNEL_IMAGE_SIZE	(512 * 1024 * 1024)
+
 #ifndef __ASSEMBLY__
 
 /*
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 2d625da..826ad37 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -40,14 +40,8 @@
 
 #ifndef __ASSEMBLY__
 
-struct pgprot;
-
 extern int page_is_ram(unsigned long pagenr);
 extern int devmem_is_allowed(unsigned long pagenr);
-extern void map_devmem(unsigned long pfn, unsigned long size,
-		       struct pgprot vma_prot);
-extern void unmap_devmem(unsigned long pfn, unsigned long size,
-			 struct pgprot vma_prot);
 
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 0617d5c..7727aa8 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -317,8 +317,6 @@
 #if PAGETABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
 	void (*set_pte_atomic)(pte_t *ptep, pte_t pteval);
-	void (*set_pte_present)(struct mm_struct *mm, unsigned long addr,
-				pte_t *ptep, pte_t pte);
 	void (*pte_clear)(struct mm_struct *mm, unsigned long addr,
 			  pte_t *ptep);
 	void (*pmd_clear)(pmd_t *pmdp);
@@ -389,7 +387,7 @@
 
 #define paravirt_type(op)				\
 	[paravirt_typenum] "i" (PARAVIRT_PATCH(op)),	\
-	[paravirt_opptr] "m" (op)
+	[paravirt_opptr] "i" (&(op))
 #define paravirt_clobber(clobber)		\
 	[paravirt_clobber] "i" (clobber)
 
@@ -443,7 +441,7 @@
  * offset into the paravirt_patch_template structure, and can therefore be
  * freely converted back into a structure offset.
  */
-#define PARAVIRT_CALL	"call *%[paravirt_opptr];"
+#define PARAVIRT_CALL	"call *%c[paravirt_opptr];"
 
 /*
  * These macros are intended to wrap calls through one of the paravirt
@@ -1365,13 +1363,6 @@
 		    pte.pte, pte.pte >> 32);
 }
 
-static inline void set_pte_present(struct mm_struct *mm, unsigned long addr,
-				   pte_t *ptep, pte_t pte)
-{
-	/* 5 arg words */
-	pv_mmu_ops.set_pte_present(mm, addr, ptep, pte);
-}
-
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
 			     pte_t *ptep)
 {
@@ -1388,12 +1379,6 @@
 	set_pte(ptep, pte);
 }
 
-static inline void set_pte_present(struct mm_struct *mm, unsigned long addr,
-				   pte_t *ptep, pte_t pte)
-{
-	set_pte(ptep, pte);
-}
-
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
 			     pte_t *ptep)
 {
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index b0e7005..2cd07b9 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_PAT_H
 
 #include <linux/types.h>
+#include <asm/pgtable_types.h>
 
 #ifdef CONFIG_X86_PAT
 extern int pat_enabled;
@@ -17,5 +18,9 @@
 
 extern int kernel_map_sync_memtype(u64 base, unsigned long size,
 		unsigned long flag);
+extern void map_devmem(unsigned long pfn, unsigned long size,
+		       struct pgprot vma_prot);
+extern void unmap_devmem(unsigned long pfn, unsigned long size,
+			 struct pgprot vma_prot);
 
 #endif /* _ASM_X86_PAT_H */
diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h
index c1774ac..2334982 100644
--- a/arch/x86/include/asm/pgtable-2level.h
+++ b/arch/x86/include/asm/pgtable-2level.h
@@ -26,13 +26,6 @@
 	native_set_pte(ptep, pte);
 }
 
-static inline void native_set_pte_present(struct mm_struct *mm,
-					  unsigned long addr,
-					  pte_t *ptep, pte_t pte)
-{
-	native_set_pte(ptep, pte);
-}
-
 static inline void native_pmd_clear(pmd_t *pmdp)
 {
 	native_set_pmd(pmdp, __pmd(0));
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index 3f13cdf..177b016 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -31,23 +31,6 @@
 	ptep->pte_low = pte.pte_low;
 }
 
-/*
- * Since this is only called on user PTEs, and the page fault handler
- * must handle the already racy situation of simultaneous page faults,
- * we are justified in merely clearing the PTE present bit, followed
- * by a set.  The ordering here is important.
- */
-static inline void native_set_pte_present(struct mm_struct *mm,
-					  unsigned long addr,
-					  pte_t *ptep, pte_t pte)
-{
-	ptep->pte_low = 0;
-	smp_wmb();
-	ptep->pte_high = pte.pte_high;
-	smp_wmb();
-	ptep->pte_low = pte.pte_low;
-}
-
 static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
 {
 	set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index d0812e1..29d96d1 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -31,8 +31,6 @@
 #define set_pte(ptep, pte)		native_set_pte(ptep, pte)
 #define set_pte_at(mm, addr, ptep, pte)	native_set_pte_at(mm, addr, ptep, pte)
 
-#define set_pte_present(mm, addr, ptep, pte)				\
-	native_set_pte_present(mm, addr, ptep, pte)
 #define set_pte_atomic(ptep, pte)					\
 	native_set_pte_atomic(ptep, pte)
 
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index 97612fc..31bd120 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -42,9 +42,6 @@
  */
 #undef TEST_ACCESS_OK
 
-/* The boot page tables (all created as a single array) */
-extern unsigned long pg0[];
-
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h
index bd8df3b..2733fad 100644
--- a/arch/x86/include/asm/pgtable_32_types.h
+++ b/arch/x86/include/asm/pgtable_32_types.h
@@ -25,6 +25,11 @@
  * area for the same reason. ;)
  */
 #define VMALLOC_OFFSET	(8 * 1024 * 1024)
+
+#ifndef __ASSEMBLER__
+extern bool __vmalloc_start_set; /* set once high_memory is set */
+#endif
+
 #define VMALLOC_START	((unsigned long)high_memory + VMALLOC_OFFSET)
 #ifdef CONFIG_X86_PAE
 #define LAST_PKMAP 512
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 4d258ad..b8238dc 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -273,6 +273,7 @@
 
 extern pteval_t __supported_pte_mask;
 extern int nx_enabled;
+extern void set_nx(void);
 
 #define pgprot_writecombine	pgprot_writecombine
 extern pgprot_t pgprot_writecombine(pgprot_t prot);
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 7613950..ae85a8d 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -75,9 +75,9 @@
 #else
 	/* Number of 4K pages in DTLB/ITLB combined(in pages): */
 	int			x86_tlbsize;
+#endif
 	__u8			x86_virt_bits;
 	__u8			x86_phys_bits;
-#endif
 	/* CPUID returned core id bits: */
 	__u8			x86_coreid_bits;
 	/* Max extended CPUID function supported: */
@@ -391,6 +391,9 @@
 DECLARE_INIT_PER_CPU(irq_stack_union);
 
 DECLARE_PER_CPU(char *, irq_stack_ptr);
+DECLARE_PER_CPU(unsigned int, irq_count);
+extern unsigned long kernel_eflags;
+extern asmlinkage void ignore_sysret(void);
 #else	/* X86_64 */
 #ifdef CONFIG_CC_STACKPROTECTOR
 DECLARE_PER_CPU(unsigned long, stack_canary);
diff --git a/arch/x86/include/asm/sections.h b/arch/x86/include/asm/sections.h
index 2b8c516..1b7ee5d 100644
--- a/arch/x86/include/asm/sections.h
+++ b/arch/x86/include/asm/sections.h
@@ -1 +1,8 @@
+#ifndef _ASM_X86_SECTIONS_H
+#define _ASM_X86_SECTIONS_H
+
 #include <asm-generic/sections.h>
+
+extern char __brk_base[], __brk_limit[];
+
+#endif	/* _ASM_X86_SECTIONS_H */
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 05c6f6b..bdc2ada 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -64,7 +64,7 @@
 #include <asm/bootparam.h>
 
 /* Interrupt control for vSMPowered x86_64 systems */
-#ifdef CONFIG_X86_VSMP
+#ifdef CONFIG_X86_64
 void vsmp_init(void);
 #else
 static inline void vsmp_init(void) { }
@@ -100,20 +100,51 @@
  */
 #define LOWMEMSIZE()	(0x9f000)
 
+/* exceedingly early brk-like allocator */
+extern unsigned long _brk_end;
+void *extend_brk(size_t size, size_t align);
+
+/*
+ * Reserve space in the brk section.  The name must be unique within
+ * the file, and somewhat descriptive.  The size is in bytes.  Must be
+ * used at file scope.
+ *
+ * (This uses a temp function to wrap the asm so we can pass it the
+ * size parameter; otherwise we wouldn't be able to.  We can't use a
+ * "section" attribute on a normal variable because it always ends up
+ * being @progbits, which ends up allocating space in the vmlinux
+ * executable.)
+ */
+#define RESERVE_BRK(name,sz)						\
+	static void __section(.discard) __used				\
+	__brk_reservation_fn_##name##__(void) {				\
+		asm volatile (						\
+			".pushsection .brk_reservation,\"aw\",@nobits;" \
+			".brk." #name ":"				\
+			" 1:.skip %c0;"					\
+			" .size .brk." #name ", . - 1b;"		\
+			" .popsection"					\
+			: : "i" (sz));					\
+	}
+
 #ifdef __i386__
 
 void __init i386_start_kernel(void);
 extern void probe_roms(void);
 
-extern unsigned long init_pg_tables_start;
-extern unsigned long init_pg_tables_end;
-
 #else
 void __init x86_64_start_kernel(char *real_mode);
 void __init x86_64_start_reservations(char *real_mode_data);
 
 #endif /* __i386__ */
 #endif /* _SETUP */
+#else
+#define RESERVE_BRK(name,sz)				\
+	.pushsection .brk_reservation,"aw",@nobits;	\
+.brk.name:						\
+1:	.skip sz;					\
+	.size .brk.name,.-1b;				\
+	.popsection
 #endif /* __ASSEMBLY__ */
 #endif  /*  __KERNEL__  */
 
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index a81195e..bd37ed4 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -12,9 +12,9 @@
 
 #ifdef CONFIG_X86_32
 extern int timer_ack;
-extern int recalibrate_cpu_khz(void);
 extern irqreturn_t timer_interrupt(int irq, void *dev_id);
 #endif /* CONFIG_X86_32 */
+extern int recalibrate_cpu_khz(void);
 
 extern int no_timer_check;
 
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 777327e..9f4dfba 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -199,6 +199,10 @@
 #define SCIR_CPU_ACTIVITY	0x02	/* not idle */
 #define SCIR_CPU_HB_INTERVAL	(HZ)	/* once per second */
 
+/* Loop through all installed blades */
+#define for_each_possible_blade(bid)		\
+	for ((bid) = 0; (bid) < uv_num_possible_blades(); (bid)++)
+
 /*
  * Macros for converting between kernel virtual addresses, socket local physical
  * addresses, and UV global physical addresses.
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index 5e79ca6..9c371e4 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -296,6 +296,8 @@
 static inline int
 HYPERVISOR_update_descriptor(u64 ma, u64 desc)
 {
+	if (sizeof(u64) == sizeof(long))
+		return _hypercall2(int, update_descriptor, ma, desc);
 	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
 }
 
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 1fc811b..c611ad6 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -70,7 +70,6 @@
 obj-$(CONFIG_KEXEC)		+= machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC)		+= relocate_kernel_$(BITS).o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump_$(BITS).o
-obj-$(CONFIG_X86_VSMP)		+= vsmp_64.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_MODULES)		+= module_$(BITS).o
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
@@ -111,7 +110,7 @@
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
-	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o
+	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
 	obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
 	obj-$(CONFIG_AUDIT)		+= audit_64.o
 
@@ -120,4 +119,5 @@
 	obj-$(CONFIG_AMD_IOMMU)		+= amd_iommu_init.o amd_iommu.o
 
 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+	obj-y				+= vsmp_64.o
 endif
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 6907b8e..4c80f15 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -414,9 +414,17 @@
 	   that might execute the to be patched code.
 	   Other CPUs are not running. */
 	stop_nmi();
-#ifdef CONFIG_X86_MCE
-	stop_mce();
-#endif
+
+	/*
+	 * Don't stop machine check exceptions while patching.
+	 * MCEs only happen when something got corrupted and in this
+	 * case we must do something about the corruption.
+	 * Ignoring it is worse than a unlikely patching race.
+	 * Also machine checks tend to be broadcast and if one CPU
+	 * goes into machine check the others follow quickly, so we don't
+	 * expect a machine check to cause undue problems during to code
+	 * patching.
+	 */
 
 	apply_alternatives(__alt_instructions, __alt_instructions_end);
 
@@ -456,9 +464,6 @@
 				(unsigned long)__smp_locks_end);
 
 	restart_nmi();
-#ifdef CONFIG_X86_MCE
-	restart_mce();
-#endif
 }
 
 /**
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index f9cecdf..85eb8e1 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -46,6 +46,7 @@
 #include <asm/idle.h>
 #include <asm/mtrr.h>
 #include <asm/smp.h>
+#include <asm/mce.h>
 
 unsigned int num_processors;
 
@@ -808,7 +809,7 @@
 	u32 v;
 
 	/* APIC hasn't been mapped yet */
-	if (!apic_phys)
+	if (!x2apic && !apic_phys)
 		return;
 
 	maxlvt = lapic_get_maxlvt();
@@ -842,6 +843,14 @@
 		apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
 	}
 #endif
+#ifdef CONFIG_X86_MCE_INTEL
+	if (maxlvt >= 6) {
+		v = apic_read(APIC_LVTCMCI);
+		if (!(v & APIC_LVT_MASKED))
+			apic_write(APIC_LVTCMCI, v | APIC_LVT_MASKED);
+	}
+#endif
+
 	/*
 	 * Clean APIC state for other OSs:
 	 */
@@ -1241,6 +1250,12 @@
 	apic_write(APIC_LVT1, value);
 
 	preempt_enable();
+
+#ifdef CONFIG_X86_MCE_INTEL
+	/* Recheck CMCI information after local APIC is up on CPU #0 */
+	if (smp_processor_id() == 0)
+		cmci_recheck();
+#endif
 }
 
 void __cpuinit end_local_APIC_setup(void)
@@ -1319,15 +1334,16 @@
 		return;
 	}
 
-	local_irq_save(flags);
-	mask_8259A();
-
-	ret = save_mask_IO_APIC_setup();
+	ret = save_IO_APIC_setup();
 	if (ret) {
 		pr_info("Saving IO-APIC state failed: %d\n", ret);
 		goto end;
 	}
 
+	local_irq_save(flags);
+	mask_IO_APIC_setup();
+	mask_8259A();
+
 	ret = enable_intr_remapping(1);
 
 	if (ret && x2apic_preenabled) {
@@ -1352,10 +1368,10 @@
 	else
 		reinit_intr_remapped_IO_APIC(x2apic_preenabled);
 
-end:
 	unmask_8259A();
 	local_irq_restore(flags);
 
+end:
 	if (!ret) {
 		if (!x2apic_preenabled)
 			pr_info("Enabled x2apic and interrupt-remapping\n");
@@ -1508,12 +1524,10 @@
  */
 void __init init_apic_mappings(void)
 {
-#ifdef CONFIG_X86_X2APIC
 	if (x2apic) {
 		boot_cpu_physical_apicid = read_apic_id();
 		return;
 	}
-#endif
 
 	/*
 	 * If no local APIC can be found then set up a fake all
@@ -1957,12 +1971,9 @@
 
 	local_irq_save(flags);
 
-#ifdef CONFIG_X86_X2APIC
 	if (x2apic)
 		enable_x2apic();
-	else
-#endif
-	{
+	else {
 		/*
 		 * Make sure the APICBASE points to the right address
 		 *
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index f933822..0014714 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -159,20 +159,6 @@
 	return physid_isset(read_xapic_id(), phys_cpu_present_map);
 }
 
-static unsigned int flat_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-	return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
-}
-
-static unsigned int flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-						const struct cpumask *andmask)
-{
-	unsigned long mask1 = cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
-	unsigned long mask2 = cpumask_bits(andmask)[0] & APIC_ALL_CPUS;
-
-	return mask1 & mask2;
-}
-
 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
 {
 	return hard_smp_processor_id() >> index_msb;
@@ -213,8 +199,8 @@
 	.set_apic_id			= set_apic_id,
 	.apic_id_mask			= 0xFFu << 24,
 
-	.cpu_mask_to_apicid		= flat_cpu_mask_to_apicid,
-	.cpu_mask_to_apicid_and		= flat_cpu_mask_to_apicid_and,
+	.cpu_mask_to_apicid		= default_cpu_mask_to_apicid,
+	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and,
 
 	.send_IPI_mask			= flat_send_IPI_mask,
 	.send_IPI_mask_allbutself	= flat_send_IPI_mask_allbutself,
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 00e6071..da99ffc 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -389,6 +389,8 @@
 	unsigned int index;
 	unsigned int unused[3];
 	unsigned int data;
+	unsigned int unused2[11];
+	unsigned int eoi;
 };
 
 static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
@@ -397,6 +399,12 @@
 		+ (mp_ioapics[idx].apicaddr & ~PAGE_MASK);
 }
 
+static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(vector, &io_apic->eoi);
+}
+
 static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
 {
 	struct io_apic __iomem *io_apic = io_apic_base(apic);
@@ -546,16 +554,12 @@
 
 		apic = entry->apic;
 		pin = entry->pin;
-#ifdef CONFIG_INTR_REMAP
 		/*
 		 * With interrupt-remapping, destination information comes
 		 * from interrupt-remapping table entry.
 		 */
 		if (!irq_remapped(irq))
 			io_apic_write(apic, 0x11 + pin*2, dest);
-#else
-		io_apic_write(apic, 0x11 + pin*2, dest);
-#endif
 		reg = io_apic_read(apic, 0x10 + pin*2);
 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
 		reg |= vector;
@@ -588,10 +592,12 @@
 	if (assign_irq_vector(irq, cfg, mask))
 		return BAD_APICID;
 
-	cpumask_and(desc->affinity, cfg->domain, mask);
+	/* check that before desc->addinity get updated */
 	set_extra_move_desc(desc, mask);
 
-	return apic->cpu_mask_to_apicid_and(desc->affinity, cpu_online_mask);
+	cpumask_copy(desc->affinity, mask);
+
+	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
 }
 
 static void
@@ -849,9 +855,9 @@
 static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
 
 /*
- * Saves and masks all the unmasked IO-APIC RTE's
+ * Saves all the IO-APIC RTE's
  */
-int save_mask_IO_APIC_setup(void)
+int save_IO_APIC_setup(void)
 {
 	union IO_APIC_reg_01 reg_01;
 	unsigned long flags;
@@ -876,16 +882,9 @@
 	}
 
 	for (apic = 0; apic < nr_ioapics; apic++)
-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-			struct IO_APIC_route_entry entry;
-
-			entry = early_ioapic_entries[apic][pin] =
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			early_ioapic_entries[apic][pin] =
 				ioapic_read_entry(apic, pin);
-			if (!entry.mask) {
-				entry.mask = 1;
-				ioapic_write_entry(apic, pin, entry);
-			}
-		}
 
 	return 0;
 
@@ -898,6 +897,25 @@
 	return -ENOMEM;
 }
 
+void mask_IO_APIC_setup(void)
+{
+	int apic, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		if (!early_ioapic_entries[apic])
+			break;
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+
+			entry = early_ioapic_entries[apic][pin];
+			if (!entry.mask) {
+				entry.mask = 1;
+				ioapic_write_entry(apic, pin, entry);
+			}
+		}
+	}
+}
+
 void restore_IO_APIC_setup(void)
 {
 	int apic, pin;
@@ -1411,9 +1429,7 @@
 }
 
 static struct irq_chip ioapic_chip;
-#ifdef CONFIG_INTR_REMAP
 static struct irq_chip ir_ioapic_chip;
-#endif
 
 #define IOAPIC_AUTO     -1
 #define IOAPIC_EDGE     0
@@ -1452,7 +1468,6 @@
 	else
 		desc->status &= ~IRQ_LEVEL;
 
-#ifdef CONFIG_INTR_REMAP
 	if (irq_remapped(irq)) {
 		desc->status |= IRQ_MOVE_PCNTXT;
 		if (trigger)
@@ -1464,7 +1479,7 @@
 						      handle_edge_irq, "edge");
 		return;
 	}
-#endif
+
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
 	    trigger == IOAPIC_LEVEL)
 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
@@ -1478,14 +1493,13 @@
 int setup_ioapic_entry(int apic_id, int irq,
 		       struct IO_APIC_route_entry *entry,
 		       unsigned int destination, int trigger,
-		       int polarity, int vector)
+		       int polarity, int vector, int pin)
 {
 	/*
 	 * add it to the IO-APIC irq-routing table:
 	 */
 	memset(entry,0,sizeof(*entry));
 
-#ifdef CONFIG_INTR_REMAP
 	if (intr_remapping_enabled) {
 		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
 		struct irte irte;
@@ -1504,7 +1518,14 @@
 
 		irte.present = 1;
 		irte.dst_mode = apic->irq_dest_mode;
-		irte.trigger_mode = trigger;
+		/*
+		 * Trigger mode in the IRTE will always be edge, and the
+		 * actual level or edge trigger will be setup in the IO-APIC
+		 * RTE. This will help simplify level triggered irq migration.
+		 * For more details, see the comments above explainig IO-APIC
+		 * irq migration in the presence of interrupt-remapping.
+		 */
+		irte.trigger_mode = 0;
 		irte.dlvry_mode = apic->irq_delivery_mode;
 		irte.vector = vector;
 		irte.dest_id = IRTE_DEST(destination);
@@ -1515,18 +1536,21 @@
 		ir_entry->zero = 0;
 		ir_entry->format = 1;
 		ir_entry->index = (index & 0x7fff);
-	} else
-#endif
-	{
+		/*
+		 * IO-APIC RTE will be configured with virtual vector.
+		 * irq handler will do the explicit EOI to the io-apic.
+		 */
+		ir_entry->vector = pin;
+	} else {
 		entry->delivery_mode = apic->irq_delivery_mode;
 		entry->dest_mode = apic->irq_dest_mode;
 		entry->dest = destination;
+		entry->vector = vector;
 	}
 
 	entry->mask = 0;				/* enable IRQ */
 	entry->trigger = trigger;
 	entry->polarity = polarity;
-	entry->vector = vector;
 
 	/* Mask level triggered irqs.
 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
@@ -1561,7 +1585,7 @@
 
 
 	if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry,
-			       dest, trigger, polarity, cfg->vector)) {
+			       dest, trigger, polarity, cfg->vector, pin)) {
 		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
 		       mp_ioapics[apic_id].apicid, pin);
 		__clear_irq_vector(irq, cfg);
@@ -1642,10 +1666,8 @@
 {
 	struct IO_APIC_route_entry entry;
 
-#ifdef CONFIG_INTR_REMAP
 	if (intr_remapping_enabled)
 		return;
-#endif
 
 	memset(&entry, 0, sizeof(entry));
 
@@ -2040,8 +2062,13 @@
 	 * If the i8259 is routed through an IOAPIC
 	 * Put that IOAPIC in virtual wire mode
 	 * so legacy interrupts can be delivered.
+	 *
+	 * With interrupt-remapping, for now we will use virtual wire A mode,
+	 * as virtual wire B is little complex (need to configure both
+	 * IOAPIC RTE aswell as interrupt-remapping table entry).
+	 * As this gets called during crash dump, keep this simple for now.
 	 */
-	if (ioapic_i8259.pin != -1) {
+	if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
 		struct IO_APIC_route_entry entry;
 
 		memset(&entry, 0, sizeof(entry));
@@ -2061,7 +2088,10 @@
 		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
 	}
 
-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+	/*
+	 * Use virtual wire A mode when interrupt remapping is enabled.
+	 */
+	disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
 }
 
 #ifdef CONFIG_X86_32
@@ -2303,37 +2333,24 @@
 #ifdef CONFIG_SMP
 
 #ifdef CONFIG_INTR_REMAP
-static void ir_irq_migration(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
 
 /*
  * Migrate the IO-APIC irq in the presence of intr-remapping.
  *
- * For edge triggered, irq migration is a simple atomic update(of vector
- * and cpu destination) of IRTE and flush the hardware cache.
+ * For both level and edge triggered, irq migration is a simple atomic
+ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
  *
- * For level triggered, we need to modify the io-apic RTE aswell with the update
- * vector information, along with modifying IRTE with vector and destination.
- * So irq migration for level triggered is little  bit more complex compared to
- * edge triggered migration. But the good news is, we use the same algorithm
- * for level triggered migration as we have today, only difference being,
- * we now initiate the irq migration from process context instead of the
- * interrupt context.
- *
- * In future, when we do a directed EOI (combined with cpu EOI broadcast
- * suppression) to the IO-APIC, level triggered irq migration will also be
- * as simple as edge triggered migration and we can do the irq migration
- * with a simple atomic update to IO-APIC RTE.
+ * For level triggered, we eliminate the io-apic RTE modification (with the
+ * updated vector information), by using a virtual vector (io-apic pin number).
+ * Real vector that is used for interrupting cpu will be coming from
+ * the interrupt-remapping table entry.
  */
 static void
 migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
 {
 	struct irq_cfg *cfg;
 	struct irte irte;
-	int modify_ioapic_rte;
 	unsigned int dest;
-	unsigned long flags;
 	unsigned int irq;
 
 	if (!cpumask_intersects(mask, cpu_online_mask))
@@ -2351,13 +2368,6 @@
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
 
-	modify_ioapic_rte = desc->status & IRQ_LEVEL;
-	if (modify_ioapic_rte) {
-		spin_lock_irqsave(&ioapic_lock, flags);
-		__target_IO_APIC_irq(irq, dest, cfg);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
-	}
-
 	irte.vector = cfg->vector;
 	irte.dest_id = IRTE_DEST(dest);
 
@@ -2372,73 +2382,12 @@
 	cpumask_copy(desc->affinity, mask);
 }
 
-static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
-{
-	int ret = -1;
-	struct irq_cfg *cfg = desc->chip_data;
-
-	mask_IO_APIC_irq_desc(desc);
-
-	if (io_apic_level_ack_pending(cfg)) {
-		/*
-		 * Interrupt in progress. Migrating irq now will change the
-		 * vector information in the IO-APIC RTE and that will confuse
-		 * the EOI broadcast performed by cpu.
-		 * So, delay the irq migration to the next instance.
-		 */
-		schedule_delayed_work(&ir_migration_work, 1);
-		goto unmask;
-	}
-
-	/* everthing is clear. we have right of way */
-	migrate_ioapic_irq_desc(desc, desc->pending_mask);
-
-	ret = 0;
-	desc->status &= ~IRQ_MOVE_PENDING;
-	cpumask_clear(desc->pending_mask);
-
-unmask:
-	unmask_IO_APIC_irq_desc(desc);
-
-	return ret;
-}
-
-static void ir_irq_migration(struct work_struct *work)
-{
-	unsigned int irq;
-	struct irq_desc *desc;
-
-	for_each_irq_desc(irq, desc) {
-		if (desc->status & IRQ_MOVE_PENDING) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&desc->lock, flags);
-			if (!desc->chip->set_affinity ||
-			    !(desc->status & IRQ_MOVE_PENDING)) {
-				desc->status &= ~IRQ_MOVE_PENDING;
-				spin_unlock_irqrestore(&desc->lock, flags);
-				continue;
-			}
-
-			desc->chip->set_affinity(irq, desc->pending_mask);
-			spin_unlock_irqrestore(&desc->lock, flags);
-		}
-	}
-}
-
 /*
  * Migrates the IRQ destination in the process context.
  */
 static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
 					    const struct cpumask *mask)
 {
-	if (desc->status & IRQ_LEVEL) {
-		desc->status |= IRQ_MOVE_PENDING;
-		cpumask_copy(desc->pending_mask, mask);
-		migrate_irq_remapped_level_desc(desc);
-		return;
-	}
-
 	migrate_ioapic_irq_desc(desc, mask);
 }
 static void set_ir_ioapic_affinity_irq(unsigned int irq,
@@ -2448,6 +2397,11 @@
 
 	set_ir_ioapic_affinity_irq_desc(desc, mask);
 }
+#else
+static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+						   const struct cpumask *mask)
+{
+}
 #endif
 
 asmlinkage void smp_irq_move_cleanup_interrupt(void)
@@ -2461,6 +2415,7 @@
 	me = smp_processor_id();
 	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
 		unsigned int irq;
+		unsigned int irr;
 		struct irq_desc *desc;
 		struct irq_cfg *cfg;
 		irq = __get_cpu_var(vector_irq)[vector];
@@ -2480,6 +2435,18 @@
 		if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
 			goto unlock;
 
+		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
+		/*
+		 * Check if the vector that needs to be cleanedup is
+		 * registered at the cpu's IRR. If so, then this is not
+		 * the best time to clean it up. Lets clean it up in the
+		 * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
+		 * to myself.
+		 */
+		if (irr  & (1 << (vector % 32))) {
+			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
+			goto unlock;
+		}
 		__get_cpu_var(vector_irq)[vector] = -1;
 		cfg->move_cleanup_count--;
 unlock:
@@ -2529,9 +2496,44 @@
 #endif
 
 #ifdef CONFIG_INTR_REMAP
+static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+	int apic, pin;
+	struct irq_pin_list *entry;
+
+	entry = cfg->irq_2_pin;
+	for (;;) {
+
+		if (!entry)
+			break;
+
+		apic = entry->apic;
+		pin = entry->pin;
+		io_apic_eoi(apic, pin);
+		entry = entry->next;
+	}
+}
+
+static void
+eoi_ioapic_irq(struct irq_desc *desc)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int irq;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__eoi_ioapic_irq(irq, cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 static void ack_x2apic_level(unsigned int irq)
 {
+	struct irq_desc *desc = irq_to_desc(irq);
 	ack_x2APIC_irq();
+	eoi_ioapic_irq(desc);
 }
 
 static void ack_x2apic_edge(unsigned int irq)
@@ -2662,20 +2664,20 @@
 	.retrigger	= ioapic_retrigger_irq,
 };
 
-#ifdef CONFIG_INTR_REMAP
 static struct irq_chip ir_ioapic_chip __read_mostly = {
 	.name		= "IR-IO-APIC",
 	.startup	= startup_ioapic_irq,
 	.mask		= mask_IO_APIC_irq,
 	.unmask		= unmask_IO_APIC_irq,
+#ifdef CONFIG_INTR_REMAP
 	.ack		= ack_x2apic_edge,
 	.eoi		= ack_x2apic_level,
 #ifdef CONFIG_SMP
 	.set_affinity	= set_ir_ioapic_affinity_irq,
 #endif
+#endif
 	.retrigger	= ioapic_retrigger_irq,
 };
-#endif
 
 static inline void init_IO_APIC_traps(void)
 {
@@ -2901,10 +2903,8 @@
 	 * 8259A.
 	 */
 	if (pin1 == -1) {
-#ifdef CONFIG_INTR_REMAP
 		if (intr_remapping_enabled)
 			panic("BIOS bug: timer not connected to IO-APIC");
-#endif
 		pin1 = pin2;
 		apic1 = apic2;
 		no_pin1 = 1;
@@ -2940,10 +2940,8 @@
 				clear_IO_APIC_pin(0, pin1);
 			goto out;
 		}
-#ifdef CONFIG_INTR_REMAP
 		if (intr_remapping_enabled)
 			panic("timer doesn't work through Interrupt-remapped IO-APIC");
-#endif
 		local_irq_disable();
 		clear_IO_APIC_pin(apic1, pin1);
 		if (!no_pin1)
@@ -3237,9 +3235,7 @@
 	if (desc)
 		desc->chip_data = cfg;
 
-#ifdef CONFIG_INTR_REMAP
 	free_irte(irq);
-#endif
 	spin_lock_irqsave(&vector_lock, flags);
 	__clear_irq_vector(irq, cfg);
 	spin_unlock_irqrestore(&vector_lock, flags);
@@ -3265,7 +3261,6 @@
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
-#ifdef CONFIG_INTR_REMAP
 	if (irq_remapped(irq)) {
 		struct irte irte;
 		int ir_index;
@@ -3291,10 +3286,13 @@
 				  MSI_ADDR_IR_SHV |
 				  MSI_ADDR_IR_INDEX1(ir_index) |
 				  MSI_ADDR_IR_INDEX2(ir_index);
-	} else
-#endif
-	{
-		msg->address_hi = MSI_ADDR_BASE_HI;
+	} else {
+		if (x2apic_enabled())
+			msg->address_hi = MSI_ADDR_BASE_HI |
+					  MSI_ADDR_EXT_DEST_ID(dest);
+		else
+			msg->address_hi = MSI_ADDR_BASE_HI;
+
 		msg->address_lo =
 			MSI_ADDR_BASE_LO |
 			((apic->irq_dest_mode == 0) ?
@@ -3394,15 +3392,16 @@
 	.retrigger	= ioapic_retrigger_irq,
 };
 
-#ifdef CONFIG_INTR_REMAP
 static struct irq_chip msi_ir_chip = {
 	.name		= "IR-PCI-MSI",
 	.unmask		= unmask_msi_irq,
 	.mask		= mask_msi_irq,
+#ifdef CONFIG_INTR_REMAP
 	.ack		= ack_x2apic_edge,
 #ifdef CONFIG_SMP
 	.set_affinity	= ir_set_msi_irq_affinity,
 #endif
+#endif
 	.retrigger	= ioapic_retrigger_irq,
 };
 
@@ -3432,7 +3431,6 @@
 	}
 	return index;
 }
-#endif
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
@@ -3446,7 +3444,6 @@
 	set_irq_msi(irq, msidesc);
 	write_msi_msg(irq, &msg);
 
-#ifdef CONFIG_INTR_REMAP
 	if (irq_remapped(irq)) {
 		struct irq_desc *desc = irq_to_desc(irq);
 		/*
@@ -3455,7 +3452,6 @@
 		desc->status |= IRQ_MOVE_PCNTXT;
 		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
 	} else
-#endif
 		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
 	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
@@ -3469,11 +3465,8 @@
 	int ret, sub_handle;
 	struct msi_desc *msidesc;
 	unsigned int irq_want;
-
-#ifdef CONFIG_INTR_REMAP
-	struct intel_iommu *iommu = 0;
+	struct intel_iommu *iommu = NULL;
 	int index = 0;
-#endif
 
 	irq_want = nr_irqs_gsi;
 	sub_handle = 0;
@@ -3482,7 +3475,6 @@
 		if (irq == 0)
 			return -1;
 		irq_want = irq + 1;
-#ifdef CONFIG_INTR_REMAP
 		if (!intr_remapping_enabled)
 			goto no_ir;
 
@@ -3510,7 +3502,6 @@
 			set_irte_irq(irq, iommu, index, sub_handle);
 		}
 no_ir:
-#endif
 		ret = setup_msi_irq(dev, msidesc, irq);
 		if (ret < 0)
 			goto error;
@@ -3528,7 +3519,7 @@
 	destroy_irq(irq);
 }
 
-#ifdef CONFIG_DMAR
+#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
 #ifdef CONFIG_SMP
 static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
@@ -3609,7 +3600,7 @@
 
 #endif /* CONFIG_SMP */
 
-struct irq_chip hpet_msi_type = {
+static struct irq_chip hpet_msi_type = {
 	.name = "HPET_MSI",
 	.unmask = hpet_msi_unmask,
 	.mask = hpet_msi_mask,
@@ -4045,11 +4036,9 @@
 			else
 				mask = apic->target_cpus();
 
-#ifdef CONFIG_INTR_REMAP
 			if (intr_remapping_enabled)
 				set_ir_ioapic_affinity_irq_desc(desc, mask);
 			else
-#endif
 				set_ioapic_affinity_irq_desc(desc, mask);
 		}
 
@@ -4142,9 +4131,12 @@
 	struct resource *r = ioapic_resources;
 
 	if (!r) {
-		printk(KERN_ERR
-		       "IO APIC resources could be not be allocated.\n");
-		return -1;
+		if (nr_ioapics > 0) {
+			printk(KERN_ERR
+				"IO APIC resources couldn't be allocated.\n");
+			return -1;
+		}
+		return 0;
 	}
 
 	for (i = 0; i < nr_ioapics; i++) {
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c
index 8d7748e..1783652 100644
--- a/arch/x86/kernel/apic/probe_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -68,6 +68,13 @@
 			apic = &apic_physflat;
 		printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
 	}
+
+	/*
+	 * Now that apic routing model is selected, configure the
+	 * fault handling for intr remapping.
+	 */
+	if (intr_remapping_enabled)
+		enable_drhd_fault_handling();
 }
 
 /* Same for both flat and physical. */
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 8fb87b6..4a903e2 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -57,6 +57,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask) {
 		__x2apic_send_IPI_dest(
@@ -73,6 +75,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask) {
 		if (query_cpu == this_cpu)
@@ -90,6 +94,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_online_cpu(query_cpu) {
 		if (query_cpu == this_cpu)
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 23625b9..a284359 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -58,6 +58,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask) {
 		__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
@@ -73,6 +75,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask) {
 		if (query_cpu != this_cpu)
@@ -89,6 +93,8 @@
 	unsigned long query_cpu;
 	unsigned long flags;
 
+	x2apic_wrmsr_fence();
+
 	local_irq_save(flags);
 	for_each_online_cpu(query_cpu) {
 		if (query_cpu == this_cpu)
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index 2ac0ab7..fc999e6 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -83,15 +83,15 @@
 		u64 size;
 		addr = find_e820_area_size(addr, &size, PAGE_SIZE);
 
-		if (addr == 0)
+		if (!(addr + 1))
+			break;
+
+		if (addr >= corruption_check_size)
 			break;
 
 		if ((addr + size) > corruption_check_size)
 			size = corruption_check_size - addr;
 
-		if (size == 0)
-			break;
-
 		e820_update_range(addr, size, E820_RAM, E820_RESERVED);
 		scan_areas[num_scan_areas].addr = addr;
 		scan_areas[num_scan_areas].size = size;
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 82db7f4..4e242f9 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -14,11 +14,12 @@
 obj-$(CONFIG_X86_32)	+= bugs.o cmpxchg.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
 
+obj-$(CONFIG_X86_CPU_DEBUG)		+= cpu_debug.o
+
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
 obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o
 obj-$(CONFIG_CPU_SUP_CYRIX_32)		+= cyrix.o
-obj-$(CONFIG_CPU_SUP_CENTAUR_32)	+= centaur.o
-obj-$(CONFIG_CPU_SUP_CENTAUR_64)	+= centaur_64.o
+obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c
index 6882a73..8220ae6 100644
--- a/arch/x86/kernel/cpu/addon_cpuid_features.c
+++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -29,7 +29,7 @@
 	u32 regs[4];
 	const struct cpuid_bit *cb;
 
-	static const struct cpuid_bit cpuid_bits[] = {
+	static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
 		{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
 		{ 0, 0, 0, 0 }
 	};
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 25423a5..7e4a459 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -5,6 +5,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/apic.h>
+#include <asm/cpu.h>
 
 #ifdef CONFIG_X86_64
 # include <asm/numa_64.h>
@@ -141,6 +142,55 @@
 	}
 }
 
+static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_SMP
+	/* calling is from identify_secondary_cpu() ? */
+	if (c->cpu_index == boot_cpu_id)
+		return;
+
+	/*
+	 * Certain Athlons might work (for various values of 'work') in SMP
+	 * but they are not certified as MP capable.
+	 */
+	/* Athlon 660/661 is valid. */
+	if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
+	    (c->x86_mask == 1)))
+		goto valid_k7;
+
+	/* Duron 670 is valid */
+	if ((c->x86_model == 7) && (c->x86_mask == 0))
+		goto valid_k7;
+
+	/*
+	 * Athlon 662, Duron 671, and Athlon >model 7 have capability
+	 * bit. It's worth noting that the A5 stepping (662) of some
+	 * Athlon XP's have the MP bit set.
+	 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
+	 * more.
+	 */
+	if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
+	    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
+	     (c->x86_model > 7))
+		if (cpu_has_mp)
+			goto valid_k7;
+
+	/* If we get here, not a certified SMP capable AMD system. */
+
+	/*
+	 * Don't taint if we are running SMP kernel on a single non-MP
+	 * approved Athlon
+	 */
+	WARN_ONCE(1, "WARNING: This combination of AMD"
+		"processors is not suitable for SMP.\n");
+	if (!test_taint(TAINT_UNSAFE_SMP))
+		add_taint(TAINT_UNSAFE_SMP);
+
+valid_k7:
+	;
+#endif
+}
+
 static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
@@ -175,6 +225,8 @@
 	}
 
 	set_cpu_cap(c, X86_FEATURE_K7);
+
+	amd_k7_smp_check(c);
 }
 #endif
 
@@ -450,7 +502,7 @@
 }
 #endif
 
-static struct cpu_dev amd_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
 	.c_vendor	= "AMD",
 	.c_ident	= { "AuthenticAMD" },
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index 89bfdd9..c95e831 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -1,11 +1,11 @@
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/bitops.h>
 
 #include <asm/processor.h>
-#include <asm/msr.h>
 #include <asm/e820.h>
 #include <asm/mtrr.h>
+#include <asm/msr.h>
 
 #include "cpu.h"
 
@@ -276,7 +276,7 @@
 		 */
 		c->x86_capability[5] = cpuid_edx(0xC0000001);
 	}
-
+#ifdef CONFIG_X86_32
 	/* Cyrix III family needs CX8 & PGE explicitly enabled. */
 	if (c->x86_model >= 6 && c->x86_model <= 9) {
 		rdmsr(MSR_VIA_FCR, lo, hi);
@@ -288,6 +288,11 @@
 	/* Before Nehemiah, the C3's had 3dNOW! */
 	if (c->x86_model >= 6 && c->x86_model < 9)
 		set_cpu_cap(c, X86_FEATURE_3DNOW);
+#endif
+	if (c->x86 == 0x6 && c->x86_model >= 0xf) {
+		c->x86_cache_alignment = c->x86_clflush_size * 2;
+		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+	}
 
 	display_cacheinfo(c);
 }
@@ -316,16 +321,25 @@
 static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
 {
 	switch (c->x86) {
+#ifdef CONFIG_X86_32
 	case 5:
 		/* Emulate MTRRs using Centaur's MCR. */
 		set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
 		break;
+#endif
+	case 6:
+		if (c->x86_model >= 0xf)
+			set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+		break;
 	}
+#ifdef CONFIG_X86_64
+	set_cpu_cap(c, X86_FEATURE_SYSENTER32);
+#endif
 }
 
 static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
 {
-
+#ifdef CONFIG_X86_32
 	char *name;
 	u32  fcr_set = 0;
 	u32  fcr_clr = 0;
@@ -337,8 +351,10 @@
 	 * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
 	 */
 	clear_cpu_cap(c, 0*32+31);
-
+#endif
+	early_init_centaur(c);
 	switch (c->x86) {
+#ifdef CONFIG_X86_32
 	case 5:
 		switch (c->x86_model) {
 		case 4:
@@ -442,16 +458,20 @@
 		}
 		sprintf(c->x86_model_id, "WinChip %s", name);
 		break;
-
+#endif
 	case 6:
 		init_c3(c);
 		break;
 	}
+#ifdef CONFIG_X86_64
+	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+#endif
 }
 
 static unsigned int __cpuinit
 centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 {
+#ifdef CONFIG_X86_32
 	/* VIA C3 CPUs (670-68F) need further shifting. */
 	if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
 		size >>= 8;
@@ -464,11 +484,11 @@
 	if ((c->x86 == 6) && (c->x86_model == 9) &&
 				(c->x86_mask == 1) && (size == 65))
 		size -= 1;
-
+#endif
 	return size;
 }
 
-static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst centaur_cpu_dev = {
 	.c_vendor	= "Centaur",
 	.c_ident	= { "CentaurHauls" },
 	.c_early_init	= early_init_centaur,
diff --git a/arch/x86/kernel/cpu/centaur_64.c b/arch/x86/kernel/cpu/centaur_64.c
deleted file mode 100644
index a1625f5..0000000
--- a/arch/x86/kernel/cpu/centaur_64.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/cpufeature.h>
-#include <asm/processor.h>
-
-#include "cpu.h"
-
-static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
-{
-	if (c->x86 == 0x6 && c->x86_model >= 0xf)
-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
-
-	set_cpu_cap(c, X86_FEATURE_SYSENTER32);
-}
-
-static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
-{
-	early_init_centaur(c);
-
-	if (c->x86 == 0x6 && c->x86_model >= 0xf) {
-		c->x86_cache_alignment = c->x86_clflush_size * 2;
-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
-	}
-	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
-}
-
-static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
-	.c_vendor	= "Centaur",
-	.c_ident	= { "CentaurHauls" },
-	.c_early_init	= early_init_centaur,
-	.c_init		= init_centaur,
-	.c_x86_vendor	= X86_VENDOR_CENTAUR,
-};
-
-cpu_dev_register(centaur_cpu_dev);
-
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 826d5c8..e2962cc 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1,52 +1,52 @@
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
 #include <linux/bootmem.h>
+#include <linux/linkage.h>
 #include <linux/bitops.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/kgdb.h>
-#include <linux/topology.h>
-#include <linux/delay.h>
-#include <linux/smp.h>
 #include <linux/percpu.h>
-#include <asm/i387.h>
-#include <asm/msr.h>
-#include <asm/io.h>
-#include <asm/linkage.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/stackprotector.h>
 #include <asm/mmu_context.h>
-#include <asm/mtrr.h>
-#include <asm/mce.h>
-#include <asm/pat.h>
-#include <asm/asm.h>
-#include <asm/numa.h>
-#include <asm/smp.h>
-#include <asm/cpu.h>
+#include <asm/hypervisor.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/topology.h>
 #include <asm/cpumask.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/proto.h>
+#include <asm/setup.h>
 #include <asm/apic.h>
+#include <asm/desc.h>
+#include <asm/i387.h>
+#include <asm/mtrr.h>
+#include <asm/numa.h>
+#include <asm/asm.h>
+#include <asm/cpu.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+#include <asm/pat.h>
+#include <asm/smp.h>
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
 #endif
 
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/desc.h>
-#include <asm/atomic.h>
-#include <asm/proto.h>
-#include <asm/sections.h>
-#include <asm/setup.h>
-#include <asm/hypervisor.h>
-#include <asm/stackprotector.h>
-
 #include "cpu.h"
 
 #ifdef CONFIG_X86_64
 
 /* all of these masks are initialized in setup_cpu_local_masks() */
-cpumask_var_t cpu_callin_mask;
-cpumask_var_t cpu_callout_mask;
 cpumask_var_t cpu_initialized_mask;
+cpumask_var_t cpu_callout_mask;
+cpumask_var_t cpu_callin_mask;
 
 /* representing cpus for which sibling maps can be computed */
 cpumask_var_t cpu_sibling_setup_mask;
@@ -62,15 +62,15 @@
 
 #else /* CONFIG_X86_32 */
 
-cpumask_t cpu_callin_map;
+cpumask_t cpu_sibling_setup_map;
 cpumask_t cpu_callout_map;
 cpumask_t cpu_initialized;
-cpumask_t cpu_sibling_setup_map;
+cpumask_t cpu_callin_map;
 
 #endif /* CONFIG_X86_32 */
 
 
-static struct cpu_dev *this_cpu __cpuinitdata;
+static const struct cpu_dev *this_cpu __cpuinitdata;
 
 DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
 #ifdef CONFIG_X86_64
@@ -79,48 +79,48 @@
 	 * IRET will check the segment types  kkeil 2000/10/28
 	 * Also sysret mandates a special GDT layout
 	 *
-	 * The TLS descriptors are currently at a different place compared to i386.
+	 * TLS descriptors are currently at a different place compared to i386.
 	 * Hopefully nobody expects them at a fixed place (Wine?)
 	 */
-	[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
-	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
-	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
-	[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
-	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
-	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
+	[GDT_ENTRY_KERNEL32_CS]		= { { { 0x0000ffff, 0x00cf9b00 } } },
+	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00af9b00 } } },
+	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9300 } } },
+	[GDT_ENTRY_DEFAULT_USER32_CS]	= { { { 0x0000ffff, 0x00cffb00 } } },
+	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff300 } } },
+	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00affb00 } } },
 #else
-	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
-	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
-	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
-	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
+	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00cf9a00 } } },
+	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9200 } } },
+	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00cffa00 } } },
+	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff200 } } },
 	/*
 	 * Segments used for calling PnP BIOS have byte granularity.
 	 * They code segments and data segments have fixed 64k limits,
 	 * the transfer segment sizes are set at run time.
 	 */
 	/* 32-bit code */
-	[GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } },
+	[GDT_ENTRY_PNPBIOS_CS32]	= { { { 0x0000ffff, 0x00409a00 } } },
 	/* 16-bit code */
-	[GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
+	[GDT_ENTRY_PNPBIOS_CS16]	= { { { 0x0000ffff, 0x00009a00 } } },
 	/* 16-bit data */
-	[GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
+	[GDT_ENTRY_PNPBIOS_DS]		= { { { 0x0000ffff, 0x00009200 } } },
 	/* 16-bit data */
-	[GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
+	[GDT_ENTRY_PNPBIOS_TS1]		= { { { 0x00000000, 0x00009200 } } },
 	/* 16-bit data */
-	[GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
+	[GDT_ENTRY_PNPBIOS_TS2]		= { { { 0x00000000, 0x00009200 } } },
 	/*
 	 * The APM segments have byte granularity and their bases
 	 * are set at run time.  All have 64k limits.
 	 */
 	/* 32-bit code */
-	[GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } },
+	[GDT_ENTRY_APMBIOS_BASE]	= { { { 0x0000ffff, 0x00409a00 } } },
 	/* 16-bit code */
-	[GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
+	[GDT_ENTRY_APMBIOS_BASE+1]	= { { { 0x0000ffff, 0x00009a00 } } },
 	/* data */
-	[GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },
+	[GDT_ENTRY_APMBIOS_BASE+2]	= { { { 0x0000ffff, 0x00409200 } } },
 
-	[GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
-	[GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } },
+	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x00000000, 0x00c09200 } } },
+	[GDT_ENTRY_PERCPU]		= { { { 0x0000ffff, 0x00cf9200 } } },
 	GDT_STACK_CANARY_INIT
 #endif
 } };
@@ -164,16 +164,17 @@
 	 * the CPUID. Add "volatile" to not allow gcc to
 	 * optimize the subsequent calls to this function.
 	 */
-	asm volatile ("pushfl\n\t"
-		      "pushfl\n\t"
-		      "popl %0\n\t"
-		      "movl %0,%1\n\t"
-		      "xorl %2,%0\n\t"
-		      "pushl %0\n\t"
-		      "popfl\n\t"
-		      "pushfl\n\t"
-		      "popl %0\n\t"
-		      "popfl\n\t"
+	asm volatile ("pushfl		\n\t"
+		      "pushfl		\n\t"
+		      "popl %0		\n\t"
+		      "movl %0, %1	\n\t"
+		      "xorl %2, %0	\n\t"
+		      "pushl %0		\n\t"
+		      "popfl		\n\t"
+		      "pushfl		\n\t"
+		      "popl %0		\n\t"
+		      "popfl		\n\t"
+
 		      : "=&r" (f1), "=&r" (f2)
 		      : "ir" (flag));
 
@@ -188,18 +189,22 @@
 
 static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
 {
-	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
-		/* Disable processor serial number */
-		unsigned long lo, hi;
-		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
-		lo |= 0x200000;
-		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
-		printk(KERN_NOTICE "CPU serial number disabled.\n");
-		clear_cpu_cap(c, X86_FEATURE_PN);
+	unsigned long lo, hi;
 
-		/* Disabling the serial number may affect the cpuid level */
-		c->cpuid_level = cpuid_eax(0);
-	}
+	if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr)
+		return;
+
+	/* Disable processor serial number: */
+
+	rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+	lo |= 0x200000;
+	wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+
+	printk(KERN_NOTICE "CPU serial number disabled.\n");
+	clear_cpu_cap(c, X86_FEATURE_PN);
+
+	/* Disabling the serial number may affect the cpuid level */
+	c->cpuid_level = cpuid_eax(0);
 }
 
 static int __init x86_serial_nr_setup(char *s)
@@ -232,6 +237,7 @@
 	u32 feature;
 	u32 level;
 };
+
 static const struct cpuid_dependent_feature __cpuinitconst
 cpuid_dependent_features[] = {
 	{ X86_FEATURE_MWAIT,		0x00000005 },
@@ -243,7 +249,11 @@
 static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
 {
 	const struct cpuid_dependent_feature *df;
+
 	for (df = cpuid_dependent_features; df->feature; df++) {
+
+		if (!cpu_has(c, df->feature))
+			continue;
 		/*
 		 * Note: cpuid_level is set to -1 if unavailable, but
 		 * extended_extended_level is set to 0 if unavailable
@@ -251,32 +261,32 @@
 		 * when signed; hence the weird messing around with
 		 * signs here...
 		 */
-		if (cpu_has(c, df->feature) &&
-		    ((s32)df->level < 0 ?
+		if (!((s32)df->level < 0 ?
 		     (u32)df->level > (u32)c->extended_cpuid_level :
-		     (s32)df->level > (s32)c->cpuid_level)) {
-			clear_cpu_cap(c, df->feature);
-			if (warn)
-				printk(KERN_WARNING
-				       "CPU: CPU feature %s disabled "
-				       "due to lack of CPUID level 0x%x\n",
-				       x86_cap_flags[df->feature],
-				       df->level);
-		}
+		     (s32)df->level > (s32)c->cpuid_level))
+			continue;
+
+		clear_cpu_cap(c, df->feature);
+		if (!warn)
+			continue;
+
+		printk(KERN_WARNING
+		       "CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
+				x86_cap_flags[df->feature], df->level);
 	}
 }
 
 /*
  * Naming convention should be: <Name> [(<Codename>)]
  * This table only is used unless init_<vendor>() below doesn't set it;
- * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
- *
+ * in particular, if CPUID levels 0x80000002..4 are supported, this
+ * isn't used
  */
 
 /* Look up CPU names by table lookup. */
-static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
+static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c)
 {
-	struct cpu_model_info *info;
+	const struct cpu_model_info *info;
 
 	if (c->x86_model >= 16)
 		return NULL;	/* Range check */
@@ -307,8 +317,10 @@
 	load_stack_canary_segment();
 }
 
-/* Current gdt points %fs at the "master" per-cpu area: after this,
- * it's on the real one. */
+/*
+ * Current gdt points %fs at the "master" per-cpu area: after this,
+ * it's on the real one.
+ */
 void switch_to_new_gdt(int cpu)
 {
 	struct desc_ptr gdt_descr;
@@ -321,7 +333,7 @@
 	load_percpu_segment(cpu);
 }
 
-static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
 
 static void __cpuinit default_init(struct cpuinfo_x86 *c)
 {
@@ -340,7 +352,7 @@
 #endif
 }
 
-static struct cpu_dev __cpuinitdata default_cpu = {
+static const struct cpu_dev __cpuinitconst default_cpu = {
 	.c_init	= default_init,
 	.c_vendor = "Unknown",
 	.c_x86_vendor = X86_VENDOR_UNKNOWN,
@@ -354,22 +366,24 @@
 	if (c->extended_cpuid_level < 0x80000004)
 		return;
 
-	v = (unsigned int *) c->x86_model_id;
+	v = (unsigned int *)c->x86_model_id;
 	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
 	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
 	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
 	c->x86_model_id[48] = 0;
 
-	/* Intel chips right-justify this string for some dumb reason;
-	   undo that brain damage */
+	/*
+	 * Intel chips right-justify this string for some dumb reason;
+	 * undo that brain damage:
+	 */
 	p = q = &c->x86_model_id[0];
 	while (*p == ' ')
-	     p++;
+		p++;
 	if (p != q) {
-	     while (*p)
-		  *q++ = *p++;
-	     while (q <= &c->x86_model_id[48])
-		  *q++ = '\0';	/* Zero-pad the rest */
+		while (*p)
+			*q++ = *p++;
+		while (q <= &c->x86_model_id[48])
+			*q++ = '\0';	/* Zero-pad the rest */
 	}
 }
 
@@ -438,28 +452,31 @@
 
 	if (smp_num_siblings == 1) {
 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
-	} else if (smp_num_siblings > 1) {
-
-		if (smp_num_siblings > nr_cpu_ids) {
-			printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
-					smp_num_siblings);
-			smp_num_siblings = 1;
-			return;
-		}
-
-		index_msb = get_count_order(smp_num_siblings);
-		c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
-
-		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
-
-		index_msb = get_count_order(smp_num_siblings);
-
-		core_bits = get_count_order(c->x86_max_cores);
-
-		c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
-					       ((1 << core_bits) - 1);
+		goto out;
 	}
 
+	if (smp_num_siblings <= 1)
+		goto out;
+
+	if (smp_num_siblings > nr_cpu_ids) {
+		pr_warning("CPU: Unsupported number of siblings %d",
+			   smp_num_siblings);
+		smp_num_siblings = 1;
+		return;
+	}
+
+	index_msb = get_count_order(smp_num_siblings);
+	c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
+
+	smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+
+	index_msb = get_count_order(smp_num_siblings);
+
+	core_bits = get_count_order(c->x86_max_cores);
+
+	c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
+				       ((1 << core_bits) - 1);
+
 out:
 	if ((c->x86_max_cores * smp_num_siblings) > 1) {
 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
@@ -473,8 +490,8 @@
 static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
 	char *v = c->x86_vendor_id;
-	int i;
 	static int printed;
+	int i;
 
 	for (i = 0; i < X86_VENDOR_NUM; i++) {
 		if (!cpu_devs[i])
@@ -483,6 +500,7 @@
 		if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
 		    (cpu_devs[i]->c_ident[1] &&
 		     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+
 			this_cpu = cpu_devs[i];
 			c->x86_vendor = this_cpu->c_x86_vendor;
 			return;
@@ -491,7 +509,9 @@
 
 	if (!printed) {
 		printed++;
-		printk(KERN_ERR "CPU: vendor_id '%s' unknown, using generic init.\n", v);
+		printk(KERN_ERR
+		    "CPU: vendor_id '%s' unknown, using generic init.\n", v);
+
 		printk(KERN_ERR "CPU: Your system may be unstable.\n");
 	}
 
@@ -511,14 +531,17 @@
 	/* Intel-defined flags: level 0x00000001 */
 	if (c->cpuid_level >= 0x00000001) {
 		u32 junk, tfms, cap0, misc;
+
 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
 		c->x86 = (tfms >> 8) & 0xf;
 		c->x86_model = (tfms >> 4) & 0xf;
 		c->x86_mask = tfms & 0xf;
+
 		if (c->x86 == 0xf)
 			c->x86 += (tfms >> 20) & 0xff;
 		if (c->x86 >= 0x6)
 			c->x86_model += ((tfms >> 16) & 0xf) << 4;
+
 		if (cap0 & (1<<19)) {
 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
 			c->x86_cache_alignment = c->x86_clflush_size;
@@ -534,6 +557,7 @@
 	/* Intel-defined flags: level 0x00000001 */
 	if (c->cpuid_level >= 0x00000001) {
 		u32 capability, excap;
+
 		cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
 		c->x86_capability[0] = capability;
 		c->x86_capability[4] = excap;
@@ -542,6 +566,7 @@
 	/* AMD-defined flags: level 0x80000001 */
 	xlvl = cpuid_eax(0x80000000);
 	c->extended_cpuid_level = xlvl;
+
 	if ((xlvl & 0xffff0000) == 0x80000000) {
 		if (xlvl >= 0x80000001) {
 			c->x86_capability[1] = cpuid_edx(0x80000001);
@@ -549,13 +574,15 @@
 		}
 	}
 
-#ifdef CONFIG_X86_64
 	if (c->extended_cpuid_level >= 0x80000008) {
 		u32 eax = cpuid_eax(0x80000008);
 
 		c->x86_virt_bits = (eax >> 8) & 0xff;
 		c->x86_phys_bits = eax & 0xff;
 	}
+#ifdef CONFIG_X86_32
+	else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
+		c->x86_phys_bits = 36;
 #endif
 
 	if (c->extended_cpuid_level >= 0x80000007)
@@ -602,8 +629,12 @@
 {
 #ifdef CONFIG_X86_64
 	c->x86_clflush_size = 64;
+	c->x86_phys_bits = 36;
+	c->x86_virt_bits = 48;
 #else
 	c->x86_clflush_size = 32;
+	c->x86_phys_bits = 32;
+	c->x86_virt_bits = 32;
 #endif
 	c->x86_cache_alignment = c->x86_clflush_size;
 
@@ -634,12 +665,12 @@
 
 void __init early_cpu_init(void)
 {
-	struct cpu_dev **cdev;
+	const struct cpu_dev *const *cdev;
 	int count = 0;
 
-	printk("KERNEL supported cpus:\n");
+	printk(KERN_INFO "KERNEL supported cpus:\n");
 	for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
-		struct cpu_dev *cpudev = *cdev;
+		const struct cpu_dev *cpudev = *cdev;
 		unsigned int j;
 
 		if (count >= X86_VENDOR_NUM)
@@ -650,7 +681,7 @@
 		for (j = 0; j < 2; j++) {
 			if (!cpudev->c_ident[j])
 				continue;
-			printk("  %s %s\n", cpudev->c_vendor,
+			printk(KERN_INFO "  %s %s\n", cpudev->c_vendor,
 				cpudev->c_ident[j]);
 		}
 	}
@@ -726,9 +757,13 @@
 	c->x86_coreid_bits = 0;
 #ifdef CONFIG_X86_64
 	c->x86_clflush_size = 64;
+	c->x86_phys_bits = 36;
+	c->x86_virt_bits = 48;
 #else
 	c->cpuid_level = -1;	/* CPUID not detected */
 	c->x86_clflush_size = 32;
+	c->x86_phys_bits = 32;
+	c->x86_virt_bits = 32;
 #endif
 	c->x86_cache_alignment = c->x86_clflush_size;
 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
@@ -759,8 +794,8 @@
 	squash_the_stupid_serial_number(c);
 
 	/*
-	 * The vendor-specific functions might have changed features.  Now
-	 * we do "generic changes."
+	 * The vendor-specific functions might have changed features.
+	 * Now we do "generic changes."
 	 */
 
 	/* Filter out anything that depends on CPUID levels we don't have */
@@ -768,7 +803,7 @@
 
 	/* If the model name is still unset, do table lookup. */
 	if (!c->x86_model_id[0]) {
-		char *p;
+		const char *p;
 		p = table_lookup_model(c);
 		if (p)
 			strcpy(c->x86_model_id, p);
@@ -843,11 +878,11 @@
 }
 
 struct msr_range {
-	unsigned min;
-	unsigned max;
+	unsigned	min;
+	unsigned	max;
 };
 
-static struct msr_range msr_range_array[] __cpuinitdata = {
+static const struct msr_range msr_range_array[] __cpuinitconst = {
 	{ 0x00000000, 0x00000418},
 	{ 0xc0000000, 0xc000040b},
 	{ 0xc0010000, 0xc0010142},
@@ -856,14 +891,15 @@
 
 static void __cpuinit print_cpu_msr(void)
 {
+	unsigned index_min, index_max;
 	unsigned index;
 	u64 val;
 	int i;
-	unsigned index_min, index_max;
 
 	for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
 		index_min = msr_range_array[i].min;
 		index_max = msr_range_array[i].max;
+
 		for (index = index_min; index < index_max; index++) {
 			if (rdmsrl_amd_safe(index, &val))
 				continue;
@@ -873,6 +909,7 @@
 }
 
 static int show_msr __cpuinitdata;
+
 static __init int setup_show_msr(char *arg)
 {
 	int num;
@@ -894,12 +931,14 @@
 
 void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
 {
-	char *vendor = NULL;
+	const char *vendor = NULL;
 
-	if (c->x86_vendor < X86_VENDOR_NUM)
+	if (c->x86_vendor < X86_VENDOR_NUM) {
 		vendor = this_cpu->c_vendor;
-	else if (c->cpuid_level >= 0)
-		vendor = c->x86_vendor_id;
+	} else {
+		if (c->cpuid_level >= 0)
+			vendor = c->x86_vendor_id;
+	}
 
 	if (vendor && !strstr(c->x86_model_id, vendor))
 		printk(KERN_CONT "%s ", vendor);
@@ -926,10 +965,12 @@
 static __init int setup_disablecpuid(char *arg)
 {
 	int bit;
+
 	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
 		setup_clear_cpu_cap(bit);
 	else
 		return 0;
+
 	return 1;
 }
 __setup("clearcpuid=", setup_disablecpuid);
@@ -939,6 +980,7 @@
 
 DEFINE_PER_CPU_FIRST(union irq_stack_union,
 		     irq_stack_union) __aligned(PAGE_SIZE);
+
 DEFINE_PER_CPU(char *, irq_stack_ptr) =
 	init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
 
@@ -948,12 +990,21 @@
 
 DEFINE_PER_CPU(unsigned int, irq_count) = -1;
 
+/*
+ * Special IST stacks which the CPU switches to when it calls
+ * an IST-marked descriptor entry. Up to 7 stacks (hardware
+ * limit), all of them are 4K, except the debug stack which
+ * is 8K.
+ */
+static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
+	  [0 ... N_EXCEPTION_STACKS - 1]	= EXCEPTION_STKSZ,
+	  [DEBUG_STACK - 1]			= DEBUG_STKSZ
+};
+
 static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
 	[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ])
 	__aligned(PAGE_SIZE);
 
-extern asmlinkage void ignore_sysret(void);
-
 /* May not be marked __init: used by software suspend */
 void syscall_init(void)
 {
@@ -983,7 +1034,7 @@
  */
 DEFINE_PER_CPU(struct orig_ist, orig_ist);
 
-#else	/* x86_64 */
+#else	/* CONFIG_X86_64 */
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 DEFINE_PER_CPU(unsigned long, stack_canary);
@@ -995,9 +1046,26 @@
 	memset(regs, 0, sizeof(struct pt_regs));
 	regs->fs = __KERNEL_PERCPU;
 	regs->gs = __KERNEL_STACK_CANARY;
+
 	return regs;
 }
-#endif	/* x86_64 */
+#endif	/* CONFIG_X86_64 */
+
+/*
+ * Clear all 6 debug registers:
+ */
+static void clear_all_debug_regs(void)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		/* Ignore db4, db5 */
+		if ((i == 4) || (i == 5))
+			continue;
+
+		set_debugreg(0, i);
+	}
+}
 
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
@@ -1007,15 +1075,20 @@
  * A lot of state is already set up in PDA init for 64 bit
  */
 #ifdef CONFIG_X86_64
+
 void __cpuinit cpu_init(void)
 {
-	int cpu = stack_smp_processor_id();
-	struct tss_struct *t = &per_cpu(init_tss, cpu);
-	struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
-	unsigned long v;
+	struct orig_ist *orig_ist;
 	struct task_struct *me;
+	struct tss_struct *t;
+	unsigned long v;
+	int cpu;
 	int i;
 
+	cpu = stack_smp_processor_id();
+	t = &per_cpu(init_tss, cpu);
+	orig_ist = &per_cpu(orig_ist, cpu);
+
 #ifdef CONFIG_NUMA
 	if (cpu != 0 && percpu_read(node_number) == 0 &&
 	    cpu_to_node(cpu) != NUMA_NO_NODE)
@@ -1056,19 +1129,17 @@
 	 * set up and load the per-CPU TSS
 	 */
 	if (!orig_ist->ist[0]) {
-		static const unsigned int sizes[N_EXCEPTION_STACKS] = {
-		  [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
-		  [DEBUG_STACK - 1] = DEBUG_STKSZ
-		};
 		char *estacks = per_cpu(exception_stacks, cpu);
+
 		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
-			estacks += sizes[v];
+			estacks += exception_stack_sizes[v];
 			orig_ist->ist[v] = t->x86_tss.ist[v] =
 					(unsigned long)estacks;
 		}
 	}
 
 	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
+
 	/*
 	 * <= is required because the CPU will access up to
 	 * 8 bits beyond the end of the IO permission bitmap.
@@ -1078,8 +1149,7 @@
 
 	atomic_inc(&init_mm.mm_count);
 	me->active_mm = &init_mm;
-	if (me->mm)
-		BUG();
+	BUG_ON(me->mm);
 	enter_lazy_tlb(&init_mm, me);
 
 	load_sp0(t, &current->thread);
@@ -1098,17 +1168,7 @@
 		arch_kgdb_ops.correct_hw_break();
 	else
 #endif
-	{
-		/*
-		 * Clear all 6 debug registers:
-		 */
-		set_debugreg(0UL, 0);
-		set_debugreg(0UL, 1);
-		set_debugreg(0UL, 2);
-		set_debugreg(0UL, 3);
-		set_debugreg(0UL, 6);
-		set_debugreg(0UL, 7);
-	}
+		clear_all_debug_regs();
 
 	fpu_init();
 
@@ -1129,7 +1189,8 @@
 
 	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
 		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
-		for (;;) local_irq_enable();
+		for (;;)
+			local_irq_enable();
 	}
 
 	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
@@ -1145,8 +1206,7 @@
 	 */
 	atomic_inc(&init_mm.mm_count);
 	curr->active_mm = &init_mm;
-	if (curr->mm)
-		BUG();
+	BUG_ON(curr->mm);
 	enter_lazy_tlb(&init_mm, curr);
 
 	load_sp0(t, thread);
@@ -1159,13 +1219,7 @@
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
 #endif
 
-	/* Clear all 6 debug registers: */
-	set_debugreg(0, 0);
-	set_debugreg(0, 1);
-	set_debugreg(0, 2);
-	set_debugreg(0, 3);
-	set_debugreg(0, 6);
-	set_debugreg(0, 7);
+	clear_all_debug_regs();
 
 	/*
 	 * Force FPU initialization:
@@ -1185,6 +1239,4 @@
 
 	xsave_init();
 }
-
-
 #endif
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index de4094a..6de9a90 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -3,33 +3,34 @@
 #define ARCH_X86_CPU_H
 
 struct cpu_model_info {
-	int vendor;
-	int family;
-	char *model_names[16];
+	int		vendor;
+	int		family;
+	const char	*model_names[16];
 };
 
 /* attempt to consolidate cpu attributes */
 struct cpu_dev {
-	char	* c_vendor;
+	const char	*c_vendor;
 
 	/* some have two possibilities for cpuid string */
-	char	* c_ident[2];	
+	const char	*c_ident[2];
 
 	struct		cpu_model_info c_models[4];
 
-	void            (*c_early_init)(struct cpuinfo_x86 *c);
-	void		(*c_init)(struct cpuinfo_x86 * c);
-	void		(*c_identify)(struct cpuinfo_x86 * c);
-	unsigned int	(*c_size_cache)(struct cpuinfo_x86 * c, unsigned int size);
-	int	c_x86_vendor;
+	void            (*c_early_init)(struct cpuinfo_x86 *);
+	void		(*c_init)(struct cpuinfo_x86 *);
+	void		(*c_identify)(struct cpuinfo_x86 *);
+	unsigned int	(*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
+	int		c_x86_vendor;
 };
 
 #define cpu_dev_register(cpu_devX) \
-	static struct cpu_dev *__cpu_dev_##cpu_devX __used \
+	static const struct cpu_dev *const __cpu_dev_##cpu_devX __used \
 	__attribute__((__section__(".x86_cpu_dev.init"))) = \
 	&cpu_devX;
 
-extern struct cpu_dev *__x86_cpu_dev_start[], *__x86_cpu_dev_end[];
+extern const struct cpu_dev *const __x86_cpu_dev_start[],
+			    *const __x86_cpu_dev_end[];
 
 extern void display_cacheinfo(struct cpuinfo_x86 *c);
 
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c
new file mode 100755
index 0000000..46e29ab
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpu_debug.c
@@ -0,0 +1,901 @@
+/*
+ * CPU x86 architecture debug code
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+
+#include <asm/cpu_debug.h>
+#include <asm/paravirt.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/apic.h>
+#include <asm/desc.h>
+
+static DEFINE_PER_CPU(struct cpu_cpuX_base, cpu_arr[CPU_REG_ALL_BIT]);
+static DEFINE_PER_CPU(struct cpu_private *, priv_arr[MAX_CPU_FILES]);
+static DEFINE_PER_CPU(unsigned, cpu_modelflag);
+static DEFINE_PER_CPU(int, cpu_priv_count);
+static DEFINE_PER_CPU(unsigned, cpu_model);
+
+static DEFINE_MUTEX(cpu_debug_lock);
+
+static struct dentry *cpu_debugfs_dir;
+
+static struct cpu_debug_base cpu_base[] = {
+	{ "mc",		CPU_MC,		0	},
+	{ "monitor",	CPU_MONITOR,	0	},
+	{ "time",	CPU_TIME,	0	},
+	{ "pmc",	CPU_PMC,	1	},
+	{ "platform",	CPU_PLATFORM,	0	},
+	{ "apic",	CPU_APIC,	0	},
+	{ "poweron",	CPU_POWERON,	0	},
+	{ "control",	CPU_CONTROL,	0	},
+	{ "features",	CPU_FEATURES,	0	},
+	{ "lastbranch",	CPU_LBRANCH,	0	},
+	{ "bios",	CPU_BIOS,	0	},
+	{ "freq",	CPU_FREQ,	0	},
+	{ "mtrr",	CPU_MTRR,	0	},
+	{ "perf",	CPU_PERF,	0	},
+	{ "cache",	CPU_CACHE,	0	},
+	{ "sysenter",	CPU_SYSENTER,	0	},
+	{ "therm",	CPU_THERM,	0	},
+	{ "misc",	CPU_MISC,	0	},
+	{ "debug",	CPU_DEBUG,	0	},
+	{ "pat",	CPU_PAT,	0	},
+	{ "vmx",	CPU_VMX,	0	},
+	{ "call",	CPU_CALL,	0	},
+	{ "base",	CPU_BASE,	0	},
+	{ "ver",	CPU_VER,	0	},
+	{ "conf",	CPU_CONF,	0	},
+	{ "smm",	CPU_SMM,	0	},
+	{ "svm",	CPU_SVM,	0	},
+	{ "osvm",	CPU_OSVM,	0	},
+	{ "tss",	CPU_TSS,	0	},
+	{ "cr",		CPU_CR,		0	},
+	{ "dt",		CPU_DT,		0	},
+	{ "registers",	CPU_REG_ALL,	0	},
+};
+
+static struct cpu_file_base cpu_file[] = {
+	{ "index",	CPU_REG_ALL,	0	},
+	{ "value",	CPU_REG_ALL,	1	},
+};
+
+/* Intel Registers Range */
+static struct cpu_debug_range cpu_intel_range[] = {
+	{ 0x00000000, 0x00000001, CPU_MC,	CPU_INTEL_ALL		},
+	{ 0x00000006, 0x00000007, CPU_MONITOR,	CPU_CX_AT_XE		},
+	{ 0x00000010, 0x00000010, CPU_TIME,	CPU_INTEL_ALL		},
+	{ 0x00000011, 0x00000013, CPU_PMC,	CPU_INTEL_PENTIUM	},
+	{ 0x00000017, 0x00000017, CPU_PLATFORM,	CPU_PX_CX_AT_XE		},
+	{ 0x0000001B, 0x0000001B, CPU_APIC,	CPU_P6_CX_AT_XE		},
+
+	{ 0x0000002A, 0x0000002A, CPU_POWERON,	CPU_PX_CX_AT_XE		},
+	{ 0x0000002B, 0x0000002B, CPU_POWERON,	CPU_INTEL_XEON		},
+	{ 0x0000002C, 0x0000002C, CPU_FREQ,	CPU_INTEL_XEON		},
+	{ 0x0000003A, 0x0000003A, CPU_CONTROL,	CPU_CX_AT_XE		},
+
+	{ 0x00000040, 0x00000043, CPU_LBRANCH,	CPU_PM_CX_AT_XE		},
+	{ 0x00000044, 0x00000047, CPU_LBRANCH,	CPU_PM_CO_AT		},
+	{ 0x00000060, 0x00000063, CPU_LBRANCH,	CPU_C2_AT		},
+	{ 0x00000064, 0x00000067, CPU_LBRANCH,	CPU_INTEL_ATOM		},
+
+	{ 0x00000079, 0x00000079, CPU_BIOS,	CPU_P6_CX_AT_XE		},
+	{ 0x00000088, 0x0000008A, CPU_CACHE,	CPU_INTEL_P6		},
+	{ 0x0000008B, 0x0000008B, CPU_BIOS,	CPU_P6_CX_AT_XE		},
+	{ 0x0000009B, 0x0000009B, CPU_MONITOR,	CPU_INTEL_XEON		},
+
+	{ 0x000000C1, 0x000000C2, CPU_PMC,	CPU_P6_CX_AT		},
+	{ 0x000000CD, 0x000000CD, CPU_FREQ,	CPU_CX_AT		},
+	{ 0x000000E7, 0x000000E8, CPU_PERF,	CPU_CX_AT		},
+	{ 0x000000FE, 0x000000FE, CPU_MTRR,	CPU_P6_CX_XE		},
+
+	{ 0x00000116, 0x00000116, CPU_CACHE,	CPU_INTEL_P6		},
+	{ 0x00000118, 0x00000118, CPU_CACHE,	CPU_INTEL_P6		},
+	{ 0x00000119, 0x00000119, CPU_CACHE,	CPU_INTEL_PX		},
+	{ 0x0000011A, 0x0000011B, CPU_CACHE,	CPU_INTEL_P6		},
+	{ 0x0000011E, 0x0000011E, CPU_CACHE,	CPU_PX_CX_AT		},
+
+	{ 0x00000174, 0x00000176, CPU_SYSENTER,	CPU_P6_CX_AT_XE		},
+	{ 0x00000179, 0x0000017A, CPU_MC,	CPU_PX_CX_AT_XE		},
+	{ 0x0000017B, 0x0000017B, CPU_MC,	CPU_P6_XE		},
+	{ 0x00000186, 0x00000187, CPU_PMC,	CPU_P6_CX_AT		},
+	{ 0x00000198, 0x00000199, CPU_PERF,	CPU_PM_CX_AT_XE		},
+	{ 0x0000019A, 0x0000019A, CPU_TIME,	CPU_PM_CX_AT_XE		},
+	{ 0x0000019B, 0x0000019D, CPU_THERM,	CPU_PM_CX_AT_XE		},
+	{ 0x000001A0, 0x000001A0, CPU_MISC,	CPU_PM_CX_AT_XE		},
+
+	{ 0x000001C9, 0x000001C9, CPU_LBRANCH,	CPU_PM_CX_AT		},
+	{ 0x000001D7, 0x000001D8, CPU_LBRANCH,	CPU_INTEL_XEON		},
+	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	CPU_CX_AT_XE		},
+	{ 0x000001DA, 0x000001DA, CPU_LBRANCH,	CPU_INTEL_XEON		},
+	{ 0x000001DB, 0x000001DB, CPU_LBRANCH,	CPU_P6_XE		},
+	{ 0x000001DC, 0x000001DC, CPU_LBRANCH,	CPU_INTEL_P6		},
+	{ 0x000001DD, 0x000001DE, CPU_LBRANCH,	CPU_PX_CX_AT_XE		},
+	{ 0x000001E0, 0x000001E0, CPU_LBRANCH,	CPU_INTEL_P6		},
+
+	{ 0x00000200, 0x0000020F, CPU_MTRR,	CPU_P6_CX_XE		},
+	{ 0x00000250, 0x00000250, CPU_MTRR,	CPU_P6_CX_XE		},
+	{ 0x00000258, 0x00000259, CPU_MTRR,	CPU_P6_CX_XE		},
+	{ 0x00000268, 0x0000026F, CPU_MTRR,	CPU_P6_CX_XE		},
+	{ 0x00000277, 0x00000277, CPU_PAT,	CPU_C2_AT_XE		},
+	{ 0x000002FF, 0x000002FF, CPU_MTRR,	CPU_P6_CX_XE		},
+
+	{ 0x00000300, 0x00000308, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x00000309, 0x0000030B, CPU_PMC,	CPU_C2_AT_XE		},
+	{ 0x0000030C, 0x00000311, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x00000345, 0x00000345, CPU_PMC,	CPU_C2_AT		},
+	{ 0x00000360, 0x00000371, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x0000038D, 0x00000390, CPU_PMC,	CPU_C2_AT		},
+	{ 0x000003A0, 0x000003BE, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x000003C0, 0x000003CD, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x000003E0, 0x000003E1, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x000003F0, 0x000003F0, CPU_PMC,	CPU_INTEL_XEON		},
+	{ 0x000003F1, 0x000003F1, CPU_PMC,	CPU_C2_AT_XE		},
+	{ 0x000003F2, 0x000003F2, CPU_PMC,	CPU_INTEL_XEON		},
+
+	{ 0x00000400, 0x00000402, CPU_MC,	CPU_PM_CX_AT_XE		},
+	{ 0x00000403, 0x00000403, CPU_MC,	CPU_INTEL_XEON		},
+	{ 0x00000404, 0x00000406, CPU_MC,	CPU_PM_CX_AT_XE		},
+	{ 0x00000407, 0x00000407, CPU_MC,	CPU_INTEL_XEON		},
+	{ 0x00000408, 0x0000040A, CPU_MC,	CPU_PM_CX_AT_XE		},
+	{ 0x0000040B, 0x0000040B, CPU_MC,	CPU_INTEL_XEON		},
+	{ 0x0000040C, 0x0000040E, CPU_MC,	CPU_PM_CX_XE		},
+	{ 0x0000040F, 0x0000040F, CPU_MC,	CPU_INTEL_XEON		},
+	{ 0x00000410, 0x00000412, CPU_MC,	CPU_PM_CX_AT_XE		},
+	{ 0x00000413, 0x00000417, CPU_MC,	CPU_CX_AT_XE		},
+	{ 0x00000480, 0x0000048B, CPU_VMX,	CPU_CX_AT_XE		},
+
+	{ 0x00000600, 0x00000600, CPU_DEBUG,	CPU_PM_CX_AT_XE		},
+	{ 0x00000680, 0x0000068F, CPU_LBRANCH,	CPU_INTEL_XEON		},
+	{ 0x000006C0, 0x000006CF, CPU_LBRANCH,	CPU_INTEL_XEON		},
+
+	{ 0x000107CC, 0x000107D3, CPU_PMC,	CPU_INTEL_XEON_MP	},
+
+	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	CPU_INTEL_XEON		},
+	{ 0xC0000081, 0xC0000082, CPU_CALL,	CPU_INTEL_XEON		},
+	{ 0xC0000084, 0xC0000084, CPU_CALL,	CPU_INTEL_XEON		},
+	{ 0xC0000100, 0xC0000102, CPU_BASE,	CPU_INTEL_XEON		},
+};
+
+/* AMD Registers Range */
+static struct cpu_debug_range cpu_amd_range[] = {
+	{ 0x00000000, 0x00000001, CPU_MC,	CPU_K10_PLUS,		},
+	{ 0x00000010, 0x00000010, CPU_TIME,	CPU_K8_PLUS,		},
+	{ 0x0000001B, 0x0000001B, CPU_APIC,	CPU_K8_PLUS,		},
+	{ 0x0000002A, 0x0000002A, CPU_POWERON,	CPU_K7_PLUS		},
+	{ 0x0000008B, 0x0000008B, CPU_VER,	CPU_K8_PLUS		},
+	{ 0x000000FE, 0x000000FE, CPU_MTRR,	CPU_K8_PLUS,		},
+
+	{ 0x00000174, 0x00000176, CPU_SYSENTER,	CPU_K8_PLUS,		},
+	{ 0x00000179, 0x0000017B, CPU_MC,	CPU_K8_PLUS,		},
+	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	CPU_K8_PLUS,		},
+	{ 0x000001DB, 0x000001DE, CPU_LBRANCH,	CPU_K8_PLUS,		},
+
+	{ 0x00000200, 0x0000020F, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000250, 0x00000250, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000258, 0x00000259, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000268, 0x0000026F, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0x00000277, 0x00000277, CPU_PAT,	CPU_K8_PLUS,		},
+	{ 0x000002FF, 0x000002FF, CPU_MTRR,	CPU_K8_PLUS,		},
+
+	{ 0x00000400, 0x00000413, CPU_MC,	CPU_K8_PLUS,		},
+
+	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	CPU_AMD_ALL,		},
+	{ 0xC0000081, 0xC0000084, CPU_CALL,	CPU_K8_PLUS,		},
+	{ 0xC0000100, 0xC0000102, CPU_BASE,	CPU_K8_PLUS,		},
+	{ 0xC0000103, 0xC0000103, CPU_TIME,	CPU_K10_PLUS,		},
+
+	{ 0xC0010000, 0xC0010007, CPU_PMC,	CPU_K8_PLUS,		},
+	{ 0xC0010010, 0xC0010010, CPU_CONF,	CPU_K7_PLUS,		},
+	{ 0xC0010015, 0xC0010015, CPU_CONF,	CPU_K7_PLUS,		},
+	{ 0xC0010016, 0xC001001A, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0xC001001D, 0xC001001D, CPU_MTRR,	CPU_K8_PLUS,		},
+	{ 0xC001001F, 0xC001001F, CPU_CONF,	CPU_K8_PLUS,		},
+	{ 0xC0010030, 0xC0010035, CPU_BIOS,	CPU_K8_PLUS,		},
+	{ 0xC0010044, 0xC0010048, CPU_MC,	CPU_K8_PLUS,		},
+	{ 0xC0010050, 0xC0010056, CPU_SMM,	CPU_K0F_PLUS,		},
+	{ 0xC0010058, 0xC0010058, CPU_CONF,	CPU_K10_PLUS,		},
+	{ 0xC0010060, 0xC0010060, CPU_CACHE,	CPU_AMD_11,		},
+	{ 0xC0010061, 0xC0010068, CPU_SMM,	CPU_K10_PLUS,		},
+	{ 0xC0010069, 0xC001006B, CPU_SMM,	CPU_AMD_11,		},
+	{ 0xC0010070, 0xC0010071, CPU_SMM,	CPU_K10_PLUS,		},
+	{ 0xC0010111, 0xC0010113, CPU_SMM,	CPU_K8_PLUS,		},
+	{ 0xC0010114, 0xC0010118, CPU_SVM,	CPU_K10_PLUS,		},
+	{ 0xC0010140, 0xC0010141, CPU_OSVM,	CPU_K10_PLUS,		},
+	{ 0xC0011022, 0xC0011023, CPU_CONF,	CPU_K10_PLUS,		},
+};
+
+
+/* Intel */
+static int get_intel_modelflag(unsigned model)
+{
+	int flag;
+
+	switch (model) {
+	case 0x0501:
+	case 0x0502:
+	case 0x0504:
+		flag = CPU_INTEL_PENTIUM;
+		break;
+	case 0x0601:
+	case 0x0603:
+	case 0x0605:
+	case 0x0607:
+	case 0x0608:
+	case 0x060A:
+	case 0x060B:
+		flag = CPU_INTEL_P6;
+		break;
+	case 0x0609:
+	case 0x060D:
+		flag = CPU_INTEL_PENTIUM_M;
+		break;
+	case 0x060E:
+		flag = CPU_INTEL_CORE;
+		break;
+	case 0x060F:
+	case 0x0617:
+		flag = CPU_INTEL_CORE2;
+		break;
+	case 0x061C:
+		flag = CPU_INTEL_ATOM;
+		break;
+	case 0x0F00:
+	case 0x0F01:
+	case 0x0F02:
+	case 0x0F03:
+	case 0x0F04:
+		flag = CPU_INTEL_XEON_P4;
+		break;
+	case 0x0F06:
+		flag = CPU_INTEL_XEON_MP;
+		break;
+	default:
+		flag = CPU_NONE;
+		break;
+	}
+
+	return flag;
+}
+
+/* AMD */
+static int get_amd_modelflag(unsigned model)
+{
+	int flag;
+
+	switch (model >> 8) {
+	case 0x6:
+		flag = CPU_AMD_K6;
+		break;
+	case 0x7:
+		flag = CPU_AMD_K7;
+		break;
+	case 0x8:
+		flag = CPU_AMD_K8;
+		break;
+	case 0xf:
+		flag = CPU_AMD_0F;
+		break;
+	case 0x10:
+		flag = CPU_AMD_10;
+		break;
+	case 0x11:
+		flag = CPU_AMD_11;
+		break;
+	default:
+		flag = CPU_NONE;
+		break;
+	}
+
+	return flag;
+}
+
+static int get_cpu_modelflag(unsigned cpu)
+{
+	int flag;
+
+	flag = per_cpu(cpu_model, cpu);
+
+	switch (flag >> 16) {
+	case X86_VENDOR_INTEL:
+		flag = get_intel_modelflag(flag);
+		break;
+	case X86_VENDOR_AMD:
+		flag = get_amd_modelflag(flag & 0xffff);
+		break;
+	default:
+		flag = CPU_NONE;
+		break;
+	}
+
+	return flag;
+}
+
+static int get_cpu_range_count(unsigned cpu)
+{
+	int index;
+
+	switch (per_cpu(cpu_model, cpu) >> 16) {
+	case X86_VENDOR_INTEL:
+		index = ARRAY_SIZE(cpu_intel_range);
+		break;
+	case X86_VENDOR_AMD:
+		index = ARRAY_SIZE(cpu_amd_range);
+		break;
+	default:
+		index = 0;
+		break;
+	}
+
+	return index;
+}
+
+static int is_typeflag_valid(unsigned cpu, unsigned flag)
+{
+	unsigned vendor, modelflag;
+	int i, index;
+
+	/* Standard Registers should be always valid */
+	if (flag >= CPU_TSS)
+		return 1;
+
+	modelflag = per_cpu(cpu_modelflag, cpu);
+	vendor = per_cpu(cpu_model, cpu) >> 16;
+	index = get_cpu_range_count(cpu);
+
+	for (i = 0; i < index; i++) {
+		switch (vendor) {
+		case X86_VENDOR_INTEL:
+			if ((cpu_intel_range[i].model & modelflag) &&
+			    (cpu_intel_range[i].flag & flag))
+				return 1;
+			break;
+		case X86_VENDOR_AMD:
+			if ((cpu_amd_range[i].model & modelflag) &&
+			    (cpu_amd_range[i].flag & flag))
+				return 1;
+			break;
+		}
+	}
+
+	/* Invalid */
+	return 0;
+}
+
+static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max,
+			      int index, unsigned flag)
+{
+	unsigned modelflag;
+
+	modelflag = per_cpu(cpu_modelflag, cpu);
+	*max = 0;
+	switch (per_cpu(cpu_model, cpu) >> 16) {
+	case X86_VENDOR_INTEL:
+		if ((cpu_intel_range[index].model & modelflag) &&
+		    (cpu_intel_range[index].flag & flag)) {
+			*min = cpu_intel_range[index].min;
+			*max = cpu_intel_range[index].max;
+		}
+		break;
+	case X86_VENDOR_AMD:
+		if ((cpu_amd_range[index].model & modelflag) &&
+		    (cpu_amd_range[index].flag & flag)) {
+			*min = cpu_amd_range[index].min;
+			*max = cpu_amd_range[index].max;
+		}
+		break;
+	}
+
+	return *max;
+}
+
+/* This function can also be called with seq = NULL for printk */
+static void print_cpu_data(struct seq_file *seq, unsigned type,
+			   u32 low, u32 high)
+{
+	struct cpu_private *priv;
+	u64 val = high;
+
+	if (seq) {
+		priv = seq->private;
+		if (priv->file) {
+			val = (val << 32) | low;
+			seq_printf(seq, "0x%llx\n", val);
+		} else
+			seq_printf(seq, " %08x: %08x_%08x\n",
+				   type, high, low);
+	} else
+		printk(KERN_INFO " %08x: %08x_%08x\n", type, high, low);
+}
+
+/* This function can also be called with seq = NULL for printk */
+static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag)
+{
+	unsigned msr, msr_min, msr_max;
+	struct cpu_private *priv;
+	u32 low, high;
+	int i, range;
+
+	if (seq) {
+		priv = seq->private;
+		if (priv->file) {
+			if (!rdmsr_safe_on_cpu(priv->cpu, priv->reg,
+					       &low, &high))
+				print_cpu_data(seq, priv->reg, low, high);
+			return;
+		}
+	}
+
+	range = get_cpu_range_count(cpu);
+
+	for (i = 0; i < range; i++) {
+		if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag))
+			continue;
+
+		for (msr = msr_min; msr <= msr_max; msr++) {
+			if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
+				continue;
+			print_cpu_data(seq, msr, low, high);
+		}
+	}
+}
+
+static void print_tss(void *arg)
+{
+	struct pt_regs *regs = task_pt_regs(current);
+	struct seq_file *seq = arg;
+	unsigned int seg;
+
+	seq_printf(seq, " RAX\t: %016lx\n", regs->ax);
+	seq_printf(seq, " RBX\t: %016lx\n", regs->bx);
+	seq_printf(seq, " RCX\t: %016lx\n", regs->cx);
+	seq_printf(seq, " RDX\t: %016lx\n", regs->dx);
+
+	seq_printf(seq, " RSI\t: %016lx\n", regs->si);
+	seq_printf(seq, " RDI\t: %016lx\n", regs->di);
+	seq_printf(seq, " RBP\t: %016lx\n", regs->bp);
+	seq_printf(seq, " ESP\t: %016lx\n", regs->sp);
+
+#ifdef CONFIG_X86_64
+	seq_printf(seq, " R08\t: %016lx\n", regs->r8);
+	seq_printf(seq, " R09\t: %016lx\n", regs->r9);
+	seq_printf(seq, " R10\t: %016lx\n", regs->r10);
+	seq_printf(seq, " R11\t: %016lx\n", regs->r11);
+	seq_printf(seq, " R12\t: %016lx\n", regs->r12);
+	seq_printf(seq, " R13\t: %016lx\n", regs->r13);
+	seq_printf(seq, " R14\t: %016lx\n", regs->r14);
+	seq_printf(seq, " R15\t: %016lx\n", regs->r15);
+#endif
+
+	asm("movl %%cs,%0" : "=r" (seg));
+	seq_printf(seq, " CS\t:             %04x\n", seg);
+	asm("movl %%ds,%0" : "=r" (seg));
+	seq_printf(seq, " DS\t:             %04x\n", seg);
+	seq_printf(seq, " SS\t:             %04lx\n", regs->ss & 0xffff);
+	asm("movl %%es,%0" : "=r" (seg));
+	seq_printf(seq, " ES\t:             %04x\n", seg);
+	asm("movl %%fs,%0" : "=r" (seg));
+	seq_printf(seq, " FS\t:             %04x\n", seg);
+	asm("movl %%gs,%0" : "=r" (seg));
+	seq_printf(seq, " GS\t:             %04x\n", seg);
+
+	seq_printf(seq, " EFLAGS\t: %016lx\n", regs->flags);
+
+	seq_printf(seq, " EIP\t: %016lx\n", regs->ip);
+}
+
+static void print_cr(void *arg)
+{
+	struct seq_file *seq = arg;
+
+	seq_printf(seq, " cr0\t: %016lx\n", read_cr0());
+	seq_printf(seq, " cr2\t: %016lx\n", read_cr2());
+	seq_printf(seq, " cr3\t: %016lx\n", read_cr3());
+	seq_printf(seq, " cr4\t: %016lx\n", read_cr4_safe());
+#ifdef CONFIG_X86_64
+	seq_printf(seq, " cr8\t: %016lx\n", read_cr8());
+#endif
+}
+
+static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt)
+{
+	seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size));
+}
+
+static void print_dt(void *seq)
+{
+	struct desc_ptr dt;
+	unsigned long ldt;
+
+	/* IDT */
+	store_idt((struct desc_ptr *)&dt);
+	print_desc_ptr("IDT", seq, dt);
+
+	/* GDT */
+	store_gdt((struct desc_ptr *)&dt);
+	print_desc_ptr("GDT", seq, dt);
+
+	/* LDT */
+	store_ldt(ldt);
+	seq_printf(seq, " LDT\t: %016lx\n", ldt);
+
+	/* TR */
+	store_tr(ldt);
+	seq_printf(seq, " TR\t: %016lx\n", ldt);
+}
+
+static void print_dr(void *arg)
+{
+	struct seq_file *seq = arg;
+	unsigned long dr;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		/* Ignore db4, db5 */
+		if ((i == 4) || (i == 5))
+			continue;
+		get_debugreg(dr, i);
+		seq_printf(seq, " dr%d\t: %016lx\n", i, dr);
+	}
+
+	seq_printf(seq, "\n MSR\t:\n");
+}
+
+static void print_apic(void *arg)
+{
+	struct seq_file *seq = arg;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	seq_printf(seq, " LAPIC\t:\n");
+	seq_printf(seq, " ID\t\t: %08x\n",  apic_read(APIC_ID) >> 24);
+	seq_printf(seq, " LVR\t\t: %08x\n",  apic_read(APIC_LVR));
+	seq_printf(seq, " TASKPRI\t: %08x\n",  apic_read(APIC_TASKPRI));
+	seq_printf(seq, " ARBPRI\t\t: %08x\n",  apic_read(APIC_ARBPRI));
+	seq_printf(seq, " PROCPRI\t: %08x\n",  apic_read(APIC_PROCPRI));
+	seq_printf(seq, " LDR\t\t: %08x\n",  apic_read(APIC_LDR));
+	seq_printf(seq, " DFR\t\t: %08x\n",  apic_read(APIC_DFR));
+	seq_printf(seq, " SPIV\t\t: %08x\n",  apic_read(APIC_SPIV));
+	seq_printf(seq, " ISR\t\t: %08x\n",  apic_read(APIC_ISR));
+	seq_printf(seq, " ESR\t\t: %08x\n",  apic_read(APIC_ESR));
+	seq_printf(seq, " ICR\t\t: %08x\n",  apic_read(APIC_ICR));
+	seq_printf(seq, " ICR2\t\t: %08x\n",  apic_read(APIC_ICR2));
+	seq_printf(seq, " LVTT\t\t: %08x\n",  apic_read(APIC_LVTT));
+	seq_printf(seq, " LVTTHMR\t: %08x\n",  apic_read(APIC_LVTTHMR));
+	seq_printf(seq, " LVTPC\t\t: %08x\n",  apic_read(APIC_LVTPC));
+	seq_printf(seq, " LVT0\t\t: %08x\n",  apic_read(APIC_LVT0));
+	seq_printf(seq, " LVT1\t\t: %08x\n",  apic_read(APIC_LVT1));
+	seq_printf(seq, " LVTERR\t\t: %08x\n",  apic_read(APIC_LVTERR));
+	seq_printf(seq, " TMICT\t\t: %08x\n",  apic_read(APIC_TMICT));
+	seq_printf(seq, " TMCCT\t\t: %08x\n",  apic_read(APIC_TMCCT));
+	seq_printf(seq, " TDCR\t\t: %08x\n",  apic_read(APIC_TDCR));
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+	seq_printf(seq, "\n MSR\t:\n");
+}
+
+static int cpu_seq_show(struct seq_file *seq, void *v)
+{
+	struct cpu_private *priv = seq->private;
+
+	if (priv == NULL)
+		return -EINVAL;
+
+	switch (cpu_base[priv->type].flag) {
+	case CPU_TSS:
+		smp_call_function_single(priv->cpu, print_tss, seq, 1);
+		break;
+	case CPU_CR:
+		smp_call_function_single(priv->cpu, print_cr, seq, 1);
+		break;
+	case CPU_DT:
+		smp_call_function_single(priv->cpu, print_dt, seq, 1);
+		break;
+	case CPU_DEBUG:
+		if (priv->file == CPU_INDEX_BIT)
+			smp_call_function_single(priv->cpu, print_dr, seq, 1);
+		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		break;
+	case CPU_APIC:
+		if (priv->file == CPU_INDEX_BIT)
+			smp_call_function_single(priv->cpu, print_apic, seq, 1);
+		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		break;
+
+	default:
+		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		break;
+	}
+	seq_printf(seq, "\n");
+
+	return 0;
+}
+
+static void *cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos == 0) /* One time is enough ;-) */
+		return seq;
+
+	return NULL;
+}
+
+static void *cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	(*pos)++;
+
+	return cpu_seq_start(seq, pos);
+}
+
+static void cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations cpu_seq_ops = {
+	.start		= cpu_seq_start,
+	.next		= cpu_seq_next,
+	.stop		= cpu_seq_stop,
+	.show		= cpu_seq_show,
+};
+
+static int cpu_seq_open(struct inode *inode, struct file *file)
+{
+	struct cpu_private *priv = inode->i_private;
+	struct seq_file *seq;
+	int err;
+
+	err = seq_open(file, &cpu_seq_ops);
+	if (!err) {
+		seq = file->private_data;
+		seq->private = priv;
+	}
+
+	return err;
+}
+
+static int write_msr(struct cpu_private *priv, u64 val)
+{
+	u32 low, high;
+
+	high = (val >> 32) & 0xffffffff;
+	low = val & 0xffffffff;
+
+	if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high))
+		return 0;
+
+	return -EPERM;
+}
+
+static int write_cpu_register(struct cpu_private *priv, const char *buf)
+{
+	int ret = -EPERM;
+	u64 val;
+
+	ret = strict_strtoull(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	/* Supporting only MSRs */
+	if (priv->type < CPU_TSS_BIT)
+		return write_msr(priv, val);
+
+	return ret;
+}
+
+static ssize_t cpu_write(struct file *file, const char __user *ubuf,
+			     size_t count, loff_t *off)
+{
+	struct seq_file *seq = file->private_data;
+	struct cpu_private *priv = seq->private;
+	char buf[19];
+
+	if ((priv == NULL) || (count >= sizeof(buf)))
+		return -EINVAL;
+
+	if (copy_from_user(&buf, ubuf, count))
+		return -EFAULT;
+
+	buf[count] = 0;
+
+	if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write))
+		if (!write_cpu_register(priv, buf))
+			return count;
+
+	return -EACCES;
+}
+
+static const struct file_operations cpu_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cpu_seq_open,
+	.read		= seq_read,
+	.write		= cpu_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
+			   unsigned file, struct dentry *dentry)
+{
+	struct cpu_private *priv = NULL;
+
+	/* Already intialized */
+	if (file == CPU_INDEX_BIT)
+		if (per_cpu(cpu_arr[type].init, cpu))
+			return 0;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+
+	priv->cpu = cpu;
+	priv->type = type;
+	priv->reg = reg;
+	priv->file = file;
+	mutex_lock(&cpu_debug_lock);
+	per_cpu(priv_arr[type], cpu) = priv;
+	per_cpu(cpu_priv_count, cpu)++;
+	mutex_unlock(&cpu_debug_lock);
+
+	if (file)
+		debugfs_create_file(cpu_file[file].name, S_IRUGO,
+				    dentry, (void *)priv, &cpu_fops);
+	else {
+		debugfs_create_file(cpu_base[type].name, S_IRUGO,
+				    per_cpu(cpu_arr[type].dentry, cpu),
+				    (void *)priv, &cpu_fops);
+		mutex_lock(&cpu_debug_lock);
+		per_cpu(cpu_arr[type].init, cpu) = 1;
+		mutex_unlock(&cpu_debug_lock);
+	}
+
+	return 0;
+}
+
+static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg,
+			     struct dentry *dentry)
+{
+	unsigned file;
+	int err = 0;
+
+	for (file = 0; file <  ARRAY_SIZE(cpu_file); file++) {
+		err = cpu_create_file(cpu, type, reg, file, dentry);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry)
+{
+	struct dentry *cpu_dentry = NULL;
+	unsigned reg, reg_min, reg_max;
+	int i, range, err = 0;
+	char reg_dir[12];
+	u32 low, high;
+
+	range = get_cpu_range_count(cpu);
+
+	for (i = 0; i < range; i++) {
+		if (!get_cpu_range(cpu, &reg_min, &reg_max, i,
+				   cpu_base[type].flag))
+			continue;
+
+		for (reg = reg_min; reg <= reg_max; reg++) {
+			if (rdmsr_safe_on_cpu(cpu, reg, &low, &high))
+				continue;
+
+			sprintf(reg_dir, "0x%x", reg);
+			cpu_dentry = debugfs_create_dir(reg_dir, dentry);
+			err = cpu_init_regfiles(cpu, type, reg, cpu_dentry);
+			if (err)
+				return err;
+		}
+	}
+
+	return err;
+}
+
+static int cpu_init_allreg(unsigned cpu, struct dentry *dentry)
+{
+	struct dentry *cpu_dentry = NULL;
+	unsigned type;
+	int err = 0;
+
+	for (type = 0; type <  ARRAY_SIZE(cpu_base) - 1; type++) {
+		if (!is_typeflag_valid(cpu, cpu_base[type].flag))
+			continue;
+		cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry);
+		per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry;
+
+		if (type < CPU_TSS_BIT)
+			err = cpu_init_msr(cpu, type, cpu_dentry);
+		else
+			err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT,
+					      cpu_dentry);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int cpu_init_cpu(void)
+{
+	struct dentry *cpu_dentry = NULL;
+	struct cpuinfo_x86 *cpui;
+	char cpu_dir[12];
+	unsigned cpu;
+	int err = 0;
+
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
+		cpui = &cpu_data(cpu);
+		if (!cpu_has(cpui, X86_FEATURE_MSR))
+			continue;
+		per_cpu(cpu_model, cpu) = ((cpui->x86_vendor << 16) |
+					   (cpui->x86 << 8) |
+					   (cpui->x86_model));
+		per_cpu(cpu_modelflag, cpu) = get_cpu_modelflag(cpu);
+
+		sprintf(cpu_dir, "cpu%d", cpu);
+		cpu_dentry = debugfs_create_dir(cpu_dir, cpu_debugfs_dir);
+		err = cpu_init_allreg(cpu, cpu_dentry);
+
+		pr_info("cpu%d(%d) debug files %d\n",
+			cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu));
+		if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) {
+			pr_err("Register files count %d exceeds limit %d\n",
+				per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES);
+			per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES;
+			err = -ENFILE;
+		}
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int __init cpu_debug_init(void)
+{
+	cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir);
+
+	return cpu_init_cpu();
+}
+
+static void __exit cpu_debug_exit(void)
+{
+	int i, cpu;
+
+	if (cpu_debugfs_dir)
+		debugfs_remove_recursive(cpu_debugfs_dir);
+
+	for (cpu = 0; cpu <  nr_cpu_ids; cpu++)
+		for (i = 0; i < per_cpu(cpu_priv_count, cpu); i++)
+			kfree(per_cpu(priv_arr[i], cpu));
+}
+
+module_init(cpu_debug_init);
+module_exit(cpu_debug_exit);
+
+MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_DESCRIPTION("CPU Debug module");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index ffd0f5e..593171e 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -61,23 +61,23 @@
  */
 static unsigned char Cx86_dir0_msb __cpuinitdata = 0;
 
-static char Cx86_model[][9] __cpuinitdata = {
+static const char __cpuinitconst Cx86_model[][9] = {
 	"Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
 	"M II ", "Unknown"
 };
-static char Cx486_name[][5] __cpuinitdata = {
+static const char __cpuinitconst Cx486_name[][5] = {
 	"SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
 	"SRx2", "DRx2"
 };
-static char Cx486S_name[][4] __cpuinitdata = {
+static const char __cpuinitconst Cx486S_name[][4] = {
 	"S", "S2", "Se", "S2e"
 };
-static char Cx486D_name[][4] __cpuinitdata = {
+static const char __cpuinitconst Cx486D_name[][4] = {
 	"DX", "DX2", "?", "?", "?", "DX4"
 };
 static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock";
-static char cyrix_model_mult1[] __cpuinitdata = "12??43";
-static char cyrix_model_mult2[] __cpuinitdata = "12233445";
+static const char __cpuinitconst cyrix_model_mult1[] = "12??43";
+static const char __cpuinitconst cyrix_model_mult2[] = "12233445";
 
 /*
  * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
@@ -435,7 +435,7 @@
 	}
 }
 
-static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst cyrix_cpu_dev = {
 	.c_vendor	= "Cyrix",
 	.c_ident	= { "CyrixInstead" },
 	.c_early_init	= early_init_cyrix,
@@ -446,7 +446,7 @@
 
 cpu_dev_register(cyrix_cpu_dev);
 
-static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst nsc_cpu_dev = {
 	.c_vendor	= "NSC",
 	.c_ident	= { "Geode by NSC" },
 	.c_init		= init_nsc,
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1a89a2b..7437fa1 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -14,6 +14,7 @@
 #include <asm/uaccess.h>
 #include <asm/ds.h>
 #include <asm/bugs.h>
+#include <asm/cpu.h>
 
 #ifdef CONFIG_X86_64
 #include <asm/topology.h>
@@ -54,6 +55,11 @@
 		c->x86_cache_alignment = 128;
 #endif
 
+	/* CPUID workaround for 0F33/0F34 CPU */
+	if (c->x86 == 0xF && c->x86_model == 0x3
+	    && (c->x86_mask == 0x3 || c->x86_mask == 0x4))
+		c->x86_phys_bits = 36;
+
 	/*
 	 * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
 	 * with P/T states and does not stop in deep C-states.
@@ -116,6 +122,28 @@
 }
 #endif
 
+static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_SMP
+	/* calling is from identify_secondary_cpu() ? */
+	if (c->cpu_index == boot_cpu_id)
+		return;
+
+	/*
+	 * Mask B, Pentium, but not Pentium MMX
+	 */
+	if (c->x86 == 5 &&
+	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
+	    c->x86_model <= 3) {
+		/*
+		 * Remember we have B step Pentia with bugs
+		 */
+		WARN_ONCE(1, "WARNING: SMP operation may be unreliable"
+				    "with B stepping processors.\n");
+	}
+#endif
+}
+
 static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
 {
 	unsigned long lo, hi;
@@ -192,6 +220,8 @@
 #ifdef CONFIG_X86_NUMAQ
 	numaq_tsc_disable();
 #endif
+
+	intel_smp_check(c);
 }
 #else
 static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
@@ -391,7 +421,7 @@
 }
 #endif
 
-static struct cpu_dev intel_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst intel_cpu_dev = {
 	.c_vendor	= "Intel",
 	.c_ident	= { "GenuineIntel" },
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 7293508..c471eb1 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -32,7 +32,7 @@
 };
 
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
-static struct _cache_table cache_table[] __cpuinitdata =
+static const struct _cache_table __cpuinitconst cache_table[] =
 {
 	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
@@ -206,15 +206,15 @@
 	unsigned val;
 };
 
-static unsigned short assocs[] __cpuinitdata = {
+static const unsigned short __cpuinitconst assocs[] = {
 	[1] = 1, [2] = 2, [4] = 4, [6] = 8,
 	[8] = 16, [0xa] = 32, [0xb] = 48,
 	[0xc] = 64,
 	[0xf] = 0xffff // ??
 };
 
-static unsigned char levels[] __cpuinitdata = { 1, 1, 2, 3 };
-static unsigned char types[] __cpuinitdata = { 1, 2, 3, 3 };
+static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 };
+static const unsigned char __cpuinitconst types[] = { 1, 2, 3, 3 };
 
 static void __cpuinit
 amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index d7d2323..b2f8982 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -4,3 +4,4 @@
 obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel_64.o
 obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd_64.o
 obj-$(CONFIG_X86_MCE_NONFATAL)	+= non-fatal.o
+obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce_32.c b/arch/x86/kernel/cpu/mcheck/mce_32.c
index dfaebce..3552119 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_32.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_32.c
@@ -60,20 +60,6 @@
 	}
 }
 
-static unsigned long old_cr4 __initdata;
-
-void __init stop_mce(void)
-{
-	old_cr4 = read_cr4();
-	clear_in_cr4(X86_CR4_MCE);
-}
-
-void __init restart_mce(void)
-{
-	if (old_cr4 & X86_CR4_MCE)
-		set_in_cr4(X86_CR4_MCE);
-}
-
 static int __init mcheck_disable(char *str)
 {
 	mce_disabled = 1;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index fe79985..ca14604 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -3,6 +3,8 @@
  * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
  * Rest from unknown author(s).
  * 2004 Andi Kleen. Rewrote most of it.
+ * Copyright 2008 Intel Corporation
+ * Author: Andi Kleen
  */
 
 #include <linux/init.h>
@@ -24,6 +26,9 @@
 #include <linux/ctype.h>
 #include <linux/kmod.h>
 #include <linux/kdebug.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/ratelimit.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -32,7 +37,6 @@
 #include <asm/idle.h>
 
 #define MISC_MCELOG_MINOR 227
-#define NR_SYSFS_BANKS 6
 
 atomic_t mce_entry;
 
@@ -47,7 +51,7 @@
  */
 static int tolerant = 1;
 static int banks;
-static unsigned long bank[NR_SYSFS_BANKS] = { [0 ... NR_SYSFS_BANKS-1] = ~0UL };
+static u64 *bank;
 static unsigned long notify_user;
 static int rip_msr;
 static int mce_bootlog = -1;
@@ -58,6 +62,19 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
 
+/* MCA banks polled by the period polling timer for corrected events */
+DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
+	[0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
+};
+
+/* Do initial initialization of a struct mce */
+void mce_setup(struct mce *m)
+{
+	memset(m, 0, sizeof(struct mce));
+	m->cpu = smp_processor_id();
+	rdtscll(m->tsc);
+}
+
 /*
  * Lockless MCE logging infrastructure.
  * This avoids deadlocks on printk locks without having to break locks. Also
@@ -119,11 +136,11 @@
 			print_symbol("{%s}", m->ip);
 		printk("\n");
 	}
-	printk(KERN_EMERG "TSC %Lx ", m->tsc);
+	printk(KERN_EMERG "TSC %llx ", m->tsc);
 	if (m->addr)
-		printk("ADDR %Lx ", m->addr);
+		printk("ADDR %llx ", m->addr);
 	if (m->misc)
-		printk("MISC %Lx ", m->misc);
+		printk("MISC %llx ", m->misc);
 	printk("\n");
 	printk(KERN_EMERG "This is not a software problem!\n");
 	printk(KERN_EMERG "Run through mcelog --ascii to decode "
@@ -149,8 +166,10 @@
 	panic(msg);
 }
 
-static int mce_available(struct cpuinfo_x86 *c)
+int mce_available(struct cpuinfo_x86 *c)
 {
+	if (mce_dont_init)
+		return 0;
 	return cpu_has(c, X86_FEATURE_MCE) && cpu_has(c, X86_FEATURE_MCA);
 }
 
@@ -172,7 +191,77 @@
 }
 
 /*
- * The actual machine check handler
+ * Poll for corrected events or events that happened before reset.
+ * Those are just logged through /dev/mcelog.
+ *
+ * This is executed in standard interrupt context.
+ */
+void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
+{
+	struct mce m;
+	int i;
+
+	mce_setup(&m);
+
+	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+	for (i = 0; i < banks; i++) {
+		if (!bank[i] || !test_bit(i, *b))
+			continue;
+
+		m.misc = 0;
+		m.addr = 0;
+		m.bank = i;
+		m.tsc = 0;
+
+		barrier();
+		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
+		if (!(m.status & MCI_STATUS_VAL))
+			continue;
+
+		/*
+		 * Uncorrected events are handled by the exception handler
+		 * when it is enabled. But when the exception is disabled log
+		 * everything.
+		 *
+		 * TBD do the same check for MCI_STATUS_EN here?
+		 */
+		if ((m.status & MCI_STATUS_UC) && !(flags & MCP_UC))
+			continue;
+
+		if (m.status & MCI_STATUS_MISCV)
+			rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
+		if (m.status & MCI_STATUS_ADDRV)
+			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
+
+		if (!(flags & MCP_TIMESTAMP))
+			m.tsc = 0;
+		/*
+		 * Don't get the IP here because it's unlikely to
+		 * have anything to do with the actual error location.
+		 */
+
+		mce_log(&m);
+		add_taint(TAINT_MACHINE_CHECK);
+
+		/*
+		 * Clear state for this bank.
+		 */
+		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	}
+
+	/*
+	 * Don't clear MCG_STATUS here because it's only defined for
+	 * exceptions.
+	 */
+}
+
+/*
+ * The actual machine check handler. This only handles real
+ * exceptions when something got corrupted coming in through int 18.
+ *
+ * This is executed in NMI context not subject to normal locking rules. This
+ * implies that most kernel services cannot be safely used. Don't even
+ * think about putting a printk in there!
  */
 void do_machine_check(struct pt_regs * regs, long error_code)
 {
@@ -190,17 +279,18 @@
 	 * error.
 	 */
 	int kill_it = 0;
+	DECLARE_BITMAP(toclear, MAX_NR_BANKS);
 
 	atomic_inc(&mce_entry);
 
-	if ((regs
-	     && notify_die(DIE_NMI, "machine check", regs, error_code,
+	if (notify_die(DIE_NMI, "machine check", regs, error_code,
 			   18, SIGKILL) == NOTIFY_STOP)
-	    || !banks)
+		goto out2;
+	if (!banks)
 		goto out2;
 
-	memset(&m, 0, sizeof(struct mce));
-	m.cpu = smp_processor_id();
+	mce_setup(&m);
+
 	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
 	/* if the restart IP is not valid, we're done for */
 	if (!(m.mcgstatus & MCG_STATUS_RIPV))
@@ -210,18 +300,32 @@
 	barrier();
 
 	for (i = 0; i < banks; i++) {
-		if (i < NR_SYSFS_BANKS && !bank[i])
+		__clear_bit(i, toclear);
+		if (!bank[i])
 			continue;
 
 		m.misc = 0;
 		m.addr = 0;
 		m.bank = i;
-		m.tsc = 0;
 
 		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
 		if ((m.status & MCI_STATUS_VAL) == 0)
 			continue;
 
+		/*
+		 * Non uncorrected errors are handled by machine_check_poll
+		 * Leave them alone.
+		 */
+		if ((m.status & MCI_STATUS_UC) == 0)
+			continue;
+
+		/*
+		 * Set taint even when machine check was not enabled.
+		 */
+		add_taint(TAINT_MACHINE_CHECK);
+
+		__set_bit(i, toclear);
+
 		if (m.status & MCI_STATUS_EN) {
 			/* if PCC was set, there's no way out */
 			no_way_out |= !!(m.status & MCI_STATUS_PCC);
@@ -235,6 +339,12 @@
 					no_way_out = 1;
 				kill_it = 1;
 			}
+		} else {
+			/*
+			 * Machine check event was not enabled. Clear, but
+			 * ignore.
+			 */
+			continue;
 		}
 
 		if (m.status & MCI_STATUS_MISCV)
@@ -243,10 +353,7 @@
 			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
 
 		mce_get_rip(&m, regs);
-		if (error_code >= 0)
-			rdtscll(m.tsc);
-		if (error_code != -2)
-			mce_log(&m);
+		mce_log(&m);
 
 		/* Did this bank cause the exception? */
 		/* Assume that the bank with uncorrectable errors did it,
@@ -255,14 +362,8 @@
 			panicm = m;
 			panicm_found = 1;
 		}
-
-		add_taint(TAINT_MACHINE_CHECK);
 	}
 
-	/* Never do anything final in the polling timer */
-	if (!regs)
-		goto out;
-
 	/* If we didn't find an uncorrectable error, pick
 	   the last one (shouldn't happen, just being safe). */
 	if (!panicm_found)
@@ -309,10 +410,11 @@
 	/* notify userspace ASAP */
 	set_thread_flag(TIF_MCE_NOTIFY);
 
- out:
 	/* the last thing we do is clear state */
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	for (i = 0; i < banks; i++) {
+		if (test_bit(i, toclear))
+			wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+	}
 	wrmsrl(MSR_IA32_MCG_STATUS, 0);
  out2:
 	atomic_dec(&mce_entry);
@@ -332,15 +434,13 @@
  * and historically has been the register value of the
  * MSR_IA32_THERMAL_STATUS (Intel) msr.
  */
-void mce_log_therm_throt_event(unsigned int cpu, __u64 status)
+void mce_log_therm_throt_event(__u64 status)
 {
 	struct mce m;
 
-	memset(&m, 0, sizeof(m));
-	m.cpu = cpu;
+	mce_setup(&m);
 	m.bank = MCE_THERMAL_BANK;
 	m.status = status;
-	rdtscll(m.tsc);
 	mce_log(&m);
 }
 #endif /* CONFIG_X86_MCE_INTEL */
@@ -353,18 +453,18 @@
 
 static int check_interval = 5 * 60; /* 5 minutes */
 static int next_interval; /* in jiffies */
-static void mcheck_timer(struct work_struct *work);
-static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer);
+static void mcheck_timer(unsigned long);
+static DEFINE_PER_CPU(struct timer_list, mce_timer);
 
-static void mcheck_check_cpu(void *info)
+static void mcheck_timer(unsigned long data)
 {
+	struct timer_list *t = &per_cpu(mce_timer, data);
+
+	WARN_ON(smp_processor_id() != data);
+
 	if (mce_available(&current_cpu_data))
-		do_machine_check(NULL, 0);
-}
-
-static void mcheck_timer(struct work_struct *work)
-{
-	on_each_cpu(mcheck_check_cpu, NULL, 1);
+		machine_check_poll(MCP_TIMESTAMP,
+				&__get_cpu_var(mce_poll_banks));
 
 	/*
 	 * Alert userspace if needed.  If we logged an MCE, reduce the
@@ -377,31 +477,41 @@
 				(int)round_jiffies_relative(check_interval*HZ));
 	}
 
-	schedule_delayed_work(&mcheck_work, next_interval);
+	t->expires = jiffies + next_interval;
+	add_timer(t);
 }
 
+static void mce_do_trigger(struct work_struct *work)
+{
+	call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
+}
+
+static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
+
 /*
- * This is only called from process context.  This is where we do
- * anything we need to alert userspace about new MCEs.  This is called
- * directly from the poller and also from entry.S and idle, thanks to
- * TIF_MCE_NOTIFY.
+ * Notify the user(s) about new machine check events.
+ * Can be called from interrupt context, but not from machine check/NMI
+ * context.
  */
 int mce_notify_user(void)
 {
+	/* Not more than two messages every minute */
+	static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2);
+
 	clear_thread_flag(TIF_MCE_NOTIFY);
 	if (test_and_clear_bit(0, &notify_user)) {
-		static unsigned long last_print;
-		unsigned long now = jiffies;
-
 		wake_up_interruptible(&mce_wait);
-		if (trigger[0])
-			call_usermodehelper(trigger, trigger_argv, NULL,
-						UMH_NO_WAIT);
 
-		if (time_after_eq(now, last_print + (check_interval*HZ))) {
-			last_print = now;
+		/*
+		 * There is no risk of missing notifications because
+		 * work_pending is always cleared before the function is
+		 * executed.
+		 */
+		if (trigger[0] && !work_pending(&mce_trigger_work))
+			schedule_work(&mce_trigger_work);
+
+		if (__ratelimit(&ratelimit))
 			printk(KERN_INFO "Machine check events logged\n");
-		}
 
 		return 1;
 	}
@@ -425,63 +535,78 @@
 
 static __init int periodic_mcheck_init(void)
 {
-	next_interval = check_interval * HZ;
-	if (next_interval)
-		schedule_delayed_work(&mcheck_work,
-				      round_jiffies_relative(next_interval));
-	idle_notifier_register(&mce_idle_notifier);
-	return 0;
+       idle_notifier_register(&mce_idle_notifier);
+       return 0;
 }
 __initcall(periodic_mcheck_init);
 
-
 /*
  * Initialize Machine Checks for a CPU.
  */
-static void mce_init(void *dummy)
+static int mce_cap_init(void)
 {
 	u64 cap;
-	int i;
+	unsigned b;
 
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	banks = cap & 0xff;
-	if (banks > MCE_EXTENDED_BANK) {
-		banks = MCE_EXTENDED_BANK;
-		printk(KERN_INFO "MCE: warning: using only %d banks\n",
-		       MCE_EXTENDED_BANK);
+	b = cap & 0xff;
+	if (b > MAX_NR_BANKS) {
+		printk(KERN_WARNING
+		       "MCE: Using only %u machine check banks out of %u\n",
+			MAX_NR_BANKS, b);
+		b = MAX_NR_BANKS;
 	}
+
+	/* Don't support asymmetric configurations today */
+	WARN_ON(banks != 0 && b != banks);
+	banks = b;
+	if (!bank) {
+		bank = kmalloc(banks * sizeof(u64), GFP_KERNEL);
+		if (!bank)
+			return -ENOMEM;
+		memset(bank, 0xff, banks * sizeof(u64));
+	}
+
 	/* Use accurate RIP reporting if available. */
 	if ((cap & (1<<9)) && ((cap >> 16) & 0xff) >= 9)
 		rip_msr = MSR_IA32_MCG_EIP;
 
-	/* Log the machine checks left over from the previous reset.
-	   This also clears all registers */
-	do_machine_check(NULL, mce_bootlog ? -1 : -2);
+	return 0;
+}
+
+static void mce_init(void *dummy)
+{
+	u64 cap;
+	int i;
+	mce_banks_t all_banks;
+
+	/*
+	 * Log the machine checks left over from the previous reset.
+	 */
+	bitmap_fill(all_banks, MAX_NR_BANKS);
+	machine_check_poll(MCP_UC, &all_banks);
 
 	set_in_cr4(X86_CR4_MCE);
 
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
 	if (cap & MCG_CTL_P)
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 
 	for (i = 0; i < banks; i++) {
-		if (i < NR_SYSFS_BANKS)
-			wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
-		else
-			wrmsrl(MSR_IA32_MC0_CTL+4*i, ~0UL);
-
+		wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
 		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
 	}
 }
 
 /* Add per CPU specific workarounds here */
-static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
+static void mce_cpu_quirks(struct cpuinfo_x86 *c)
 {
 	/* This should be disabled by the BIOS, but isn't always */
 	if (c->x86_vendor == X86_VENDOR_AMD) {
-		if(c->x86 == 15)
+		if (c->x86 == 15 && banks > 4)
 			/* disable GART TBL walk error reporting, which trips off
 			   incorrectly with the IOMMU & 3ware & Cerberus. */
-			clear_bit(10, &bank[4]);
+			clear_bit(10, (unsigned long *)&bank[4]);
 		if(c->x86 <= 17 && mce_bootlog < 0)
 			/* Lots of broken BIOS around that don't clear them
 			   by default and leave crap in there. Don't log. */
@@ -504,20 +629,38 @@
 	}
 }
 
+static void mce_init_timer(void)
+{
+	struct timer_list *t = &__get_cpu_var(mce_timer);
+
+	/* data race harmless because everyone sets to the same value */
+	if (!next_interval)
+		next_interval = check_interval * HZ;
+	if (!next_interval)
+		return;
+	setup_timer(t, mcheck_timer, smp_processor_id());
+	t->expires = round_jiffies(jiffies + next_interval);
+	add_timer(t);
+}
+
 /*
  * Called for each booted CPU to set up machine checks.
  * Must be called with preempt off.
  */
 void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
 {
-	mce_cpu_quirks(c);
-
-	if (mce_dont_init ||
-	    !mce_available(c))
+	if (!mce_available(c))
 		return;
 
+	if (mce_cap_init() < 0) {
+		mce_dont_init = 1;
+		return;
+	}
+	mce_cpu_quirks(c);
+
 	mce_init(NULL);
 	mce_cpu_features(c);
+	mce_init_timer();
 }
 
 /*
@@ -573,7 +716,7 @@
 {
 	unsigned long *cpu_tsc;
 	static DEFINE_MUTEX(mce_read_mutex);
-	unsigned next;
+	unsigned prev, next;
 	char __user *buf = ubuf;
 	int i, err;
 
@@ -592,25 +735,32 @@
 	}
 
 	err = 0;
-	for (i = 0; i < next; i++) {
-		unsigned long start = jiffies;
+	prev = 0;
+	do {
+		for (i = prev; i < next; i++) {
+			unsigned long start = jiffies;
 
-		while (!mcelog.entry[i].finished) {
-			if (time_after_eq(jiffies, start + 2)) {
-				memset(mcelog.entry + i,0, sizeof(struct mce));
-				goto timeout;
+			while (!mcelog.entry[i].finished) {
+				if (time_after_eq(jiffies, start + 2)) {
+					memset(mcelog.entry + i, 0,
+					       sizeof(struct mce));
+					goto timeout;
+				}
+				cpu_relax();
 			}
-			cpu_relax();
+			smp_rmb();
+			err |= copy_to_user(buf, mcelog.entry + i,
+					    sizeof(struct mce));
+			buf += sizeof(struct mce);
+timeout:
+			;
 		}
-		smp_rmb();
-		err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
-		buf += sizeof(struct mce);
- timeout:
-		;
-	}
 
-	memset(mcelog.entry, 0, next * sizeof(struct mce));
-	mcelog.next = 0;
+		memset(mcelog.entry + prev, 0,
+		       (next - prev) * sizeof(struct mce));
+		prev = next;
+		next = cmpxchg(&mcelog.next, prev, 0);
+	} while (next != prev);
 
 	synchronize_sched();
 
@@ -680,20 +830,6 @@
 	&mce_chrdev_ops,
 };
 
-static unsigned long old_cr4 __initdata;
-
-void __init stop_mce(void)
-{
-	old_cr4 = read_cr4();
-	clear_in_cr4(X86_CR4_MCE);
-}
-
-void __init restart_mce(void)
-{
-	if (old_cr4 & X86_CR4_MCE)
-		set_in_cr4(X86_CR4_MCE);
-}
-
 /*
  * Old style boot options parsing. Only for compatibility.
  */
@@ -703,8 +839,7 @@
 	return 1;
 }
 
-/* mce=off disables machine check. Note you can re-enable it later
-   using sysfs.
+/* mce=off disables machine check.
    mce=TOLERANCELEVEL (number, see above)
    mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
    mce=nobootlog Don't log MCEs from before booting. */
@@ -728,6 +863,29 @@
  * Sysfs support
  */
 
+/*
+ * Disable machine checks on suspend and shutdown. We can't really handle
+ * them later.
+ */
+static int mce_disable(void)
+{
+	int i;
+
+	for (i = 0; i < banks; i++)
+		wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+	return 0;
+}
+
+static int mce_suspend(struct sys_device *dev, pm_message_t state)
+{
+	return mce_disable();
+}
+
+static int mce_shutdown(struct sys_device *dev)
+{
+	return mce_disable();
+}
+
 /* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
    Only one CPU is active at this time, the others get readded later using
    CPU hotplug. */
@@ -738,20 +896,24 @@
 	return 0;
 }
 
+static void mce_cpu_restart(void *data)
+{
+	del_timer_sync(&__get_cpu_var(mce_timer));
+	if (mce_available(&current_cpu_data))
+		mce_init(NULL);
+	mce_init_timer();
+}
+
 /* Reinit MCEs after user configuration changes */
 static void mce_restart(void)
 {
-	if (next_interval)
-		cancel_delayed_work(&mcheck_work);
-	/* Timer race is harmless here */
-	on_each_cpu(mce_init, NULL, 1);
 	next_interval = check_interval * HZ;
-	if (next_interval)
-		schedule_delayed_work(&mcheck_work,
-				      round_jiffies_relative(next_interval));
+	on_each_cpu(mce_cpu_restart, NULL, 1);
 }
 
 static struct sysdev_class mce_sysclass = {
+	.suspend = mce_suspend,
+	.shutdown = mce_shutdown,
 	.resume = mce_resume,
 	.name = "machinecheck",
 };
@@ -778,16 +940,26 @@
 	}								\
 	static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name);
 
-/*
- * TBD should generate these dynamically based on number of available banks.
- * Have only 6 contol banks in /sysfs until then.
- */
-ACCESSOR(bank0ctl,bank[0],mce_restart())
-ACCESSOR(bank1ctl,bank[1],mce_restart())
-ACCESSOR(bank2ctl,bank[2],mce_restart())
-ACCESSOR(bank3ctl,bank[3],mce_restart())
-ACCESSOR(bank4ctl,bank[4],mce_restart())
-ACCESSOR(bank5ctl,bank[5],mce_restart())
+static struct sysdev_attribute *bank_attrs;
+
+static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
+			 char *buf)
+{
+	u64 b = bank[attr - bank_attrs];
+	return sprintf(buf, "%llx\n", b);
+}
+
+static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
+			const char *buf, size_t siz)
+{
+	char *end;
+	u64 new = simple_strtoull(buf, &end, 0);
+	if (end == buf)
+		return -EINVAL;
+	bank[attr - bank_attrs] = new;
+	mce_restart();
+	return end-buf;
+}
 
 static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr,
 				char *buf)
@@ -814,8 +986,6 @@
 static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
 ACCESSOR(check_interval,check_interval,mce_restart())
 static struct sysdev_attribute *mce_attributes[] = {
-	&attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
-	&attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl,
 	&attr_tolerant.attr, &attr_check_interval, &attr_trigger,
 	NULL
 };
@@ -845,11 +1015,22 @@
 		if (err)
 			goto error;
 	}
+	for (i = 0; i < banks; i++) {
+		err = sysdev_create_file(&per_cpu(device_mce, cpu),
+					&bank_attrs[i]);
+		if (err)
+			goto error2;
+	}
 	cpu_set(cpu, mce_device_initialized);
 
 	return 0;
+error2:
+	while (--i >= 0) {
+		sysdev_remove_file(&per_cpu(device_mce, cpu),
+					&bank_attrs[i]);
+	}
 error:
-	while (i--) {
+	while (--i >= 0) {
 		sysdev_remove_file(&per_cpu(device_mce,cpu),
 				   mce_attributes[i]);
 	}
@@ -868,15 +1049,46 @@
 	for (i = 0; mce_attributes[i]; i++)
 		sysdev_remove_file(&per_cpu(device_mce,cpu),
 			mce_attributes[i]);
+	for (i = 0; i < banks; i++)
+		sysdev_remove_file(&per_cpu(device_mce, cpu),
+			&bank_attrs[i]);
 	sysdev_unregister(&per_cpu(device_mce,cpu));
 	cpu_clear(cpu, mce_device_initialized);
 }
 
+/* Make sure there are no machine checks on offlined CPUs. */
+static void mce_disable_cpu(void *h)
+{
+	int i;
+	unsigned long action = *(unsigned long *)h;
+
+	if (!mce_available(&current_cpu_data))
+		return;
+	if (!(action & CPU_TASKS_FROZEN))
+		cmci_clear();
+	for (i = 0; i < banks; i++)
+		wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+}
+
+static void mce_reenable_cpu(void *h)
+{
+	int i;
+	unsigned long action = *(unsigned long *)h;
+
+	if (!mce_available(&current_cpu_data))
+		return;
+	if (!(action & CPU_TASKS_FROZEN))
+		cmci_reenable();
+	for (i = 0; i < banks; i++)
+		wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+}
+
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
 static int __cpuinit mce_cpu_callback(struct notifier_block *nfb,
 				      unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
+	struct timer_list *t = &per_cpu(mce_timer, cpu);
 
 	switch (action) {
 	case CPU_ONLINE:
@@ -891,6 +1103,21 @@
 			threshold_cpu_callback(action, cpu);
 		mce_remove_device(cpu);
 		break;
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		del_timer_sync(t);
+		smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
+		break;
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
+		t->expires = round_jiffies(jiffies + next_interval);
+		add_timer_on(t, cpu);
+		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
+		break;
+	case CPU_POST_DEAD:
+		/* intentionally ignoring frozen here */
+		cmci_rediscover(cpu);
+		break;
 	}
 	return NOTIFY_OK;
 }
@@ -899,6 +1126,34 @@
 	.notifier_call = mce_cpu_callback,
 };
 
+static __init int mce_init_banks(void)
+{
+	int i;
+
+	bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks,
+				GFP_KERNEL);
+	if (!bank_attrs)
+		return -ENOMEM;
+
+	for (i = 0; i < banks; i++) {
+		struct sysdev_attribute *a = &bank_attrs[i];
+		a->attr.name = kasprintf(GFP_KERNEL, "bank%d", i);
+		if (!a->attr.name)
+			goto nomem;
+		a->attr.mode = 0644;
+		a->show = show_bank;
+		a->store = set_bank;
+	}
+	return 0;
+
+nomem:
+	while (--i >= 0)
+		kfree(bank_attrs[i].attr.name);
+	kfree(bank_attrs);
+	bank_attrs = NULL;
+	return -ENOMEM;
+}
+
 static __init int mce_init_device(void)
 {
 	int err;
@@ -906,6 +1161,11 @@
 
 	if (!mce_available(&boot_cpu_data))
 		return -EIO;
+
+	err = mce_init_banks();
+	if (err)
+		return err;
+
 	err = sysdev_class_register(&mce_sysclass);
 	if (err)
 		return err;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
index 9817506..7d01be8 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -79,6 +79,8 @@
 
 static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
 
+static void amd_threshold_interrupt(void);
+
 /*
  * CPU Initialization
  */
@@ -90,7 +92,8 @@
 };
 
 /* must be called with correct cpu affinity */
-static long threshold_restart_bank(void *_tr)
+/* Called via smp_call_function_single() */
+static void threshold_restart_bank(void *_tr)
 {
 	struct thresh_restart *tr = _tr;
 	u32 mci_misc_hi, mci_misc_lo;
@@ -117,7 +120,6 @@
 
 	mci_misc_hi |= MASK_COUNT_EN_HI;
 	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
-	return 0;
 }
 
 /* cpu init entry point, called from mce.c with preempt off */
@@ -174,6 +176,8 @@
 			tr.reset = 0;
 			tr.old_limit = 0;
 			threshold_restart_bank(&tr);
+
+			mce_threshold_vector = amd_threshold_interrupt;
 		}
 	}
 }
@@ -187,19 +191,13 @@
  * the interrupt goes off when error_count reaches threshold_limit.
  * the handler will simply log mcelog w/ software defined bank number.
  */
-asmlinkage void mce_threshold_interrupt(void)
+static void amd_threshold_interrupt(void)
 {
 	unsigned int bank, block;
 	struct mce m;
 	u32 low = 0, high = 0, address = 0;
 
-	ack_APIC_irq();
-	exit_idle();
-	irq_enter();
-
-	memset(&m, 0, sizeof(m));
-	rdtscll(m.tsc);
-	m.cpu = smp_processor_id();
+	mce_setup(&m);
 
 	/* assume first bank caused it */
 	for (bank = 0; bank < NR_BANKS; ++bank) {
@@ -233,7 +231,8 @@
 
 			/* Log the machine check that caused the threshold
 			   event. */
-			do_machine_check(NULL, 0);
+			machine_check_poll(MCP_TIMESTAMP,
+					&__get_cpu_var(mce_poll_banks));
 
 			if (high & MASK_OVERFLOW_HI) {
 				rdmsrl(address, m.misc);
@@ -243,13 +242,10 @@
 				       + bank * NR_BLOCKS
 				       + block;
 				mce_log(&m);
-				goto out;
+				return;
 			}
 		}
 	}
-out:
-	inc_irq_stat(irq_threshold_count);
-	irq_exit();
 }
 
 /*
@@ -283,7 +279,7 @@
 	tr.b = b;
 	tr.reset = 0;
 	tr.old_limit = 0;
-	work_on_cpu(b->cpu, threshold_restart_bank, &tr);
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
 
 	return end - buf;
 }
@@ -305,23 +301,32 @@
 	tr.b = b;
 	tr.reset = 0;
 
-	work_on_cpu(b->cpu, threshold_restart_bank, &tr);
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
 
 	return end - buf;
 }
 
-static long local_error_count(void *_b)
+struct threshold_block_cross_cpu {
+	struct threshold_block *tb;
+	long retval;
+};
+
+static void local_error_count_handler(void *_tbcc)
 {
-	struct threshold_block *b = _b;
+	struct threshold_block_cross_cpu *tbcc = _tbcc;
+	struct threshold_block *b = tbcc->tb;
 	u32 low, high;
 
 	rdmsr(b->address, low, high);
-	return (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
+	tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
 }
 
 static ssize_t show_error_count(struct threshold_block *b, char *buf)
 {
-	return sprintf(buf, "%lx\n", work_on_cpu(b->cpu, local_error_count, b));
+	struct threshold_block_cross_cpu tbcc = { .tb = b, };
+
+	smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
+	return sprintf(buf, "%lx\n", tbcc.retval);
 }
 
 static ssize_t store_error_count(struct threshold_block *b,
@@ -329,7 +334,7 @@
 {
 	struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
 
-	work_on_cpu(b->cpu, threshold_restart_bank, &tr);
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
 	return 1;
 }
 
@@ -398,7 +403,7 @@
 	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
 		return 0;
 
-	if (rdmsr_safe(address, &low, &high))
+	if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
 		return 0;
 
 	if (!(high & MASK_VALID_HI)) {
@@ -462,12 +467,11 @@
 	return err;
 }
 
-static __cpuinit long local_allocate_threshold_blocks(void *_bank)
+static __cpuinit long
+local_allocate_threshold_blocks(int cpu, unsigned int bank)
 {
-	unsigned int *bank = _bank;
-
-	return allocate_threshold_blocks(smp_processor_id(), *bank, 0,
-					 MSR_IA32_MC0_MISC + *bank * 4);
+	return allocate_threshold_blocks(cpu, bank, 0,
+					 MSR_IA32_MC0_MISC + bank * 4);
 }
 
 /* symlinks sibling shared banks to first core.  first core owns dir/files. */
@@ -530,7 +534,7 @@
 
 	per_cpu(threshold_banks, cpu)[bank] = b;
 
-	err = work_on_cpu(cpu, local_allocate_threshold_blocks, &bank);
+	err = local_allocate_threshold_blocks(cpu, bank);
 	if (err)
 		goto out_free;
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index aa5e287..57df3d3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -1,6 +1,8 @@
 /*
  * Intel specific MCE features.
  * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
+ * Copyright (C) 2008, 2009 Intel Corporation
+ * Author: Andi Kleen
  */
 
 #include <linux/init.h>
@@ -13,6 +15,7 @@
 #include <asm/hw_irq.h>
 #include <asm/idle.h>
 #include <asm/therm_throt.h>
+#include <asm/apic.h>
 
 asmlinkage void smp_thermal_interrupt(void)
 {
@@ -25,7 +28,7 @@
 
 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 	if (therm_throt_process(msr_val & 1))
-		mce_log_therm_throt_event(smp_processor_id(), msr_val);
+		mce_log_therm_throt_event(msr_val);
 
 	inc_irq_stat(irq_thermal_count);
 	irq_exit();
@@ -85,7 +88,209 @@
 	return;
 }
 
+/*
+ * Support for Intel Correct Machine Check Interrupts. This allows
+ * the CPU to raise an interrupt when a corrected machine check happened.
+ * Normally we pick those up using a regular polling timer.
+ * Also supports reliable discovery of shared banks.
+ */
+
+static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
+
+/*
+ * cmci_discover_lock protects against parallel discovery attempts
+ * which could race against each other.
+ */
+static DEFINE_SPINLOCK(cmci_discover_lock);
+
+#define CMCI_THRESHOLD 1
+
+static int cmci_supported(int *banks)
+{
+	u64 cap;
+
+	/*
+	 * Vendor check is not strictly needed, but the initial
+	 * initialization is vendor keyed and this
+	 * makes sure none of the backdoors are entered otherwise.
+	 */
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return 0;
+	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
+		return 0;
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
+	return !!(cap & MCG_CMCI_P);
+}
+
+/*
+ * The interrupt handler. This is called on every event.
+ * Just call the poller directly to log any events.
+ * This could in theory increase the threshold under high load,
+ * but doesn't for now.
+ */
+static void intel_threshold_interrupt(void)
+{
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	mce_notify_user();
+}
+
+static void print_update(char *type, int *hdr, int num)
+{
+	if (*hdr == 0)
+		printk(KERN_INFO "CPU %d MCA banks", smp_processor_id());
+	*hdr = 1;
+	printk(KERN_CONT " %s:%d", type, num);
+}
+
+/*
+ * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks
+ * on this CPU. Use the algorithm recommended in the SDM to discover shared
+ * banks.
+ */
+static void cmci_discover(int banks, int boot)
+{
+	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
+	int hdr = 0;
+	int i;
+
+	spin_lock(&cmci_discover_lock);
+	for (i = 0; i < banks; i++) {
+		u64 val;
+
+		if (test_bit(i, owned))
+			continue;
+
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Already owned by someone else? */
+		if (val & CMCI_EN) {
+			if (test_and_clear_bit(i, owned) || boot)
+				print_update("SHD", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+			continue;
+		}
+
+		val |= CMCI_EN | CMCI_THRESHOLD;
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Did the enable bit stick? -- the bank supports CMCI */
+		if (val & CMCI_EN) {
+			if (!test_and_set_bit(i, owned) || boot)
+				print_update("CMCI", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+		} else {
+			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
+		}
+	}
+	spin_unlock(&cmci_discover_lock);
+	if (hdr)
+		printk(KERN_CONT "\n");
+}
+
+/*
+ * Just in case we missed an event during initialization check
+ * all the CMCI owned banks.
+ */
+void cmci_recheck(void)
+{
+	unsigned long flags;
+	int banks;
+
+	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
+		return;
+	local_irq_save(flags);
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	local_irq_restore(flags);
+}
+
+/*
+ * Disable CMCI on this CPU for all banks it owns when it goes down.
+ * This allows other CPUs to claim the banks on rediscovery.
+ */
+void cmci_clear(void)
+{
+	int i;
+	int banks;
+	u64 val;
+
+	if (!cmci_supported(&banks))
+		return;
+	spin_lock(&cmci_discover_lock);
+	for (i = 0; i < banks; i++) {
+		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
+			continue;
+		/* Disable CMCI */
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		__clear_bit(i, __get_cpu_var(mce_banks_owned));
+	}
+	spin_unlock(&cmci_discover_lock);
+}
+
+/*
+ * After a CPU went down cycle through all the others and rediscover
+ * Must run in process context.
+ */
+void cmci_rediscover(int dying)
+{
+	int banks;
+	int cpu;
+	cpumask_var_t old;
+
+	if (!cmci_supported(&banks))
+		return;
+	if (!alloc_cpumask_var(&old, GFP_KERNEL))
+		return;
+	cpumask_copy(old, &current->cpus_allowed);
+
+	for_each_online_cpu (cpu) {
+		if (cpu == dying)
+			continue;
+		if (set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)))
+			continue;
+		/* Recheck banks in case CPUs don't all have the same */
+		if (cmci_supported(&banks))
+			cmci_discover(banks, 0);
+	}
+
+	set_cpus_allowed_ptr(current, old);
+	free_cpumask_var(old);
+}
+
+/*
+ * Reenable CMCI on this CPU in case a CPU down failed.
+ */
+void cmci_reenable(void)
+{
+	int banks;
+	if (cmci_supported(&banks))
+		cmci_discover(banks, 0);
+}
+
+static void intel_init_cmci(void)
+{
+	int banks;
+
+	if (!cmci_supported(&banks))
+		return;
+
+	mce_threshold_vector = intel_threshold_interrupt;
+	cmci_discover(banks, 1);
+	/*
+	 * For CPU #0 this runs with still disabled APIC, but that's
+	 * ok because only the vector is set up. We still do another
+	 * check for the banks later for CPU #0 just to make sure
+	 * to not miss any events.
+	 */
+	apic_write(APIC_LVTCMCI, THRESHOLD_APIC_VECTOR|APIC_DM_FIXED);
+	cmci_recheck();
+}
+
 void mce_intel_feature_init(struct cpuinfo_x86 *c)
 {
 	intel_init_thermal(c);
+	intel_init_cmci();
 }
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c
new file mode 100644
index 0000000..23ee9e7
--- /dev/null
+++ b/arch/x86/kernel/cpu/mcheck/threshold.c
@@ -0,0 +1,29 @@
+/*
+ * Common corrected MCE threshold handler code:
+ */
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_vectors.h>
+#include <asm/apic.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
+
+static void default_threshold_interrupt(void)
+{
+	printk(KERN_ERR "Unexpected threshold interrupt at vector %x\n",
+			 THRESHOLD_APIC_VECTOR);
+}
+
+void (*mce_threshold_vector)(void) = default_threshold_interrupt;
+
+asmlinkage void mce_threshold_interrupt(void)
+{
+	exit_idle();
+	irq_enter();
+	inc_irq_stat(irq_threshold_count);
+	mce_threshold_vector();
+	irq_exit();
+	/* Ack only at the end to avoid potential reentry */
+	ack_APIC_irq();
+}
diff --git a/arch/x86/kernel/cpu/mtrr/Makefile b/arch/x86/kernel/cpu/mtrr/Makefile
index 191fc05..f4361b5 100644
--- a/arch/x86/kernel/cpu/mtrr/Makefile
+++ b/arch/x86/kernel/cpu/mtrr/Makefile
@@ -1,3 +1,3 @@
-obj-y		:= main.o if.o generic.o state.o
+obj-y		:= main.o if.o generic.o state.o cleanup.o
 obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o
 
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c
new file mode 100644
index 0000000..ce0fe4b
--- /dev/null
+++ b/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -0,0 +1,1101 @@
+/*  MTRR (Memory Type Range Register) cleanup
+
+    Copyright (C) 2009 Yinghai Lu
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+#include <linux/sort.h>
+
+#include <asm/e820.h>
+#include <asm/mtrr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/kvm_para.h>
+#include "mtrr.h"
+
+/* should be related to MTRR_VAR_RANGES nums */
+#define RANGE_NUM 256
+
+struct res_range {
+	unsigned long start;
+	unsigned long end;
+};
+
+static int __init
+add_range(struct res_range *range, int nr_range, unsigned long start,
+			      unsigned long end)
+{
+	/* out of slots */
+	if (nr_range >= RANGE_NUM)
+		return nr_range;
+
+	range[nr_range].start = start;
+	range[nr_range].end = end;
+
+	nr_range++;
+
+	return nr_range;
+}
+
+static int __init
+add_range_with_merge(struct res_range *range, int nr_range, unsigned long start,
+			      unsigned long end)
+{
+	int i;
+
+	/* try to merge it with old one */
+	for (i = 0; i < nr_range; i++) {
+		unsigned long final_start, final_end;
+		unsigned long common_start, common_end;
+
+		if (!range[i].end)
+			continue;
+
+		common_start = max(range[i].start, start);
+		common_end = min(range[i].end, end);
+		if (common_start > common_end + 1)
+			continue;
+
+		final_start = min(range[i].start, start);
+		final_end = max(range[i].end, end);
+
+		range[i].start = final_start;
+		range[i].end =  final_end;
+		return nr_range;
+	}
+
+	/* need to add that */
+	return add_range(range, nr_range, start, end);
+}
+
+static void __init
+subtract_range(struct res_range *range, unsigned long start, unsigned long end)
+{
+	int i, j;
+
+	for (j = 0; j < RANGE_NUM; j++) {
+		if (!range[j].end)
+			continue;
+
+		if (start <= range[j].start && end >= range[j].end) {
+			range[j].start = 0;
+			range[j].end = 0;
+			continue;
+		}
+
+		if (start <= range[j].start && end < range[j].end &&
+		    range[j].start < end + 1) {
+			range[j].start = end + 1;
+			continue;
+		}
+
+
+		if (start > range[j].start && end >= range[j].end &&
+		    range[j].end > start - 1) {
+			range[j].end = start - 1;
+			continue;
+		}
+
+		if (start > range[j].start && end < range[j].end) {
+			/* find the new spare */
+			for (i = 0; i < RANGE_NUM; i++) {
+				if (range[i].end == 0)
+					break;
+			}
+			if (i < RANGE_NUM) {
+				range[i].end = range[j].end;
+				range[i].start = end + 1;
+			} else {
+				printk(KERN_ERR "run of slot in ranges\n");
+			}
+			range[j].end = start - 1;
+			continue;
+		}
+	}
+}
+
+static int __init cmp_range(const void *x1, const void *x2)
+{
+	const struct res_range *r1 = x1;
+	const struct res_range *r2 = x2;
+	long start1, start2;
+
+	start1 = r1->start;
+	start2 = r2->start;
+
+	return start1 - start2;
+}
+
+struct var_mtrr_range_state {
+	unsigned long base_pfn;
+	unsigned long size_pfn;
+	mtrr_type type;
+};
+
+static struct var_mtrr_range_state __initdata range_state[RANGE_NUM];
+static int __initdata debug_print;
+
+static int __init
+x86_get_mtrr_mem_range(struct res_range *range, int nr_range,
+		       unsigned long extra_remove_base,
+		       unsigned long extra_remove_size)
+{
+	unsigned long base, size;
+	mtrr_type type;
+	int i;
+
+	for (i = 0; i < num_var_ranges; i++) {
+		type = range_state[i].type;
+		if (type != MTRR_TYPE_WRBACK)
+			continue;
+		base = range_state[i].base_pfn;
+		size = range_state[i].size_pfn;
+		nr_range = add_range_with_merge(range, nr_range, base,
+						base + size - 1);
+	}
+	if (debug_print) {
+		printk(KERN_DEBUG "After WB checking\n");
+		for (i = 0; i < nr_range; i++)
+			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
+				 range[i].start, range[i].end + 1);
+	}
+
+	/* take out UC ranges */
+	for (i = 0; i < num_var_ranges; i++) {
+		type = range_state[i].type;
+		if (type != MTRR_TYPE_UNCACHABLE &&
+		    type != MTRR_TYPE_WRPROT)
+			continue;
+		size = range_state[i].size_pfn;
+		if (!size)
+			continue;
+		base = range_state[i].base_pfn;
+		if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed &&
+		    (mtrr_state.enabled & 1)) {
+			/* Var MTRR contains UC entry below 1M? Skip it: */
+			printk(KERN_WARNING "WARNING: BIOS bug: VAR MTRR %d "
+				"contains strange UC entry under 1M, check "
+				"with your system vendor!\n", i);
+			if (base + size <= (1<<(20-PAGE_SHIFT)))
+				continue;
+			size -= (1<<(20-PAGE_SHIFT)) - base;
+			base = 1<<(20-PAGE_SHIFT);
+		}
+		subtract_range(range, base, base + size - 1);
+	}
+	if (extra_remove_size)
+		subtract_range(range, extra_remove_base,
+				 extra_remove_base + extra_remove_size  - 1);
+
+	/* get new range num */
+	nr_range = 0;
+	for (i = 0; i < RANGE_NUM; i++) {
+		if (!range[i].end)
+			continue;
+		nr_range++;
+	}
+	if  (debug_print) {
+		printk(KERN_DEBUG "After UC checking\n");
+		for (i = 0; i < nr_range; i++)
+			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
+				 range[i].start, range[i].end + 1);
+	}
+
+	/* sort the ranges */
+	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
+	if  (debug_print) {
+		printk(KERN_DEBUG "After sorting\n");
+		for (i = 0; i < nr_range; i++)
+			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
+				 range[i].start, range[i].end + 1);
+	}
+
+	/* clear those is not used */
+	for (i = nr_range; i < RANGE_NUM; i++)
+		memset(&range[i], 0, sizeof(range[i]));
+
+	return nr_range;
+}
+
+static struct res_range __initdata range[RANGE_NUM];
+static int __initdata nr_range;
+
+#ifdef CONFIG_MTRR_SANITIZER
+
+static unsigned long __init sum_ranges(struct res_range *range, int nr_range)
+{
+	unsigned long sum;
+	int i;
+
+	sum = 0;
+	for (i = 0; i < nr_range; i++)
+		sum += range[i].end + 1 - range[i].start;
+
+	return sum;
+}
+
+static int enable_mtrr_cleanup __initdata =
+	CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT;
+
+static int __init disable_mtrr_cleanup_setup(char *str)
+{
+	enable_mtrr_cleanup = 0;
+	return 0;
+}
+early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup);
+
+static int __init enable_mtrr_cleanup_setup(char *str)
+{
+	enable_mtrr_cleanup = 1;
+	return 0;
+}
+early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
+
+static int __init mtrr_cleanup_debug_setup(char *str)
+{
+	debug_print = 1;
+	return 0;
+}
+early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup);
+
+struct var_mtrr_state {
+	unsigned long	range_startk;
+	unsigned long	range_sizek;
+	unsigned long	chunk_sizek;
+	unsigned long	gran_sizek;
+	unsigned int	reg;
+};
+
+static void __init
+set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek,
+		unsigned char type, unsigned int address_bits)
+{
+	u32 base_lo, base_hi, mask_lo, mask_hi;
+	u64 base, mask;
+
+	if (!sizek) {
+		fill_mtrr_var_range(reg, 0, 0, 0, 0);
+		return;
+	}
+
+	mask = (1ULL << address_bits) - 1;
+	mask &= ~((((u64)sizek) << 10) - 1);
+
+	base  = ((u64)basek) << 10;
+
+	base |= type;
+	mask |= 0x800;
+
+	base_lo = base & ((1ULL<<32) - 1);
+	base_hi = base >> 32;
+
+	mask_lo = mask & ((1ULL<<32) - 1);
+	mask_hi = mask >> 32;
+
+	fill_mtrr_var_range(reg, base_lo, base_hi, mask_lo, mask_hi);
+}
+
+static void __init
+save_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek,
+		unsigned char type)
+{
+	range_state[reg].base_pfn = basek >> (PAGE_SHIFT - 10);
+	range_state[reg].size_pfn = sizek >> (PAGE_SHIFT - 10);
+	range_state[reg].type = type;
+}
+
+static void __init
+set_var_mtrr_all(unsigned int address_bits)
+{
+	unsigned long basek, sizek;
+	unsigned char type;
+	unsigned int reg;
+
+	for (reg = 0; reg < num_var_ranges; reg++) {
+		basek = range_state[reg].base_pfn << (PAGE_SHIFT - 10);
+		sizek = range_state[reg].size_pfn << (PAGE_SHIFT - 10);
+		type = range_state[reg].type;
+
+		set_var_mtrr(reg, basek, sizek, type, address_bits);
+	}
+}
+
+static unsigned long to_size_factor(unsigned long sizek, char *factorp)
+{
+	char factor;
+	unsigned long base = sizek;
+
+	if (base & ((1<<10) - 1)) {
+		/* not MB alignment */
+		factor = 'K';
+	} else if (base & ((1<<20) - 1)) {
+		factor = 'M';
+		base >>= 10;
+	} else {
+		factor = 'G';
+		base >>= 20;
+	}
+
+	*factorp = factor;
+
+	return base;
+}
+
+static unsigned int __init
+range_to_mtrr(unsigned int reg, unsigned long range_startk,
+	      unsigned long range_sizek, unsigned char type)
+{
+	if (!range_sizek || (reg >= num_var_ranges))
+		return reg;
+
+	while (range_sizek) {
+		unsigned long max_align, align;
+		unsigned long sizek;
+
+		/* Compute the maximum size I can make a range */
+		if (range_startk)
+			max_align = ffs(range_startk) - 1;
+		else
+			max_align = 32;
+		align = fls(range_sizek) - 1;
+		if (align > max_align)
+			align = max_align;
+
+		sizek = 1 << align;
+		if (debug_print) {
+			char start_factor = 'K', size_factor = 'K';
+			unsigned long start_base, size_base;
+
+			start_base = to_size_factor(range_startk,
+							 &start_factor),
+			size_base = to_size_factor(sizek, &size_factor),
+
+			printk(KERN_DEBUG "Setting variable MTRR %d, "
+				"base: %ld%cB, range: %ld%cB, type %s\n",
+				reg, start_base, start_factor,
+				size_base, size_factor,
+				(type == MTRR_TYPE_UNCACHABLE) ? "UC" :
+				   ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other")
+				);
+		}
+		save_var_mtrr(reg++, range_startk, sizek, type);
+		range_startk += sizek;
+		range_sizek -= sizek;
+		if (reg >= num_var_ranges)
+			break;
+	}
+	return reg;
+}
+
+static unsigned __init
+range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
+			unsigned long sizek)
+{
+	unsigned long hole_basek, hole_sizek;
+	unsigned long second_basek, second_sizek;
+	unsigned long range0_basek, range0_sizek;
+	unsigned long range_basek, range_sizek;
+	unsigned long chunk_sizek;
+	unsigned long gran_sizek;
+
+	hole_basek = 0;
+	hole_sizek = 0;
+	second_basek = 0;
+	second_sizek = 0;
+	chunk_sizek = state->chunk_sizek;
+	gran_sizek = state->gran_sizek;
+
+	/* align with gran size, prevent small block used up MTRRs */
+	range_basek = ALIGN(state->range_startk, gran_sizek);
+	if ((range_basek > basek) && basek)
+		return second_sizek;
+	state->range_sizek -= (range_basek - state->range_startk);
+	range_sizek = ALIGN(state->range_sizek, gran_sizek);
+
+	while (range_sizek > state->range_sizek) {
+		range_sizek -= gran_sizek;
+		if (!range_sizek)
+			return 0;
+	}
+	state->range_sizek = range_sizek;
+
+	/* try to append some small hole */
+	range0_basek = state->range_startk;
+	range0_sizek = ALIGN(state->range_sizek, chunk_sizek);
+
+	/* no increase */
+	if (range0_sizek == state->range_sizek) {
+		if (debug_print)
+			printk(KERN_DEBUG "rangeX: %016lx - %016lx\n",
+				range0_basek<<10,
+				(range0_basek + state->range_sizek)<<10);
+		state->reg = range_to_mtrr(state->reg, range0_basek,
+				state->range_sizek, MTRR_TYPE_WRBACK);
+		return 0;
+	}
+
+	/* only cut back, when it is not the last */
+	if (sizek) {
+		while (range0_basek + range0_sizek > (basek + sizek)) {
+			if (range0_sizek >= chunk_sizek)
+				range0_sizek -= chunk_sizek;
+			else
+				range0_sizek = 0;
+
+			if (!range0_sizek)
+				break;
+		}
+	}
+
+second_try:
+	range_basek = range0_basek + range0_sizek;
+
+	/* one hole in the middle */
+	if (range_basek > basek && range_basek <= (basek + sizek))
+		second_sizek = range_basek - basek;
+
+	if (range0_sizek > state->range_sizek) {
+
+		/* one hole in middle or at end */
+		hole_sizek = range0_sizek - state->range_sizek - second_sizek;
+
+		/* hole size should be less than half of range0 size */
+		if (hole_sizek >= (range0_sizek >> 1) &&
+		    range0_sizek >= chunk_sizek) {
+			range0_sizek -= chunk_sizek;
+			second_sizek = 0;
+			hole_sizek = 0;
+
+			goto second_try;
+		}
+	}
+
+	if (range0_sizek) {
+		if (debug_print)
+			printk(KERN_DEBUG "range0: %016lx - %016lx\n",
+				range0_basek<<10,
+				(range0_basek + range0_sizek)<<10);
+		state->reg = range_to_mtrr(state->reg, range0_basek,
+				range0_sizek, MTRR_TYPE_WRBACK);
+	}
+
+	if (range0_sizek < state->range_sizek) {
+		/* need to handle left over */
+		range_sizek = state->range_sizek - range0_sizek;
+
+		if (debug_print)
+			printk(KERN_DEBUG "range: %016lx - %016lx\n",
+				 range_basek<<10,
+				 (range_basek + range_sizek)<<10);
+		state->reg = range_to_mtrr(state->reg, range_basek,
+				 range_sizek, MTRR_TYPE_WRBACK);
+	}
+
+	if (hole_sizek) {
+		hole_basek = range_basek - hole_sizek - second_sizek;
+		if (debug_print)
+			printk(KERN_DEBUG "hole: %016lx - %016lx\n",
+				 hole_basek<<10,
+				 (hole_basek + hole_sizek)<<10);
+		state->reg = range_to_mtrr(state->reg, hole_basek,
+				 hole_sizek, MTRR_TYPE_UNCACHABLE);
+	}
+
+	return second_sizek;
+}
+
+static void __init
+set_var_mtrr_range(struct var_mtrr_state *state, unsigned long base_pfn,
+		   unsigned long size_pfn)
+{
+	unsigned long basek, sizek;
+	unsigned long second_sizek = 0;
+
+	if (state->reg >= num_var_ranges)
+		return;
+
+	basek = base_pfn << (PAGE_SHIFT - 10);
+	sizek = size_pfn << (PAGE_SHIFT - 10);
+
+	/* See if I can merge with the last range */
+	if ((basek <= 1024) ||
+	    (state->range_startk + state->range_sizek == basek)) {
+		unsigned long endk = basek + sizek;
+		state->range_sizek = endk - state->range_startk;
+		return;
+	}
+	/* Write the range mtrrs */
+	if (state->range_sizek != 0)
+		second_sizek = range_to_mtrr_with_hole(state, basek, sizek);
+
+	/* Allocate an msr */
+	state->range_startk = basek + second_sizek;
+	state->range_sizek  = sizek - second_sizek;
+}
+
+/* mininum size of mtrr block that can take hole */
+static u64 mtrr_chunk_size __initdata = (256ULL<<20);
+
+static int __init parse_mtrr_chunk_size_opt(char *p)
+{
+	if (!p)
+		return -EINVAL;
+	mtrr_chunk_size = memparse(p, &p);
+	return 0;
+}
+early_param("mtrr_chunk_size", parse_mtrr_chunk_size_opt);
+
+/* granity of mtrr of block */
+static u64 mtrr_gran_size __initdata;
+
+static int __init parse_mtrr_gran_size_opt(char *p)
+{
+	if (!p)
+		return -EINVAL;
+	mtrr_gran_size = memparse(p, &p);
+	return 0;
+}
+early_param("mtrr_gran_size", parse_mtrr_gran_size_opt);
+
+static int nr_mtrr_spare_reg __initdata =
+				 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT;
+
+static int __init parse_mtrr_spare_reg(char *arg)
+{
+	if (arg)
+		nr_mtrr_spare_reg = simple_strtoul(arg, NULL, 0);
+	return 0;
+}
+
+early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg);
+
+static int __init
+x86_setup_var_mtrrs(struct res_range *range, int nr_range,
+		    u64 chunk_size, u64 gran_size)
+{
+	struct var_mtrr_state var_state;
+	int i;
+	int num_reg;
+
+	var_state.range_startk	= 0;
+	var_state.range_sizek	= 0;
+	var_state.reg		= 0;
+	var_state.chunk_sizek	= chunk_size >> 10;
+	var_state.gran_sizek	= gran_size >> 10;
+
+	memset(range_state, 0, sizeof(range_state));
+
+	/* Write the range etc */
+	for (i = 0; i < nr_range; i++)
+		set_var_mtrr_range(&var_state, range[i].start,
+				   range[i].end - range[i].start + 1);
+
+	/* Write the last range */
+	if (var_state.range_sizek != 0)
+		range_to_mtrr_with_hole(&var_state, 0, 0);
+
+	num_reg = var_state.reg;
+	/* Clear out the extra MTRR's */
+	while (var_state.reg < num_var_ranges) {
+		save_var_mtrr(var_state.reg, 0, 0, 0);
+		var_state.reg++;
+	}
+
+	return num_reg;
+}
+
+struct mtrr_cleanup_result {
+	unsigned long gran_sizek;
+	unsigned long chunk_sizek;
+	unsigned long lose_cover_sizek;
+	unsigned int num_reg;
+	int bad;
+};
+
+/*
+ * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G
+ * chunk size: gran_size, ..., 2G
+ * so we need (1+16)*8
+ */
+#define NUM_RESULT	136
+#define PSHIFT		(PAGE_SHIFT - 10)
+
+static struct mtrr_cleanup_result __initdata result[NUM_RESULT];
+static unsigned long __initdata min_loss_pfn[RANGE_NUM];
+
+static void __init print_out_mtrr_range_state(void)
+{
+	int i;
+	char start_factor = 'K', size_factor = 'K';
+	unsigned long start_base, size_base;
+	mtrr_type type;
+
+	for (i = 0; i < num_var_ranges; i++) {
+
+		size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10);
+		if (!size_base)
+			continue;
+
+		size_base = to_size_factor(size_base, &size_factor),
+		start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10);
+		start_base = to_size_factor(start_base, &start_factor),
+		type = range_state[i].type;
+
+		printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
+			i, start_base, start_factor,
+			size_base, size_factor,
+			(type == MTRR_TYPE_UNCACHABLE) ? "UC" :
+			    ((type == MTRR_TYPE_WRPROT) ? "WP" :
+			     ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other"))
+			);
+	}
+}
+
+static int __init mtrr_need_cleanup(void)
+{
+	int i;
+	mtrr_type type;
+	unsigned long size;
+	/* extra one for all 0 */
+	int num[MTRR_NUM_TYPES + 1];
+
+	/* check entries number */
+	memset(num, 0, sizeof(num));
+	for (i = 0; i < num_var_ranges; i++) {
+		type = range_state[i].type;
+		size = range_state[i].size_pfn;
+		if (type >= MTRR_NUM_TYPES)
+			continue;
+		if (!size)
+			type = MTRR_NUM_TYPES;
+		if (type == MTRR_TYPE_WRPROT)
+			type = MTRR_TYPE_UNCACHABLE;
+		num[type]++;
+	}
+
+	/* check if we got UC entries */
+	if (!num[MTRR_TYPE_UNCACHABLE])
+		return 0;
+
+	/* check if we only had WB and UC */
+	if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
+		num_var_ranges - num[MTRR_NUM_TYPES])
+		return 0;
+
+	return 1;
+}
+
+static unsigned long __initdata range_sums;
+static void __init mtrr_calc_range_state(u64 chunk_size, u64 gran_size,
+					 unsigned long extra_remove_base,
+					 unsigned long extra_remove_size,
+					 int i)
+{
+	int num_reg;
+	static struct res_range range_new[RANGE_NUM];
+	static int nr_range_new;
+	unsigned long range_sums_new;
+
+	/* convert ranges to var ranges state */
+	num_reg = x86_setup_var_mtrrs(range, nr_range,
+						chunk_size, gran_size);
+
+	/* we got new setting in range_state, check it */
+	memset(range_new, 0, sizeof(range_new));
+	nr_range_new = x86_get_mtrr_mem_range(range_new, 0,
+				extra_remove_base, extra_remove_size);
+	range_sums_new = sum_ranges(range_new, nr_range_new);
+
+	result[i].chunk_sizek = chunk_size >> 10;
+	result[i].gran_sizek = gran_size >> 10;
+	result[i].num_reg = num_reg;
+	if (range_sums < range_sums_new) {
+		result[i].lose_cover_sizek =
+			(range_sums_new - range_sums) << PSHIFT;
+		result[i].bad = 1;
+	} else
+		result[i].lose_cover_sizek =
+			(range_sums - range_sums_new) << PSHIFT;
+
+	/* double check it */
+	if (!result[i].bad && !result[i].lose_cover_sizek) {
+		if (nr_range_new != nr_range ||
+			memcmp(range, range_new, sizeof(range)))
+				result[i].bad = 1;
+	}
+
+	if (!result[i].bad && (range_sums - range_sums_new <
+				min_loss_pfn[num_reg])) {
+		min_loss_pfn[num_reg] =
+			range_sums - range_sums_new;
+	}
+}
+
+static void __init mtrr_print_out_one_result(int i)
+{
+	char gran_factor, chunk_factor, lose_factor;
+	unsigned long gran_base, chunk_base, lose_base;
+
+	gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
+	chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
+	lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
+	printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t",
+			result[i].bad ? "*BAD*" : " ",
+			gran_base, gran_factor, chunk_base, chunk_factor);
+	printk(KERN_CONT "num_reg: %d  \tlose cover RAM: %s%ld%c\n",
+			result[i].num_reg, result[i].bad ? "-" : "",
+			lose_base, lose_factor);
+}
+
+static int __init mtrr_search_optimal_index(void)
+{
+	int i;
+	int num_reg_good;
+	int index_good;
+
+	if (nr_mtrr_spare_reg >= num_var_ranges)
+		nr_mtrr_spare_reg = num_var_ranges - 1;
+	num_reg_good = -1;
+	for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) {
+		if (!min_loss_pfn[i])
+			num_reg_good = i;
+	}
+
+	index_good = -1;
+	if (num_reg_good != -1) {
+		for (i = 0; i < NUM_RESULT; i++) {
+			if (!result[i].bad &&
+			    result[i].num_reg == num_reg_good &&
+			    !result[i].lose_cover_sizek) {
+				index_good = i;
+				break;
+			}
+		}
+	}
+
+	return index_good;
+}
+
+
+int __init mtrr_cleanup(unsigned address_bits)
+{
+	unsigned long extra_remove_base, extra_remove_size;
+	unsigned long base, size, def, dummy;
+	mtrr_type type;
+	u64 chunk_size, gran_size;
+	int index_good;
+	int i;
+
+	if (!is_cpu(INTEL) || enable_mtrr_cleanup < 1)
+		return 0;
+	rdmsr(MTRRdefType_MSR, def, dummy);
+	def &= 0xff;
+	if (def != MTRR_TYPE_UNCACHABLE)
+		return 0;
+
+	/* get it and store it aside */
+	memset(range_state, 0, sizeof(range_state));
+	for (i = 0; i < num_var_ranges; i++) {
+		mtrr_if->get(i, &base, &size, &type);
+		range_state[i].base_pfn = base;
+		range_state[i].size_pfn = size;
+		range_state[i].type = type;
+	}
+
+	/* check if we need handle it and can handle it */
+	if (!mtrr_need_cleanup())
+		return 0;
+
+	/* print original var MTRRs at first, for debugging: */
+	printk(KERN_DEBUG "original variable MTRRs\n");
+	print_out_mtrr_range_state();
+
+	memset(range, 0, sizeof(range));
+	extra_remove_size = 0;
+	extra_remove_base = 1 << (32 - PAGE_SHIFT);
+	if (mtrr_tom2)
+		extra_remove_size =
+			(mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base;
+	nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base,
+					  extra_remove_size);
+	/*
+	 * [0, 1M) should always be coverred by var mtrr with WB
+	 * and fixed mtrrs should take effective before var mtrr for it
+	 */
+	nr_range = add_range_with_merge(range, nr_range, 0,
+					(1ULL<<(20 - PAGE_SHIFT)) - 1);
+	/* sort the ranges */
+	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
+
+	range_sums = sum_ranges(range, nr_range);
+	printk(KERN_INFO "total RAM coverred: %ldM\n",
+	       range_sums >> (20 - PAGE_SHIFT));
+
+	if (mtrr_chunk_size && mtrr_gran_size) {
+		i = 0;
+		mtrr_calc_range_state(mtrr_chunk_size, mtrr_gran_size,
+				      extra_remove_base, extra_remove_size, i);
+
+		mtrr_print_out_one_result(i);
+
+		if (!result[i].bad) {
+			set_var_mtrr_all(address_bits);
+			printk(KERN_DEBUG "New variable MTRRs\n");
+			print_out_mtrr_range_state();
+			return 1;
+		}
+		printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, "
+		       "will find optimal one\n");
+	}
+
+	i = 0;
+	memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn));
+	memset(result, 0, sizeof(result));
+	for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) {
+
+		for (chunk_size = gran_size; chunk_size < (1ULL<<32);
+		     chunk_size <<= 1) {
+
+			if (i >= NUM_RESULT)
+				continue;
+
+			mtrr_calc_range_state(chunk_size, gran_size,
+				      extra_remove_base, extra_remove_size, i);
+			if (debug_print) {
+				mtrr_print_out_one_result(i);
+				printk(KERN_INFO "\n");
+			}
+
+			i++;
+		}
+	}
+
+	/* try to find the optimal index */
+	index_good = mtrr_search_optimal_index();
+
+	if (index_good != -1) {
+		printk(KERN_INFO "Found optimal setting for mtrr clean up\n");
+		i = index_good;
+		mtrr_print_out_one_result(i);
+
+		/* convert ranges to var ranges state */
+		chunk_size = result[i].chunk_sizek;
+		chunk_size <<= 10;
+		gran_size = result[i].gran_sizek;
+		gran_size <<= 10;
+		x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size);
+		set_var_mtrr_all(address_bits);
+		printk(KERN_DEBUG "New variable MTRRs\n");
+		print_out_mtrr_range_state();
+		return 1;
+	} else {
+		/* print out all */
+		for (i = 0; i < NUM_RESULT; i++)
+			mtrr_print_out_one_result(i);
+	}
+
+	printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n");
+	printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n");
+
+	return 0;
+}
+#else
+int __init mtrr_cleanup(unsigned address_bits)
+{
+	return 0;
+}
+#endif
+
+static int disable_mtrr_trim;
+
+static int __init disable_mtrr_trim_setup(char *str)
+{
+	disable_mtrr_trim = 1;
+	return 0;
+}
+early_param("disable_mtrr_trim", disable_mtrr_trim_setup);
+
+/*
+ * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
+ * for memory >4GB. Check for that here.
+ * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
+ * apply to are wrong, but so far we don't know of any such case in the wild.
+ */
+#define Tom2Enabled (1U << 21)
+#define Tom2ForceMemTypeWB (1U << 22)
+
+int __init amd_special_default_mtrr(void)
+{
+	u32 l, h;
+
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return 0;
+	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+		return 0;
+	/* In case some hypervisor doesn't pass SYSCFG through */
+	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
+		return 0;
+	/*
+	 * Memory between 4GB and top of mem is forced WB by this magic bit.
+	 * Reserved before K8RevF, but should be zero there.
+	 */
+	if ((l & (Tom2Enabled | Tom2ForceMemTypeWB)) ==
+		 (Tom2Enabled | Tom2ForceMemTypeWB))
+		return 1;
+	return 0;
+}
+
+static u64 __init real_trim_memory(unsigned long start_pfn,
+				   unsigned long limit_pfn)
+{
+	u64 trim_start, trim_size;
+	trim_start = start_pfn;
+	trim_start <<= PAGE_SHIFT;
+	trim_size = limit_pfn;
+	trim_size <<= PAGE_SHIFT;
+	trim_size -= trim_start;
+
+	return e820_update_range(trim_start, trim_size, E820_RAM,
+				E820_RESERVED);
+}
+/**
+ * mtrr_trim_uncached_memory - trim RAM not covered by MTRRs
+ * @end_pfn: ending page frame number
+ *
+ * Some buggy BIOSes don't setup the MTRRs properly for systems with certain
+ * memory configurations.  This routine checks that the highest MTRR matches
+ * the end of memory, to make sure the MTRRs having a write back type cover
+ * all of the memory the kernel is intending to use. If not, it'll trim any
+ * memory off the end by adjusting end_pfn, removing it from the kernel's
+ * allocation pools, warning the user with an obnoxious message.
+ */
+int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
+{
+	unsigned long i, base, size, highest_pfn = 0, def, dummy;
+	mtrr_type type;
+	u64 total_trim_size;
+
+	/* extra one for all 0 */
+	int num[MTRR_NUM_TYPES + 1];
+	/*
+	 * Make sure we only trim uncachable memory on machines that
+	 * support the Intel MTRR architecture:
+	 */
+	if (!is_cpu(INTEL) || disable_mtrr_trim)
+		return 0;
+	rdmsr(MTRRdefType_MSR, def, dummy);
+	def &= 0xff;
+	if (def != MTRR_TYPE_UNCACHABLE)
+		return 0;
+
+	/* get it and store it aside */
+	memset(range_state, 0, sizeof(range_state));
+	for (i = 0; i < num_var_ranges; i++) {
+		mtrr_if->get(i, &base, &size, &type);
+		range_state[i].base_pfn = base;
+		range_state[i].size_pfn = size;
+		range_state[i].type = type;
+	}
+
+	/* Find highest cached pfn */
+	for (i = 0; i < num_var_ranges; i++) {
+		type = range_state[i].type;
+		if (type != MTRR_TYPE_WRBACK)
+			continue;
+		base = range_state[i].base_pfn;
+		size = range_state[i].size_pfn;
+		if (highest_pfn < base + size)
+			highest_pfn = base + size;
+	}
+
+	/* kvm/qemu doesn't have mtrr set right, don't trim them all */
+	if (!highest_pfn) {
+		printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n");
+		return 0;
+	}
+
+	/* check entries number */
+	memset(num, 0, sizeof(num));
+	for (i = 0; i < num_var_ranges; i++) {
+		type = range_state[i].type;
+		if (type >= MTRR_NUM_TYPES)
+			continue;
+		size = range_state[i].size_pfn;
+		if (!size)
+			type = MTRR_NUM_TYPES;
+		num[type]++;
+	}
+
+	/* no entry for WB? */
+	if (!num[MTRR_TYPE_WRBACK])
+		return 0;
+
+	/* check if we only had WB and UC */
+	if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
+		num_var_ranges - num[MTRR_NUM_TYPES])
+		return 0;
+
+	memset(range, 0, sizeof(range));
+	nr_range = 0;
+	if (mtrr_tom2) {
+		range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT));
+		range[nr_range].end = (mtrr_tom2 >> PAGE_SHIFT) - 1;
+		if (highest_pfn < range[nr_range].end + 1)
+			highest_pfn = range[nr_range].end + 1;
+		nr_range++;
+	}
+	nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0);
+
+	total_trim_size = 0;
+	/* check the head */
+	if (range[0].start)
+		total_trim_size += real_trim_memory(0, range[0].start);
+	/* check the holes */
+	for (i = 0; i < nr_range - 1; i++) {
+		if (range[i].end + 1 < range[i+1].start)
+			total_trim_size += real_trim_memory(range[i].end + 1,
+							    range[i+1].start);
+	}
+	/* check the top */
+	i = nr_range - 1;
+	if (range[i].end + 1 < end_pfn)
+		total_trim_size += real_trim_memory(range[i].end + 1,
+							 end_pfn);
+
+	if (total_trim_size) {
+		printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
+			" all of memory, losing %lluMB of RAM.\n",
+			total_trim_size >> 20);
+
+		if (!changed_by_mtrr_cleanup)
+			WARN_ON(1);
+
+		printk(KERN_INFO "update e820 for mtrr\n");
+		update_e820();
+
+		return 1;
+	}
+
+	return 0;
+}
+
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 0c0a455..37f28fc 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -33,13 +33,31 @@
 struct mtrr_state_type mtrr_state = {};
 EXPORT_SYMBOL_GPL(mtrr_state);
 
-static int __initdata mtrr_show;
-static int __init mtrr_debug(char *opt)
+/**
+ * BIOS is expected to clear MtrrFixDramModEn bit, see for example
+ * "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
+ * Opteron Processors" (26094 Rev. 3.30 February 2006), section
+ * "13.2.1.2 SYSCFG Register": "The MtrrFixDramModEn bit should be set
+ * to 1 during BIOS initalization of the fixed MTRRs, then cleared to
+ * 0 for operation."
+ */
+static inline void k8_check_syscfg_dram_mod_en(void)
 {
-	mtrr_show = 1;
-	return 0;
+	u32 lo, hi;
+
+	if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+	      (boot_cpu_data.x86 >= 0x0f)))
+		return;
+
+	rdmsr(MSR_K8_SYSCFG, lo, hi);
+	if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) {
+		printk(KERN_ERR FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
+		       " not cleared by BIOS, clearing this bit\n",
+		       smp_processor_id());
+		lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
+		mtrr_wrmsr(MSR_K8_SYSCFG, lo, hi);
+	}
 }
-early_param("mtrr.show", mtrr_debug);
 
 /*
  * Returns the effective MTRR type for the region
@@ -174,6 +192,8 @@
 	unsigned int *p = (unsigned int *) frs;
 	int i;
 
+	k8_check_syscfg_dram_mod_en();
+
 	rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
 
 	for (i = 0; i < 2; i++)
@@ -188,18 +208,94 @@
 		get_fixed_ranges(mtrr_state.fixed_ranges);
 }
 
-static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+static unsigned __initdata last_fixed_start;
+static unsigned __initdata last_fixed_end;
+static mtrr_type __initdata last_fixed_type;
+
+static void __init print_fixed_last(void)
+{
+	if (!last_fixed_end)
+		return;
+
+	printk(KERN_DEBUG "  %05X-%05X %s\n", last_fixed_start,
+		last_fixed_end - 1, mtrr_attrib_to_str(last_fixed_type));
+
+	last_fixed_end = 0;
+}
+
+static void __init update_fixed_last(unsigned base, unsigned end,
+				       mtrr_type type)
+{
+	last_fixed_start = base;
+	last_fixed_end = end;
+	last_fixed_type = type;
+}
+
+static void __init print_fixed(unsigned base, unsigned step,
+			       const mtrr_type *types)
 {
 	unsigned i;
 
-	for (i = 0; i < 8; ++i, ++types, base += step)
-		printk(KERN_INFO "MTRR %05X-%05X %s\n",
-			base, base + step - 1, mtrr_attrib_to_str(*types));
+	for (i = 0; i < 8; ++i, ++types, base += step) {
+		if (last_fixed_end == 0) {
+			update_fixed_last(base, base + step, *types);
+			continue;
+		}
+		if (last_fixed_end == base && last_fixed_type == *types) {
+			last_fixed_end = base + step;
+			continue;
+		}
+		/* new segments: gap or different type */
+		print_fixed_last();
+		update_fixed_last(base, base + step, *types);
+	}
 }
 
 static void prepare_set(void);
 static void post_set(void);
 
+static void __init print_mtrr_state(void)
+{
+	unsigned int i;
+	int high_width;
+
+	printk(KERN_DEBUG "MTRR default type: %s\n",
+			 mtrr_attrib_to_str(mtrr_state.def_type));
+	if (mtrr_state.have_fixed) {
+		printk(KERN_DEBUG "MTRR fixed ranges %sabled:\n",
+		       mtrr_state.enabled & 1 ? "en" : "dis");
+		print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
+		for (i = 0; i < 2; ++i)
+			print_fixed(0x80000 + i * 0x20000, 0x04000, mtrr_state.fixed_ranges + (i + 1) * 8);
+		for (i = 0; i < 8; ++i)
+			print_fixed(0xC0000 + i * 0x08000, 0x01000, mtrr_state.fixed_ranges + (i + 3) * 8);
+
+		/* tail */
+		print_fixed_last();
+	}
+	printk(KERN_DEBUG "MTRR variable ranges %sabled:\n",
+	       mtrr_state.enabled & 2 ? "en" : "dis");
+	high_width = ((size_or_mask ? ffs(size_or_mask) - 1 : 32) - (32 - PAGE_SHIFT) + 3) / 4;
+	for (i = 0; i < num_var_ranges; ++i) {
+		if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
+			printk(KERN_DEBUG "  %u base %0*X%05X000 mask %0*X%05X000 %s\n",
+			       i,
+			       high_width,
+			       mtrr_state.var_ranges[i].base_hi,
+			       mtrr_state.var_ranges[i].base_lo >> 12,
+			       high_width,
+			       mtrr_state.var_ranges[i].mask_hi,
+			       mtrr_state.var_ranges[i].mask_lo >> 12,
+			       mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
+		else
+			printk(KERN_DEBUG "  %u disabled\n", i);
+	}
+	if (mtrr_tom2) {
+		printk(KERN_DEBUG "TOM2: %016llx aka %lldM\n",
+				  mtrr_tom2, mtrr_tom2>>20);
+	}
+}
+
 /*  Grab all of the MTRR state for this CPU into *state  */
 void __init get_mtrr_state(void)
 {
@@ -231,41 +327,9 @@
 		mtrr_tom2 |= low;
 		mtrr_tom2 &= 0xffffff800000ULL;
 	}
-	if (mtrr_show) {
-		int high_width;
 
-		printk(KERN_INFO "MTRR default type: %s\n", mtrr_attrib_to_str(mtrr_state.def_type));
-		if (mtrr_state.have_fixed) {
-			printk(KERN_INFO "MTRR fixed ranges %sabled:\n",
-			       mtrr_state.enabled & 1 ? "en" : "dis");
-			print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
-			for (i = 0; i < 2; ++i)
-				print_fixed(0x80000 + i * 0x20000, 0x04000, mtrr_state.fixed_ranges + (i + 1) * 8);
-			for (i = 0; i < 8; ++i)
-				print_fixed(0xC0000 + i * 0x08000, 0x01000, mtrr_state.fixed_ranges + (i + 3) * 8);
-		}
-		printk(KERN_INFO "MTRR variable ranges %sabled:\n",
-		       mtrr_state.enabled & 2 ? "en" : "dis");
-		high_width = ((size_or_mask ? ffs(size_or_mask) - 1 : 32) - (32 - PAGE_SHIFT) + 3) / 4;
-		for (i = 0; i < num_var_ranges; ++i) {
-			if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
-				printk(KERN_INFO "MTRR %u base %0*X%05X000 mask %0*X%05X000 %s\n",
-				       i,
-				       high_width,
-				       mtrr_state.var_ranges[i].base_hi,
-				       mtrr_state.var_ranges[i].base_lo >> 12,
-				       high_width,
-				       mtrr_state.var_ranges[i].mask_hi,
-				       mtrr_state.var_ranges[i].mask_lo >> 12,
-				       mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
-			else
-				printk(KERN_INFO "MTRR %u disabled\n", i);
-		}
-		if (mtrr_tom2) {
-			printk(KERN_INFO "TOM2: %016llx aka %lldM\n",
-					  mtrr_tom2, mtrr_tom2>>20);
-		}
-	}
+	print_mtrr_state();
+
 	mtrr_state_set = 1;
 
 	/* PAT setup for BP. We need to go through sync steps here */
@@ -308,27 +372,10 @@
 }
 
 /**
- * Enable and allow read/write of extended fixed-range MTRR bits on K8 CPUs
- * see AMD publication no. 24593, chapter 3.2.1 for more information
- */
-static inline void k8_enable_fixed_iorrs(void)
-{
-	unsigned lo, hi;
-
-	rdmsr(MSR_K8_SYSCFG, lo, hi);
-	mtrr_wrmsr(MSR_K8_SYSCFG, lo
-				| K8_MTRRFIXRANGE_DRAM_ENABLE
-				| K8_MTRRFIXRANGE_DRAM_MODIFY, hi);
-}
-
-/**
  * set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have
  * @msr: MSR address of the MTTR which should be checked and updated
  * @changed: pointer which indicates whether the MTRR needed to be changed
  * @msrwords: pointer to the MSR values which the MSR should have
- *
- * If K8 extentions are wanted, update the K8 SYSCFG MSR also.
- * See AMD publication no. 24593, chapter 7.8.1, page 233 for more information.
  */
 static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
 {
@@ -337,10 +384,6 @@
 	rdmsr(msr, lo, hi);
 
 	if (lo != msrwords[0] || hi != msrwords[1]) {
-		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-		    (boot_cpu_data.x86 >= 0x0f && boot_cpu_data.x86 <= 0x11) &&
-		    ((msrwords[0] | msrwords[1]) & K8_MTRR_RDMEM_WRMEM_MASK))
-			k8_enable_fixed_iorrs();
 		mtrr_wrmsr(msr, msrwords[0], msrwords[1]);
 		*changed = true;
 	}
@@ -376,22 +419,31 @@
 {
 	unsigned int mask_lo, mask_hi, base_lo, base_hi;
 	unsigned int tmp, hi;
+	int cpu;
+
+	/*
+	 * get_mtrr doesn't need to update mtrr_state, also it could be called
+	 * from any cpu, so try to print it out directly.
+	 */
+	cpu = get_cpu();
 
 	rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
+
 	if ((mask_lo & 0x800) == 0) {
 		/*  Invalid (i.e. free) range  */
 		*base = 0;
 		*size = 0;
 		*type = 0;
-		return;
+		goto out_put_cpu;
 	}
 
 	rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
 
-	/* Work out the shifted address mask. */
+	/* Work out the shifted address mask: */
 	tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
 	mask_lo = size_or_mask | tmp;
-	/* Expand tmp with high bits to all 1s*/
+
+	/* Expand tmp with high bits to all 1s: */
 	hi = fls(tmp);
 	if (hi > 0) {
 		tmp |= ~((1<<(hi - 1)) - 1);
@@ -402,11 +454,19 @@
 		}
 	}
 
-	/* This works correctly if size is a power of two, i.e. a
-	   contiguous range. */
+	/*
+	 * This works correctly if size is a power of two, i.e. a
+	 * contiguous range:
+	 */
 	*size = -mask_lo;
 	*base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
 	*type = base_lo & 0xff;
+
+	printk(KERN_DEBUG "  get_mtrr: cpu%d reg%02d base=%010lx size=%010lx %s\n",
+			cpu, reg, *base, *size,
+			mtrr_attrib_to_str(*type & 0xff));
+out_put_cpu:
+	put_cpu();
 }
 
 /**
@@ -419,6 +479,8 @@
 	bool changed = false;
 	int block=-1, range;
 
+	k8_check_syscfg_dram_mod_en();
+
 	while (fixed_range_blocks[++block].ranges)
 	    for (range=0; range < fixed_range_blocks[block].ranges; range++)
 		set_fixed_range(fixed_range_blocks[block].base_msr + range,
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 236a401..03cda01 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -574,7 +574,7 @@
 	unsigned long	lsize;
 };
 
-static struct mtrr_value mtrr_state[MTRR_MAX_VAR_RANGES];
+static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES];
 
 static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
 {
@@ -582,9 +582,9 @@
 
 	for (i = 0; i < num_var_ranges; i++) {
 		mtrr_if->get(i,
-			     &mtrr_state[i].lbase,
-			     &mtrr_state[i].lsize,
-			     &mtrr_state[i].ltype);
+			     &mtrr_value[i].lbase,
+			     &mtrr_value[i].lsize,
+			     &mtrr_value[i].ltype);
 	}
 	return 0;
 }
@@ -594,11 +594,11 @@
 	int i;
 
 	for (i = 0; i < num_var_ranges; i++) {
-		if (mtrr_state[i].lsize) 
+		if (mtrr_value[i].lsize)
 			set_mtrr(i,
-				 mtrr_state[i].lbase,
-				 mtrr_state[i].lsize,
-				 mtrr_state[i].ltype);
+				 mtrr_value[i].lbase,
+				 mtrr_value[i].lsize,
+				 mtrr_value[i].ltype);
 	}
 	return 0;
 }
@@ -610,1058 +610,7 @@
 	.resume		= mtrr_restore,
 };
 
-/* should be related to MTRR_VAR_RANGES nums */
-#define RANGE_NUM 256
-
-struct res_range {
-	unsigned long start;
-	unsigned long end;
-};
-
-static int __init
-add_range(struct res_range *range, int nr_range, unsigned long start,
-			      unsigned long end)
-{
-	/* out of slots */
-	if (nr_range >= RANGE_NUM)
-		return nr_range;
-
-	range[nr_range].start = start;
-	range[nr_range].end = end;
-
-	nr_range++;
-
-	return nr_range;
-}
-
-static int __init
-add_range_with_merge(struct res_range *range, int nr_range, unsigned long start,
-			      unsigned long end)
-{
-	int i;
-
-	/* try to merge it with old one */
-	for (i = 0; i < nr_range; i++) {
-		unsigned long final_start, final_end;
-		unsigned long common_start, common_end;
-
-		if (!range[i].end)
-			continue;
-
-		common_start = max(range[i].start, start);
-		common_end = min(range[i].end, end);
-		if (common_start > common_end + 1)
-			continue;
-
-		final_start = min(range[i].start, start);
-		final_end = max(range[i].end, end);
-
-		range[i].start = final_start;
-		range[i].end =  final_end;
-		return nr_range;
-	}
-
-	/* need to add that */
-	return add_range(range, nr_range, start, end);
-}
-
-static void __init
-subtract_range(struct res_range *range, unsigned long start, unsigned long end)
-{
-	int i, j;
-
-	for (j = 0; j < RANGE_NUM; j++) {
-		if (!range[j].end)
-			continue;
-
-		if (start <= range[j].start && end >= range[j].end) {
-			range[j].start = 0;
-			range[j].end = 0;
-			continue;
-		}
-
-		if (start <= range[j].start && end < range[j].end &&
-		    range[j].start < end + 1) {
-			range[j].start = end + 1;
-			continue;
-		}
-
-
-		if (start > range[j].start && end >= range[j].end &&
-		    range[j].end > start - 1) {
-			range[j].end = start - 1;
-			continue;
-		}
-
-		if (start > range[j].start && end < range[j].end) {
-			/* find the new spare */
-			for (i = 0; i < RANGE_NUM; i++) {
-				if (range[i].end == 0)
-					break;
-			}
-			if (i < RANGE_NUM) {
-				range[i].end = range[j].end;
-				range[i].start = end + 1;
-			} else {
-				printk(KERN_ERR "run of slot in ranges\n");
-			}
-			range[j].end = start - 1;
-			continue;
-		}
-	}
-}
-
-static int __init cmp_range(const void *x1, const void *x2)
-{
-	const struct res_range *r1 = x1;
-	const struct res_range *r2 = x2;
-	long start1, start2;
-
-	start1 = r1->start;
-	start2 = r2->start;
-
-	return start1 - start2;
-}
-
-struct var_mtrr_range_state {
-	unsigned long base_pfn;
-	unsigned long size_pfn;
-	mtrr_type type;
-};
-
-static struct var_mtrr_range_state __initdata range_state[RANGE_NUM];
-static int __initdata debug_print;
-
-static int __init
-x86_get_mtrr_mem_range(struct res_range *range, int nr_range,
-		       unsigned long extra_remove_base,
-		       unsigned long extra_remove_size)
-{
-	unsigned long i, base, size;
-	mtrr_type type;
-
-	for (i = 0; i < num_var_ranges; i++) {
-		type = range_state[i].type;
-		if (type != MTRR_TYPE_WRBACK)
-			continue;
-		base = range_state[i].base_pfn;
-		size = range_state[i].size_pfn;
-		nr_range = add_range_with_merge(range, nr_range, base,
-						base + size - 1);
-	}
-	if (debug_print) {
-		printk(KERN_DEBUG "After WB checking\n");
-		for (i = 0; i < nr_range; i++)
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
-	}
-
-	/* take out UC ranges */
-	for (i = 0; i < num_var_ranges; i++) {
-		type = range_state[i].type;
-		if (type != MTRR_TYPE_UNCACHABLE &&
-		    type != MTRR_TYPE_WRPROT)
-			continue;
-		size = range_state[i].size_pfn;
-		if (!size)
-			continue;
-		base = range_state[i].base_pfn;
-		subtract_range(range, base, base + size - 1);
-	}
-	if (extra_remove_size)
-		subtract_range(range, extra_remove_base,
-				 extra_remove_base + extra_remove_size  - 1);
-
-	/* get new range num */
-	nr_range = 0;
-	for (i = 0; i < RANGE_NUM; i++) {
-		if (!range[i].end)
-			continue;
-		nr_range++;
-	}
-	if  (debug_print) {
-		printk(KERN_DEBUG "After UC checking\n");
-		for (i = 0; i < nr_range; i++)
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
-	}
-
-	/* sort the ranges */
-	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
-	if  (debug_print) {
-		printk(KERN_DEBUG "After sorting\n");
-		for (i = 0; i < nr_range; i++)
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
-	}
-
-	/* clear those is not used */
-	for (i = nr_range; i < RANGE_NUM; i++)
-		memset(&range[i], 0, sizeof(range[i]));
-
-	return nr_range;
-}
-
-static struct res_range __initdata range[RANGE_NUM];
-static int __initdata nr_range;
-
-#ifdef CONFIG_MTRR_SANITIZER
-
-static unsigned long __init sum_ranges(struct res_range *range, int nr_range)
-{
-	unsigned long sum;
-	int i;
-
-	sum = 0;
-	for (i = 0; i < nr_range; i++)
-		sum += range[i].end + 1 - range[i].start;
-
-	return sum;
-}
-
-static int enable_mtrr_cleanup __initdata =
-	CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT;
-
-static int __init disable_mtrr_cleanup_setup(char *str)
-{
-	enable_mtrr_cleanup = 0;
-	return 0;
-}
-early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup);
-
-static int __init enable_mtrr_cleanup_setup(char *str)
-{
-	enable_mtrr_cleanup = 1;
-	return 0;
-}
-early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
-
-static int __init mtrr_cleanup_debug_setup(char *str)
-{
-	debug_print = 1;
-	return 0;
-}
-early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup);
-
-struct var_mtrr_state {
-	unsigned long	range_startk;
-	unsigned long	range_sizek;
-	unsigned long	chunk_sizek;
-	unsigned long	gran_sizek;
-	unsigned int	reg;
-};
-
-static void __init
-set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek,
-		unsigned char type, unsigned int address_bits)
-{
-	u32 base_lo, base_hi, mask_lo, mask_hi;
-	u64 base, mask;
-
-	if (!sizek) {
-		fill_mtrr_var_range(reg, 0, 0, 0, 0);
-		return;
-	}
-
-	mask = (1ULL << address_bits) - 1;
-	mask &= ~((((u64)sizek) << 10) - 1);
-
-	base  = ((u64)basek) << 10;
-
-	base |= type;
-	mask |= 0x800;
-
-	base_lo = base & ((1ULL<<32) - 1);
-	base_hi = base >> 32;
-
-	mask_lo = mask & ((1ULL<<32) - 1);
-	mask_hi = mask >> 32;
-
-	fill_mtrr_var_range(reg, base_lo, base_hi, mask_lo, mask_hi);
-}
-
-static void __init
-save_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek,
-		unsigned char type)
-{
-	range_state[reg].base_pfn = basek >> (PAGE_SHIFT - 10);
-	range_state[reg].size_pfn = sizek >> (PAGE_SHIFT - 10);
-	range_state[reg].type = type;
-}
-
-static void __init
-set_var_mtrr_all(unsigned int address_bits)
-{
-	unsigned long basek, sizek;
-	unsigned char type;
-	unsigned int reg;
-
-	for (reg = 0; reg < num_var_ranges; reg++) {
-		basek = range_state[reg].base_pfn << (PAGE_SHIFT - 10);
-		sizek = range_state[reg].size_pfn << (PAGE_SHIFT - 10);
-		type = range_state[reg].type;
-
-		set_var_mtrr(reg, basek, sizek, type, address_bits);
-	}
-}
-
-static unsigned long to_size_factor(unsigned long sizek, char *factorp)
-{
-	char factor;
-	unsigned long base = sizek;
-
-	if (base & ((1<<10) - 1)) {
-		/* not MB alignment */
-		factor = 'K';
-	} else if (base & ((1<<20) - 1)){
-		factor = 'M';
-		base >>= 10;
-	} else {
-		factor = 'G';
-		base >>= 20;
-	}
-
-	*factorp = factor;
-
-	return base;
-}
-
-static unsigned int __init
-range_to_mtrr(unsigned int reg, unsigned long range_startk,
-	      unsigned long range_sizek, unsigned char type)
-{
-	if (!range_sizek || (reg >= num_var_ranges))
-		return reg;
-
-	while (range_sizek) {
-		unsigned long max_align, align;
-		unsigned long sizek;
-
-		/* Compute the maximum size I can make a range */
-		if (range_startk)
-			max_align = ffs(range_startk) - 1;
-		else
-			max_align = 32;
-		align = fls(range_sizek) - 1;
-		if (align > max_align)
-			align = max_align;
-
-		sizek = 1 << align;
-		if (debug_print) {
-			char start_factor = 'K', size_factor = 'K';
-			unsigned long start_base, size_base;
-
-			start_base = to_size_factor(range_startk, &start_factor),
-			size_base = to_size_factor(sizek, &size_factor),
-
-			printk(KERN_DEBUG "Setting variable MTRR %d, "
-				"base: %ld%cB, range: %ld%cB, type %s\n",
-				reg, start_base, start_factor,
-				size_base, size_factor,
-				(type == MTRR_TYPE_UNCACHABLE)?"UC":
-				    ((type == MTRR_TYPE_WRBACK)?"WB":"Other")
-				);
-		}
-		save_var_mtrr(reg++, range_startk, sizek, type);
-		range_startk += sizek;
-		range_sizek -= sizek;
-		if (reg >= num_var_ranges)
-			break;
-	}
-	return reg;
-}
-
-static unsigned __init
-range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
-			unsigned long sizek)
-{
-	unsigned long hole_basek, hole_sizek;
-	unsigned long second_basek, second_sizek;
-	unsigned long range0_basek, range0_sizek;
-	unsigned long range_basek, range_sizek;
-	unsigned long chunk_sizek;
-	unsigned long gran_sizek;
-
-	hole_basek = 0;
-	hole_sizek = 0;
-	second_basek = 0;
-	second_sizek = 0;
-	chunk_sizek = state->chunk_sizek;
-	gran_sizek = state->gran_sizek;
-
-	/* align with gran size, prevent small block used up MTRRs */
-	range_basek = ALIGN(state->range_startk, gran_sizek);
-	if ((range_basek > basek) && basek)
-		return second_sizek;
-	state->range_sizek -= (range_basek - state->range_startk);
-	range_sizek = ALIGN(state->range_sizek, gran_sizek);
-
-	while (range_sizek > state->range_sizek) {
-		range_sizek -= gran_sizek;
-		if (!range_sizek)
-			return 0;
-	}
-	state->range_sizek = range_sizek;
-
-	/* try to append some small hole */
-	range0_basek = state->range_startk;
-	range0_sizek = ALIGN(state->range_sizek, chunk_sizek);
-
-	/* no increase */
-	if (range0_sizek == state->range_sizek) {
-		if (debug_print)
-			printk(KERN_DEBUG "rangeX: %016lx - %016lx\n",
-				range0_basek<<10,
-				(range0_basek + state->range_sizek)<<10);
-		state->reg = range_to_mtrr(state->reg, range0_basek,
-				state->range_sizek, MTRR_TYPE_WRBACK);
-		return 0;
-	}
-
-	/* only cut back, when it is not the last */
-	if (sizek) {
-		while (range0_basek + range0_sizek > (basek + sizek)) {
-			if (range0_sizek >= chunk_sizek)
-				range0_sizek -= chunk_sizek;
-			else
-				range0_sizek = 0;
-
-			if (!range0_sizek)
-				break;
-		}
-	}
-
-second_try:
-	range_basek = range0_basek + range0_sizek;
-
-	/* one hole in the middle */
-	if (range_basek > basek && range_basek <= (basek + sizek))
-		second_sizek = range_basek - basek;
-
-	if (range0_sizek > state->range_sizek) {
-
-		/* one hole in middle or at end */
-		hole_sizek = range0_sizek - state->range_sizek - second_sizek;
-
-		/* hole size should be less than half of range0 size */
-		if (hole_sizek >= (range0_sizek >> 1) &&
-		    range0_sizek >= chunk_sizek) {
-			range0_sizek -= chunk_sizek;
-			second_sizek = 0;
-			hole_sizek = 0;
-
-			goto second_try;
-		}
-	}
-
-	if (range0_sizek) {
-		if (debug_print)
-			printk(KERN_DEBUG "range0: %016lx - %016lx\n",
-				range0_basek<<10,
-				(range0_basek + range0_sizek)<<10);
-		state->reg = range_to_mtrr(state->reg, range0_basek,
-				range0_sizek, MTRR_TYPE_WRBACK);
-	}
-
-	if (range0_sizek < state->range_sizek) {
-		/* need to handle left over */
-		range_sizek = state->range_sizek - range0_sizek;
-
-		if (debug_print)
-			printk(KERN_DEBUG "range: %016lx - %016lx\n",
-				 range_basek<<10,
-				 (range_basek + range_sizek)<<10);
-		state->reg = range_to_mtrr(state->reg, range_basek,
-				 range_sizek, MTRR_TYPE_WRBACK);
-	}
-
-	if (hole_sizek) {
-		hole_basek = range_basek - hole_sizek - second_sizek;
-		if (debug_print)
-			printk(KERN_DEBUG "hole: %016lx - %016lx\n",
-				 hole_basek<<10,
-				 (hole_basek + hole_sizek)<<10);
-		state->reg = range_to_mtrr(state->reg, hole_basek,
-				 hole_sizek, MTRR_TYPE_UNCACHABLE);
-	}
-
-	return second_sizek;
-}
-
-static void __init
-set_var_mtrr_range(struct var_mtrr_state *state, unsigned long base_pfn,
-		   unsigned long size_pfn)
-{
-	unsigned long basek, sizek;
-	unsigned long second_sizek = 0;
-
-	if (state->reg >= num_var_ranges)
-		return;
-
-	basek = base_pfn << (PAGE_SHIFT - 10);
-	sizek = size_pfn << (PAGE_SHIFT - 10);
-
-	/* See if I can merge with the last range */
-	if ((basek <= 1024) ||
-	    (state->range_startk + state->range_sizek == basek)) {
-		unsigned long endk = basek + sizek;
-		state->range_sizek = endk - state->range_startk;
-		return;
-	}
-	/* Write the range mtrrs */
-	if (state->range_sizek != 0)
-		second_sizek = range_to_mtrr_with_hole(state, basek, sizek);
-
-	/* Allocate an msr */
-	state->range_startk = basek + second_sizek;
-	state->range_sizek  = sizek - second_sizek;
-}
-
-/* mininum size of mtrr block that can take hole */
-static u64 mtrr_chunk_size __initdata = (256ULL<<20);
-
-static int __init parse_mtrr_chunk_size_opt(char *p)
-{
-	if (!p)
-		return -EINVAL;
-	mtrr_chunk_size = memparse(p, &p);
-	return 0;
-}
-early_param("mtrr_chunk_size", parse_mtrr_chunk_size_opt);
-
-/* granity of mtrr of block */
-static u64 mtrr_gran_size __initdata;
-
-static int __init parse_mtrr_gran_size_opt(char *p)
-{
-	if (!p)
-		return -EINVAL;
-	mtrr_gran_size = memparse(p, &p);
-	return 0;
-}
-early_param("mtrr_gran_size", parse_mtrr_gran_size_opt);
-
-static int nr_mtrr_spare_reg __initdata =
-				 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT;
-
-static int __init parse_mtrr_spare_reg(char *arg)
-{
-	if (arg)
-		nr_mtrr_spare_reg = simple_strtoul(arg, NULL, 0);
-	return 0;
-}
-
-early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg);
-
-static int __init
-x86_setup_var_mtrrs(struct res_range *range, int nr_range,
-		    u64 chunk_size, u64 gran_size)
-{
-	struct var_mtrr_state var_state;
-	int i;
-	int num_reg;
-
-	var_state.range_startk	= 0;
-	var_state.range_sizek	= 0;
-	var_state.reg		= 0;
-	var_state.chunk_sizek	= chunk_size >> 10;
-	var_state.gran_sizek	= gran_size >> 10;
-
-	memset(range_state, 0, sizeof(range_state));
-
-	/* Write the range etc */
-	for (i = 0; i < nr_range; i++)
-		set_var_mtrr_range(&var_state, range[i].start,
-				   range[i].end - range[i].start + 1);
-
-	/* Write the last range */
-	if (var_state.range_sizek != 0)
-		range_to_mtrr_with_hole(&var_state, 0, 0);
-
-	num_reg = var_state.reg;
-	/* Clear out the extra MTRR's */
-	while (var_state.reg < num_var_ranges) {
-		save_var_mtrr(var_state.reg, 0, 0, 0);
-		var_state.reg++;
-	}
-
-	return num_reg;
-}
-
-struct mtrr_cleanup_result {
-	unsigned long gran_sizek;
-	unsigned long chunk_sizek;
-	unsigned long lose_cover_sizek;
-	unsigned int num_reg;
-	int bad;
-};
-
-/*
- * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G
- * chunk size: gran_size, ..., 2G
- * so we need (1+16)*8
- */
-#define NUM_RESULT	136
-#define PSHIFT		(PAGE_SHIFT - 10)
-
-static struct mtrr_cleanup_result __initdata result[NUM_RESULT];
-static unsigned long __initdata min_loss_pfn[RANGE_NUM];
-
-static void __init print_out_mtrr_range_state(void)
-{
-	int i;
-	char start_factor = 'K', size_factor = 'K';
-	unsigned long start_base, size_base;
-	mtrr_type type;
-
-	for (i = 0; i < num_var_ranges; i++) {
-
-		size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10);
-		if (!size_base)
-			continue;
-
-		size_base = to_size_factor(size_base, &size_factor),
-		start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10);
-		start_base = to_size_factor(start_base, &start_factor),
-		type = range_state[i].type;
-
-		printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
-			i, start_base, start_factor,
-			size_base, size_factor,
-			(type == MTRR_TYPE_UNCACHABLE) ? "UC" :
-			    ((type == MTRR_TYPE_WRPROT) ? "WP" :
-			     ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other"))
-			);
-	}
-}
-
-static int __init mtrr_need_cleanup(void)
-{
-	int i;
-	mtrr_type type;
-	unsigned long size;
-	/* extra one for all 0 */
-	int num[MTRR_NUM_TYPES + 1];
-
-	/* check entries number */
-	memset(num, 0, sizeof(num));
-	for (i = 0; i < num_var_ranges; i++) {
-		type = range_state[i].type;
-		size = range_state[i].size_pfn;
-		if (type >= MTRR_NUM_TYPES)
-			continue;
-		if (!size)
-			type = MTRR_NUM_TYPES;
-		if (type == MTRR_TYPE_WRPROT)
-			type = MTRR_TYPE_UNCACHABLE;
-		num[type]++;
-	}
-
-	/* check if we got UC entries */
-	if (!num[MTRR_TYPE_UNCACHABLE])
-		return 0;
-
-	/* check if we only had WB and UC */
-	if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
-		num_var_ranges - num[MTRR_NUM_TYPES])
-		return 0;
-
-	return 1;
-}
-
-static unsigned long __initdata range_sums;
-static void __init mtrr_calc_range_state(u64 chunk_size, u64 gran_size,
-					 unsigned long extra_remove_base,
-					 unsigned long extra_remove_size,
-					 int i)
-{
-	int num_reg;
-	static struct res_range range_new[RANGE_NUM];
-	static int nr_range_new;
-	unsigned long range_sums_new;
-
-	/* convert ranges to var ranges state */
-	num_reg = x86_setup_var_mtrrs(range, nr_range,
-						chunk_size, gran_size);
-
-	/* we got new setting in range_state, check it */
-	memset(range_new, 0, sizeof(range_new));
-	nr_range_new = x86_get_mtrr_mem_range(range_new, 0,
-				extra_remove_base, extra_remove_size);
-	range_sums_new = sum_ranges(range_new, nr_range_new);
-
-	result[i].chunk_sizek = chunk_size >> 10;
-	result[i].gran_sizek = gran_size >> 10;
-	result[i].num_reg = num_reg;
-	if (range_sums < range_sums_new) {
-		result[i].lose_cover_sizek =
-			(range_sums_new - range_sums) << PSHIFT;
-		result[i].bad = 1;
-	} else
-		result[i].lose_cover_sizek =
-			(range_sums - range_sums_new) << PSHIFT;
-
-	/* double check it */
-	if (!result[i].bad && !result[i].lose_cover_sizek) {
-		if (nr_range_new != nr_range ||
-			memcmp(range, range_new, sizeof(range)))
-				result[i].bad = 1;
-	}
-
-	if (!result[i].bad && (range_sums - range_sums_new <
-				min_loss_pfn[num_reg])) {
-		min_loss_pfn[num_reg] =
-			range_sums - range_sums_new;
-	}
-}
-
-static void __init mtrr_print_out_one_result(int i)
-{
-	char gran_factor, chunk_factor, lose_factor;
-	unsigned long gran_base, chunk_base, lose_base;
-
-	gran_base = to_size_factor(result[i].gran_sizek, &gran_factor),
-	chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor),
-	lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor),
-	printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t",
-			result[i].bad ? "*BAD*" : " ",
-			gran_base, gran_factor, chunk_base, chunk_factor);
-	printk(KERN_CONT "num_reg: %d  \tlose cover RAM: %s%ld%c\n",
-			result[i].num_reg, result[i].bad ? "-" : "",
-			lose_base, lose_factor);
-}
-
-static int __init mtrr_search_optimal_index(void)
-{
-	int i;
-	int num_reg_good;
-	int index_good;
-
-	if (nr_mtrr_spare_reg >= num_var_ranges)
-		nr_mtrr_spare_reg = num_var_ranges - 1;
-	num_reg_good = -1;
-	for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) {
-		if (!min_loss_pfn[i])
-			num_reg_good = i;
-	}
-
-	index_good = -1;
-	if (num_reg_good != -1) {
-		for (i = 0; i < NUM_RESULT; i++) {
-			if (!result[i].bad &&
-			    result[i].num_reg == num_reg_good &&
-			    !result[i].lose_cover_sizek) {
-				index_good = i;
-				break;
-			}
-		}
-	}
-
-	return index_good;
-}
-
-
-static int __init mtrr_cleanup(unsigned address_bits)
-{
-	unsigned long extra_remove_base, extra_remove_size;
-	unsigned long base, size, def, dummy;
-	mtrr_type type;
-	u64 chunk_size, gran_size;
-	int index_good;
-	int i;
-
-	if (!is_cpu(INTEL) || enable_mtrr_cleanup < 1)
-		return 0;
-	rdmsr(MTRRdefType_MSR, def, dummy);
-	def &= 0xff;
-	if (def != MTRR_TYPE_UNCACHABLE)
-		return 0;
-
-	/* get it and store it aside */
-	memset(range_state, 0, sizeof(range_state));
-	for (i = 0; i < num_var_ranges; i++) {
-		mtrr_if->get(i, &base, &size, &type);
-		range_state[i].base_pfn = base;
-		range_state[i].size_pfn = size;
-		range_state[i].type = type;
-	}
-
-	/* check if we need handle it and can handle it */
-	if (!mtrr_need_cleanup())
-		return 0;
-
-	/* print original var MTRRs at first, for debugging: */
-	printk(KERN_DEBUG "original variable MTRRs\n");
-	print_out_mtrr_range_state();
-
-	memset(range, 0, sizeof(range));
-	extra_remove_size = 0;
-	extra_remove_base = 1 << (32 - PAGE_SHIFT);
-	if (mtrr_tom2)
-		extra_remove_size =
-			(mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base;
-	nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base,
-					  extra_remove_size);
-	/*
-	 * [0, 1M) should always be coverred by var mtrr with WB
-	 * and fixed mtrrs should take effective before var mtrr for it
-	 */
-	nr_range = add_range_with_merge(range, nr_range, 0,
-					(1ULL<<(20 - PAGE_SHIFT)) - 1);
-	/* sort the ranges */
-	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
-
-	range_sums = sum_ranges(range, nr_range);
-	printk(KERN_INFO "total RAM coverred: %ldM\n",
-	       range_sums >> (20 - PAGE_SHIFT));
-
-	if (mtrr_chunk_size && mtrr_gran_size) {
-		i = 0;
-		mtrr_calc_range_state(mtrr_chunk_size, mtrr_gran_size,
-				      extra_remove_base, extra_remove_size, i);
-
-		mtrr_print_out_one_result(i);
-
-		if (!result[i].bad) {
-			set_var_mtrr_all(address_bits);
-			return 1;
-		}
-		printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, "
-		       "will find optimal one\n");
-	}
-
-	i = 0;
-	memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn));
-	memset(result, 0, sizeof(result));
-	for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) {
-
-		for (chunk_size = gran_size; chunk_size < (1ULL<<32);
-		     chunk_size <<= 1) {
-
-			if (i >= NUM_RESULT)
-				continue;
-
-			mtrr_calc_range_state(chunk_size, gran_size,
-				      extra_remove_base, extra_remove_size, i);
-			if (debug_print) {
-				mtrr_print_out_one_result(i);
-				printk(KERN_INFO "\n");
-			}
-
-			i++;
-		}
-	}
-
-	/* try to find the optimal index */
-	index_good = mtrr_search_optimal_index();
-
-	if (index_good != -1) {
-		printk(KERN_INFO "Found optimal setting for mtrr clean up\n");
-		i = index_good;
-		mtrr_print_out_one_result(i);
-
-		/* convert ranges to var ranges state */
-		chunk_size = result[i].chunk_sizek;
-		chunk_size <<= 10;
-		gran_size = result[i].gran_sizek;
-		gran_size <<= 10;
-		x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size);
-		set_var_mtrr_all(address_bits);
-		printk(KERN_DEBUG "New variable MTRRs\n");
-		print_out_mtrr_range_state();
-		return 1;
-	} else {
-		/* print out all */
-		for (i = 0; i < NUM_RESULT; i++)
-			mtrr_print_out_one_result(i);
-	}
-
-	printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n");
-	printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n");
-
-	return 0;
-}
-#else
-static int __init mtrr_cleanup(unsigned address_bits)
-{
-	return 0;
-}
-#endif
-
-static int __initdata changed_by_mtrr_cleanup;
-
-static int disable_mtrr_trim;
-
-static int __init disable_mtrr_trim_setup(char *str)
-{
-	disable_mtrr_trim = 1;
-	return 0;
-}
-early_param("disable_mtrr_trim", disable_mtrr_trim_setup);
-
-/*
- * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
- * for memory >4GB. Check for that here.
- * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
- * apply to are wrong, but so far we don't know of any such case in the wild.
- */
-#define Tom2Enabled (1U << 21)
-#define Tom2ForceMemTypeWB (1U << 22)
-
-int __init amd_special_default_mtrr(void)
-{
-	u32 l, h;
-
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-		return 0;
-	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
-		return 0;
-	/* In case some hypervisor doesn't pass SYSCFG through */
-	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
-		return 0;
-	/*
-	 * Memory between 4GB and top of mem is forced WB by this magic bit.
-	 * Reserved before K8RevF, but should be zero there.
-	 */
-	if ((l & (Tom2Enabled | Tom2ForceMemTypeWB)) ==
-		 (Tom2Enabled | Tom2ForceMemTypeWB))
-		return 1;
-	return 0;
-}
-
-static u64 __init real_trim_memory(unsigned long start_pfn,
-				   unsigned long limit_pfn)
-{
-	u64 trim_start, trim_size;
-	trim_start = start_pfn;
-	trim_start <<= PAGE_SHIFT;
-	trim_size = limit_pfn;
-	trim_size <<= PAGE_SHIFT;
-	trim_size -= trim_start;
-
-	return e820_update_range(trim_start, trim_size, E820_RAM,
-				E820_RESERVED);
-}
-/**
- * mtrr_trim_uncached_memory - trim RAM not covered by MTRRs
- * @end_pfn: ending page frame number
- *
- * Some buggy BIOSes don't setup the MTRRs properly for systems with certain
- * memory configurations.  This routine checks that the highest MTRR matches
- * the end of memory, to make sure the MTRRs having a write back type cover
- * all of the memory the kernel is intending to use. If not, it'll trim any
- * memory off the end by adjusting end_pfn, removing it from the kernel's
- * allocation pools, warning the user with an obnoxious message.
- */
-int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
-{
-	unsigned long i, base, size, highest_pfn = 0, def, dummy;
-	mtrr_type type;
-	u64 total_trim_size;
-
-	/* extra one for all 0 */
-	int num[MTRR_NUM_TYPES + 1];
-	/*
-	 * Make sure we only trim uncachable memory on machines that
-	 * support the Intel MTRR architecture:
-	 */
-	if (!is_cpu(INTEL) || disable_mtrr_trim)
-		return 0;
-	rdmsr(MTRRdefType_MSR, def, dummy);
-	def &= 0xff;
-	if (def != MTRR_TYPE_UNCACHABLE)
-		return 0;
-
-	/* get it and store it aside */
-	memset(range_state, 0, sizeof(range_state));
-	for (i = 0; i < num_var_ranges; i++) {
-		mtrr_if->get(i, &base, &size, &type);
-		range_state[i].base_pfn = base;
-		range_state[i].size_pfn = size;
-		range_state[i].type = type;
-	}
-
-	/* Find highest cached pfn */
-	for (i = 0; i < num_var_ranges; i++) {
-		type = range_state[i].type;
-		if (type != MTRR_TYPE_WRBACK)
-			continue;
-		base = range_state[i].base_pfn;
-		size = range_state[i].size_pfn;
-		if (highest_pfn < base + size)
-			highest_pfn = base + size;
-	}
-
-	/* kvm/qemu doesn't have mtrr set right, don't trim them all */
-	if (!highest_pfn) {
-		printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n");
-		return 0;
-	}
-
-	/* check entries number */
-	memset(num, 0, sizeof(num));
-	for (i = 0; i < num_var_ranges; i++) {
-		type = range_state[i].type;
-		if (type >= MTRR_NUM_TYPES)
-			continue;
-		size = range_state[i].size_pfn;
-		if (!size)
-			type = MTRR_NUM_TYPES;
-		num[type]++;
-	}
-
-	/* no entry for WB? */
-	if (!num[MTRR_TYPE_WRBACK])
-		return 0;
-
-	/* check if we only had WB and UC */
-	if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
-		num_var_ranges - num[MTRR_NUM_TYPES])
-		return 0;
-
-	memset(range, 0, sizeof(range));
-	nr_range = 0;
-	if (mtrr_tom2) {
-		range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT));
-		range[nr_range].end = (mtrr_tom2 >> PAGE_SHIFT) - 1;
-		if (highest_pfn < range[nr_range].end + 1)
-			highest_pfn = range[nr_range].end + 1;
-		nr_range++;
-	}
-	nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0);
-
-	total_trim_size = 0;
-	/* check the head */
-	if (range[0].start)
-		total_trim_size += real_trim_memory(0, range[0].start);
-	/* check the holes */
-	for (i = 0; i < nr_range - 1; i++) {
-		if (range[i].end + 1 < range[i+1].start)
-			total_trim_size += real_trim_memory(range[i].end + 1,
-							    range[i+1].start);
-	}
-	/* check the top */
-	i = nr_range - 1;
-	if (range[i].end + 1 < end_pfn)
-		total_trim_size += real_trim_memory(range[i].end + 1,
-							 end_pfn);
-
-	if (total_trim_size) {
-		printk(KERN_WARNING "WARNING: BIOS bug: CPU MTRRs don't cover"
-			" all of memory, losing %lluMB of RAM.\n",
-			total_trim_size >> 20);
-
-		if (!changed_by_mtrr_cleanup)
-			WARN_ON(1);
-
-		printk(KERN_INFO "update e820 for mtrr\n");
-		update_e820();
-
-		return 1;
-	}
-
-	return 0;
-}
+int __initdata changed_by_mtrr_cleanup;
 
 /**
  * mtrr_bp_init - initialize mtrrs on the boot CPU
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index ffd6040..77f67f7 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -79,6 +79,7 @@
 
 extern unsigned int num_var_ranges;
 extern u64 mtrr_tom2;
+extern struct mtrr_state_type mtrr_state;
 
 void mtrr_state_warn(void);
 const char *mtrr_attrib_to_str(int x);
@@ -88,3 +89,6 @@
 int amd_init_mtrr(void);
 int cyrix_init_mtrr(void);
 int centaur_init_mtrr(void);
+
+extern int changed_by_mtrr_cleanup;
+extern int mtrr_cleanup(unsigned address_bits);
diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c
index 52b3fef..bb62b3e 100644
--- a/arch/x86/kernel/cpu/transmeta.c
+++ b/arch/x86/kernel/cpu/transmeta.c
@@ -98,7 +98,7 @@
 #endif
 }
 
-static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst transmeta_cpu_dev = {
 	.c_vendor	= "Transmeta",
 	.c_ident	= { "GenuineTMx86", "TransmetaCPU" },
 	.c_early_init	= early_init_transmeta,
diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c
index e777f79..fd2c37b 100644
--- a/arch/x86/kernel/cpu/umc.c
+++ b/arch/x86/kernel/cpu/umc.c
@@ -8,7 +8,7 @@
  * so no special init takes place.
  */
 
-static struct cpu_dev umc_cpu_dev __cpuinitdata = {
+static const struct cpu_dev __cpuinitconst umc_cpu_dev = {
 	.c_vendor	= "UMC",
 	.c_ident	= { "UMC UMC UMC" },
 	.c_models = {
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 87d103d..dd2130b 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -10,6 +10,7 @@
 #include <linux/kdebug.h>
 #include <linux/module.h>
 #include <linux/ptrace.h>
+#include <linux/ftrace.h>
 #include <linux/kexec.h>
 #include <linux/bug.h>
 #include <linux/nmi.h>
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 508bec1..ef2c356 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -110,19 +110,50 @@
 /*
  * Add a memory region to the kernel e820 map.
  */
-void __init e820_add_region(u64 start, u64 size, int type)
+static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
+					 int type)
 {
-	int x = e820.nr_map;
+	int x = e820x->nr_map;
 
-	if (x == ARRAY_SIZE(e820.map)) {
+	if (x == ARRAY_SIZE(e820x->map)) {
 		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
 		return;
 	}
 
-	e820.map[x].addr = start;
-	e820.map[x].size = size;
-	e820.map[x].type = type;
-	e820.nr_map++;
+	e820x->map[x].addr = start;
+	e820x->map[x].size = size;
+	e820x->map[x].type = type;
+	e820x->nr_map++;
+}
+
+void __init e820_add_region(u64 start, u64 size, int type)
+{
+	__e820_add_region(&e820, start, size, type);
+}
+
+static void __init e820_print_type(u32 type)
+{
+	switch (type) {
+	case E820_RAM:
+	case E820_RESERVED_KERN:
+		printk(KERN_CONT "(usable)");
+		break;
+	case E820_RESERVED:
+		printk(KERN_CONT "(reserved)");
+		break;
+	case E820_ACPI:
+		printk(KERN_CONT "(ACPI data)");
+		break;
+	case E820_NVS:
+		printk(KERN_CONT "(ACPI NVS)");
+		break;
+	case E820_UNUSABLE:
+		printk(KERN_CONT "(unusable)");
+		break;
+	default:
+		printk(KERN_CONT "type %u", type);
+		break;
+	}
 }
 
 void __init e820_print_map(char *who)
@@ -134,27 +165,8 @@
 		       (unsigned long long) e820.map[i].addr,
 		       (unsigned long long)
 		       (e820.map[i].addr + e820.map[i].size));
-		switch (e820.map[i].type) {
-		case E820_RAM:
-		case E820_RESERVED_KERN:
-			printk(KERN_CONT "(usable)\n");
-			break;
-		case E820_RESERVED:
-			printk(KERN_CONT "(reserved)\n");
-			break;
-		case E820_ACPI:
-			printk(KERN_CONT "(ACPI data)\n");
-			break;
-		case E820_NVS:
-			printk(KERN_CONT "(ACPI NVS)\n");
-			break;
-		case E820_UNUSABLE:
-			printk("(unusable)\n");
-			break;
-		default:
-			printk(KERN_CONT "type %u\n", e820.map[i].type);
-			break;
-		}
+		e820_print_type(e820.map[i].type);
+		printk(KERN_CONT "\n");
 	}
 }
 
@@ -221,7 +233,7 @@
  */
 
 int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
-				int *pnr_map)
+			     u32 *pnr_map)
 {
 	struct change_member {
 		struct e820entry *pbios; /* pointer to original bios entry */
@@ -417,11 +429,12 @@
 	return __append_e820_map(biosmap, nr_map);
 }
 
-static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
+static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
 					u64 size, unsigned old_type,
 					unsigned new_type)
 {
-	int i;
+	u64 end;
+	unsigned int i;
 	u64 real_updated_size = 0;
 
 	BUG_ON(old_type == new_type);
@@ -429,27 +442,55 @@
 	if (size > (ULLONG_MAX - start))
 		size = ULLONG_MAX - start;
 
-	for (i = 0; i < e820.nr_map; i++) {
+	end = start + size;
+	printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
+		       (unsigned long long) start,
+		       (unsigned long long) end);
+	e820_print_type(old_type);
+	printk(KERN_CONT " ==> ");
+	e820_print_type(new_type);
+	printk(KERN_CONT "\n");
+
+	for (i = 0; i < e820x->nr_map; i++) {
 		struct e820entry *ei = &e820x->map[i];
 		u64 final_start, final_end;
+		u64 ei_end;
+
 		if (ei->type != old_type)
 			continue;
-		/* totally covered? */
-		if (ei->addr >= start &&
-		    (ei->addr + ei->size) <= (start + size)) {
+
+		ei_end = ei->addr + ei->size;
+		/* totally covered by new range? */
+		if (ei->addr >= start && ei_end <= end) {
 			ei->type = new_type;
 			real_updated_size += ei->size;
 			continue;
 		}
+
+		/* new range is totally covered? */
+		if (ei->addr < start && ei_end > end) {
+			__e820_add_region(e820x, start, size, new_type);
+			__e820_add_region(e820x, end, ei_end - end, ei->type);
+			ei->size = start - ei->addr;
+			real_updated_size += size;
+			continue;
+		}
+
 		/* partially covered */
 		final_start = max(start, ei->addr);
-		final_end = min(start + size, ei->addr + ei->size);
+		final_end = min(end, ei_end);
 		if (final_start >= final_end)
 			continue;
-		e820_add_region(final_start, final_end - final_start,
-					 new_type);
+
+		__e820_add_region(e820x, final_start, final_end - final_start,
+				  new_type);
+
 		real_updated_size += final_end - final_start;
 
+		/*
+		 * left range could be head or tail, so need to update
+		 * size at first.
+		 */
 		ei->size -= final_end - final_start;
 		if (ei->addr < final_start)
 			continue;
@@ -461,13 +502,13 @@
 u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
 			     unsigned new_type)
 {
-	return e820_update_range_map(&e820, start, size, old_type, new_type);
+	return __e820_update_range(&e820, start, size, old_type, new_type);
 }
 
 static u64 __init e820_update_range_saved(u64 start, u64 size,
 					  unsigned old_type, unsigned new_type)
 {
-	return e820_update_range_map(&e820_saved, start, size, old_type,
+	return __e820_update_range(&e820_saved, start, size, old_type,
 				     new_type);
 }
 
@@ -511,7 +552,7 @@
 
 void __init update_e820(void)
 {
-	int nr_map;
+	u32 nr_map;
 
 	nr_map = e820.nr_map;
 	if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
@@ -522,7 +563,7 @@
 }
 static void __init update_e820_saved(void)
 {
-	int nr_map;
+	u32 nr_map;
 
 	nr_map = e820_saved.nr_map;
 	if (sanitize_e820_map(e820_saved.map, ARRAY_SIZE(e820_saved.map), &nr_map))
@@ -1020,8 +1061,8 @@
 			continue;
 		return addr;
 	}
-	return -1UL;
 
+	return -1ULL;
 }
 
 /*
@@ -1034,13 +1075,22 @@
 	u64 start;
 
 	start = startt;
-	while (size < sizet)
+	while (size < sizet && (start + 1))
 		start = find_e820_area_size(start, &size, align);
 
 	if (size < sizet)
 		return 0;
 
+#ifdef CONFIG_X86_32
+	if (start >= MAXMEM)
+		return 0;
+	if (start + size > MAXMEM)
+		size = MAXMEM - start;
+#endif
+
 	addr = round_down(start + size - sizet, align);
+	if (addr < start)
+		return 0;
 	e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
 	e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
 	printk(KERN_INFO "update e820 for early_reserve_e820\n");
@@ -1253,7 +1303,7 @@
 void __init finish_e820_parsing(void)
 {
 	if (userdef) {
-		int nr = e820.nr_map;
+		u32 nr = e820.nr_map;
 
 		if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr) < 0)
 			early_panic("Invalid user supplied memory map");
@@ -1336,7 +1386,7 @@
 char *__init default_machine_specific_memory_setup(void)
 {
 	char *who = "BIOS-e820";
-	int new_nr;
+	u32 new_nr;
 	/*
 	 * Try to copy the BIOS-supplied E820-map.
 	 *
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 639ad98..335f049 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -250,7 +250,7 @@
 	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
 }
 
-static void dbgp_mdelay(int ms)
+static void __init dbgp_mdelay(int ms)
 {
 	int i;
 
@@ -311,7 +311,7 @@
 	writel(hi, &ehci_debug->data47);
 }
 
-static void dbgp_get_data(void *buf, int size)
+static void __init dbgp_get_data(void *buf, int size)
 {
 	unsigned char *bytes = buf;
 	u32 lo, hi;
@@ -355,7 +355,7 @@
 	return ret;
 }
 
-static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
+static int __init dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
 				 int size)
 {
 	u32 pids, addr, ctrl;
@@ -386,8 +386,8 @@
 	return ret;
 }
 
-static int dbgp_control_msg(unsigned devnum, int requesttype, int request,
-	int value, int index, void *data, int size)
+static int __init dbgp_control_msg(unsigned devnum, int requesttype,
+	int request, int value, int index, void *data, int size)
 {
 	u32 pids, addr, ctrl;
 	struct usb_ctrlrequest req;
@@ -489,7 +489,7 @@
 	return 0;
 }
 
-static int ehci_reset_port(int port)
+static int __init ehci_reset_port(int port)
 {
 	u32 portsc;
 	u32 delay_time, delay;
@@ -532,7 +532,7 @@
 	return -EBUSY;
 }
 
-static int ehci_wait_for_port(int port)
+static int __init ehci_wait_for_port(int port)
 {
 	u32 status;
 	int ret, reps;
@@ -557,13 +557,13 @@
 
 typedef void (*set_debug_port_t)(int port);
 
-static void default_set_debug_port(int port)
+static void __init default_set_debug_port(int port)
 {
 }
 
-static set_debug_port_t set_debug_port = default_set_debug_port;
+static set_debug_port_t __initdata set_debug_port = default_set_debug_port;
 
-static void nvidia_set_debug_port(int port)
+static void __init nvidia_set_debug_port(int port)
 {
 	u32 dword;
 	dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 899e893..c929add 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -442,8 +442,7 @@
 
 	GET_THREAD_INFO(%ebp)
 
-	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
-	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
 	jnz sysenter_audit
 sysenter_do_call:
 	cmpl $(nr_syscalls), %eax
@@ -454,7 +453,7 @@
 	DISABLE_INTERRUPTS(CLBR_ANY)
 	TRACE_IRQS_OFF
 	movl TI_flags(%ebp), %ecx
-	testw $_TIF_ALLWORK_MASK, %cx
+	testl $_TIF_ALLWORK_MASK, %ecx
 	jne sysexit_audit
 sysenter_exit:
 /* if something modifies registers it must also disable sysexit */
@@ -468,7 +467,7 @@
 
 #ifdef CONFIG_AUDITSYSCALL
 sysenter_audit:
-	testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 	jnz syscall_trace_entry
 	addl $4,%esp
 	CFI_ADJUST_CFA_OFFSET -4
@@ -485,7 +484,7 @@
 	jmp sysenter_do_call
 
 sysexit_audit:
-	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
 	jne syscall_exit_work
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_ANY)
@@ -498,7 +497,7 @@
 	DISABLE_INTERRUPTS(CLBR_ANY)
 	TRACE_IRQS_OFF
 	movl TI_flags(%ebp), %ecx
-	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
 	jne syscall_exit_work
 	movl PT_EAX(%esp),%eax	/* reload syscall return value */
 	jmp sysenter_exit
@@ -523,8 +522,7 @@
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 					# system call tracing in operation / emulation
-	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
-	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
 	jnz syscall_trace_entry
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
@@ -538,7 +536,7 @@
 					# between sampling and the iret
 	TRACE_IRQS_OFF
 	movl TI_flags(%ebp), %ecx
-	testw $_TIF_ALLWORK_MASK, %cx	# current->work
+	testl $_TIF_ALLWORK_MASK, %ecx	# current->work
 	jne syscall_exit_work
 
 restore_all:
@@ -673,7 +671,7 @@
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb $_TIF_WORK_SYSCALL_EXIT, %cl
+	testl $_TIF_WORK_SYSCALL_EXIT, %ecx
 	jz work_pending
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 83d1836..a331ec3 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -368,6 +368,7 @@
 END(save_rest)
 
 /* save complete stack frame */
+	.pushsection .kprobes.text, "ax"
 ENTRY(save_paranoid)
 	XCPT_FRAME 1 RDI+8
 	cld
@@ -396,6 +397,7 @@
 1:	ret
 	CFI_ENDPROC
 END(save_paranoid)
+	.popsection
 
 /*
  * A newly forked process directly context switches into this address.
@@ -416,7 +418,6 @@
 
 	GET_THREAD_INFO(%rcx)
 
-	CFI_REMEMBER_STATE
 	RESTORE_REST
 
 	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
@@ -428,7 +429,6 @@
 	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
 	jmp ret_from_sys_call			# go to the SYSRET fastpath
 
-	CFI_RESTORE_STATE
 	CFI_ENDPROC
 END(ret_from_fork)
 
@@ -984,6 +984,8 @@
 #endif
 apicinterrupt LOCAL_TIMER_VECTOR \
 	apic_timer_interrupt smp_apic_timer_interrupt
+apicinterrupt GENERIC_INTERRUPT_VECTOR \
+	generic_interrupt smp_generic_interrupt
 
 #ifdef CONFIG_SMP
 apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 231bdd3..76f7141 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -389,79 +389,6 @@
 
 #endif /* !CONFIG_DYNAMIC_FTRACE */
 
-/* Add a function return address to the trace stack on thread info.*/
-static int push_return_trace(unsigned long ret, unsigned long long time,
-				unsigned long func, int *depth)
-{
-	int index;
-
-	if (!current->ret_stack)
-		return -EBUSY;
-
-	/* The return trace stack is full */
-	if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
-		atomic_inc(&current->trace_overrun);
-		return -EBUSY;
-	}
-
-	index = ++current->curr_ret_stack;
-	barrier();
-	current->ret_stack[index].ret = ret;
-	current->ret_stack[index].func = func;
-	current->ret_stack[index].calltime = time;
-	*depth = index;
-
-	return 0;
-}
-
-/* Retrieve a function return address to the trace stack on thread info.*/
-static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
-{
-	int index;
-
-	index = current->curr_ret_stack;
-
-	if (unlikely(index < 0)) {
-		ftrace_graph_stop();
-		WARN_ON(1);
-		/* Might as well panic, otherwise we have no where to go */
-		*ret = (unsigned long)panic;
-		return;
-	}
-
-	*ret = current->ret_stack[index].ret;
-	trace->func = current->ret_stack[index].func;
-	trace->calltime = current->ret_stack[index].calltime;
-	trace->overrun = atomic_read(&current->trace_overrun);
-	trace->depth = index;
-	barrier();
-	current->curr_ret_stack--;
-
-}
-
-/*
- * Send the trace to the ring-buffer.
- * @return the original return address.
- */
-unsigned long ftrace_return_to_handler(void)
-{
-	struct ftrace_graph_ret trace;
-	unsigned long ret;
-
-	pop_return_trace(&trace, &ret);
-	trace.rettime = cpu_clock(raw_smp_processor_id());
-	ftrace_graph_return(&trace);
-
-	if (unlikely(!ret)) {
-		ftrace_graph_stop();
-		WARN_ON(1);
-		/* Might as well panic. What else to do? */
-		ret = (unsigned long)panic;
-	}
-
-	return ret;
-}
-
 /*
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
@@ -521,7 +448,7 @@
 
 	calltime = cpu_clock(raw_smp_processor_id());
 
-	if (push_return_trace(old, calltime,
+	if (ftrace_push_return_trace(old, calltime,
 				self_addr, &trace.depth) == -EBUSY) {
 		*parent = old;
 		return;
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index ac108d1..3f8579f 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -18,7 +18,7 @@
 {
 	reserve_trampoline_memory();
 
-	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
@@ -29,9 +29,6 @@
 		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
 	}
 #endif
-	reserve_early(init_pg_tables_start, init_pg_tables_end,
-			"INIT_PG_TABLE");
-
 	reserve_ebda_region();
 
 	/*
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index f5b2722..70eaa85 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -100,7 +100,7 @@
 
 	reserve_trampoline_memory();
 
-	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Reserve INITRD */
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index c32ca19..3068388 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -38,42 +38,40 @@
 #define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id
 
 /*
- * This is how much memory *in addition to the memory covered up to
- * and including _end* we need mapped initially.
+ * This is how much memory in addition to the memory covered up to
+ * and including _end we need mapped initially.
  * We need:
- *  - one bit for each possible page, but only in low memory, which means
- *     2^32/4096/8 = 128K worst case (4G/4G split.)
- *  - enough space to map all low memory, which means
- *     (2^32/4096) / 1024 pages (worst case, non PAE)
- *     (2^32/4096) / 512 + 4 pages (worst case for PAE)
- *  - a few pages for allocator use before the kernel pagetable has
- *     been set up
+ *     (KERNEL_IMAGE_SIZE/4096) / 1024 pages (worst case, non PAE)
+ *     (KERNEL_IMAGE_SIZE/4096) / 512 + 4 pages (worst case for PAE)
  *
  * Modulo rounding, each megabyte assigned here requires a kilobyte of
  * memory, which is currently unreclaimed.
  *
  * This should be a multiple of a page.
+ *
+ * KERNEL_IMAGE_SIZE should be greater than pa(_end)
+ * and small than max_low_pfn, otherwise will waste some page table entries
  */
-LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)
-
-/*
- * To preserve the DMA pool in PAGEALLOC kernels, we'll allocate
- * pagetables from above the 16MB DMA limit, so we'll have to set
- * up pagetables 16MB more (worst-case):
- */
-#ifdef CONFIG_DEBUG_PAGEALLOC
-LOW_PAGES = LOW_PAGES + 0x1000000
-#endif
 
 #if PTRS_PER_PMD > 1
-PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD
+#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
 #else
-PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD)
+#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
-BOOTBITMAP_SIZE = LOW_PAGES / 8
-ALLOCATOR_SLOP = 4
 
-INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm
+/* Enough space to fit pagetables for the low memory linear map */
+MAPPING_BEYOND_END = \
+	PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+
+/*
+ * Worst-case size of the kernel mapping we need to make:
+ * the worst-case size of the kernel itself, plus the extra we need
+ * to map for the linear map.
+ */
+KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+
+INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
+RESERVE_BRK(pagetables, INIT_MAP_SIZE)
 
 /*
  * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
@@ -166,10 +164,10 @@
 
 /*
  * Initialize page tables.  This creates a PDE and a set of page
- * tables, which are located immediately beyond _end.  The variable
- * init_pg_tables_end is set up to point to the first "safe" location.
+ * tables, which are located immediately beyond __brk_base.  The variable
+ * _brk_end is set up to point to the first "safe" location.
  * Mappings are created both at virtual address 0 (identity mapping)
- * and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END.
+ * and PAGE_OFFSET for up to _end.
  *
  * Note that the stack is not yet set up!
  */
@@ -190,8 +188,7 @@
 
 	xorl %ebx,%ebx				/* %ebx is kept at zero */
 
-	movl $pa(pg0), %edi
-	movl %edi, pa(init_pg_tables_start)
+	movl $pa(__brk_base), %edi
 	movl $pa(swapper_pg_pmd), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
@@ -209,14 +206,14 @@
 	loop 11b
 
 	/*
-	 * End condition: we must map up to and including INIT_MAP_BEYOND_END
-	 * bytes beyond the end of our own page tables.
+	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
 	 */
-	leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp
+	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
 	cmpl %ebp,%eax
 	jb 10b
 1:
-	movl %edi,pa(init_pg_tables_end)
+	addl $__PAGE_OFFSET, %edi
+	movl %edi, pa(_brk_end)
 	shrl $12, %eax
 	movl %eax, pa(max_pfn_mapped)
 
@@ -227,8 +224,7 @@
 
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
-	movl $pa(pg0), %edi
-	movl %edi, pa(init_pg_tables_start)
+	movl $pa(__brk_base), %edi
 	movl $pa(swapper_pg_dir), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
@@ -242,14 +238,13 @@
 	addl $0x1000,%eax
 	loop 11b
 	/*
-	 * End condition: we must map up to and including INIT_MAP_BEYOND_END
-	 * bytes beyond the end of our own page tables; the +0x007 is
-	 * the attribute bits
+	 * End condition: we must map up to the end + MAPPING_BEYOND_END.
 	 */
-	leal (INIT_MAP_BEYOND_END+PTE_IDENT_ATTR)(%edi),%ebp
+	movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
 	cmpl %ebp,%eax
 	jb 10b
-	movl %edi,pa(init_pg_tables_end)
+	addl $__PAGE_OFFSET, %edi
+	movl %edi, pa(_brk_end)
 	shrl $12, %eax
 	movl %eax, pa(max_pfn_mapped)
 
@@ -636,6 +631,7 @@
 	.fill 1024,4,0
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
+
 /*
  * This starts the data section.
  */
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index 10f92fb..3475440 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -3,17 +3,17 @@
  *
  */
 #include <linux/clockchips.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/spinlock.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
 
-#include <asm/smp.h>
-#include <asm/delay.h>
 #include <asm/i8253.h>
-#include <asm/io.h>
 #include <asm/hpet.h>
+#include <asm/smp.h>
 
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
@@ -40,7 +40,7 @@
 {
 	spin_lock(&i8253_lock);
 
-	switch(mode) {
+	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		/* binary, mode 2, LSB/MSB, ch 0 */
 		outb_pit(0x34, PIT_MODE);
@@ -95,7 +95,7 @@
  * registered. This mechanism replaces the previous #ifdef LOCAL_APIC -
  * !using_apic_timer decisions in do_timer_interrupt_hook()
  */
-static struct clock_event_device pit_clockevent = {
+static struct clock_event_device pit_ce = {
 	.name		= "pit",
 	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.set_mode	= init_pit_timer,
@@ -114,15 +114,13 @@
 	 * Start pit with the boot cpu mask and make it global after the
 	 * IO_APIC has been initialized.
 	 */
-	pit_clockevent.cpumask = cpumask_of(smp_processor_id());
-	pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
-				     pit_clockevent.shift);
-	pit_clockevent.max_delta_ns =
-		clockevent_delta2ns(0x7FFF, &pit_clockevent);
-	pit_clockevent.min_delta_ns =
-		clockevent_delta2ns(0xF, &pit_clockevent);
-	clockevents_register_device(&pit_clockevent);
-	global_clock_event = &pit_clockevent;
+	pit_ce.cpumask = cpumask_of(smp_processor_id());
+	pit_ce.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
+	pit_ce.max_delta_ns = clockevent_delta2ns(0x7FFF, &pit_ce);
+	pit_ce.min_delta_ns = clockevent_delta2ns(0xF, &pit_ce);
+
+	clockevents_register_device(&pit_ce);
+	global_clock_event = &pit_ce;
 }
 
 #ifndef CONFIG_X86_64
@@ -133,11 +131,11 @@
  */
 static cycle_t pit_read(void)
 {
+	static int old_count;
+	static u32 old_jifs;
 	unsigned long flags;
 	int count;
 	u32 jifs;
-	static int old_count;
-	static u32 old_jifs;
 
 	spin_lock_irqsave(&i8253_lock, flags);
 	/*
@@ -179,9 +177,9 @@
 	 * Previous attempts to handle these cases intelligently were
 	 * buggy, so we just do the simple thing now.
 	 */
-	if (count > old_count && jifs == old_jifs) {
+	if (count > old_count && jifs == old_jifs)
 		count = old_count;
-	}
+
 	old_count = count;
 	old_jifs = jifs;
 
@@ -192,13 +190,13 @@
 	return (cycle_t)(jifs * LATCH) + count;
 }
 
-static struct clocksource clocksource_pit = {
-	.name	= "pit",
-	.rating = 110,
-	.read	= pit_read,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.mult	= 0,
-	.shift	= 20,
+static struct clocksource pit_cs = {
+	.name		= "pit",
+	.rating		= 110,
+	.read		= pit_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.mult		= 0,
+	.shift		= 20,
 };
 
 static void pit_disable_clocksource(void)
@@ -206,9 +204,9 @@
 	/*
 	 * Use mult to check whether it is registered or not
 	 */
-	if (clocksource_pit.mult) {
-		clocksource_unregister(&clocksource_pit);
-		clocksource_pit.mult = 0;
+	if (pit_cs.mult) {
+		clocksource_unregister(&pit_cs);
+		pit_cs.mult = 0;
 	}
 }
 
@@ -222,13 +220,13 @@
 	  * - when local APIC timer is active (PIT is switched off)
 	  */
 	if (num_possible_cpus() > 1 || is_hpet_enabled() ||
-	    pit_clockevent.mode != CLOCK_EVT_MODE_PERIODIC)
+	    pit_ce.mode != CLOCK_EVT_MODE_PERIODIC)
 		return 0;
 
-	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
-						   clocksource_pit.shift);
-	return clocksource_register(&clocksource_pit);
+	pit_cs.mult = clocksource_hz2mult(CLOCK_TICK_RATE, pit_cs.shift);
+
+	return clocksource_register(&pit_cs);
 }
 arch_initcall(init_pit_clocksource);
 
-#endif
+#endif /* !CONFIG_X86_64 */
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
index 720d260..a979b5b 100644
--- a/arch/x86/kernel/io_delay.c
+++ b/arch/x86/kernel/io_delay.c
@@ -7,10 +7,10 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/dmi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE;
 
@@ -47,8 +47,7 @@
 static int __init dmi_io_delay_0xed_port(const struct dmi_system_id *id)
 {
 	if (io_delay_type == CONFIG_IO_DELAY_TYPE_0X80) {
-		printk(KERN_NOTICE "%s: using 0xed I/O delay port\n",
-			id->ident);
+		pr_notice("%s: using 0xed I/O delay port\n", id->ident);
 		io_delay_type = CONFIG_IO_DELAY_TYPE_0XED;
 	}
 
@@ -64,40 +63,40 @@
 		.callback	= dmi_io_delay_0xed_port,
 		.ident		= "Compaq Presario V6000",
 		.matches	= {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-			DMI_MATCH(DMI_BOARD_NAME, "30B7")
+			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME,	"30B7")
 		}
 	},
 	{
 		.callback	= dmi_io_delay_0xed_port,
 		.ident		= "HP Pavilion dv9000z",
 		.matches	= {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-			DMI_MATCH(DMI_BOARD_NAME, "30B9")
+			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME,	"30B9")
 		}
 	},
 	{
 		.callback	= dmi_io_delay_0xed_port,
 		.ident		= "HP Pavilion dv6000",
 		.matches	= {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-			DMI_MATCH(DMI_BOARD_NAME, "30B8")
+			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME,	"30B8")
 		}
 	},
 	{
 		.callback	= dmi_io_delay_0xed_port,
 		.ident		= "HP Pavilion tx1000",
 		.matches	= {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-			DMI_MATCH(DMI_BOARD_NAME, "30BF")
+			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME,	"30BF")
 		}
 	},
 	{
 		.callback	= dmi_io_delay_0xed_port,
 		.ident		= "Presario F700",
 		.matches	= {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
-			DMI_MATCH(DMI_BOARD_NAME, "30D3")
+			DMI_MATCH(DMI_BOARD_VENDOR,	"Quanta"),
+			DMI_MATCH(DMI_BOARD_NAME,	"30D3")
 		}
 	},
 	{ }
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index f13ca16..3aaf7b9 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -15,6 +15,9 @@
 
 atomic_t irq_err_count;
 
+/* Function pointer for generic interrupt vector handling */
+void (*generic_interrupt_extension)(void) = NULL;
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -42,55 +45,60 @@
 /*
  * /proc/interrupts printing:
  */
-static int show_other_interrupts(struct seq_file *p)
+static int show_other_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
-	seq_printf(p, "NMI: ");
+	seq_printf(p, "%*s: ", prec, "NMI");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
 	seq_printf(p, "  Non-maskable interrupts\n");
 #ifdef CONFIG_X86_LOCAL_APIC
-	seq_printf(p, "LOC: ");
+	seq_printf(p, "%*s: ", prec, "LOC");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
 	seq_printf(p, "  Local timer interrupts\n");
+
+	seq_printf(p, "%*s: ", prec, "SPU");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+	seq_printf(p, "  Spurious interrupts\n");
 #endif
+	if (generic_interrupt_extension) {
+		seq_printf(p, "PLT: ");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
+		seq_printf(p, "  Platform interrupts\n");
+	}
 #ifdef CONFIG_SMP
-	seq_printf(p, "RES: ");
+	seq_printf(p, "%*s: ", prec, "RES");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
 	seq_printf(p, "  Rescheduling interrupts\n");
-	seq_printf(p, "CAL: ");
+	seq_printf(p, "%*s: ", prec, "CAL");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
 	seq_printf(p, "  Function call interrupts\n");
-	seq_printf(p, "TLB: ");
+	seq_printf(p, "%*s: ", prec, "TLB");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
 	seq_printf(p, "  TLB shootdowns\n");
 #endif
 #ifdef CONFIG_X86_MCE
-	seq_printf(p, "TRM: ");
+	seq_printf(p, "%*s: ", prec, "TRM");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
 	seq_printf(p, "  Thermal event interrupts\n");
 # ifdef CONFIG_X86_64
-	seq_printf(p, "THR: ");
+	seq_printf(p, "%*s: ", prec, "THR");
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
 	seq_printf(p, "  Threshold APIC interrupts\n");
 # endif
 #endif
-#ifdef CONFIG_X86_LOCAL_APIC
-	seq_printf(p, "SPU: ");
-	for_each_online_cpu(j)
-		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
-	seq_printf(p, "  Spurious interrupts\n");
-#endif
-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
 #if defined(CONFIG_X86_IO_APIC)
-	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
 #endif
 	return 0;
 }
@@ -98,19 +106,22 @@
 int show_interrupts(struct seq_file *p, void *v)
 {
 	unsigned long flags, any_count = 0;
-	int i = *(loff_t *) v, j;
+	int i = *(loff_t *) v, j, prec;
 	struct irqaction *action;
 	struct irq_desc *desc;
 
 	if (i > nr_irqs)
 		return 0;
 
+	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
+		j *= 10;
+
 	if (i == nr_irqs)
-		return show_other_interrupts(p);
+		return show_other_interrupts(p, prec);
 
 	/* print header */
 	if (i == 0) {
-		seq_printf(p, "           ");
+		seq_printf(p, "%*s", prec + 8, "");
 		for_each_online_cpu(j)
 			seq_printf(p, "CPU%-8d", j);
 		seq_putc(p, '\n');
@@ -121,23 +132,15 @@
 		return 0;
 
 	spin_lock_irqsave(&desc->lock, flags);
-#ifndef CONFIG_SMP
-	any_count = kstat_irqs(i);
-#else
 	for_each_online_cpu(j)
 		any_count |= kstat_irqs_cpu(i, j);
-#endif
 	action = desc->action;
 	if (!action && !any_count)
 		goto out;
 
-	seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-	seq_printf(p, "%10u ", kstat_irqs(i));
-#else
+	seq_printf(p, "%*d: ", prec, i);
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
 	seq_printf(p, " %8s", desc->chip->name);
 	seq_printf(p, "-%-8s", desc->name);
 
@@ -162,7 +165,10 @@
 
 #ifdef CONFIG_X86_LOCAL_APIC
 	sum += irq_stats(cpu)->apic_timer_irqs;
+	sum += irq_stats(cpu)->irq_spurious_count;
 #endif
+	if (generic_interrupt_extension)
+		sum += irq_stats(cpu)->generic_irqs;
 #ifdef CONFIG_SMP
 	sum += irq_stats(cpu)->irq_resched_count;
 	sum += irq_stats(cpu)->irq_call_count;
@@ -174,9 +180,6 @@
 	sum += irq_stats(cpu)->irq_threshold_count;
 #endif
 #endif
-#ifdef CONFIG_X86_LOCAL_APIC
-	sum += irq_stats(cpu)->irq_spurious_count;
-#endif
 	return sum;
 }
 
@@ -226,4 +229,27 @@
 	return 1;
 }
 
+/*
+ * Handler for GENERIC_INTERRUPT_VECTOR.
+ */
+void smp_generic_interrupt(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	ack_APIC_irq();
+
+	exit_idle();
+
+	irq_enter();
+
+	inc_irq_stat(generic_irqs);
+
+	if (generic_interrupt_extension)
+		generic_interrupt_extension();
+
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index 50b8c3a..bc13261 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -175,6 +175,9 @@
 	/* self generated IPI for local APIC timer */
 	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
+	/* generic IPI for platform specific use */
+	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
+
 	/* IPI vectors for APIC spurious and error interrupts */
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
index da481a1..c7a49e0 100644
--- a/arch/x86/kernel/irqinit_64.c
+++ b/arch/x86/kernel/irqinit_64.c
@@ -147,6 +147,9 @@
 	/* self generated IPI for local APIC timer */
 	alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
+	/* generic IPI for platform specific use */
+	alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
+
 	/* IPI vectors for APIC spurious and error interrupts */
 	alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index ff7d3b0..e444357 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -8,11 +8,11 @@
  */
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
-#include <linux/stat.h>
+#include <linux/module.h>
 #include <linux/init.h>
+#include <linux/stat.h>
 #include <linux/io.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 
 #include <asm/setup.h>
 
@@ -26,9 +26,8 @@
 	u32 len;
 };
 
-static ssize_t
-setup_data_read(struct file *file, char __user *user_buf, size_t count,
-		loff_t *ppos)
+static ssize_t setup_data_read(struct file *file, char __user *user_buf,
+			       size_t count, loff_t *ppos)
 {
 	struct setup_data_node *node = file->private_data;
 	unsigned long remain;
@@ -39,20 +38,21 @@
 
 	if (pos < 0)
 		return -EINVAL;
+
 	if (pos >= node->len)
 		return 0;
 
 	if (count > node->len - pos)
 		count = node->len - pos;
+
 	pa = node->paddr + sizeof(struct setup_data) + pos;
 	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
 	if (PageHighMem(pg)) {
 		p = ioremap_cache(pa, count);
 		if (!p)
 			return -ENXIO;
-	} else {
+	} else
 		p = __va(pa);
-	}
 
 	remain = copy_to_user(user_buf, p, count);
 
@@ -70,12 +70,13 @@
 static int setup_data_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
+
 	return 0;
 }
 
 static const struct file_operations fops_setup_data = {
-	.read =		setup_data_read,
-	.open =		setup_data_open,
+	.read		= setup_data_read,
+	.open		= setup_data_open,
 };
 
 static int __init
@@ -84,57 +85,50 @@
 {
 	struct dentry *d, *type, *data;
 	char buf[16];
-	int error;
 
 	sprintf(buf, "%d", no);
 	d = debugfs_create_dir(buf, parent);
-	if (!d) {
-		error = -ENOMEM;
-		goto err_return;
-	}
+	if (!d)
+		return -ENOMEM;
+
 	type = debugfs_create_x32("type", S_IRUGO, d, &node->type);
-	if (!type) {
-		error = -ENOMEM;
+	if (!type)
 		goto err_dir;
-	}
+
 	data = debugfs_create_file("data", S_IRUGO, d, node, &fops_setup_data);
-	if (!data) {
-		error = -ENOMEM;
+	if (!data)
 		goto err_type;
-	}
+
 	return 0;
 
 err_type:
 	debugfs_remove(type);
 err_dir:
 	debugfs_remove(d);
-err_return:
-	return error;
+	return -ENOMEM;
 }
 
 static int __init create_setup_data_nodes(struct dentry *parent)
 {
 	struct setup_data_node *node;
 	struct setup_data *data;
-	int error, no = 0;
+	int error = -ENOMEM;
 	struct dentry *d;
 	struct page *pg;
 	u64 pa_data;
+	int no = 0;
 
 	d = debugfs_create_dir("setup_data", parent);
-	if (!d) {
-		error = -ENOMEM;
-		goto err_return;
-	}
+	if (!d)
+		return -ENOMEM;
 
 	pa_data = boot_params.hdr.setup_data;
 
 	while (pa_data) {
 		node = kmalloc(sizeof(*node), GFP_KERNEL);
-		if (!node) {
-			error = -ENOMEM;
+		if (!node)
 			goto err_dir;
-		}
+
 		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
 		if (PageHighMem(pg)) {
 			data = ioremap_cache(pa_data, sizeof(*data));
@@ -143,9 +137,8 @@
 				error = -ENXIO;
 				goto err_dir;
 			}
-		} else {
+		} else
 			data = __va(pa_data);
-		}
 
 		node->paddr = pa_data;
 		node->type = data->type;
@@ -159,11 +152,11 @@
 			goto err_dir;
 		no++;
 	}
+
 	return 0;
 
 err_dir:
 	debugfs_remove(d);
-err_return:
 	return error;
 }
 
@@ -175,28 +168,26 @@
 static int __init boot_params_kdebugfs_init(void)
 {
 	struct dentry *dbp, *version, *data;
-	int error;
+	int error = -ENOMEM;
 
 	dbp = debugfs_create_dir("boot_params", NULL);
-	if (!dbp) {
-		error = -ENOMEM;
-		goto err_return;
-	}
+	if (!dbp)
+		return -ENOMEM;
+
 	version = debugfs_create_x16("version", S_IRUGO, dbp,
 				     &boot_params.hdr.version);
-	if (!version) {
-		error = -ENOMEM;
+	if (!version)
 		goto err_dir;
-	}
+
 	data = debugfs_create_blob("data", S_IRUGO, dbp,
 				   &boot_params_blob);
-	if (!data) {
-		error = -ENOMEM;
+	if (!data)
 		goto err_version;
-	}
+
 	error = create_setup_data_nodes(dbp);
 	if (error)
 		goto err_data;
+
 	return 0;
 
 err_data:
@@ -205,10 +196,9 @@
 	debugfs_remove(version);
 err_dir:
 	debugfs_remove(dbp);
-err_return:
 	return error;
 }
-#endif
+#endif /* CONFIG_DEBUG_BOOT_PARAMS */
 
 static int __init arch_kdebugfs_init(void)
 {
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 4558dd3..55b9461 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -193,7 +193,7 @@
 	kprobe_opcode_t opcode;
 	kprobe_opcode_t *orig_opcodes = opcodes;
 
-	if (search_exception_tables(opcodes))
+	if (search_exception_tables((unsigned long)opcodes))
 		return 0;	/* Page fault may occur on this address. */
 
 retry:
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 478bca9..33019dd 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -138,12 +138,6 @@
 	kvm_mmu_write(ptep, pte_val(pte));
 }
 
-static void kvm_set_pte_present(struct mm_struct *mm, unsigned long addr,
-				pte_t *ptep, pte_t pte)
-{
-	kvm_mmu_write(ptep, pte_val(pte));
-}
-
 static void kvm_pte_clear(struct mm_struct *mm,
 			  unsigned long addr, pte_t *ptep)
 {
@@ -220,7 +214,6 @@
 #if PAGETABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
 		pv_mmu_ops.set_pte_atomic = kvm_set_pte_atomic;
-		pv_mmu_ops.set_pte_present = kvm_set_pte_present;
 		pv_mmu_ops.pte_clear = kvm_pte_clear;
 		pv_mmu_ops.pmd_clear = kvm_pmd_clear;
 #endif
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index f5fc8c7..e7368c1 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -14,12 +14,12 @@
 #include <linux/ftrace.h>
 #include <linux/suspend.h>
 #include <linux/gfp.h>
+#include <linux/io.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
-#include <asm/io.h>
 #include <asm/apic.h>
 #include <asm/cpufeature.h>
 #include <asm/desc.h>
@@ -63,7 +63,7 @@
 		"\tmovl %%eax,%%fs\n"
 		"\tmovl %%eax,%%gs\n"
 		"\tmovl %%eax,%%ss\n"
-		::: "eax", "memory");
+		: : : "eax", "memory");
 #undef STR
 #undef __STR
 }
@@ -205,7 +205,8 @@
 
 	if (image->preserve_context) {
 #ifdef CONFIG_X86_IO_APIC
-		/* We need to put APICs in legacy mode so that we can
+		/*
+		 * We need to put APICs in legacy mode so that we can
 		 * get timer interrupts in second kernel. kexec/kdump
 		 * paths already have calls to disable_IO_APIC() in
 		 * one form or other. kexec jump path also need
@@ -227,7 +228,8 @@
 		page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
 						<< PAGE_SHIFT);
 
-	/* The segment registers are funny things, they have both a
+	/*
+	 * The segment registers are funny things, they have both a
 	 * visible and an invisible part.  Whenever the visible part is
 	 * set to a specific selector, the invisible part is loaded
 	 * with from a table in memory.  At no other time is the
@@ -237,11 +239,12 @@
 	 * segments, before I zap the gdt with an invalid value.
 	 */
 	load_segments();
-	/* The gdt & idt are now invalid.
+	/*
+	 * The gdt & idt are now invalid.
 	 * If you want to load them you must set up your own idt & gdt.
 	 */
-	set_gdt(phys_to_virt(0),0);
-	set_idt(phys_to_virt(0),0);
+	set_gdt(phys_to_virt(0), 0);
+	set_idt(phys_to_virt(0), 0);
 
 	/* now call it */
 	image->start = relocate_kernel_ptr((unsigned long)image->head,
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 6993d51..89cea4d 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -12,11 +12,47 @@
 #include <linux/reboot.h>
 #include <linux/numa.h>
 #include <linux/ftrace.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
-#include <asm/io.h>
+
+static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
+				unsigned long addr)
+{
+	pud_t *pud;
+	pmd_t *pmd;
+	struct page *page;
+	int result = -ENOMEM;
+
+	addr &= PMD_MASK;
+	pgd += pgd_index(addr);
+	if (!pgd_present(*pgd)) {
+		page = kimage_alloc_control_pages(image, 0);
+		if (!page)
+			goto out;
+		pud = (pud_t *)page_address(page);
+		memset(pud, 0, PAGE_SIZE);
+		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
+	}
+	pud = pud_offset(pgd, addr);
+	if (!pud_present(*pud)) {
+		page = kimage_alloc_control_pages(image, 0);
+		if (!page)
+			goto out;
+		pmd = (pmd_t *)page_address(page);
+		memset(pmd, 0, PAGE_SIZE);
+		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+	}
+	pmd = pmd_offset(pud, addr);
+	if (!pmd_present(*pmd))
+		set_pmd(pmd, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
+	result = 0;
+out:
+	return result;
+}
 
 static void init_level2_page(pmd_t *level2p, unsigned long addr)
 {
@@ -83,9 +119,8 @@
 		}
 		level3p = (pud_t *)page_address(page);
 		result = init_level3_page(image, level3p, addr, last_addr);
-		if (result) {
+		if (result)
 			goto out;
-		}
 		set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE));
 		addr += PGDIR_SIZE;
 	}
@@ -156,6 +191,13 @@
 	result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
 	if (result)
 		return result;
+	/*
+	 * image->start may be outside 0 ~ max_pfn, for example when
+	 * jump back to original kernel from kexeced kernel
+	 */
+	result = init_one_level2_page(image, level4p, image->start);
+	if (result)
+		return result;
 	return init_transition_pgtable(image, level4p);
 }
 
@@ -229,20 +271,45 @@
 {
 	unsigned long page_list[PAGES_NR];
 	void *control_page;
+	int save_ftrace_enabled;
 
-	tracer_disable();
+#ifdef CONFIG_KEXEC_JUMP
+	if (kexec_image->preserve_context)
+		save_processor_state();
+#endif
+
+	save_ftrace_enabled = __ftrace_enabled_save();
 
 	/* Interrupts aren't acceptable while we reboot */
 	local_irq_disable();
 
+	if (image->preserve_context) {
+#ifdef CONFIG_X86_IO_APIC
+		/*
+		 * We need to put APICs in legacy mode so that we can
+		 * get timer interrupts in second kernel. kexec/kdump
+		 * paths already have calls to disable_IO_APIC() in
+		 * one form or other. kexec jump path also need
+		 * one.
+		 */
+		disable_IO_APIC();
+#endif
+	}
+
 	control_page = page_address(image->control_code_page) + PAGE_SIZE;
-	memcpy(control_page, relocate_kernel, PAGE_SIZE);
+	memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE);
 
 	page_list[PA_CONTROL_PAGE] = virt_to_phys(control_page);
+	page_list[VA_CONTROL_PAGE] = (unsigned long)control_page;
 	page_list[PA_TABLE_PAGE] =
 	  (unsigned long)__pa(page_address(image->control_code_page));
 
-	/* The segment registers are funny things, they have both a
+	if (image->type == KEXEC_TYPE_DEFAULT)
+		page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
+						<< PAGE_SHIFT);
+
+	/*
+	 * The segment registers are funny things, they have both a
 	 * visible and an invisible part.  Whenever the visible part is
 	 * set to a specific selector, the invisible part is loaded
 	 * with from a table in memory.  At no other time is the
@@ -252,15 +319,25 @@
 	 * segments, before I zap the gdt with an invalid value.
 	 */
 	load_segments();
-	/* The gdt & idt are now invalid.
+	/*
+	 * The gdt & idt are now invalid.
 	 * If you want to load them you must set up your own idt & gdt.
 	 */
-	set_gdt(phys_to_virt(0),0);
-	set_idt(phys_to_virt(0),0);
+	set_gdt(phys_to_virt(0), 0);
+	set_idt(phys_to_virt(0), 0);
 
 	/* now call it */
-	relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
-			image->start);
+	image->start = relocate_kernel((unsigned long)image->head,
+				       (unsigned long)page_list,
+				       image->start,
+				       image->preserve_context);
+
+#ifdef CONFIG_KEXEC_JUMP
+	if (kexec_image->preserve_context)
+		restore_processor_state();
+#endif
+
+	__ftrace_enabled_restore(save_ftrace_enabled);
 }
 
 void arch_crash_save_vmcoreinfo(void)
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
index 666e43d..712d15f 100644
--- a/arch/x86/kernel/mmconf-fam10h_64.c
+++ b/arch/x86/kernel/mmconf-fam10h_64.c
@@ -226,7 +226,7 @@
         return 0;
 }
 
-static struct dmi_system_id __devinitdata mmconf_dmi_table[] = {
+static const struct dmi_system_id __cpuinitconst mmconf_dmi_table[] = {
         {
                 .callback = set_check_enable_amd_mmconf,
                 .ident = "Sun Microsystems Machine",
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 37cb1bd..dce99dc 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -109,9 +109,6 @@
 	} else
 		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
 }
-#endif
-
-#ifdef CONFIG_X86_IO_APIC
 
 static int bad_ioapic(unsigned long address)
 {
@@ -224,8 +221,12 @@
 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
 		panic("Max # of irq sources exceeded!!\n");
 }
+#else /* CONFIG_X86_IO_APIC */
+static inline void __init MP_bus_info(struct mpc_bus *m) {}
+static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
+static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
+#endif /* CONFIG_X86_IO_APIC */
 
-#endif
 
 static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
 {
@@ -275,6 +276,20 @@
 	return 1;
 }
 
+static void skip_entry(unsigned char **ptr, int *count, int size)
+{
+	*ptr += size;
+	*count += size;
+}
+
+static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
+{
+	printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
+		"type %x\n", *mpt);
+	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+			1, mpc, mpc->length, 1);
+}
+
 static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
 {
 	char str[16];
@@ -310,61 +325,30 @@
 	while (count < mpc->length) {
 		switch (*mpt) {
 		case MP_PROCESSOR:
-			{
-				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
-				/* ACPI may have already provided this data */
-				if (!acpi_lapic)
-					MP_processor_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			/* ACPI may have already provided this data */
+			if (!acpi_lapic)
+				MP_processor_info((struct mpc_cpu *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
+			break;
 		case MP_BUS:
-			{
-				struct mpc_bus *m = (struct mpc_bus *)mpt;
-#ifdef CONFIG_X86_IO_APIC
-				MP_bus_info(m);
-#endif
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			MP_bus_info((struct mpc_bus *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
+			break;
 		case MP_IOAPIC:
-			{
-#ifdef CONFIG_X86_IO_APIC
-				struct mpc_ioapic *m = (struct mpc_ioapic *)mpt;
-				MP_ioapic_info(m);
-#endif
-				mpt += sizeof(struct mpc_ioapic);
-				count += sizeof(struct mpc_ioapic);
-				break;
-			}
+			MP_ioapic_info((struct mpc_ioapic *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
+			break;
 		case MP_INTSRC:
-			{
-#ifdef CONFIG_X86_IO_APIC
-				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
-
-				MP_intsrc_info(m);
-#endif
-				mpt += sizeof(struct mpc_intsrc);
-				count += sizeof(struct mpc_intsrc);
-				break;
-			}
+			MP_intsrc_info((struct mpc_intsrc *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
+			break;
 		case MP_LINTSRC:
-			{
-				struct mpc_lintsrc *m =
-				    (struct mpc_lintsrc *)mpt;
-				MP_lintsrc_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			MP_lintsrc_info((struct mpc_lintsrc *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
+			break;
 		default:
 			/* wrong mptable */
-			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
-			printk(KERN_ERR "type %x\n", *mpt);
-			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
-					1, mpc, mpc->length, 1);
+			smp_dump_mptable(mpc, mpt);
 			count = mpc->length;
 			break;
 		}
@@ -558,6 +542,68 @@
 
 static struct mpf_intel *mpf_found;
 
+static unsigned long __init get_mpc_size(unsigned long physptr)
+{
+	struct mpc_table *mpc;
+	unsigned long size;
+
+	mpc = early_ioremap(physptr, PAGE_SIZE);
+	size = mpc->length;
+	early_iounmap(mpc, PAGE_SIZE);
+	apic_printk(APIC_VERBOSE, "  mpc: %lx-%lx\n", physptr, physptr + size);
+
+	return size;
+}
+
+static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
+{
+	struct mpc_table *mpc;
+	unsigned long size;
+
+	size = get_mpc_size(mpf->physptr);
+	mpc = early_ioremap(mpf->physptr, size);
+	/*
+	 * Read the physical hardware table.  Anything here will
+	 * override the defaults.
+	 */
+	if (!smp_read_mpc(mpc, early)) {
+#ifdef CONFIG_X86_LOCAL_APIC
+		smp_found_config = 0;
+#endif
+		printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
+			"... disabling SMP support. (tell your hw vendor)\n");
+		early_iounmap(mpc, size);
+		return -1;
+	}
+	early_iounmap(mpc, size);
+
+	if (early)
+		return -1;
+
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * If there are no explicit MP IRQ entries, then we are
+	 * broken.  We set up most of the low 16 IO-APIC pins to
+	 * ISA defaults and hope it will work.
+	 */
+	if (!mp_irq_entries) {
+		struct mpc_bus bus;
+
+		printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
+		       "using default mptable. (tell your hw vendor)\n");
+
+		bus.type = MP_BUS;
+		bus.busid = 0;
+		memcpy(bus.bustype, "ISA   ", 6);
+		MP_bus_info(&bus);
+
+		construct_default_ioirq_mptable(0);
+	}
+#endif
+
+	return 0;
+}
+
 /*
  * Scan the memory blocks for an SMP configuration block.
  */
@@ -611,45 +657,8 @@
 		construct_default_ISA_mptable(mpf->feature1);
 
 	} else if (mpf->physptr) {
-
-		/*
-		 * Read the physical hardware table.  Anything here will
-		 * override the defaults.
-		 */
-		if (!smp_read_mpc(phys_to_virt(mpf->physptr), early)) {
-#ifdef CONFIG_X86_LOCAL_APIC
-			smp_found_config = 0;
-#endif
-			printk(KERN_ERR
-			       "BIOS bug, MP table errors detected!...\n");
-			printk(KERN_ERR "... disabling SMP support. "
-			       "(tell your hw vendor)\n");
+		if (check_physptr(mpf, early))
 			return;
-		}
-
-		if (early)
-			return;
-#ifdef CONFIG_X86_IO_APIC
-		/*
-		 * If there are no explicit MP IRQ entries, then we are
-		 * broken.  We set up most of the low 16 IO-APIC pins to
-		 * ISA defaults and hope it will work.
-		 */
-		if (!mp_irq_entries) {
-			struct mpc_bus bus;
-
-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
-			       "using default mptable. "
-			       "(tell your hw vendor)\n");
-
-			bus.type = MP_BUS;
-			bus.busid = 0;
-			memcpy(bus.bustype, "ISA   ", 6);
-			MP_bus_info(&bus);
-
-			construct_default_ioirq_mptable(0);
-		}
-#endif
 	} else
 		BUG();
 
@@ -670,6 +679,31 @@
 	__get_smp_config(0);
 }
 
+static void smp_reserve_bootmem(struct mpf_intel *mpf)
+{
+	unsigned long size = get_mpc_size(mpf->physptr);
+#ifdef CONFIG_X86_32
+	/*
+	 * We cannot access to MPC table to compute table size yet,
+	 * as only few megabytes from the bottom is mapped now.
+	 * PC-9800's MPC table places on the very last of physical
+	 * memory; so that simply reserving PAGE_SIZE from mpf->physptr
+	 * yields BUG() in reserve_bootmem.
+	 * also need to make sure physptr is below than max_low_pfn
+	 * we don't need reserve the area above max_low_pfn
+	 */
+	unsigned long end = max_low_pfn * PAGE_SIZE;
+
+	if (mpf->physptr < end) {
+		if (mpf->physptr + size > end)
+			size = end - mpf->physptr;
+		reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
+	}
+#else
+	reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
+#endif
+}
+
 static int __init smp_scan_config(unsigned long base, unsigned long length,
 				  unsigned reserve)
 {
@@ -697,36 +731,10 @@
 
 			if (!reserve)
 				return 1;
-			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE,
-					BOOTMEM_DEFAULT);
-			if (mpf->physptr) {
-				unsigned long size = PAGE_SIZE;
-#ifdef CONFIG_X86_32
-				/*
-				 * We cannot access to MPC table to compute
-				 * table size yet, as only few megabytes from
-				 * the bottom is mapped now.
-				 * PC-9800's MPC table places on the very last
-				 * of physical memory; so that simply reserving
-				 * PAGE_SIZE from mpf->physptr yields BUG()
-				 * in reserve_bootmem.
-				 * also need to make sure physptr is below than
-				 * max_low_pfn
-				 * we don't need reserve the area above max_low_pfn
-				 */
-				unsigned long end = max_low_pfn * PAGE_SIZE;
-
-				if (mpf->physptr < end) {
-					if (mpf->physptr + size > end)
-						size = end - mpf->physptr;
-					reserve_bootmem_generic(mpf->physptr, size,
-							BOOTMEM_DEFAULT);
-				}
-#else
-				reserve_bootmem_generic(mpf->physptr, size,
+			reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf),
 						BOOTMEM_DEFAULT);
-#endif
-			}
+			if (mpf->physptr)
+				smp_reserve_bootmem(mpf);
 
 			return 1;
 		}
@@ -829,7 +837,57 @@
 #define SPARE_SLOT_NUM 20
 
 static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
-#endif
+
+static void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
+{
+	int i;
+
+	apic_printk(APIC_VERBOSE, "OLD ");
+	print_MP_intsrc_info(m);
+
+	i = get_MP_intsrc_index(m);
+	if (i > 0) {
+		assign_to_mpc_intsrc(&mp_irqs[i], m);
+		apic_printk(APIC_VERBOSE, "NEW ");
+		print_mp_irq_info(&mp_irqs[i]);
+		return;
+	}
+	if (!i) {
+		/* legacy, do nothing */
+		return;
+	}
+	if (*nr_m_spare < SPARE_SLOT_NUM) {
+		/*
+		 * not found (-1), or duplicated (-2) are invalid entries,
+		 * we need to use the slot later
+		 */
+		m_spare[*nr_m_spare] = m;
+		*nr_m_spare += 1;
+	}
+}
+#else /* CONFIG_X86_IO_APIC */
+static inline void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
+#endif /* CONFIG_X86_IO_APIC */
+
+static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
+		      int count)
+{
+	if (!mpc_new_phys) {
+		pr_info("No spare slots, try to append...take your risk, "
+			"new mpc_length %x\n", count);
+	} else {
+		if (count <= mpc_new_length)
+			pr_info("No spare slots, try to append..., "
+				"new mpc_length %x\n", count);
+		else {
+			pr_err("mpc_new_length %lx is too small\n",
+				mpc_new_length);
+			return -1;
+		}
+	}
+
+	return 0;
+}
 
 static int  __init replace_intsrc_all(struct mpc_table *mpc,
 					unsigned long mpc_new_phys,
@@ -837,77 +895,33 @@
 {
 #ifdef CONFIG_X86_IO_APIC
 	int i;
-	int nr_m_spare = 0;
 #endif
-
 	int count = sizeof(*mpc);
+	int nr_m_spare = 0;
 	unsigned char *mpt = ((unsigned char *)mpc) + count;
 
 	printk(KERN_INFO "mpc_length %x\n", mpc->length);
 	while (count < mpc->length) {
 		switch (*mpt) {
 		case MP_PROCESSOR:
-			{
-				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
+			break;
 		case MP_BUS:
-			{
-				struct mpc_bus *m = (struct mpc_bus *)mpt;
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
+			break;
 		case MP_IOAPIC:
-			{
-				mpt += sizeof(struct mpc_ioapic);
-				count += sizeof(struct mpc_ioapic);
-				break;
-			}
+			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
+			break;
 		case MP_INTSRC:
-			{
-#ifdef CONFIG_X86_IO_APIC
-				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
-
-				printk(KERN_INFO "OLD ");
-				print_MP_intsrc_info(m);
-				i = get_MP_intsrc_index(m);
-				if (i > 0) {
-					assign_to_mpc_intsrc(&mp_irqs[i], m);
-					printk(KERN_INFO "NEW ");
-					print_mp_irq_info(&mp_irqs[i]);
-				} else if (!i) {
-					/* legacy, do nothing */
-				} else if (nr_m_spare < SPARE_SLOT_NUM) {
-					/*
-					 * not found (-1), or duplicated (-2)
-					 * are invalid entries,
-					 * we need to use the slot  later
-					 */
-					m_spare[nr_m_spare] = m;
-					nr_m_spare++;
-				}
-#endif
-				mpt += sizeof(struct mpc_intsrc);
-				count += sizeof(struct mpc_intsrc);
-				break;
-			}
+			check_irq_src((struct mpc_intsrc *)mpt, &nr_m_spare);
+			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
+			break;
 		case MP_LINTSRC:
-			{
-				struct mpc_lintsrc *m =
-				    (struct mpc_lintsrc *)mpt;
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
+			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
+			break;
 		default:
 			/* wrong mptable */
-			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
-			printk(KERN_ERR "type %x\n", *mpt);
-			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
-					1, mpc, mpc->length, 1);
+			smp_dump_mptable(mpc, mpt);
 			goto out;
 		}
 	}
@@ -924,23 +938,15 @@
 			continue;
 
 		if (nr_m_spare > 0) {
-			printk(KERN_INFO "*NEW* found ");
+			apic_printk(APIC_VERBOSE, "*NEW* found\n");
 			nr_m_spare--;
 			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
 			m_spare[nr_m_spare] = NULL;
 		} else {
 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
 			count += sizeof(struct mpc_intsrc);
-			if (!mpc_new_phys) {
-				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
-			} else {
-				if (count <= mpc_new_length)
-					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
-				else {
-					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
-					goto out;
-				}
-			}
+			if (!check_slot(mpc_new_phys, mpc_new_length, count))
+				goto out;
 			assign_to_mpc_intsrc(&mp_irqs[i], m);
 			mpc->length = count;
 			mpt += sizeof(struct mpc_intsrc);
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 63dd358..8e45f44 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -470,7 +470,6 @@
 #if PAGETABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
 	.set_pte_atomic = native_set_pte_atomic,
-	.set_pte_present = native_set_pte_present,
 	.pte_clear = native_pte_clear,
 	.pmd_clear = native_pmd_clear,
 #endif
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index fe50214..c6d703b 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -1,14 +1,14 @@
 /* Fallback functions when the main IOMMU code is not compiled in. This
    code is roughly equivalent to i386. */
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/string.h>
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
 
-#include <asm/iommu.h>
 #include <asm/processor.h>
+#include <asm/iommu.h>
 #include <asm/dma.h>
 
 static int
@@ -80,11 +80,11 @@
 }
 
 struct dma_map_ops nommu_dma_ops = {
-	.alloc_coherent = dma_generic_alloc_coherent,
-	.free_coherent = nommu_free_coherent,
-	.map_sg = nommu_map_sg,
-	.map_page = nommu_map_page,
-	.is_phys = 1,
+	.alloc_coherent	= dma_generic_alloc_coherent,
+	.free_coherent	= nommu_free_coherent,
+	.map_sg		= nommu_map_sg,
+	.map_page	= nommu_map_page,
+	.is_phys	= 1,
 };
 
 void __init no_iommu_init(void)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 6afa523..156f875 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -65,11 +65,11 @@
 {
 	struct task_struct *me = current;
 	struct thread_struct *t = &me->thread;
+	unsigned long *bp = t->io_bitmap_ptr;
 
-	if (me->thread.io_bitmap_ptr) {
+	if (bp) {
 		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
 
-		kfree(t->io_bitmap_ptr);
 		t->io_bitmap_ptr = NULL;
 		clear_thread_flag(TIF_IO_BITMAP);
 		/*
@@ -78,6 +78,7 @@
 		memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
 		t->io_bitmap_max = 0;
 		put_cpu();
+		kfree(bp);
 	}
 
 	ds_exit_thread(current);
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 3d9672e..1937871 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -685,9 +685,8 @@
 		if (!cfg.signal)
 			return -EINVAL;
 
-		return -EOPNOTSUPP;
-
 		child->thread.bts_ovfl_signal = cfg.signal;
+		return -EOPNOTSUPP;
 	}
 
 	if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 697d1b7..e95022e 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -74,8 +74,7 @@
 	if (!force_hpet_address)
 		return;
 
-	if (rcba_base == NULL)
-		BUG();
+	BUG_ON(rcba_base == NULL);
 
 	/* read the Function Disable register, dword mode only */
 	val = readl(rcba_base + 0x3404);
diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
index 2064d0a..4123553 100644
--- a/arch/x86/kernel/relocate_kernel_32.S
+++ b/arch/x86/kernel/relocate_kernel_32.S
@@ -17,7 +17,8 @@
 
 #define PTR(x) (x << 2)
 
-/* control_page + KEXEC_CONTROL_CODE_MAX_SIZE
+/*
+ * control_page + KEXEC_CONTROL_CODE_MAX_SIZE
  * ~ control_page + PAGE_SIZE are used as data storage and stack for
  * jumping back
  */
@@ -76,8 +77,10 @@
 	movl	%eax, CP_PA_SWAP_PAGE(%edi)
 	movl	%ebx, CP_PA_BACKUP_PAGES_MAP(%edi)
 
-	/* get physical address of control page now */
-	/* this is impossible after page table switch */
+	/*
+	 * get physical address of control page now
+	 * this is impossible after page table switch
+	 */
 	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edi
 
 	/* switch to new set of page tables */
@@ -97,7 +100,8 @@
 	/* store the start address on the stack */
 	pushl   %edx
 
-	/* Set cr0 to a known state:
+	/*
+	 * Set cr0 to a known state:
 	 *  - Paging disabled
 	 *  - Alignment check disabled
 	 *  - Write protect disabled
@@ -113,7 +117,8 @@
 	/* clear cr4 if applicable */
 	testl	%ecx, %ecx
 	jz	1f
-	/* Set cr4 to a known state:
+	/*
+	 * Set cr4 to a known state:
 	 * Setting everything to zero seems safe.
 	 */
 	xorl	%eax, %eax
@@ -132,15 +137,18 @@
 	call	swap_pages
 	addl	$8, %esp
 
-	/* To be certain of avoiding problems with self-modifying code
+	/*
+	 * To be certain of avoiding problems with self-modifying code
 	 * I need to execute a serializing instruction here.
 	 * So I flush the TLB, it's handy, and not processor dependent.
 	 */
 	xorl	%eax, %eax
 	movl	%eax, %cr3
 
-	/* set all of the registers to known values */
-	/* leave %esp alone */
+	/*
+	 * set all of the registers to known values
+	 * leave %esp alone
+	 */
 
 	testl	%esi, %esi
 	jnz 1f
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index d32cfb2..4de8f5b 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -19,29 +19,77 @@
 #define PTR(x) (x << 3)
 #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 
+/*
+ * control_page + KEXEC_CONTROL_CODE_MAX_SIZE
+ * ~ control_page + PAGE_SIZE are used as data storage and stack for
+ * jumping back
+ */
+#define DATA(offset)		(KEXEC_CONTROL_CODE_MAX_SIZE+(offset))
+
+/* Minimal CPU state */
+#define RSP			DATA(0x0)
+#define CR0			DATA(0x8)
+#define CR3			DATA(0x10)
+#define CR4			DATA(0x18)
+
+/* other data */
+#define CP_PA_TABLE_PAGE	DATA(0x20)
+#define CP_PA_SWAP_PAGE		DATA(0x28)
+#define CP_PA_BACKUP_PAGES_MAP	DATA(0x30)
+
 	.text
 	.align PAGE_SIZE
 	.code64
 	.globl relocate_kernel
 relocate_kernel:
-	/* %rdi indirection_page
+	/*
+	 * %rdi indirection_page
 	 * %rsi page_list
 	 * %rdx start address
+	 * %rcx preserve_context
 	 */
 
+	/* Save the CPU context, used for jumping back */
+	pushq %rbx
+	pushq %rbp
+	pushq %r12
+	pushq %r13
+	pushq %r14
+	pushq %r15
+	pushf
+
+	movq	PTR(VA_CONTROL_PAGE)(%rsi), %r11
+	movq	%rsp, RSP(%r11)
+	movq	%cr0, %rax
+	movq	%rax, CR0(%r11)
+	movq	%cr3, %rax
+	movq	%rax, CR3(%r11)
+	movq	%cr4, %rax
+	movq	%rax, CR4(%r11)
+
 	/* zero out flags, and disable interrupts */
 	pushq $0
 	popfq
 
-	/* get physical address of control page now */
-	/* this is impossible after page table switch */
+	/*
+	 * get physical address of control page now
+	 * this is impossible after page table switch
+	 */
 	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r8
 
 	/* get physical address of page table now too */
-	movq	PTR(PA_TABLE_PAGE)(%rsi), %rcx
+	movq	PTR(PA_TABLE_PAGE)(%rsi), %r9
+
+	/* get physical address of swap page now */
+	movq	PTR(PA_SWAP_PAGE)(%rsi), %r10
+
+	/* save some information for jumping back */
+	movq	%r9, CP_PA_TABLE_PAGE(%r11)
+	movq	%r10, CP_PA_SWAP_PAGE(%r11)
+	movq	%rdi, CP_PA_BACKUP_PAGES_MAP(%r11)
 
 	/* Switch to the identity mapped page tables */
-	movq	%rcx, %cr3
+	movq	%r9, %cr3
 
 	/* setup a new stack at the end of the physical control page */
 	lea	PAGE_SIZE(%r8), %rsp
@@ -55,7 +103,8 @@
 	/* store the start address on the stack */
 	pushq   %rdx
 
-	/* Set cr0 to a known state:
+	/*
+	 * Set cr0 to a known state:
 	 *  - Paging enabled
 	 *  - Alignment check disabled
 	 *  - Write protect disabled
@@ -68,7 +117,8 @@
 	orl	$(X86_CR0_PG | X86_CR0_PE), %eax
 	movq	%rax, %cr0
 
-	/* Set cr4 to a known state:
+	/*
+	 * Set cr4 to a known state:
 	 *  - physical address extension enabled
 	 */
 	movq	$X86_CR4_PAE, %rax
@@ -78,9 +128,87 @@
 1:
 
 	/* Flush the TLB (needed?) */
-	movq	%rcx, %cr3
+	movq	%r9, %cr3
+
+	movq	%rcx, %r11
+	call	swap_pages
+
+	/*
+	 * To be certain of avoiding problems with self-modifying code
+	 * I need to execute a serializing instruction here.
+	 * So I flush the TLB by reloading %cr3 here, it's handy,
+	 * and not processor dependent.
+	 */
+	movq	%cr3, %rax
+	movq	%rax, %cr3
+
+	/*
+	 * set all of the registers to known values
+	 * leave %rsp alone
+	 */
+
+	testq	%r11, %r11
+	jnz 1f
+	xorq	%rax, %rax
+	xorq	%rbx, %rbx
+	xorq    %rcx, %rcx
+	xorq    %rdx, %rdx
+	xorq    %rsi, %rsi
+	xorq    %rdi, %rdi
+	xorq    %rbp, %rbp
+	xorq	%r8,  %r8
+	xorq	%r9,  %r9
+	xorq	%r10, %r9
+	xorq	%r11, %r11
+	xorq	%r12, %r12
+	xorq	%r13, %r13
+	xorq	%r14, %r14
+	xorq	%r15, %r15
+
+	ret
+
+1:
+	popq	%rdx
+	leaq	PAGE_SIZE(%r10), %rsp
+	call	*%rdx
+
+	/* get the re-entry point of the peer system */
+	movq	0(%rsp), %rbp
+	call	1f
+1:
+	popq	%r8
+	subq	$(1b - relocate_kernel), %r8
+	movq	CP_PA_SWAP_PAGE(%r8), %r10
+	movq	CP_PA_BACKUP_PAGES_MAP(%r8), %rdi
+	movq	CP_PA_TABLE_PAGE(%r8), %rax
+	movq	%rax, %cr3
+	lea	PAGE_SIZE(%r8), %rsp
+	call	swap_pages
+	movq	$virtual_mapped, %rax
+	pushq	%rax
+	ret
+
+virtual_mapped:
+	movq	RSP(%r8), %rsp
+	movq	CR4(%r8), %rax
+	movq	%rax, %cr4
+	movq	CR3(%r8), %rax
+	movq	CR0(%r8), %r8
+	movq	%rax, %cr3
+	movq	%r8, %cr0
+	movq	%rbp, %rax
+
+	popf
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	ret
 
 	/* Do the copies */
+swap_pages:
 	movq	%rdi, %rcx 	/* Put the page_list in %rcx */
 	xorq	%rdi, %rdi
 	xorq	%rsi, %rsi
@@ -112,36 +240,27 @@
 	movq	%rcx,   %rsi  /* For ever source page do a copy */
 	andq	$0xfffffffffffff000, %rsi
 
+	movq	%rdi, %rdx
+	movq	%rsi, %rax
+
+	movq	%r10, %rdi
 	movq	$512,   %rcx
 	rep ; movsq
+
+	movq	%rax, %rdi
+	movq	%rdx, %rsi
+	movq	$512,   %rcx
+	rep ; movsq
+
+	movq	%rdx, %rdi
+	movq	%r10, %rsi
+	movq	$512,   %rcx
+	rep ; movsq
+
+	lea	PAGE_SIZE(%rax), %rsi
 	jmp	0b
 3:
-
-	/* To be certain of avoiding problems with self-modifying code
-	 * I need to execute a serializing instruction here.
-	 * So I flush the TLB by reloading %cr3 here, it's handy,
-	 * and not processor dependent.
-	 */
-	movq	%cr3, %rax
-	movq	%rax, %cr3
-
-	/* set all of the registers to known values */
-	/* leave %rsp alone */
-
-	xorq	%rax, %rax
-	xorq	%rbx, %rbx
-	xorq    %rcx, %rcx
-	xorq    %rdx, %rdx
-	xorq    %rsi, %rsi
-	xorq    %rdi, %rdi
-	xorq    %rbp, %rbp
-	xorq	%r8,  %r8
-	xorq	%r9,  %r9
-	xorq	%r10, %r9
-	xorq	%r11, %r11
-	xorq	%r12, %r12
-	xorq	%r13, %r13
-	xorq	%r14, %r14
-	xorq	%r15, %r15
-
 	ret
+
+	.globl kexec_control_code_size
+.set kexec_control_code_size, . - relocate_kernel
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index dd6f2b7..5d465b2 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -1,14 +1,14 @@
 /*
  * RTC related functions
  */
+#include <linux/platform_device.h>
+#include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
 #include <linux/bcd.h>
-#include <linux/mc146818rtc.h>
-#include <linux/platform_device.h>
 #include <linux/pnp.h>
 
-#include <asm/time.h>
 #include <asm/vsyscall.h>
+#include <asm/time.h>
 
 #ifdef CONFIG_X86_32
 /*
@@ -16,9 +16,9 @@
  * register we are working with.  It is required for NMI access to the
  * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
  */
-volatile unsigned long cmos_lock = 0;
+volatile unsigned long cmos_lock;
 EXPORT_SYMBOL(cmos_lock);
-#endif
+#endif /* CONFIG_X86_32 */
 
 /* For two digit years assume time is always after that */
 #define CMOS_YEARS_OFFS 2000
@@ -38,9 +38,9 @@
  */
 int mach_set_rtc_mmss(unsigned long nowtime)
 {
-	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char save_control, save_freq_select;
+	int retval = 0;
 
 	 /* tell the clock it's being set */
 	save_control = CMOS_READ(RTC_CONTROL);
@@ -72,8 +72,8 @@
 			real_seconds = bin2bcd(real_seconds);
 			real_minutes = bin2bcd(real_minutes);
 		}
-		CMOS_WRITE(real_seconds,RTC_SECONDS);
-		CMOS_WRITE(real_minutes,RTC_MINUTES);
+		CMOS_WRITE(real_seconds, RTC_SECONDS);
+		CMOS_WRITE(real_minutes, RTC_MINUTES);
 	} else {
 		printk(KERN_WARNING
 		       "set_rtc_mmss: can't update from %d to %d\n",
@@ -151,6 +151,7 @@
 	outb(addr, RTC_PORT(0));
 	val = inb(RTC_PORT(1));
 	lock_cmos_suffix(addr);
+
 	return val;
 }
 EXPORT_SYMBOL(rtc_cmos_read);
@@ -166,8 +167,8 @@
 
 static int set_rtc_mmss(unsigned long nowtime)
 {
-	int retval;
 	unsigned long flags;
+	int retval;
 
 	spin_lock_irqsave(&rtc_lock, flags);
 	retval = set_wallclock(nowtime);
@@ -242,6 +243,7 @@
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
 		 "registered platform RTC device (no PNP device found)\n");
+
 	return 0;
 }
 device_initcall(add_rtc_cmos);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index b746deb..a0d2623 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -112,8 +112,13 @@
 #define ARCH_SETUP
 #endif
 
+RESERVE_BRK(dmi_alloc, 65536);
+
 unsigned int boot_cpu_id __read_mostly;
 
+static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
+unsigned long _brk_end = (unsigned long)__brk_base;
+
 #ifdef CONFIG_X86_64
 int default_cpu_present_to_apicid(int mps_cpu)
 {
@@ -158,12 +163,6 @@
 
 
 #ifdef CONFIG_X86_32
-/* This value is set up by the early boot code to point to the value
-   immediately after the boot time page tables.  It contains a *physical*
-   address, and must not be in the .bss segment! */
-unsigned long init_pg_tables_start __initdata = ~0UL;
-unsigned long init_pg_tables_end __initdata = ~0UL;
-
 static struct resource video_ram_resource = {
 	.name	= "Video RAM area",
 	.start	= 0xa0000,
@@ -202,7 +201,9 @@
 #endif
 
 #else
-struct cpuinfo_x86 boot_cpu_data __read_mostly;
+struct cpuinfo_x86 boot_cpu_data __read_mostly = {
+	.x86_phys_bits = MAX_PHYSMEM_BITS,
+};
 EXPORT_SYMBOL(boot_cpu_data);
 #endif
 
@@ -217,12 +218,6 @@
 int bootloader_type;
 
 /*
- * Early DMI memory
- */
-int dmi_alloc_index;
-char dmi_alloc_data[DMI_MAX_DATA];
-
-/*
  * Setup options
  */
 struct screen_info screen_info;
@@ -267,6 +262,35 @@
 }
 #endif
 
+void * __init extend_brk(size_t size, size_t align)
+{
+	size_t mask = align - 1;
+	void *ret;
+
+	BUG_ON(_brk_start == 0);
+	BUG_ON(align & mask);
+
+	_brk_end = (_brk_end + mask) & ~mask;
+	BUG_ON((char *)(_brk_end + size) > __brk_limit);
+
+	ret = (void *)_brk_end;
+	_brk_end += size;
+
+	memset(ret, 0, size);
+
+	return ret;
+}
+
+static void __init reserve_brk(void)
+{
+	if (_brk_end > _brk_start)
+		reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
+
+	/* Mark brk area as locked down and no longer taking any
+	   new allocations */
+	_brk_start = 0;
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 
 #ifdef CONFIG_X86_32
@@ -715,11 +739,7 @@
 	init_mm.start_code = (unsigned long) _text;
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
-#ifdef CONFIG_X86_32
-	init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
-#else
-	init_mm.brk = (unsigned long) &_end;
-#endif
+	init_mm.brk = _brk_end;
 
 	code_resource.start = virt_to_phys(_text);
 	code_resource.end = virt_to_phys(_etext)-1;
@@ -840,6 +860,8 @@
 	setup_bios_corruption_check();
 #endif
 
+	reserve_brk();
+
 	/* max_pfn_mapped is updated here */
 	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
 	max_pfn_mapped = max_low_pfn_mapped;
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index d2cc642..dfcc74a 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -211,31 +211,27 @@
 {
 	/* Default to using normal stack */
 	unsigned long sp = regs->sp;
+	int onsigstack = on_sig_stack(sp);
 
 #ifdef CONFIG_X86_64
 	/* redzone */
 	sp -= 128;
 #endif /* CONFIG_X86_64 */
 
-	/*
-	 * If we are on the alternate signal stack and would overflow it, don't.
-	 * Return an always-bogus address instead so we will die with SIGSEGV.
-	 */
-	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
-		return (void __user *) -1L;
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (sas_ss_flags(sp) == 0)
-			sp = current->sas_ss_sp + current->sas_ss_size;
-	} else {
+	if (!onsigstack) {
+		/* This is the X/Open sanctioned signal stack switching.  */
+		if (ka->sa.sa_flags & SA_ONSTACK) {
+			if (sas_ss_flags(sp) == 0)
+				sp = current->sas_ss_sp + current->sas_ss_size;
+		} else {
 #ifdef CONFIG_X86_32
-		/* This is the legacy signal stack switching. */
-		if ((regs->ss & 0xffff) != __USER_DS &&
-			!(ka->sa.sa_flags & SA_RESTORER) &&
-				ka->sa.sa_restorer)
-			sp = (unsigned long) ka->sa.sa_restorer;
+			/* This is the legacy signal stack switching. */
+			if ((regs->ss & 0xffff) != __USER_DS &&
+				!(ka->sa.sa_flags & SA_RESTORER) &&
+					ka->sa.sa_restorer)
+				sp = (unsigned long) ka->sa.sa_restorer;
 #endif /* CONFIG_X86_32 */
+		}
 	}
 
 	if (used_math()) {
@@ -244,12 +240,22 @@
 		sp = round_down(sp, 64);
 #endif /* CONFIG_X86_64 */
 		*fpstate = (void __user *)sp;
-
-		if (save_i387_xstate(*fpstate) < 0)
-			return (void __user *)-1L;
 	}
 
-	return (void __user *)align_sigframe(sp - frame_size);
+	sp = align_sigframe(sp - frame_size);
+
+	/*
+	 * If we are on the alternate signal stack and would overflow it, don't.
+	 * Return an always-bogus address instead so we will die with SIGSEGV.
+	 */
+	if (onsigstack && !likely(on_sig_stack(sp)))
+		return (void __user *)-1L;
+
+	/* save i387 state */
+	if (used_math() && save_i387_xstate(*fpstate) < 0)
+		return (void __user *)-1L;
+
+	return (void __user *)sp;
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 249334f..ef7d101 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -114,10 +114,6 @@
 
 atomic_t init_deasserted;
 
-
-/* Set if we find a B stepping CPU */
-static int __cpuinitdata smp_b_stepping;
-
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
 
 /* which logical CPUs are on which nodes */
@@ -271,8 +267,6 @@
 	cpumask_set_cpu(cpuid, cpu_callin_mask);
 }
 
-static int __cpuinitdata unsafe_smp;
-
 /*
  * Activate a secondary processor.
  */
@@ -340,76 +334,6 @@
 	cpu_idle();
 }
 
-static void __cpuinit smp_apply_quirks(struct cpuinfo_x86 *c)
-{
-	/*
-	 * Mask B, Pentium, but not Pentium MMX
-	 */
-	if (c->x86_vendor == X86_VENDOR_INTEL &&
-	    c->x86 == 5 &&
-	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
-	    c->x86_model <= 3)
-		/*
-		 * Remember we have B step Pentia with bugs
-		 */
-		smp_b_stepping = 1;
-
-	/*
-	 * Certain Athlons might work (for various values of 'work') in SMP
-	 * but they are not certified as MP capable.
-	 */
-	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
-
-		if (num_possible_cpus() == 1)
-			goto valid_k7;
-
-		/* Athlon 660/661 is valid. */
-		if ((c->x86_model == 6) && ((c->x86_mask == 0) ||
-		    (c->x86_mask == 1)))
-			goto valid_k7;
-
-		/* Duron 670 is valid */
-		if ((c->x86_model == 7) && (c->x86_mask == 0))
-			goto valid_k7;
-
-		/*
-		 * Athlon 662, Duron 671, and Athlon >model 7 have capability
-		 * bit. It's worth noting that the A5 stepping (662) of some
-		 * Athlon XP's have the MP bit set.
-		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for
-		 * more.
-		 */
-		if (((c->x86_model == 6) && (c->x86_mask >= 2)) ||
-		    ((c->x86_model == 7) && (c->x86_mask >= 1)) ||
-		     (c->x86_model > 7))
-			if (cpu_has_mp)
-				goto valid_k7;
-
-		/* If we get here, not a certified SMP capable AMD system. */
-		unsafe_smp = 1;
-	}
-
-valid_k7:
-	;
-}
-
-static void __cpuinit smp_checks(void)
-{
-	if (smp_b_stepping)
-		printk(KERN_WARNING "WARNING: SMP operation may be unreliable"
-				    "with B stepping processors.\n");
-
-	/*
-	 * Don't taint if we are running SMP kernel on a single non-MP
-	 * approved Athlon
-	 */
-	if (unsafe_smp && num_online_cpus() > 1) {
-		printk(KERN_INFO "WARNING: This combination of AMD"
-			"processors is not suitable for SMP.\n");
-		add_taint(TAINT_UNSAFE_SMP);
-	}
-}
-
 /*
  * The bootstrap kernel entry code has set these up. Save them for
  * a given CPU
@@ -423,7 +347,6 @@
 	c->cpu_index = id;
 	if (id != 0)
 		identify_secondary_cpu(c);
-	smp_apply_quirks(c);
 }
 
 
@@ -1193,7 +1116,6 @@
 	pr_debug("Boot done.\n");
 
 	impress_friends();
-	smp_checks();
 #ifdef CONFIG_X86_IO_APIC
 	setup_ioapic_dest();
 #endif
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index d038b9c..79c0732 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -750,7 +750,7 @@
 	int node;
 	int nblades;
 	int last_blade;
-	int cur_cpu = 0;
+	int cur_cpu;
 
 	if (!is_uv_system())
 		return 0;
@@ -760,6 +760,7 @@
 	uv_mmask = (1UL << uv_hub_info->n_val) - 1;
 	nblades = 0;
 	last_blade = -1;
+	cur_cpu = 0;
 	for_each_online_node(node) {
 		blade = uv_node_to_blade_id(node);
 		if (blade == last_blade)
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 0fcc95a..7e45159 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -25,10 +25,10 @@
  *
  * Send feedback to <colpatch@us.ibm.com>
  */
-#include <linux/init.h>
-#include <linux/smp.h>
 #include <linux/nodemask.h>
 #include <linux/mmzone.h>
+#include <linux/init.h>
+#include <linux/smp.h>
 #include <asm/cpu.h>
 
 static DEFINE_PER_CPU(struct x86_cpu, cpu_devices);
@@ -47,6 +47,7 @@
 	 */
 	if (num)
 		per_cpu(cpu_devices, num).cpu.hotpluggable = 1;
+
 	return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
 }
 EXPORT_SYMBOL(arch_register_cpu);
@@ -56,12 +57,13 @@
 	unregister_cpu(&per_cpu(cpu_devices, num).cpu);
 }
 EXPORT_SYMBOL(arch_unregister_cpu);
-#else
+#else /* CONFIG_HOTPLUG_CPU */
+
 static int __init arch_register_cpu(int num)
 {
 	return register_cpu(&per_cpu(cpu_devices, num).cpu, num);
 }
-#endif /*CONFIG_HOTPLUG_CPU*/
+#endif /* CONFIG_HOTPLUG_CPU */
 
 static int __init topology_init(void)
 {
@@ -70,11 +72,11 @@
 #ifdef CONFIG_NUMA
 	for_each_online_node(i)
 		register_one_node(i);
-#endif /* CONFIG_NUMA */
+#endif
 
 	for_each_present_cpu(i)
 		arch_register_cpu(i);
+
 	return 0;
 }
-
 subsys_initcall(topology_init);
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
new file mode 100644
index 0000000..2ffb6c5
--- /dev/null
+++ b/arch/x86/kernel/uv_time.c
@@ -0,0 +1,393 @@
+/*
+ * SGI RTC clock/timer routines.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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
+ *
+ *  Copyright (c) 2009 Silicon Graphics, Inc.  All Rights Reserved.
+ *  Copyright (c) Dimitri Sivanich
+ */
+#include <linux/clockchips.h>
+
+#include <asm/uv/uv_mmrs.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/bios.h>
+#include <asm/uv/uv.h>
+#include <asm/apic.h>
+#include <asm/cpu.h>
+
+#define RTC_NAME		"sgi_rtc"
+
+static cycle_t uv_read_rtc(void);
+static int uv_rtc_next_event(unsigned long, struct clock_event_device *);
+static void uv_rtc_timer_setup(enum clock_event_mode,
+				struct clock_event_device *);
+
+static struct clocksource clocksource_uv = {
+	.name		= RTC_NAME,
+	.rating		= 400,
+	.read		= uv_read_rtc,
+	.mask		= (cycle_t)UVH_RTC_REAL_TIME_CLOCK_MASK,
+	.shift		= 10,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct clock_event_device clock_event_device_uv = {
+	.name		= RTC_NAME,
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 20,
+	.rating		= 400,
+	.irq		= -1,
+	.set_next_event	= uv_rtc_next_event,
+	.set_mode	= uv_rtc_timer_setup,
+	.event_handler	= NULL,
+};
+
+static DEFINE_PER_CPU(struct clock_event_device, cpu_ced);
+
+/* There is one of these allocated per node */
+struct uv_rtc_timer_head {
+	spinlock_t	lock;
+	/* next cpu waiting for timer, local node relative: */
+	int		next_cpu;
+	/* number of cpus on this node: */
+	int		ncpus;
+	struct {
+		int	lcpu;		/* systemwide logical cpu number */
+		u64	expires;	/* next timer expiration for this cpu */
+	} cpu[1];
+};
+
+/*
+ * Access to uv_rtc_timer_head via blade id.
+ */
+static struct uv_rtc_timer_head		**blade_info __read_mostly;
+
+static int				uv_rtc_enable;
+
+/*
+ * Hardware interface routines
+ */
+
+/* Send IPIs to another node */
+static void uv_rtc_send_IPI(int cpu)
+{
+	unsigned long apicid, val;
+	int pnode;
+
+	apicid = cpu_physical_id(cpu);
+	pnode = uv_apicid_to_pnode(apicid);
+	val = (1UL << UVH_IPI_INT_SEND_SHFT) |
+	      (apicid << UVH_IPI_INT_APIC_ID_SHFT) |
+	      (GENERIC_INTERRUPT_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
+
+	uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
+}
+
+/* Check for an RTC interrupt pending */
+static int uv_intr_pending(int pnode)
+{
+	return uv_read_global_mmr64(pnode, UVH_EVENT_OCCURRED0) &
+		UVH_EVENT_OCCURRED0_RTC1_MASK;
+}
+
+/* Setup interrupt and return non-zero if early expiration occurred. */
+static int uv_setup_intr(int cpu, u64 expires)
+{
+	u64 val;
+	int pnode = uv_cpu_to_pnode(cpu);
+
+	uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG,
+		UVH_RTC1_INT_CONFIG_M_MASK);
+	uv_write_global_mmr64(pnode, UVH_INT_CMPB, -1L);
+
+	uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED0_ALIAS,
+		UVH_EVENT_OCCURRED0_RTC1_MASK);
+
+	val = (GENERIC_INTERRUPT_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
+		((u64)cpu_physical_id(cpu) << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
+
+	/* Set configuration */
+	uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG, val);
+	/* Initialize comparator value */
+	uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
+
+	return (expires < uv_read_rtc() && !uv_intr_pending(pnode));
+}
+
+/*
+ * Per-cpu timer tracking routines
+ */
+
+static __init void uv_rtc_deallocate_timers(void)
+{
+	int bid;
+
+	for_each_possible_blade(bid) {
+		kfree(blade_info[bid]);
+	}
+	kfree(blade_info);
+}
+
+/* Allocate per-node list of cpu timer expiration times. */
+static __init int uv_rtc_allocate_timers(void)
+{
+	int cpu;
+
+	blade_info = kmalloc(uv_possible_blades * sizeof(void *), GFP_KERNEL);
+	if (!blade_info)
+		return -ENOMEM;
+	memset(blade_info, 0, uv_possible_blades * sizeof(void *));
+
+	for_each_present_cpu(cpu) {
+		int nid = cpu_to_node(cpu);
+		int bid = uv_cpu_to_blade_id(cpu);
+		int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+		struct uv_rtc_timer_head *head = blade_info[bid];
+
+		if (!head) {
+			head = kmalloc_node(sizeof(struct uv_rtc_timer_head) +
+				(uv_blade_nr_possible_cpus(bid) *
+					2 * sizeof(u64)),
+				GFP_KERNEL, nid);
+			if (!head) {
+				uv_rtc_deallocate_timers();
+				return -ENOMEM;
+			}
+			spin_lock_init(&head->lock);
+			head->ncpus = uv_blade_nr_possible_cpus(bid);
+			head->next_cpu = -1;
+			blade_info[bid] = head;
+		}
+
+		head->cpu[bcpu].lcpu = cpu;
+		head->cpu[bcpu].expires = ULLONG_MAX;
+	}
+
+	return 0;
+}
+
+/* Find and set the next expiring timer.  */
+static void uv_rtc_find_next_timer(struct uv_rtc_timer_head *head, int pnode)
+{
+	u64 lowest = ULLONG_MAX;
+	int c, bcpu = -1;
+
+	head->next_cpu = -1;
+	for (c = 0; c < head->ncpus; c++) {
+		u64 exp = head->cpu[c].expires;
+		if (exp < lowest) {
+			bcpu = c;
+			lowest = exp;
+		}
+	}
+	if (bcpu >= 0) {
+		head->next_cpu = bcpu;
+		c = head->cpu[bcpu].lcpu;
+		if (uv_setup_intr(c, lowest))
+			/* If we didn't set it up in time, trigger */
+			uv_rtc_send_IPI(c);
+	} else {
+		uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG,
+			UVH_RTC1_INT_CONFIG_M_MASK);
+	}
+}
+
+/*
+ * Set expiration time for current cpu.
+ *
+ * Returns 1 if we missed the expiration time.
+ */
+static int uv_rtc_set_timer(int cpu, u64 expires)
+{
+	int pnode = uv_cpu_to_pnode(cpu);
+	int bid = uv_cpu_to_blade_id(cpu);
+	struct uv_rtc_timer_head *head = blade_info[bid];
+	int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+	u64 *t = &head->cpu[bcpu].expires;
+	unsigned long flags;
+	int next_cpu;
+
+	spin_lock_irqsave(&head->lock, flags);
+
+	next_cpu = head->next_cpu;
+	*t = expires;
+	/* Will this one be next to go off? */
+	if (next_cpu < 0 || bcpu == next_cpu ||
+			expires < head->cpu[next_cpu].expires) {
+		head->next_cpu = bcpu;
+		if (uv_setup_intr(cpu, expires)) {
+			*t = ULLONG_MAX;
+			uv_rtc_find_next_timer(head, pnode);
+			spin_unlock_irqrestore(&head->lock, flags);
+			return 1;
+		}
+	}
+
+	spin_unlock_irqrestore(&head->lock, flags);
+	return 0;
+}
+
+/*
+ * Unset expiration time for current cpu.
+ *
+ * Returns 1 if this timer was pending.
+ */
+static int uv_rtc_unset_timer(int cpu)
+{
+	int pnode = uv_cpu_to_pnode(cpu);
+	int bid = uv_cpu_to_blade_id(cpu);
+	struct uv_rtc_timer_head *head = blade_info[bid];
+	int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+	u64 *t = &head->cpu[bcpu].expires;
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&head->lock, flags);
+
+	if (head->next_cpu == bcpu && uv_read_rtc() >= *t)
+		rc = 1;
+
+	*t = ULLONG_MAX;
+
+	/* Was the hardware setup for this timer? */
+	if (head->next_cpu == bcpu)
+		uv_rtc_find_next_timer(head, pnode);
+
+	spin_unlock_irqrestore(&head->lock, flags);
+
+	return rc;
+}
+
+
+/*
+ * Kernel interface routines.
+ */
+
+/*
+ * Read the RTC.
+ */
+static cycle_t uv_read_rtc(void)
+{
+	return (cycle_t)uv_read_local_mmr(UVH_RTC);
+}
+
+/*
+ * Program the next event, relative to now
+ */
+static int uv_rtc_next_event(unsigned long delta,
+			     struct clock_event_device *ced)
+{
+	int ced_cpu = cpumask_first(ced->cpumask);
+
+	return uv_rtc_set_timer(ced_cpu, delta + uv_read_rtc());
+}
+
+/*
+ * Setup the RTC timer in oneshot mode
+ */
+static void uv_rtc_timer_setup(enum clock_event_mode mode,
+			       struct clock_event_device *evt)
+{
+	int ced_cpu = cpumask_first(evt->cpumask);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here yet */
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		uv_rtc_unset_timer(ced_cpu);
+		break;
+	}
+}
+
+static void uv_rtc_interrupt(void)
+{
+	struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
+	int cpu = smp_processor_id();
+
+	if (!ced || !ced->event_handler)
+		return;
+
+	if (uv_rtc_unset_timer(cpu) != 1)
+		return;
+
+	ced->event_handler(ced);
+}
+
+static int __init uv_enable_rtc(char *str)
+{
+	uv_rtc_enable = 1;
+
+	return 1;
+}
+__setup("uvrtc", uv_enable_rtc);
+
+static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
+{
+	struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
+
+	*ced = clock_event_device_uv;
+	ced->cpumask = cpumask_of(smp_processor_id());
+	clockevents_register_device(ced);
+}
+
+static __init int uv_rtc_setup_clock(void)
+{
+	int rc;
+
+	if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
+		return -ENODEV;
+
+	generic_interrupt_extension = uv_rtc_interrupt;
+
+	clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
+				clocksource_uv.shift);
+
+	rc = clocksource_register(&clocksource_uv);
+	if (rc) {
+		generic_interrupt_extension = NULL;
+		return rc;
+	}
+
+	/* Setup and register clockevents */
+	rc = uv_rtc_allocate_timers();
+	if (rc) {
+		clocksource_unregister(&clocksource_uv);
+		generic_interrupt_extension = NULL;
+		return rc;
+	}
+
+	clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
+				NSEC_PER_SEC, clock_event_device_uv.shift);
+
+	clock_event_device_uv.min_delta_ns = NSEC_PER_SEC /
+						sn_rtc_cycles_per_second;
+
+	clock_event_device_uv.max_delta_ns = clocksource_uv.mask *
+				(NSEC_PER_SEC / sn_rtc_cycles_per_second);
+
+	rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
+	if (rc) {
+		clocksource_unregister(&clocksource_uv);
+		generic_interrupt_extension = NULL;
+		uv_rtc_deallocate_timers();
+	}
+
+	return rc;
+}
+arch_initcall(uv_rtc_setup_clock);
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index 191a876..31ffc24 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -578,7 +578,7 @@
 static irqreturn_t piix4_master_intr(int irq, void *dev_id)
 {
 	int realirq;
-	irq_desc_t *desc;
+	struct irq_desc *desc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&i8259A_lock, flags);
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 2cc4a90..95deb9f 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -395,11 +395,6 @@
 	vmi_ops.update_pte(ptep, VMI_PAGE_PT);
 }
 
-static void vmi_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
-	vmi_ops.set_pte(pte, ptep, vmi_flags_addr_defer(mm, addr, VMI_PAGE_PT, 1));
-}
-
 static void vmi_set_pud(pud_t *pudp, pud_t pudval)
 {
 	/* Um, eww */
@@ -750,7 +745,6 @@
 		pv_mmu_ops.set_pmd = vmi_set_pmd;
 #ifdef CONFIG_X86_PAE
 		pv_mmu_ops.set_pte_atomic = vmi_set_pte_atomic;
-		pv_mmu_ops.set_pte_present = vmi_set_pte_present;
 		pv_mmu_ops.set_pud = vmi_set_pud;
 		pv_mmu_ops.pte_clear = vmi_pte_clear;
 		pv_mmu_ops.pmd_clear = vmi_pmd_clear;
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index 0d86096..62ad500 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/arch/x86/kernel/vmlinux_32.lds.S
@@ -189,15 +189,24 @@
 	*(.bss)
 	. = ALIGN(4);
 	__bss_stop = .;
-  	_end = . ;
-	/* This is where the kernel creates the early boot page tables */
+  }
+
+  .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
 	. = ALIGN(PAGE_SIZE);
-	pg0 = . ;
+	__brk_base = . ;
+ 	. += 64 * 1024 ;	/* 64k alignment slop space */
+	*(.brk_reservation)	/* areas brk users have reserved */
+	__brk_limit = . ;
+  }
+
+  .end : AT(ADDR(.end) - LOAD_OFFSET) {
+	_end = . ;
   }
 
   /* Sections to be discarded */
   /DISCARD/ : {
 	*(.exitcall.exit)
+	*(.discard)
 	}
 
   STABS_DEBUG
@@ -205,6 +214,12 @@
   DWARF_DEBUG
 }
 
+/*
+ * Build-time check on the image size:
+ */
+ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
+	"kernel image bigger than KERNEL_IMAGE_SIZE")
+
 #ifdef CONFIG_KEXEC
 /* Link time checks */
 #include <asm/kexec.h>
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index fbfced6..c874250 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -29,8 +29,8 @@
 {
   . = __START_KERNEL;
   phys_startup_64 = startup_64 - LOAD_OFFSET;
-  _text = .;			/* Text and read-only data */
   .text :  AT(ADDR(.text) - LOAD_OFFSET) {
+	_text = .;			/* Text and read-only data */
 	/* First the code that has to be first for bootstrapping */
 	*(.text.head)
 	_stext = .;
@@ -61,13 +61,13 @@
   .data : AT(ADDR(.data) - LOAD_OFFSET) {
 	DATA_DATA
 	CONSTRUCTORS
+	_edata = .;			/* End of data section */
 	} :data
 
-  _edata = .;			/* End of data section */
 
-  . = ALIGN(PAGE_SIZE);
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+	. = ALIGN(PAGE_SIZE);
+	. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
 	*(.data.cacheline_aligned)
   }
   . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
@@ -125,29 +125,29 @@
 #undef VVIRT_OFFSET
 #undef VVIRT
 
-  . = ALIGN(THREAD_SIZE);	/* init_task */
   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+	. = ALIGN(THREAD_SIZE);	/* init_task */
 	*(.data.init_task)
   }:data.init
 
-  . = ALIGN(PAGE_SIZE);
   .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+	. = ALIGN(PAGE_SIZE);
 	*(.data.page_aligned)
   }
 
-  /* might get freed after init */
-  . = ALIGN(PAGE_SIZE);
-  __smp_alt_begin = .;
-  __smp_locks = .;
   .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+	/* might get freed after init */
+	. = ALIGN(PAGE_SIZE);
+	__smp_alt_begin = .;
+	__smp_locks = .;
 	*(.smp_locks)
+	__smp_locks_end = .;
+	. = ALIGN(PAGE_SIZE);
+	__smp_alt_end = .;
   }
-  __smp_locks_end = .;
-  . = ALIGN(PAGE_SIZE);
-  __smp_alt_end = .;
 
   . = ALIGN(PAGE_SIZE);		/* Init code and data */
-  __init_begin = .;
+  __init_begin = .;	/* paired with __init_end */
   .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
 	_sinittext = .;
 	INIT_TEXT
@@ -159,40 +159,42 @@
 	__initdata_end = .;
    }
 
-  . = ALIGN(16);
-  __setup_start = .;
-  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
-  __setup_end = .;
-  __initcall_start = .;
+  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
+	. = ALIGN(16);
+	__setup_start = .;
+	*(.init.setup)
+	__setup_end = .;
+  }
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
+	__initcall_start = .;
 	INITCALLS
+	__initcall_end = .;
   }
-  __initcall_end = .;
-  __con_initcall_start = .;
   .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+	__con_initcall_start = .;
 	*(.con_initcall.init)
+	__con_initcall_end = .;
   }
-  __con_initcall_end = .;
-  __x86_cpu_dev_start = .;
   .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
+	__x86_cpu_dev_start = .;
 	*(.x86_cpu_dev.init)
+	__x86_cpu_dev_end = .;
   }
-  __x86_cpu_dev_end = .;
   SECURITY_INIT
 
   . = ALIGN(8);
   .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) {
-  __parainstructions = .;
+	__parainstructions = .;
        *(.parainstructions)
-  __parainstructions_end = .;
+	__parainstructions_end = .;
   }
 
-  . = ALIGN(8);
-  __alt_instructions = .;
   .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+	. = ALIGN(8);
+	__alt_instructions = .;
 	*(.altinstructions)
+	__alt_instructions_end = .;
   }
-  __alt_instructions_end = .;
   .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
 	*(.altinstr_replacement)
   }
@@ -207,9 +209,11 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
   . = ALIGN(PAGE_SIZE);
-  __initramfs_start = .;
-  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
-  __initramfs_end = .;
+  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+	__initramfs_start = .;
+	*(.init.ramfs)
+	__initramfs_end = .;
+  }
 #endif
 
 #ifdef CONFIG_SMP
@@ -229,20 +233,29 @@
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
-  . = ALIGN(PAGE_SIZE);
-  __nosave_begin = .;
   .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
-      *(.data.nosave)
+	. = ALIGN(PAGE_SIZE);
+	__nosave_begin = .;
+	*(.data.nosave)
+	. = ALIGN(PAGE_SIZE);
+	__nosave_end = .;
   } :data.init2 /* use another section data.init2, see PERCPU_VADDR() above */
-  . = ALIGN(PAGE_SIZE);
-  __nosave_end = .;
 
-  __bss_start = .;		/* BSS */
   .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+	. = ALIGN(PAGE_SIZE);
+	__bss_start = .;		/* BSS */
 	*(.bss.page_aligned)
 	*(.bss)
-	}
-  __bss_stop = .;
+	__bss_stop = .;
+  }
+
+  .brk : AT(ADDR(.brk) - LOAD_OFFSET) {
+	. = ALIGN(PAGE_SIZE);
+	__brk_base = . ;
+ 	. += 64 * 1024 ;	/* 64k alignment slop space */
+	*(.brk_reservation)	/* areas brk users have reserved */
+	__brk_limit = . ;
+  }
 
   _end = . ;
 
@@ -250,6 +263,7 @@
   /DISCARD/ : {
 	*(.exitcall.exit)
 	*(.eh_frame)
+	*(.discard)
 	}
 
   STABS_DEBUG
@@ -275,3 +289,10 @@
 ASSERT((per_cpu__irq_stack_union == 0),
         "irq_stack_union is not at start of per-cpu area");
 #endif
+
+#ifdef CONFIG_KEXEC
+#include <asm/kexec.h>
+
+ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
+       "kexec control code size is too big")
+#endif
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c
index 74de562..a1d804b 100644
--- a/arch/x86/kernel/vsmp_64.c
+++ b/arch/x86/kernel/vsmp_64.c
@@ -22,7 +22,7 @@
 #include <asm/paravirt.h>
 #include <asm/setup.h>
 
-#ifdef CONFIG_PARAVIRT
+#if defined CONFIG_PCI && defined CONFIG_PARAVIRT
 /*
  * Interrupt control on vSMPowered systems:
  * ~AC is a shadow of IF.  If IF is 'on' AC should be 'off'
@@ -114,6 +114,7 @@
 }
 #endif
 
+#ifdef CONFIG_PCI
 static int is_vsmp = -1;
 
 static void __init detect_vsmp_box(void)
@@ -139,6 +140,15 @@
 	}
 }
 
+#else
+static void __init detect_vsmp_box(void)
+{
+}
+int is_vsmp_box(void)
+{
+	return 0;
+}
+#endif
 void __init vsmp_init(void)
 {
 	detect_vsmp_box();
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 9fe4dda..90e44a1 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1058,14 +1058,6 @@
 	 * lguest_init() where the rest of the fairly chaotic boot setup
 	 * occurs. */
 
-	/* The native boot code sets up initial page tables immediately after
-	 * the kernel itself, and sets init_pg_tables_end so they're not
-	 * clobbered.  The Launcher places our initial pagetables somewhere at
-	 * the top of our physical memory, so we don't need extra space: set
-	 * init_pg_tables_end to the end of the kernel. */
-	init_pg_tables_start = __pa(pg0);
-	init_pg_tables_end = __pa(pg0);
-
 	/* As described in head_32.S, we map the first 128M of memory. */
 	max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
 
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index c22981f..ad5441e 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -1,30 +1,38 @@
 /* Copyright 2002 Andi Kleen */
 
 #include <linux/linkage.h>
-#include <asm/dwarf2.h>
+
 #include <asm/cpufeature.h>
+#include <asm/dwarf2.h>
 
 /*
  * memcpy - Copy a memory block.
  *
- * Input:	
- * rdi destination
- * rsi source
- * rdx count
- * 
+ * Input:
+ *  rdi destination
+ *  rsi source
+ *  rdx count
+ *
  * Output:
  * rax original destination
- */	
+ */
 
+/*
+ * memcpy_c() - fast string ops (REP MOVSQ) based variant.
+ *
+ * Calls to this get patched into the kernel image via the
+ * alternative instructions framework:
+ */
 	ALIGN
 memcpy_c:
 	CFI_STARTPROC
-	movq %rdi,%rax
-	movl %edx,%ecx
-	shrl $3,%ecx
-	andl $7,%edx
+	movq %rdi, %rax
+
+	movl %edx, %ecx
+	shrl $3, %ecx
+	andl $7, %edx
 	rep movsq
-	movl %edx,%ecx
+	movl %edx, %ecx
 	rep movsb
 	ret
 	CFI_ENDPROC
@@ -33,99 +41,110 @@
 ENTRY(__memcpy)
 ENTRY(memcpy)
 	CFI_STARTPROC
-	pushq %rbx
-	CFI_ADJUST_CFA_OFFSET 8
-	CFI_REL_OFFSET rbx, 0
-	movq %rdi,%rax
 
-	movl %edx,%ecx
-	shrl $6,%ecx
+	/*
+	 * Put the number of full 64-byte blocks into %ecx.
+	 * Tail portion is handled at the end:
+	 */
+	movq %rdi, %rax
+	movl %edx, %ecx
+	shrl   $6, %ecx
 	jz .Lhandle_tail
 
 	.p2align 4
 .Lloop_64:
+	/*
+	 * We decrement the loop index here - and the zero-flag is
+	 * checked at the end of the loop (instructions inbetween do
+	 * not change the zero flag):
+	 */
 	decl %ecx
 
-	movq (%rsi),%r11
-	movq 8(%rsi),%r8
+	/*
+	 * Move in blocks of 4x16 bytes:
+	 */
+	movq 0*8(%rsi),		%r11
+	movq 1*8(%rsi),		%r8
+	movq %r11,		0*8(%rdi)
+	movq %r8,		1*8(%rdi)
 
-	movq %r11,(%rdi)
-	movq %r8,1*8(%rdi)
+	movq 2*8(%rsi),		%r9
+	movq 3*8(%rsi),		%r10
+	movq %r9,		2*8(%rdi)
+	movq %r10,		3*8(%rdi)
 
-	movq 2*8(%rsi),%r9
-	movq 3*8(%rsi),%r10
+	movq 4*8(%rsi),		%r11
+	movq 5*8(%rsi),		%r8
+	movq %r11,		4*8(%rdi)
+	movq %r8,		5*8(%rdi)
 
-	movq %r9,2*8(%rdi)
-	movq %r10,3*8(%rdi)
+	movq 6*8(%rsi),		%r9
+	movq 7*8(%rsi),		%r10
+	movq %r9,		6*8(%rdi)
+	movq %r10,		7*8(%rdi)
 
-	movq 4*8(%rsi),%r11
-	movq 5*8(%rsi),%r8
+	leaq 64(%rsi), %rsi
+	leaq 64(%rdi), %rdi
 
-	movq %r11,4*8(%rdi)
-	movq %r8,5*8(%rdi)
-
-	movq 6*8(%rsi),%r9
-	movq 7*8(%rsi),%r10
-
-	movq %r9,6*8(%rdi)
-	movq %r10,7*8(%rdi)
-
-	leaq 64(%rsi),%rsi
-	leaq 64(%rdi),%rdi
 	jnz  .Lloop_64
 
 .Lhandle_tail:
-	movl %edx,%ecx
-	andl $63,%ecx
-	shrl $3,%ecx
+	movl %edx, %ecx
+	andl  $63, %ecx
+	shrl   $3, %ecx
 	jz   .Lhandle_7
+
 	.p2align 4
 .Lloop_8:
 	decl %ecx
-	movq (%rsi),%r8
-	movq %r8,(%rdi)
-	leaq 8(%rdi),%rdi
-	leaq 8(%rsi),%rsi
+	movq (%rsi),		%r8
+	movq %r8,		(%rdi)
+	leaq 8(%rdi),		%rdi
+	leaq 8(%rsi),		%rsi
 	jnz  .Lloop_8
 
 .Lhandle_7:
-	movl %edx,%ecx
-	andl $7,%ecx
-	jz .Lende
+	movl %edx, %ecx
+	andl $7, %ecx
+	jz .Lend
+
 	.p2align 4
 .Lloop_1:
-	movb (%rsi),%r8b
-	movb %r8b,(%rdi)
+	movb (%rsi), %r8b
+	movb %r8b, (%rdi)
 	incq %rdi
 	incq %rsi
 	decl %ecx
 	jnz .Lloop_1
 
-.Lende:
-	popq %rbx
-	CFI_ADJUST_CFA_OFFSET -8
-	CFI_RESTORE rbx
+.Lend:
 	ret
-.Lfinal:
 	CFI_ENDPROC
 ENDPROC(memcpy)
 ENDPROC(__memcpy)
 
-	/* Some CPUs run faster using the string copy instructions.
-	   It is also a lot simpler. Use this when possible */
+	/*
+	 * Some CPUs run faster using the string copy instructions.
+	 * It is also a lot simpler. Use this when possible:
+	 */
 
-	.section .altinstr_replacement,"ax"
+	.section .altinstr_replacement, "ax"
 1:	.byte 0xeb				/* jmp <disp8> */
 	.byte (memcpy_c - memcpy) - (2f - 1b)	/* offset */
 2:
 	.previous
-	.section .altinstructions,"a"
+
+	.section .altinstructions, "a"
 	.align 8
 	.quad memcpy
 	.quad 1b
 	.byte X86_FEATURE_REP_GOOD
-	/* Replace only beginning, memcpy is used to apply alternatives, so it
-	 * is silly to overwrite itself with nops - reboot is only outcome... */
+
+	/*
+	 * Replace only beginning, memcpy is used to apply alternatives,
+	 * so it is silly to overwrite itself with nops - reboot is the
+	 * only outcome...
+	 */
 	.byte 2b - 1b
 	.byte 2b - 1b
 	.previous
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 00f127c..522db5e 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -121,22 +121,13 @@
 	pagefault_enable();
 }
 
-/* This is the same as kmap_atomic() but can map memory that doesn't
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
  */
 void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
 {
-	enum fixed_addresses idx;
-	unsigned long vaddr;
-
-	pagefault_disable();
-
-	idx = type + KM_TYPE_NR*smp_processor_id();
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
-	arch_flush_lazy_mmu_mode();
-
-	return (void*) vaddr;
+	return kmap_atomic_prot_pfn(pfn, type, kmap_prot);
 }
 EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
 
@@ -158,7 +149,6 @@
 EXPORT_SYMBOL(kmap_atomic);
 EXPORT_SYMBOL(kunmap_atomic);
 
-#ifdef CONFIG_NUMA
 void __init set_highmem_pages_init(void)
 {
 	struct zone *zone;
@@ -182,11 +172,3 @@
 	}
 	totalram_pages += totalhigh_pages;
 }
-#else
-void __init set_highmem_pages_init(void)
-{
-	add_highpages_with_active_regions(0, highstart_pfn, highend_pfn);
-
-	totalram_pages += totalhigh_pages;
-}
-#endif /* CONFIG_NUMA */
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index ce6a722..fd3da1d 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -1,8 +1,345 @@
+#include <linux/ioport.h>
 #include <linux/swap.h>
+
 #include <asm/cacheflush.h>
+#include <asm/e820.h>
+#include <asm/init.h>
 #include <asm/page.h>
+#include <asm/page_types.h>
 #include <asm/sections.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
+
+unsigned long __initdata e820_table_start;
+unsigned long __meminitdata e820_table_end;
+unsigned long __meminitdata e820_table_top;
+
+int after_bootmem;
+
+int direct_gbpages
+#ifdef CONFIG_DIRECT_GBPAGES
+				= 1
+#endif
+;
+
+static void __init find_early_table_space(unsigned long end, int use_pse,
+					  int use_gbpages)
+{
+	unsigned long puds, pmds, ptes, tables, start;
+
+	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+
+	if (use_gbpages) {
+		unsigned long extra;
+
+		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
+		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+	} else
+		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+
+	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+
+	if (use_pse) {
+		unsigned long extra;
+
+		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+#ifdef CONFIG_X86_32
+		extra += PMD_SIZE;
+#endif
+		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	} else
+		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
+
+#ifdef CONFIG_X86_32
+	/* for fixmap */
+	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
+#endif
+
+	/*
+	 * RED-PEN putting page tables only on node 0 could
+	 * cause a hotspot and fill up ZONE_DMA. The page tables
+	 * need roughly 0.5KB per GB.
+	 */
+#ifdef CONFIG_X86_32
+	start = 0x7000;
+	e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
+					tables, PAGE_SIZE);
+#else /* CONFIG_X86_64 */
+	start = 0x8000;
+	e820_table_start = find_e820_area(start, end, tables, PAGE_SIZE);
+#endif
+	if (e820_table_start == -1UL)
+		panic("Cannot find space for the kernel page tables");
+
+	e820_table_start >>= PAGE_SHIFT;
+	e820_table_end = e820_table_start;
+	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
+
+	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
+		end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
+}
+
+struct map_range {
+	unsigned long start;
+	unsigned long end;
+	unsigned page_size_mask;
+};
+
+#ifdef CONFIG_X86_32
+#define NR_RANGE_MR 3
+#else /* CONFIG_X86_64 */
+#define NR_RANGE_MR 5
+#endif
+
+static int __meminit save_mr(struct map_range *mr, int nr_range,
+			     unsigned long start_pfn, unsigned long end_pfn,
+			     unsigned long page_size_mask)
+{
+	if (start_pfn < end_pfn) {
+		if (nr_range >= NR_RANGE_MR)
+			panic("run out of range for init_memory_mapping\n");
+		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
+		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
+		mr[nr_range].page_size_mask = page_size_mask;
+		nr_range++;
+	}
+
+	return nr_range;
+}
+
+#ifdef CONFIG_X86_64
+static void __init init_gbpages(void)
+{
+	if (direct_gbpages && cpu_has_gbpages)
+		printk(KERN_INFO "Using GB pages for direct mapping\n");
+	else
+		direct_gbpages = 0;
+}
+#else
+static inline void init_gbpages(void)
+{
+}
+#endif
+
+/*
+ * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+ * This runs before bootmem is initialized and gets pages directly from
+ * the physical memory. To access them they are temporarily mapped.
+ */
+unsigned long __init_refok init_memory_mapping(unsigned long start,
+					       unsigned long end)
+{
+	unsigned long page_size_mask = 0;
+	unsigned long start_pfn, end_pfn;
+	unsigned long ret = 0;
+	unsigned long pos;
+
+	struct map_range mr[NR_RANGE_MR];
+	int nr_range, i;
+	int use_pse, use_gbpages;
+
+	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
+
+	if (!after_bootmem)
+		init_gbpages();
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	/*
+	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+	 * This will simplify cpa(), which otherwise needs to support splitting
+	 * large pages into small in interrupt context, etc.
+	 */
+	use_pse = use_gbpages = 0;
+#else
+	use_pse = cpu_has_pse;
+	use_gbpages = direct_gbpages;
+#endif
+
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_PAE
+	set_nx();
+	if (nx_enabled)
+		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+#endif
+
+	/* Enable PSE if available */
+	if (cpu_has_pse)
+		set_in_cr4(X86_CR4_PSE);
+
+	/* Enable PGE if available */
+	if (cpu_has_pge) {
+		set_in_cr4(X86_CR4_PGE);
+		__supported_pte_mask |= _PAGE_GLOBAL;
+	}
+#endif
+
+	if (use_gbpages)
+		page_size_mask |= 1 << PG_LEVEL_1G;
+	if (use_pse)
+		page_size_mask |= 1 << PG_LEVEL_2M;
+
+	memset(mr, 0, sizeof(mr));
+	nr_range = 0;
+
+	/* head if not big page alignment ? */
+	start_pfn = start >> PAGE_SHIFT;
+	pos = start_pfn << PAGE_SHIFT;
+#ifdef CONFIG_X86_32
+	/*
+	 * Don't use a large page for the first 2/4MB of memory
+	 * because there are often fixed size MTRRs in there
+	 * and overlapping MTRRs into large pages can cause
+	 * slowdowns.
+	 */
+	if (pos == 0)
+		end_pfn = 1<<(PMD_SHIFT - PAGE_SHIFT);
+	else
+		end_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+				 << (PMD_SHIFT - PAGE_SHIFT);
+#else /* CONFIG_X86_64 */
+	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
+			<< (PMD_SHIFT - PAGE_SHIFT);
+#endif
+	if (end_pfn > (end >> PAGE_SHIFT))
+		end_pfn = end >> PAGE_SHIFT;
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+	/* big page (2M) range */
+	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+			 << (PMD_SHIFT - PAGE_SHIFT);
+#ifdef CONFIG_X86_32
+	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+#else /* CONFIG_X86_64 */
+	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+			 << (PUD_SHIFT - PAGE_SHIFT);
+	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
+		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
+#endif
+
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask & (1<<PG_LEVEL_2M));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+#ifdef CONFIG_X86_64
+	/* big page (1G) range */
+	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+			 << (PUD_SHIFT - PAGE_SHIFT);
+	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask &
+				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+	/* tail is not big page (1G) alignment */
+	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+			 << (PMD_SHIFT - PAGE_SHIFT);
+	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask & (1<<PG_LEVEL_2M));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+#endif
+
+	/* tail is not big page (2M) alignment */
+	start_pfn = pos>>PAGE_SHIFT;
+	end_pfn = end>>PAGE_SHIFT;
+	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+
+	/* try to merge same page size and continuous */
+	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
+		unsigned long old_start;
+		if (mr[i].end != mr[i+1].start ||
+		    mr[i].page_size_mask != mr[i+1].page_size_mask)
+			continue;
+		/* move it */
+		old_start = mr[i].start;
+		memmove(&mr[i], &mr[i+1],
+			(nr_range - 1 - i) * sizeof(struct map_range));
+		mr[i--].start = old_start;
+		nr_range--;
+	}
+
+	for (i = 0; i < nr_range; i++)
+		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
+				mr[i].start, mr[i].end,
+			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
+			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
+
+	/*
+	 * Find space for the kernel direct mapping tables.
+	 *
+	 * Later we should allocate these tables in the local node of the
+	 * memory mapped. Unfortunately this is done currently before the
+	 * nodes are discovered.
+	 */
+	if (!after_bootmem)
+		find_early_table_space(end, use_pse, use_gbpages);
+
+#ifdef CONFIG_X86_32
+	for (i = 0; i < nr_range; i++)
+		kernel_physical_mapping_init(mr[i].start, mr[i].end,
+					     mr[i].page_size_mask);
+	ret = end;
+#else /* CONFIG_X86_64 */
+	for (i = 0; i < nr_range; i++)
+		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
+						   mr[i].page_size_mask);
+#endif
+
+#ifdef CONFIG_X86_32
+	early_ioremap_page_table_range_init();
+
+	load_cr3(swapper_pg_dir);
+#endif
+
+#ifdef CONFIG_X86_64
+	if (!after_bootmem)
+		mmu_cr4_features = read_cr4();
+#endif
+	__flush_tlb_all();
+
+	if (!after_bootmem && e820_table_end > e820_table_start)
+		reserve_early(e820_table_start << PAGE_SHIFT,
+				 e820_table_end << PAGE_SHIFT, "PGTABLE");
+
+	if (!after_bootmem)
+		early_memtest(start, end);
+
+	return ret >> PAGE_SHIFT;
+}
+
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+ * is valid. The argument is a physical page number.
+ *
+ *
+ * On x86, access has to be given to the first megabyte of ram because that area
+ * contains bios code and data regions used by X and dosemu and similar apps.
+ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+ * mmio resources as well as potential bios/acpi data regions.
+ */
+int devmem_is_allowed(unsigned long pagenr)
+{
+	if (pagenr <= 256)
+		return 1;
+	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+		return 0;
+	if (!page_is_ram(pagenr))
+		return 1;
+	return 0;
+}
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
@@ -47,3 +384,10 @@
 			(unsigned long)(&__init_begin),
 			(unsigned long)(&__init_end));
 }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	free_init_pages("initrd memory", start, end);
+}
+#endif
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 47df0e1..db81e9a 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -49,6 +49,7 @@
 #include <asm/paravirt.h>
 #include <asm/setup.h>
 #include <asm/cacheflush.h>
+#include <asm/init.h>
 
 unsigned long max_low_pfn_mapped;
 unsigned long max_pfn_mapped;
@@ -58,19 +59,14 @@
 
 static noinline int do_test_wp_bit(void);
 
-
-static unsigned long __initdata table_start;
-static unsigned long __meminitdata table_end;
-static unsigned long __meminitdata table_top;
-
-static int __initdata after_init_bootmem;
+bool __read_mostly __vmalloc_start_set = false;
 
 static __init void *alloc_low_page(void)
 {
-	unsigned long pfn = table_end++;
+	unsigned long pfn = e820_table_end++;
 	void *adr;
 
-	if (pfn >= table_top)
+	if (pfn >= e820_table_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = __va(pfn * PAGE_SIZE);
@@ -90,7 +86,7 @@
 
 #ifdef CONFIG_X86_PAE
 	if (!(pgd_val(*pgd) & _PAGE_PRESENT)) {
-		if (after_init_bootmem)
+		if (after_bootmem)
 			pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
 		else
 			pmd_table = (pmd_t *)alloc_low_page();
@@ -117,7 +113,7 @@
 	if (!(pmd_val(*pmd) & _PAGE_PRESENT)) {
 		pte_t *page_table = NULL;
 
-		if (after_init_bootmem) {
+		if (after_bootmem) {
 #ifdef CONFIG_DEBUG_PAGEALLOC
 			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
 #endif
@@ -168,12 +164,12 @@
 	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
 	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
 	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
-	    && ((__pa(pte) >> PAGE_SHIFT) < table_start
-		|| (__pa(pte) >> PAGE_SHIFT) >= table_end)) {
+	    && ((__pa(pte) >> PAGE_SHIFT) < e820_table_start
+		|| (__pa(pte) >> PAGE_SHIFT) >= e820_table_end)) {
 		pte_t *newpte;
 		int i;
 
-		BUG_ON(after_init_bootmem);
+		BUG_ON(after_bootmem);
 		newpte = alloc_low_page();
 		for (i = 0; i < PTRS_PER_PTE; i++)
 			set_pte(newpte + i, pte[i]);
@@ -242,11 +238,14 @@
  * of max_low_pfn pages, by creating page tables starting from address
  * PAGE_OFFSET:
  */
-static void __init kernel_physical_mapping_init(pgd_t *pgd_base,
-						unsigned long start_pfn,
-						unsigned long end_pfn,
-						int use_pse)
+unsigned long __init
+kernel_physical_mapping_init(unsigned long start,
+			     unsigned long end,
+			     unsigned long page_size_mask)
 {
+	int use_pse = page_size_mask == (1<<PG_LEVEL_2M);
+	unsigned long start_pfn, end_pfn;
+	pgd_t *pgd_base = swapper_pg_dir;
 	int pgd_idx, pmd_idx, pte_ofs;
 	unsigned long pfn;
 	pgd_t *pgd;
@@ -255,6 +254,9 @@
 	unsigned pages_2m, pages_4k;
 	int mapping_iter;
 
+	start_pfn = start >> PAGE_SHIFT;
+	end_pfn = end >> PAGE_SHIFT;
+
 	/*
 	 * First iteration will setup identity mapping using large/small pages
 	 * based on use_pse, with other attributes same as set by
@@ -369,26 +371,6 @@
 		mapping_iter = 2;
 		goto repeat;
 	}
-}
-
-/*
- * devmem_is_allowed() checks to see if /dev/mem access to a certain address
- * is valid. The argument is a physical page number.
- *
- *
- * On x86, access has to be given to the first megabyte of ram because that area
- * contains bios code and data regions used by X and dosemu and similar apps.
- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
- * mmio resources as well as potential bios/acpi data regions.
- */
-int devmem_is_allowed(unsigned long pagenr)
-{
-	if (pagenr <= 256)
-		return 1;
-	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
-		return 0;
-	if (!page_is_ram(pagenr))
-		return 1;
 	return 0;
 }
 
@@ -545,8 +527,9 @@
  * be partially populated, and so it avoids stomping on any existing
  * mappings.
  */
-static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base)
+void __init early_ioremap_page_table_range_init(void)
 {
+	pgd_t *pgd_base = swapper_pg_dir;
 	unsigned long vaddr, end;
 
 	/*
@@ -641,7 +624,7 @@
 }
 early_param("noexec", noexec_setup);
 
-static void __init set_nx(void)
+void __init set_nx(void)
 {
 	unsigned int v[4], l, h;
 
@@ -793,6 +776,8 @@
 #ifdef CONFIG_FLATMEM
 	max_mapnr = num_physpages;
 #endif
+	__vmalloc_start_set = true;
+
 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
 			pages_to_mb(max_low_pfn));
 
@@ -814,176 +799,66 @@
 	free_area_init_nodes(max_zone_pfns);
 }
 
+static unsigned long __init setup_node_bootmem(int nodeid,
+				 unsigned long start_pfn,
+				 unsigned long end_pfn,
+				 unsigned long bootmap)
+{
+	unsigned long bootmap_size;
+
+	/* don't touch min_low_pfn */
+	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
+					 bootmap >> PAGE_SHIFT,
+					 start_pfn, end_pfn);
+	printk(KERN_INFO "  node %d low ram: %08lx - %08lx\n",
+		nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+	printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
+		 nodeid, bootmap, bootmap + bootmap_size);
+	free_bootmem_with_active_regions(nodeid, end_pfn);
+	early_res_to_bootmem(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+
+	return bootmap + bootmap_size;
+}
+
 void __init setup_bootmem_allocator(void)
 {
-	int i;
+	int nodeid;
 	unsigned long bootmap_size, bootmap;
 	/*
 	 * Initialize the boot-time allocator (with low memory only):
 	 */
 	bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT;
-	bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT,
-				 max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
+	bootmap = find_e820_area(0, max_pfn_mapped<<PAGE_SHIFT, bootmap_size,
 				 PAGE_SIZE);
 	if (bootmap == -1L)
 		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
 	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
 
-	/* don't touch min_low_pfn */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
-					 min_low_pfn, max_low_pfn);
 	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
 		 max_pfn_mapped<<PAGE_SHIFT);
-	printk(KERN_INFO "  low ram: %08lx - %08lx\n",
-		 min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT);
-	printk(KERN_INFO "  bootmap %08lx - %08lx\n",
-		 bootmap, bootmap + bootmap_size);
-	for_each_online_node(i)
-		free_bootmem_with_active_regions(i, max_low_pfn);
-	early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
+	printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
 
-	after_init_bootmem = 1;
-}
+	for_each_online_node(nodeid) {
+		 unsigned long start_pfn, end_pfn;
 
-static void __init find_early_table_space(unsigned long end, int use_pse)
-{
-	unsigned long puds, pmds, ptes, tables, start;
-
-	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-
-	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
-	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
-
-	if (use_pse) {
-		unsigned long extra;
-
-		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
-		extra += PMD_SIZE;
-		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	} else
-		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
-	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
-
-	/* for fixmap */
-	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
-
-	/*
-	 * RED-PEN putting page tables only on node 0 could
-	 * cause a hotspot and fill up ZONE_DMA. The page tables
-	 * need roughly 0.5KB per GB.
-	 */
-	start = 0x7000;
-	table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
-					tables, PAGE_SIZE);
-	if (table_start == -1UL)
-		panic("Cannot find space for the kernel page tables");
-
-	table_start >>= PAGE_SHIFT;
-	table_end = table_start;
-	table_top = table_start + (tables>>PAGE_SHIFT);
-
-	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
-		end, table_start << PAGE_SHIFT,
-		(table_start << PAGE_SHIFT) + tables);
-}
-
-unsigned long __init_refok init_memory_mapping(unsigned long start,
-						unsigned long end)
-{
-	pgd_t *pgd_base = swapper_pg_dir;
-	unsigned long start_pfn, end_pfn;
-	unsigned long big_page_start;
-#ifdef CONFIG_DEBUG_PAGEALLOC
-	/*
-	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
-	 * This will simplify cpa(), which otherwise needs to support splitting
-	 * large pages into small in interrupt context, etc.
-	 */
-	int use_pse = 0;
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+		start_pfn = node_start_pfn[nodeid];
+		end_pfn = node_end_pfn[nodeid];
+		if (start_pfn > max_low_pfn)
+			continue;
+		if (end_pfn > max_low_pfn)
+			end_pfn = max_low_pfn;
 #else
-	int use_pse = cpu_has_pse;
+		start_pfn = 0;
+		end_pfn = max_low_pfn;
 #endif
-
-	/*
-	 * Find space for the kernel direct mapping tables.
-	 */
-	if (!after_init_bootmem)
-		find_early_table_space(end, use_pse);
-
-#ifdef CONFIG_X86_PAE
-	set_nx();
-	if (nx_enabled)
-		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
-#endif
-
-	/* Enable PSE if available */
-	if (cpu_has_pse)
-		set_in_cr4(X86_CR4_PSE);
-
-	/* Enable PGE if available */
-	if (cpu_has_pge) {
-		set_in_cr4(X86_CR4_PGE);
-		__supported_pte_mask |= _PAGE_GLOBAL;
+		bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
+						 bootmap);
 	}
 
-	/*
-	 * Don't use a large page for the first 2/4MB of memory
-	 * because there are often fixed size MTRRs in there
-	 * and overlapping MTRRs into large pages can cause
-	 * slowdowns.
-	 */
-	big_page_start = PMD_SIZE;
-
-	if (start < big_page_start) {
-		start_pfn = start >> PAGE_SHIFT;
-		end_pfn = min(big_page_start>>PAGE_SHIFT, end>>PAGE_SHIFT);
-	} else {
-		/* head is not big page alignment ? */
-		start_pfn = start >> PAGE_SHIFT;
-		end_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
-				 << (PMD_SHIFT - PAGE_SHIFT);
-	}
-	if (start_pfn < end_pfn)
-		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, 0);
-
-	/* big page range */
-	start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
-			 << (PMD_SHIFT - PAGE_SHIFT);
-	if (start_pfn < (big_page_start >> PAGE_SHIFT))
-		start_pfn =  big_page_start >> PAGE_SHIFT;
-	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
-	if (start_pfn < end_pfn)
-		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn,
-					     use_pse);
-
-	/* tail is not big page alignment ? */
-	start_pfn = end_pfn;
-	if (start_pfn > (big_page_start>>PAGE_SHIFT)) {
-		end_pfn = end >> PAGE_SHIFT;
-		if (start_pfn < end_pfn)
-			kernel_physical_mapping_init(pgd_base, start_pfn,
-							 end_pfn, 0);
-	}
-
-	early_ioremap_page_table_range_init(pgd_base);
-
-	load_cr3(swapper_pg_dir);
-
-	__flush_tlb_all();
-
-	if (!after_init_bootmem)
-		reserve_early(table_start << PAGE_SHIFT,
-				 table_end << PAGE_SHIFT, "PGTABLE");
-
-	if (!after_init_bootmem)
-		early_memtest(start, end);
-
-	return end >> PAGE_SHIFT;
+	after_bootmem = 1;
 }
 
-
 /*
  * paging_init() sets up the page tables - note that the first 8MB are
  * already mapped by head.S.
@@ -1217,13 +1092,6 @@
 }
 #endif
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	free_init_pages("initrd memory", start, end);
-}
-#endif
-
 int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
 				   int flags)
 {
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 07f44d4..54efa57d 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -48,6 +48,7 @@
 #include <asm/kdebug.h>
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
+#include <asm/init.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -61,12 +62,6 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-int direct_gbpages
-#ifdef CONFIG_DIRECT_GBPAGES
-				= 1
-#endif
-;
-
 static int __init parse_direct_gbpages_off(char *arg)
 {
 	direct_gbpages = 0;
@@ -87,12 +82,10 @@
  * around without checking the pgd every time.
  */
 
-int after_bootmem;
-
 pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
-static int do_not_nx __cpuinitdata;
+static int disable_nx __cpuinitdata;
 
 /*
  * noexec=on|off
@@ -107,9 +100,9 @@
 		return -EINVAL;
 	if (!strncmp(str, "on", 2)) {
 		__supported_pte_mask |= _PAGE_NX;
-		do_not_nx = 0;
+		disable_nx = 0;
 	} else if (!strncmp(str, "off", 3)) {
-		do_not_nx = 1;
+		disable_nx = 1;
 		__supported_pte_mask &= ~_PAGE_NX;
 	}
 	return 0;
@@ -121,7 +114,7 @@
 	unsigned long efer;
 
 	rdmsrl(MSR_EFER, efer);
-	if (!(efer & EFER_NX) || do_not_nx)
+	if (!(efer & EFER_NX) || disable_nx)
 		__supported_pte_mask &= ~_PAGE_NX;
 }
 
@@ -325,13 +318,9 @@
 	}
 }
 
-static unsigned long __initdata table_start;
-static unsigned long __meminitdata table_end;
-static unsigned long __meminitdata table_top;
-
 static __ref void *alloc_low_page(unsigned long *phys)
 {
-	unsigned long pfn = table_end++;
+	unsigned long pfn = e820_table_end++;
 	void *adr;
 
 	if (after_bootmem) {
@@ -341,7 +330,7 @@
 		return adr;
 	}
 
-	if (pfn >= table_top)
+	if (pfn >= e820_table_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
@@ -581,58 +570,10 @@
 	return phys_pud_init(pud, addr, end, page_size_mask);
 }
 
-static void __init find_early_table_space(unsigned long end, int use_pse,
-					  int use_gbpages)
-{
-	unsigned long puds, pmds, ptes, tables, start;
-
-	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-	if (use_gbpages) {
-		unsigned long extra;
-		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-	} else
-		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
-	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
-
-	if (use_pse) {
-		unsigned long extra;
-		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
-		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	} else
-		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
-
-	/*
-	 * RED-PEN putting page tables only on node 0 could
-	 * cause a hotspot and fill up ZONE_DMA. The page tables
-	 * need roughly 0.5KB per GB.
-	 */
-	start = 0x8000;
-	table_start = find_e820_area(start, end, tables, PAGE_SIZE);
-	if (table_start == -1UL)
-		panic("Cannot find space for the kernel page tables");
-
-	table_start >>= PAGE_SHIFT;
-	table_end = table_start;
-	table_top = table_start + (tables >> PAGE_SHIFT);
-
-	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
-		end, table_start << PAGE_SHIFT, table_top << PAGE_SHIFT);
-}
-
-static void __init init_gbpages(void)
-{
-	if (direct_gbpages && cpu_has_gbpages)
-		printk(KERN_INFO "Using GB pages for direct mapping\n");
-	else
-		direct_gbpages = 0;
-}
-
-static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
-						unsigned long end,
-						unsigned long page_size_mask)
+unsigned long __init
+kernel_physical_mapping_init(unsigned long start,
+			     unsigned long end,
+			     unsigned long page_size_mask)
 {
 
 	unsigned long next, last_map_addr = end;
@@ -669,176 +610,6 @@
 	return last_map_addr;
 }
 
-struct map_range {
-	unsigned long start;
-	unsigned long end;
-	unsigned page_size_mask;
-};
-
-#define NR_RANGE_MR 5
-
-static int save_mr(struct map_range *mr, int nr_range,
-		   unsigned long start_pfn, unsigned long end_pfn,
-		   unsigned long page_size_mask)
-{
-
-	if (start_pfn < end_pfn) {
-		if (nr_range >= NR_RANGE_MR)
-			panic("run out of range for init_memory_mapping\n");
-		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
-		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
-		mr[nr_range].page_size_mask = page_size_mask;
-		nr_range++;
-	}
-
-	return nr_range;
-}
-
-/*
- * Setup the direct mapping of the physical memory at PAGE_OFFSET.
- * This runs before bootmem is initialized and gets pages directly from
- * the physical memory. To access them they are temporarily mapped.
- */
-unsigned long __init_refok init_memory_mapping(unsigned long start,
-					       unsigned long end)
-{
-	unsigned long last_map_addr = 0;
-	unsigned long page_size_mask = 0;
-	unsigned long start_pfn, end_pfn;
-	unsigned long pos;
-
-	struct map_range mr[NR_RANGE_MR];
-	int nr_range, i;
-	int use_pse, use_gbpages;
-
-	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
-
-	/*
-	 * Find space for the kernel direct mapping tables.
-	 *
-	 * Later we should allocate these tables in the local node of the
-	 * memory mapped. Unfortunately this is done currently before the
-	 * nodes are discovered.
-	 */
-	if (!after_bootmem)
-		init_gbpages();
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
-	/*
-	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
-	 * This will simplify cpa(), which otherwise needs to support splitting
-	 * large pages into small in interrupt context, etc.
-	 */
-	use_pse = use_gbpages = 0;
-#else
-	use_pse = cpu_has_pse;
-	use_gbpages = direct_gbpages;
-#endif
-
-	if (use_gbpages)
-		page_size_mask |= 1 << PG_LEVEL_1G;
-	if (use_pse)
-		page_size_mask |= 1 << PG_LEVEL_2M;
-
-	memset(mr, 0, sizeof(mr));
-	nr_range = 0;
-
-	/* head if not big page alignment ?*/
-	start_pfn = start >> PAGE_SHIFT;
-	pos = start_pfn << PAGE_SHIFT;
-	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
-			<< (PMD_SHIFT - PAGE_SHIFT);
-	if (end_pfn > (end >> PAGE_SHIFT))
-		end_pfn = end >> PAGE_SHIFT;
-	if (start_pfn < end_pfn) {
-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
-		pos = end_pfn << PAGE_SHIFT;
-	}
-
-	/* big page (2M) range*/
-	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
-			 << (PMD_SHIFT - PAGE_SHIFT);
-	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
-			 << (PUD_SHIFT - PAGE_SHIFT);
-	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
-		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
-	if (start_pfn < end_pfn) {
-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
-				page_size_mask & (1<<PG_LEVEL_2M));
-		pos = end_pfn << PAGE_SHIFT;
-	}
-
-	/* big page (1G) range */
-	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
-			 << (PUD_SHIFT - PAGE_SHIFT);
-	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
-	if (start_pfn < end_pfn) {
-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
-				page_size_mask &
-				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
-		pos = end_pfn << PAGE_SHIFT;
-	}
-
-	/* tail is not big page (1G) alignment */
-	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
-			 << (PMD_SHIFT - PAGE_SHIFT);
-	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
-	if (start_pfn < end_pfn) {
-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
-				page_size_mask & (1<<PG_LEVEL_2M));
-		pos = end_pfn << PAGE_SHIFT;
-	}
-
-	/* tail is not big page (2M) alignment */
-	start_pfn = pos>>PAGE_SHIFT;
-	end_pfn = end>>PAGE_SHIFT;
-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
-
-	/* try to merge same page size and continuous */
-	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
-		unsigned long old_start;
-		if (mr[i].end != mr[i+1].start ||
-		    mr[i].page_size_mask != mr[i+1].page_size_mask)
-			continue;
-		/* move it */
-		old_start = mr[i].start;
-		memmove(&mr[i], &mr[i+1],
-			 (nr_range - 1 - i) * sizeof (struct map_range));
-		mr[i--].start = old_start;
-		nr_range--;
-	}
-
-	for (i = 0; i < nr_range; i++)
-		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
-				mr[i].start, mr[i].end,
-			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
-			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
-
-	if (!after_bootmem)
-		find_early_table_space(end, use_pse, use_gbpages);
-
-	for (i = 0; i < nr_range; i++)
-		last_map_addr = kernel_physical_mapping_init(
-					mr[i].start, mr[i].end,
-					mr[i].page_size_mask);
-
-	if (!after_bootmem)
-		mmu_cr4_features = read_cr4();
-	__flush_tlb_all();
-
-	if (!after_bootmem && table_end > table_start)
-		reserve_early(table_start << PAGE_SHIFT,
-				 table_end << PAGE_SHIFT, "PGTABLE");
-
-	printk(KERN_INFO "last_map_addr: %lx end: %lx\n",
-			 last_map_addr, end);
-
-	if (!after_bootmem)
-		early_memtest(start, end);
-
-	return last_map_addr >> PAGE_SHIFT;
-}
-
 #ifndef CONFIG_NUMA
 void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 {
@@ -910,28 +681,6 @@
 
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
-/*
- * devmem_is_allowed() checks to see if /dev/mem access to a certain address
- * is valid. The argument is a physical page number.
- *
- *
- * On x86, access has to be given to the first megabyte of ram because that area
- * contains bios code and data regions used by X and dosemu and similar apps.
- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
- * mmio resources as well as potential bios/acpi data regions.
- */
-int devmem_is_allowed(unsigned long pagenr)
-{
-	if (pagenr <= 256)
-		return 1;
-	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
-		return 0;
-	if (!page_is_ram(pagenr))
-		return 1;
-	return 0;
-}
-
-
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
 			 kcore_modules, kcore_vsyscall;
 
@@ -1019,13 +768,6 @@
 
 #endif
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	free_init_pages("initrd memory", start, end);
-}
-#endif
-
 int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
 				   int flags)
 {
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index 04102d4..699c9b2 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -31,16 +31,27 @@
 }
 EXPORT_SYMBOL_GPL(is_io_mapping_possible);
 
-/* Map 'pfn' using fixed map 'type' and protections 'prot'
- */
-void *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
 {
 	enum fixed_addresses idx;
 	unsigned long vaddr;
 
 	pagefault_disable();
 
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
+	arch_flush_lazy_mmu_mode();
+
+	return (void *)vaddr;
+}
+
+/*
+ * Map 'pfn' using fixed map 'type' and protections 'prot'
+ */
+void *
+iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+{
 	/*
 	 * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
 	 * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
@@ -50,12 +61,7 @@
 	if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
 		prot = PAGE_KERNEL_UC_MINUS;
 
-	idx = type + KM_TYPE_NR*smp_processor_id();
-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-	set_pte(kmap_pte-idx, pfn_pte(pfn, prot));
-	arch_flush_lazy_mmu_mode();
-
-	return (void*) vaddr;
+	return kmap_atomic_prot_pfn(pfn, type, prot);
 }
 EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
 
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 433f7bd..0dfa09d 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -22,13 +22,17 @@
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
 
-#ifdef CONFIG_X86_64
-
-static inline int phys_addr_valid(unsigned long addr)
+static inline int phys_addr_valid(resource_size_t addr)
 {
-	return addr < (1UL << boot_cpu_data.x86_phys_bits);
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	return !(addr >> boot_cpu_data.x86_phys_bits);
+#else
+	return 1;
+#endif
 }
 
+#ifdef CONFIG_X86_64
+
 unsigned long __phys_addr(unsigned long x)
 {
 	if (x >= __START_KERNEL_map) {
@@ -38,8 +42,7 @@
 	} else {
 		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
 		x -= PAGE_OFFSET;
-		VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM :
-					!phys_addr_valid(x));
+		VIRTUAL_BUG_ON(!phys_addr_valid(x));
 	}
 	return x;
 }
@@ -56,10 +59,8 @@
 		if (x < PAGE_OFFSET)
 			return false;
 		x -= PAGE_OFFSET;
-		if (system_state == SYSTEM_BOOTING ?
-				x > MAXMEM : !phys_addr_valid(x)) {
+		if (!phys_addr_valid(x))
 			return false;
-		}
 	}
 
 	return pfn_valid(x >> PAGE_SHIFT);
@@ -68,18 +69,12 @@
 
 #else
 
-static inline int phys_addr_valid(unsigned long addr)
-{
-	return 1;
-}
-
 #ifdef CONFIG_DEBUG_VIRTUAL
 unsigned long __phys_addr(unsigned long x)
 {
-	/* VMALLOC_* aren't constants; not available at the boot time */
+	/* VMALLOC_* aren't constants  */
 	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
-	VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING &&
-		is_vmalloc_addr((void *) x));
+	VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
 	return x - PAGE_OFFSET;
 }
 EXPORT_SYMBOL(__phys_addr);
@@ -89,7 +84,9 @@
 {
 	if (x < PAGE_OFFSET)
 		return false;
-	if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x))
+	if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
+		return false;
+	if (x >= FIXADDR_START)
 		return false;
 	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
 }
@@ -508,13 +505,19 @@
 	return &bm_pte[pte_index(addr)];
 }
 
+static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
+
 void __init early_ioremap_init(void)
 {
 	pmd_t *pmd;
+	int i;
 
 	if (early_ioremap_debug)
 		printk(KERN_INFO "early_ioremap_init()\n");
 
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
+
 	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
 	memset(bm_pte, 0, sizeof(bm_pte));
 	pmd_populate_kernel(&init_mm, pmd, bm_pte);
@@ -581,6 +584,7 @@
 
 static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
 static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+
 static int __init check_early_ioremap_leak(void)
 {
 	int count = 0;
@@ -602,7 +606,8 @@
 }
 late_initcall(check_early_ioremap_leak);
 
-static void __init __iomem *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
+static void __init __iomem *
+__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
 {
 	unsigned long offset, last_addr;
 	unsigned int nrpages;
@@ -668,9 +673,9 @@
 		--nrpages;
 	}
 	if (early_ioremap_debug)
-		printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
+		printk(KERN_CONT "%08lx + %08lx\n", offset, slot_virt[slot]);
 
-	prev_map[slot] = (void __iomem *)(offset + fix_to_virt(idx0));
+	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
 	return prev_map[slot];
 }
 
@@ -738,8 +743,3 @@
 	}
 	prev_map[slot] = NULL;
 }
-
-void __this_fixmap_does_not_exist(void)
-{
-	WARN_ON(1);
-}
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c
index 6a518dd..4f115e0 100644
--- a/arch/x86/mm/kmmio.c
+++ b/arch/x86/mm/kmmio.c
@@ -310,7 +310,7 @@
 	struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx);
 
 	if (!ctx->active) {
-		pr_warning("kmmio: spurious debug trap on CPU %d.\n",
+		pr_debug("kmmio: spurious debug trap on CPU %d.\n",
 							smp_processor_id());
 		goto out;
 	}
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
index 0bcd788..605c8be 100644
--- a/arch/x86/mm/memtest.c
+++ b/arch/x86/mm/memtest.c
@@ -100,6 +100,9 @@
 {
 	if (arg)
 		memtest_pattern = simple_strtoul(arg, NULL, 0);
+	else
+		memtest_pattern = ARRAY_SIZE(patterns);
+
 	return 0;
 }
 
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 451fe95..3daefa0 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -416,10 +416,11 @@
 	for_each_online_node(nid)
 		propagate_e820_map_node(nid);
 
-	for_each_online_node(nid)
+	for_each_online_node(nid) {
 		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+		NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
+	}
 
-	NODE_DATA(0)->bdata = &bootmem_node_data[0];
 	setup_bootmem_allocator();
 }
 
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 9c42949..d71e1b6 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -16,6 +16,7 @@
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/setup.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/proto.h>
@@ -33,6 +34,7 @@
 	unsigned long	pfn;
 	unsigned	force_split : 1;
 	int		curpage;
+	struct page	**pages;
 };
 
 /*
@@ -45,6 +47,7 @@
 
 #define CPA_FLUSHTLB 1
 #define CPA_ARRAY 2
+#define CPA_PAGES_ARRAY 4
 
 #ifdef CONFIG_PROC_FS
 static unsigned long direct_pages_count[PG_LEVEL_NUM];
@@ -95,7 +98,7 @@
 
 static inline unsigned long highmap_end_pfn(void)
 {
-	return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
+	return __pa(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
 }
 
 #endif
@@ -201,10 +204,10 @@
 	}
 }
 
-static void cpa_flush_array(unsigned long *start, int numpages, int cache)
+static void cpa_flush_array(unsigned long *start, int numpages, int cache,
+			    int in_flags, struct page **pages)
 {
 	unsigned int i, level;
-	unsigned long *addr;
 
 	BUG_ON(irqs_disabled());
 
@@ -225,14 +228,22 @@
 	 * will cause all other CPUs to flush the same
 	 * cachelines:
 	 */
-	for (i = 0, addr = start; i < numpages; i++, addr++) {
-		pte_t *pte = lookup_address(*addr, &level);
+	for (i = 0; i < numpages; i++) {
+		unsigned long addr;
+		pte_t *pte;
+
+		if (in_flags & CPA_PAGES_ARRAY)
+			addr = (unsigned long)page_address(pages[i]);
+		else
+			addr = start[i];
+
+		pte = lookup_address(addr, &level);
 
 		/*
 		 * Only flush present addresses:
 		 */
 		if (pte && (pte_val(*pte) & _PAGE_PRESENT))
-			clflush_cache_range((void *) *addr, PAGE_SIZE);
+			clflush_cache_range((void *)addr, PAGE_SIZE);
 	}
 }
 
@@ -584,7 +595,9 @@
 	unsigned int level;
 	pte_t *kpte, old_pte;
 
-	if (cpa->flags & CPA_ARRAY)
+	if (cpa->flags & CPA_PAGES_ARRAY)
+		address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
+	else if (cpa->flags & CPA_ARRAY)
 		address = cpa->vaddr[cpa->curpage];
 	else
 		address = *cpa->vaddr;
@@ -687,7 +700,9 @@
 	 * No need to redo, when the primary call touched the direct
 	 * mapping already:
 	 */
-	if (cpa->flags & CPA_ARRAY)
+	if (cpa->flags & CPA_PAGES_ARRAY)
+		vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
+	else if (cpa->flags & CPA_ARRAY)
 		vaddr = cpa->vaddr[cpa->curpage];
 	else
 		vaddr = *cpa->vaddr;
@@ -698,7 +713,7 @@
 		alias_cpa = *cpa;
 		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
 		alias_cpa.vaddr = &temp_cpa_vaddr;
-		alias_cpa.flags &= ~CPA_ARRAY;
+		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
 
 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
@@ -711,7 +726,7 @@
 	 * No need to redo, when the primary call touched the high
 	 * mapping already:
 	 */
-	if (within(vaddr, (unsigned long) _text, (unsigned long) _end))
+	if (within(vaddr, (unsigned long) _text, _brk_end))
 		return 0;
 
 	/*
@@ -724,7 +739,7 @@
 	alias_cpa = *cpa;
 	temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base;
 	alias_cpa.vaddr = &temp_cpa_vaddr;
-	alias_cpa.flags &= ~CPA_ARRAY;
+	alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
 	/*
 	 * The high mapping range is imprecise, so ignore the return value.
@@ -745,7 +760,7 @@
 		 */
 		cpa->numpages = numpages;
 		/* for array changes, we can't use large page */
-		if (cpa->flags & CPA_ARRAY)
+		if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
 			cpa->numpages = 1;
 
 		if (!debug_pagealloc)
@@ -769,7 +784,7 @@
 		 */
 		BUG_ON(cpa->numpages > numpages);
 		numpages -= cpa->numpages;
-		if (cpa->flags & CPA_ARRAY)
+		if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
 			cpa->curpage++;
 		else
 			*cpa->vaddr += cpa->numpages * PAGE_SIZE;
@@ -786,7 +801,8 @@
 
 static int change_page_attr_set_clr(unsigned long *addr, int numpages,
 				    pgprot_t mask_set, pgprot_t mask_clr,
-				    int force_split, int array)
+				    int force_split, int in_flag,
+				    struct page **pages)
 {
 	struct cpa_data cpa;
 	int ret, cache, checkalias;
@@ -801,15 +817,7 @@
 		return 0;
 
 	/* Ensure we are PAGE_SIZE aligned */
-	if (!array) {
-		if (*addr & ~PAGE_MASK) {
-			*addr &= PAGE_MASK;
-			/*
-			 * People should not be passing in unaligned addresses:
-			 */
-			WARN_ON_ONCE(1);
-		}
-	} else {
+	if (in_flag & CPA_ARRAY) {
 		int i;
 		for (i = 0; i < numpages; i++) {
 			if (addr[i] & ~PAGE_MASK) {
@@ -817,6 +825,18 @@
 				WARN_ON_ONCE(1);
 			}
 		}
+	} else if (!(in_flag & CPA_PAGES_ARRAY)) {
+		/*
+		 * in_flag of CPA_PAGES_ARRAY implies it is aligned.
+		 * No need to cehck in that case
+		 */
+		if (*addr & ~PAGE_MASK) {
+			*addr &= PAGE_MASK;
+			/*
+			 * People should not be passing in unaligned addresses:
+			 */
+			WARN_ON_ONCE(1);
+		}
 	}
 
 	/* Must avoid aliasing mappings in the highmem code */
@@ -832,6 +852,7 @@
 	arch_flush_lazy_mmu_mode();
 
 	cpa.vaddr = addr;
+	cpa.pages = pages;
 	cpa.numpages = numpages;
 	cpa.mask_set = mask_set;
 	cpa.mask_clr = mask_clr;
@@ -839,8 +860,8 @@
 	cpa.curpage = 0;
 	cpa.force_split = force_split;
 
-	if (array)
-		cpa.flags |= CPA_ARRAY;
+	if (in_flag & (CPA_ARRAY | CPA_PAGES_ARRAY))
+		cpa.flags |= in_flag;
 
 	/* No alias checking for _NX bit modifications */
 	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
@@ -866,9 +887,10 @@
 	 * wbindv):
 	 */
 	if (!ret && cpu_has_clflush) {
-		if (cpa.flags & CPA_ARRAY)
-			cpa_flush_array(addr, numpages, cache);
-		else
+		if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
+			cpa_flush_array(addr, numpages, cache,
+					cpa.flags, pages);
+		} else
 			cpa_flush_range(*addr, numpages, cache);
 	} else
 		cpa_flush_all(cache);
@@ -888,14 +910,28 @@
 				       pgprot_t mask, int array)
 {
 	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0,
-		array);
+		(array ? CPA_ARRAY : 0), NULL);
 }
 
 static inline int change_page_attr_clear(unsigned long *addr, int numpages,
 					 pgprot_t mask, int array)
 {
 	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0,
-		array);
+		(array ? CPA_ARRAY : 0), NULL);
+}
+
+static inline int cpa_set_pages_array(struct page **pages, int numpages,
+				       pgprot_t mask)
+{
+	return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0,
+		CPA_PAGES_ARRAY, pages);
+}
+
+static inline int cpa_clear_pages_array(struct page **pages, int numpages,
+					 pgprot_t mask)
+{
+	return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0,
+		CPA_PAGES_ARRAY, pages);
 }
 
 int _set_memory_uc(unsigned long addr, int numpages)
@@ -1043,7 +1079,7 @@
 int set_memory_4k(unsigned long addr, int numpages)
 {
 	return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
-					__pgprot(0), 1, 0);
+					__pgprot(0), 1, 0, NULL);
 }
 
 int set_pages_uc(struct page *page, int numpages)
@@ -1054,6 +1090,35 @@
 }
 EXPORT_SYMBOL(set_pages_uc);
 
+int set_pages_array_uc(struct page **pages, int addrinarray)
+{
+	unsigned long start;
+	unsigned long end;
+	int i;
+	int free_idx;
+
+	for (i = 0; i < addrinarray; i++) {
+		start = (unsigned long)page_address(pages[i]);
+		end = start + PAGE_SIZE;
+		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
+			goto err_out;
+	}
+
+	if (cpa_set_pages_array(pages, addrinarray,
+			__pgprot(_PAGE_CACHE_UC_MINUS)) == 0) {
+		return 0; /* Success */
+	}
+err_out:
+	free_idx = i;
+	for (i = 0; i < free_idx; i++) {
+		start = (unsigned long)page_address(pages[i]);
+		end = start + PAGE_SIZE;
+		free_memtype(start, end);
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(set_pages_array_uc);
+
 int set_pages_wb(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);
@@ -1062,6 +1127,26 @@
 }
 EXPORT_SYMBOL(set_pages_wb);
 
+int set_pages_array_wb(struct page **pages, int addrinarray)
+{
+	int retval;
+	unsigned long start;
+	unsigned long end;
+	int i;
+
+	retval = cpa_clear_pages_array(pages, addrinarray,
+			__pgprot(_PAGE_CACHE_MASK));
+
+	for (i = 0; i < addrinarray; i++) {
+		start = (unsigned long)page_address(pages[i]);
+		end = start + PAGE_SIZE;
+		free_memtype(start, end);
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL(set_pages_array_wb);
+
 int set_pages_x(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 2ed3715..640339e 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -677,10 +677,11 @@
 	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
 
 	/*
-	 * reserve_pfn_range() doesn't support RAM pages.
+	 * reserve_pfn_range() doesn't support RAM pages. Maintain the current
+	 * behavior with RAM pages by returning success.
 	 */
 	if (is_ram != 0)
-		return -EINVAL;
+		return 0;
 
 	ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
 	if (ret)
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
index f2e477c..46c8834 100644
--- a/arch/x86/mm/pgtable_32.c
+++ b/arch/x86/mm/pgtable_32.c
@@ -50,7 +50,7 @@
 	}
 	pte = pte_offset_kernel(pmd, vaddr);
 	if (pte_val(pteval))
-		set_pte_present(&init_mm, vaddr, pte, pteval);
+		set_pte_at(&init_mm, vaddr, pte, pteval);
 	else
 		pte_clear(&init_mm, vaddr, pte);
 
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index a654d59..821e970 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -187,11 +187,6 @@
 		       cpumask, cpumask_of(smp_processor_id()));
 
 	/*
-	 * Make the above memory operations globally visible before
-	 * sending the IPI.
-	 */
-	smp_mb();
-	/*
 	 * We have to send the IPI only to
 	 * CPUs affected.
 	 */
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 82d22fc..8c362b9 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -90,7 +90,7 @@
 	return 0;
 }
 
-static struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitdata = {
+static const struct dmi_system_id can_skip_pciprobe_dmi_table[] __devinitconst = {
 /*
  * Systems where PCI IO resource ISA alignment can be skipped
  * when the ISA enable bit in the bridge control is not set
@@ -183,7 +183,7 @@
 }
 #endif
 
-static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
+static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = {
 #ifdef __i386__
 /*
  * Laptops which need pci=assign-busses to see Cardbus cards
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 7d388d5..9c49919 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -356,7 +356,7 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
 
 
-static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = {
+static const struct dmi_system_id __devinitconst msi_k8t_dmi_table[] = {
 	{
 		.ident = "MSI-K8T-Neo2Fir",
 		.matches = {
@@ -413,7 +413,7 @@
  */
 static u16 toshiba_line_size;
 
-static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = {
+static const struct dmi_system_id __devinitconst toshiba_ohci1394_dmi_table[] = {
 	{
 		.ident = "Toshiba PS5 based laptop",
 		.matches = {
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 5ead808..f234a37 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -319,6 +319,9 @@
 			return -EINVAL;
 		}
 		flags = new_flags;
+		vma->vm_page_prot = __pgprot(
+			(pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK) |
+			flags);
 	}
 
 	if (((vma->vm_pgoff < max_low_pfn_mapped) ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index cb6afa4..db3802f 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1723,9 +1723,9 @@
 {
 	pmd_t *kernel_pmd;
 
-	init_pg_tables_start = __pa(pgd);
-	init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;
-	max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024);
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
+				  xen_start_info->nr_pt_frames * PAGE_SIZE +
+				  512*1024);
 
 	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
 	memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
@@ -1870,7 +1870,6 @@
 
 #ifdef CONFIG_X86_PAE
 	.set_pte_atomic = xen_set_pte_atomic,
-	.set_pte_present = xen_set_pte_at,
 	.pte_clear = xen_pte_clear,
 	.pmd_clear = xen_pmd_clear,
 #endif	/* CONFIG_X86_PAE */
diff --git a/drivers/Makefile b/drivers/Makefile
index c1bf417..2618a61 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -36,13 +36,14 @@
 
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
-obj-y				+= base/ block/ misc/ mfd/ net/ media/
+obj-y				+= base/ block/ misc/ mfd/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
-obj-$(CONFIG_ATM)		+= atm/
 obj-y				+= macintosh/
 obj-$(CONFIG_IDE)		+= ide/
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_ATA)		+= ata/
+obj-y				+= net/
+obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_FUSION)		+= message/
 obj-$(CONFIG_FIREWIRE)		+= firewire/
 obj-y				+= ieee1394/
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index e7347db..b663b7f 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -45,8 +45,6 @@
 	.stepping	= 6,
 };
 
-#define PATA_ICSIDE_MAX_SG	128
-
 struct pata_icside_state {
 	void __iomem *irq_port;
 	void __iomem *ioc_base;
@@ -57,7 +55,6 @@
 		u8 disabled;
 		unsigned int speed[ATA_MAX_DEVICES];
 	} port[2];
-	struct scatterlist sg[PATA_ICSIDE_MAX_SG];
 };
 
 struct pata_icside_info {
@@ -222,9 +219,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct pata_icside_state *state = ap->host->private_data;
-	struct scatterlist *sg, *rsg = state->sg;
 	unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
-	unsigned int si;
 
 	/*
 	 * We are simplex; BUG if we try to fiddle with DMA
@@ -233,20 +228,12 @@
 	BUG_ON(dma_channel_active(state->dma));
 
 	/*
-	 * Copy ATAs scattered sg list into a contiguous array of sg
-	 */
-	for_each_sg(qc->sg, sg, qc->n_elem, si) {
-		memcpy(rsg, sg, sizeof(*sg));
-		rsg++;
-	}
-
-	/*
 	 * Route the DMA signals to the correct interface
 	 */
 	writeb(state->port[ap->port_no].port_sel, state->ioc_base);
 
 	set_dma_speed(state->dma, state->port[ap->port_no].speed[qc->dev->devno]);
-	set_dma_sg(state->dma, state->sg, rsg - state->sg);
+	set_dma_sg(state->dma, qc->sg, qc->n_elem);
 	set_dma_mode(state->dma, write ? DMA_MODE_WRITE : DMA_MODE_READ);
 
 	/* issue r/w command */
@@ -306,8 +293,8 @@
 
 static struct scsi_host_template pata_icside_sht = {
 	ATA_BASE_SHT(DRV_NAME),
-	.sg_tablesize		= PATA_ICSIDE_MAX_SG,
-	.dma_boundary		= ~0, /* no dma boundaries */
+	.sg_tablesize		= SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.dma_boundary		= IOMD_DMA_BOUNDARY,
 };
 
 static void pata_icside_postreset(struct ata_link *link, unsigned int *classes)
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index ba68a46..538313f 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -102,7 +102,7 @@
 		return -EBUSY;
 
 	if (cpu_is_omap24xx()) {
-		rng_ick = clk_get(&pdev->dev, "rng_ick");
+		rng_ick = clk_get(&pdev->dev, "ick");
 		if (IS_ERR(rng_ick)) {
 			dev_err(&pdev->dev, "Could not get rng_ick\n");
 			ret = PTR_ERR(rng_ick);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 96adf28..20d90e6 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -90,6 +90,7 @@
 	blkdev_put(bdev, filp->f_mode);
 out:
 	mutex_unlock(&raw_mutex);
+	unlock_kernel();
 	return err;
 }
 
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index ae50a9d..da781d1 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1649,7 +1649,7 @@
 	}
 
 	/* Get IPU clock */
-	ipu_data.ipu_clk = clk_get(&pdev->dev, "ipu_clk");
+	ipu_data.ipu_clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(ipu_data.ipu_clk)) {
 		ret = PTR_ERR(ipu_data.ipu_clk);
 		goto err_clk_get;
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index eb8f72c..d420cc5 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -604,9 +604,7 @@
 
 	/* register new adapter to i2c module... */
 	adap->algo = &i2c_bit_algo;
-
-	adap->timeout = 100;	/* default values, should	*/
-	adap->retries = 3;	/* be replaced by defines	*/
+	adap->retries = 3;
 
 	return 0;
 }
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index d50b329..f68e5f8 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -22,14 +22,18 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pca.h>
 
-#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
-#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
-#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
+#define DEB1(fmt, args...) do { if (i2c_debug >= 1)			\
+				 printk(KERN_DEBUG fmt, ## args); } while (0)
+#define DEB2(fmt, args...) do { if (i2c_debug >= 2)			\
+				 printk(KERN_DEBUG fmt, ## args); } while (0)
+#define DEB3(fmt, args...) do { if (i2c_debug >= 3)			\
+				 printk(KERN_DEBUG fmt, ## args); } while (0)
 
 static int i2c_debug;
 
@@ -43,19 +47,27 @@
 #define pca_wait(adap) adap->wait_for_completion(adap->data)
 #define pca_reset(adap) adap->reset_chip(adap->data)
 
+static void pca9665_reset(void *pd)
+{
+	struct i2c_algo_pca_data *adap = pd;
+	pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
+	pca_outw(adap, I2C_PCA_IND, 0xA5);
+	pca_outw(adap, I2C_PCA_IND, 0x5A);
+}
+
 /*
  * Generate a start condition on the i2c bus.
  *
  * returns after the start condition has occurred
  */
-static void pca_start(struct i2c_algo_pca_data *adap)
+static int pca_start(struct i2c_algo_pca_data *adap)
 {
 	int sta = pca_get_con(adap);
 	DEB2("=== START\n");
 	sta |= I2C_PCA_CON_STA;
 	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
 	pca_set_con(adap, sta);
-	pca_wait(adap);
+	return pca_wait(adap);
 }
 
 /*
@@ -63,14 +75,14 @@
  *
  * return after the repeated start condition has occurred
  */
-static void pca_repeated_start(struct i2c_algo_pca_data *adap)
+static int pca_repeated_start(struct i2c_algo_pca_data *adap)
 {
 	int sta = pca_get_con(adap);
 	DEB2("=== REPEATED START\n");
 	sta |= I2C_PCA_CON_STA;
 	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
 	pca_set_con(adap, sta);
-	pca_wait(adap);
+	return pca_wait(adap);
 }
 
 /*
@@ -96,7 +108,7 @@
  *
  * returns after the address has been sent
  */
-static void pca_address(struct i2c_algo_pca_data *adap,
+static int pca_address(struct i2c_algo_pca_data *adap,
 			struct i2c_msg *msg)
 {
 	int sta = pca_get_con(adap);
@@ -113,7 +125,7 @@
 	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
 	pca_set_con(adap, sta);
 
-	pca_wait(adap);
+	return pca_wait(adap);
 }
 
 /*
@@ -121,7 +133,7 @@
  *
  * Returns after the byte has been transmitted
  */
-static void pca_tx_byte(struct i2c_algo_pca_data *adap,
+static int pca_tx_byte(struct i2c_algo_pca_data *adap,
 			__u8 b)
 {
 	int sta = pca_get_con(adap);
@@ -131,7 +143,7 @@
 	sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
 	pca_set_con(adap, sta);
 
-	pca_wait(adap);
+	return pca_wait(adap);
 }
 
 /*
@@ -151,7 +163,7 @@
  *
  * Returns after next byte has arrived.
  */
-static void pca_rx_ack(struct i2c_algo_pca_data *adap,
+static int pca_rx_ack(struct i2c_algo_pca_data *adap,
 		       int ack)
 {
 	int sta = pca_get_con(adap);
@@ -162,7 +174,7 @@
 		sta |= I2C_PCA_CON_AA;
 
 	pca_set_con(adap, sta);
-	pca_wait(adap);
+	return pca_wait(adap);
 }
 
 static int pca_xfer(struct i2c_adapter *i2c_adap,
@@ -175,14 +187,17 @@
 	int numbytes = 0;
 	int state;
 	int ret;
-	int timeout = i2c_adap->timeout;
+	int completed = 1;
+	unsigned long timeout = jiffies + i2c_adap->timeout;
 
-	while ((state = pca_status(adap)) != 0xf8 && timeout--) {
-		msleep(10);
-	}
-	if (state != 0xf8) {
-		dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
-		return -EAGAIN;
+	while (pca_status(adap) != 0xf8) {
+		if (time_before(jiffies, timeout)) {
+			msleep(10);
+		} else {
+			dev_dbg(&i2c_adap->dev, "bus is not idle. status is "
+				"%#04x\n", state);
+			return -EAGAIN;
+		}
 	}
 
 	DEB1("{{{ XFER %d messages\n", num);
@@ -218,18 +233,19 @@
 
 		switch (state) {
 		case 0xf8: /* On reset or stop the bus is idle */
-			pca_start(adap);
+			completed = pca_start(adap);
 			break;
 
 		case 0x08: /* A START condition has been transmitted */
 		case 0x10: /* A repeated start condition has been transmitted */
-			pca_address(adap, msg);
+			completed = pca_address(adap, msg);
 			break;
 
 		case 0x18: /* SLA+W has been transmitted; ACK has been received */
 		case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
 			if (numbytes < msg->len) {
-				pca_tx_byte(adap, msg->buf[numbytes]);
+				completed = pca_tx_byte(adap,
+							msg->buf[numbytes]);
 				numbytes++;
 				break;
 			}
@@ -237,7 +253,7 @@
 			if (curmsg == num)
 				pca_stop(adap);
 			else
-				pca_repeated_start(adap);
+				completed = pca_repeated_start(adap);
 			break;
 
 		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
@@ -246,21 +262,22 @@
 			goto out;
 
 		case 0x40: /* SLA+R has been transmitted; ACK has been received */
-			pca_rx_ack(adap, msg->len > 1);
+			completed = pca_rx_ack(adap, msg->len > 1);
 			break;
 
 		case 0x50: /* Data bytes has been received; ACK has been returned */
 			if (numbytes < msg->len) {
 				pca_rx_byte(adap, &msg->buf[numbytes], 1);
 				numbytes++;
-				pca_rx_ack(adap, numbytes < msg->len - 1);
+				completed = pca_rx_ack(adap,
+						       numbytes < msg->len - 1);
 				break;
 			}
 			curmsg++; numbytes = 0;
 			if (curmsg == num)
 				pca_stop(adap);
 			else
-				pca_repeated_start(adap);
+				completed = pca_repeated_start(adap);
 			break;
 
 		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
@@ -283,7 +300,7 @@
 				if (curmsg == num)
 					pca_stop(adap);
 				else
-					pca_repeated_start(adap);
+					completed = pca_repeated_start(adap);
 			} else {
 				DEB2("NOT ACK sent after data byte received. "
 				     "Not final byte. numbytes %d. len %d\n",
@@ -309,11 +326,13 @@
 			break;
 		}
 
+		if (!completed)
+			goto out;
 	}
 
 	ret = curmsg;
  out:
-	DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
+	DEB1("}}} transfered %d/%d messages. "
 	     "status is %#04x. control is %#04x\n",
 	     curmsg, num, pca_status(adap),
 	     pca_get_con(adap));
@@ -330,26 +349,171 @@
 	.functionality	= pca_func,
 };
 
+static unsigned int pca_probe_chip(struct i2c_adapter *adap)
+{
+	struct i2c_algo_pca_data *pca_data = adap->algo_data;
+	/* The trick here is to check if there is an indirect register
+	 * available. If there is one, we will read the value we first
+	 * wrote on I2C_PCA_IADR. Otherwise, we will read the last value
+	 * we wrote on I2C_PCA_ADR
+	 */
+	pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
+	pca_outw(pca_data, I2C_PCA_IND, 0xAA);
+	pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ITO);
+	pca_outw(pca_data, I2C_PCA_IND, 0x00);
+	pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
+	if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) {
+		printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name);
+		return I2C_PCA_CHIP_9665;
+	} else {
+		printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name);
+		return I2C_PCA_CHIP_9564;
+	}
+}
+
 static int pca_init(struct i2c_adapter *adap)
 {
-	static int freqs[] = {330,288,217,146,88,59,44,36};
-	int clock;
 	struct i2c_algo_pca_data *pca_data = adap->algo_data;
 
-	if (pca_data->i2c_clock > 7) {
-		printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
-			adap->name);
-		pca_data->i2c_clock = I2C_PCA_CON_59kHz;
-	}
-
 	adap->algo = &pca_algo;
 
-	pca_reset(pca_data);
+	if (pca_probe_chip(adap) == I2C_PCA_CHIP_9564) {
+		static int freqs[] = {330, 288, 217, 146, 88, 59, 44, 36};
+		int clock;
 
-	clock = pca_clock(pca_data);
-	DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
+		if (pca_data->i2c_clock > 7) {
+			switch (pca_data->i2c_clock) {
+			case 330000:
+				pca_data->i2c_clock = I2C_PCA_CON_330kHz;
+				break;
+			case 288000:
+				pca_data->i2c_clock = I2C_PCA_CON_288kHz;
+				break;
+			case 217000:
+				pca_data->i2c_clock = I2C_PCA_CON_217kHz;
+				break;
+			case 146000:
+				pca_data->i2c_clock = I2C_PCA_CON_146kHz;
+				break;
+			case 88000:
+				pca_data->i2c_clock = I2C_PCA_CON_88kHz;
+				break;
+			case 59000:
+				pca_data->i2c_clock = I2C_PCA_CON_59kHz;
+				break;
+			case 44000:
+				pca_data->i2c_clock = I2C_PCA_CON_44kHz;
+				break;
+			case 36000:
+				pca_data->i2c_clock = I2C_PCA_CON_36kHz;
+				break;
+			default:
+				printk(KERN_WARNING
+					"%s: Invalid I2C clock speed selected."
+					" Using default 59kHz.\n", adap->name);
+			pca_data->i2c_clock = I2C_PCA_CON_59kHz;
+			}
+		} else {
+			printk(KERN_WARNING "%s: "
+				"Choosing the clock frequency based on "
+				"index is deprecated."
+				" Use the nominal frequency.\n", adap->name);
+		}
 
-	pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
+		pca_reset(pca_data);
+
+		clock = pca_clock(pca_data);
+		printk(KERN_INFO "%s: Clock frequency is %dkHz\n",
+		     adap->name, freqs[clock]);
+
+		pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
+	} else {
+		int clock;
+		int mode;
+		int tlow, thi;
+		/* Values can be found on PCA9665 datasheet section 7.3.2.6 */
+		int min_tlow, min_thi;
+		/* These values are the maximum raise and fall values allowed
+		 * by the I2C operation mode (Standard, Fast or Fast+)
+		 * They are used (added) below to calculate the clock dividers
+		 * of PCA9665. Note that they are slightly different of the
+		 * real maximum, to allow the change on mode exactly on the
+		 * maximum clock rate for each mode
+		 */
+		int raise_fall_time;
+
+		struct i2c_algo_pca_data *pca_data = adap->algo_data;
+
+		/* Ignore the reset function from the module,
+		 * we can use the parallel bus reset
+		 */
+		pca_data->reset_chip = pca9665_reset;
+
+		if (pca_data->i2c_clock > 1265800) {
+			printk(KERN_WARNING "%s: I2C clock speed too high."
+				" Using 1265.8kHz.\n", adap->name);
+			pca_data->i2c_clock = 1265800;
+		}
+
+		if (pca_data->i2c_clock < 60300) {
+			printk(KERN_WARNING "%s: I2C clock speed too low."
+				" Using 60.3kHz.\n", adap->name);
+			pca_data->i2c_clock = 60300;
+		}
+
+		/* To avoid integer overflow, use clock/100 for calculations */
+		clock = pca_clock(pca_data) / 100;
+
+		if (pca_data->i2c_clock > 10000) {
+			mode = I2C_PCA_MODE_TURBO;
+			min_tlow = 14;
+			min_thi  = 5;
+			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
+		} else if (pca_data->i2c_clock > 4000) {
+			mode = I2C_PCA_MODE_FASTP;
+			min_tlow = 17;
+			min_thi  = 9;
+			raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
+		} else if (pca_data->i2c_clock > 1000) {
+			mode = I2C_PCA_MODE_FAST;
+			min_tlow = 44;
+			min_thi  = 20;
+			raise_fall_time = 58; /* Raise 29e-8s, Fall 29e-8s */
+		} else {
+			mode = I2C_PCA_MODE_STD;
+			min_tlow = 157;
+			min_thi  = 134;
+			raise_fall_time = 127; /* Raise 29e-8s, Fall 98e-8s */
+		}
+
+		/* The minimum clock that respects the thi/tlow = 134/157 is
+		 * 64800 Hz. Below that, we have to fix the tlow to 255 and
+		 * calculate the thi factor.
+		 */
+		if (clock < 648) {
+			tlow = 255;
+			thi = 1000000 - clock * raise_fall_time;
+			thi /= (I2C_PCA_OSC_PER * clock) - tlow;
+		} else {
+			tlow = (1000000 - clock * raise_fall_time) * min_tlow;
+			tlow /= I2C_PCA_OSC_PER * clock * (min_thi + min_tlow);
+			thi = tlow * min_thi / min_tlow;
+		}
+
+		pca_reset(pca_data);
+
+		printk(KERN_INFO
+		     "%s: Clock frequency is %dHz\n", adap->name, clock * 100);
+
+		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE);
+		pca_outw(pca_data, I2C_PCA_IND, mode);
+		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
+		pca_outw(pca_data, I2C_PCA_IND, tlow);
+		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
+		pca_outw(pca_data, I2C_PCA_IND, thi);
+
+		pca_set_con(pca_data, I2C_PCA_CON_ENSIO);
+	}
 	udelay(500); /* 500 us for oscilator to stabilise */
 
 	return 0;
@@ -384,7 +548,7 @@
 
 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>, "
 	"Wolfram Sang <w.sang@pengutronix.de>");
-MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
+MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm");
 MODULE_LICENSE("GPL");
 
 module_param(i2c_debug, int, 0);
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 3e01992..7ce7577 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -1,31 +1,30 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters		     */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-1997 Simon G. Vogl
-                   1998-2000 Hans Berglund
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.		     */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
-   Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
-   <mbailey@littlefeet-inc.com> */
-
-/* Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
-   messages, proper stop/repstart signaling during receive,
-   added detect code */
+/*
+ * i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters
+ *
+ *   Copyright (C) 1995-1997 Simon G. Vogl
+ *		   1998-2000 Hans Berglund
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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.
+ *
+ * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+ * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
+ * <mbailey@littlefeet-inc.com>
+ *
+ * Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
+ * messages, proper stop/repstart signaling during receive, added detect code
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -38,17 +37,18 @@
 #include "i2c-algo-pcf.h"
 
 
-#define DEB2(x) if (i2c_debug>=2) x
-#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) x;
- 	/* debug the protocol by showing transferred bits */
+#define DEB2(x) if (i2c_debug >= 2) x
+#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */
+#define DEBPROTO(x) if (i2c_debug >= 9) x;
+	/* debug the protocol by showing transferred bits */
 #define DEF_TIMEOUT 16
 
-/* module parameters:
+/*
+ * module parameters:
  */
 static int i2c_debug;
 
-/* --- setting states on the bus with the right timing: ---------------	*/
+/* setting states on the bus with the right timing: */
 
 #define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val)
 #define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl)
@@ -57,22 +57,21 @@
 #define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val)
 #define i2c_inb(adap) adap->getpcf(adap->data, 0)
 
-/* --- other auxiliary functions --------------------------------------	*/
+/* other auxiliary functions */
 
-static void i2c_start(struct i2c_algo_pcf_data *adap) 
+static void i2c_start(struct i2c_algo_pcf_data *adap)
 {
-	DEBPROTO(printk("S "));
+	DEBPROTO(printk(KERN_DEBUG "S "));
 	set_pcf(adap, 1, I2C_PCF_START);
 }
 
-static void i2c_repstart(struct i2c_algo_pcf_data *adap) 
+static void i2c_repstart(struct i2c_algo_pcf_data *adap)
 {
 	DEBPROTO(printk(" Sr "));
 	set_pcf(adap, 1, I2C_PCF_REPSTART);
 }
 
-
-static void i2c_stop(struct i2c_algo_pcf_data *adap) 
+static void i2c_stop(struct i2c_algo_pcf_data *adap)
 {
 	DEBPROTO(printk("P\n"));
 	set_pcf(adap, 1, I2C_PCF_STOP);
@@ -82,17 +81,17 @@
 {
 	DEB2(printk(KERN_INFO
 		"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
-		 *status));
-
-	/* Cleanup from LAB -- reset and enable ESO.
+		*status));
+	/*
+	 * Cleanup from LAB -- reset and enable ESO.
 	 * This resets the PCF8584; since we've lost the bus, no
 	 * further attempts should be made by callers to clean up
 	 * (no i2c_stop() etc.)
 	 */
 	set_pcf(adap, 1, I2C_PCF_PIN);
 	set_pcf(adap, 1, I2C_PCF_ESO);
-
-	/* We pause for a time period sufficient for any running
+	/*
+	 * We pause for a time period sufficient for any running
 	 * I2C transaction to complete -- the arbitration logic won't
 	 * work properly until the next START is seen.
 	 * It is assumed the bus driver or client has set a proper value.
@@ -108,48 +107,50 @@
 		get_pcf(adap, 1)));
 }
 
-static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
+static int wait_for_bb(struct i2c_algo_pcf_data *adap)
+{
 
 	int timeout = DEF_TIMEOUT;
 	int status;
 
 	status = get_pcf(adap, 1);
-#ifndef STUB_I2C
-	while (timeout-- && !(status & I2C_PCF_BB)) {
+
+	while (!(status & I2C_PCF_BB) && --timeout) {
 		udelay(100); /* wait for 100 us */
 		status = get_pcf(adap, 1);
 	}
-#endif
-	if (timeout <= 0) {
+
+	if (timeout == 0) {
 		printk(KERN_ERR "Timeout waiting for Bus Busy\n");
+		return -ETIMEDOUT;
 	}
-	
-	return (timeout<=0);
+
+	return 0;
 }
 
-
-static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
+static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status)
+{
 
 	int timeout = DEF_TIMEOUT;
 
 	*status = get_pcf(adap, 1);
-#ifndef STUB_I2C
-	while (timeout-- && (*status & I2C_PCF_PIN)) {
+
+	while ((*status & I2C_PCF_PIN) && --timeout) {
 		adap->waitforpin(adap->data);
 		*status = get_pcf(adap, 1);
 	}
 	if (*status & I2C_PCF_LAB) {
 		handle_lab(adap, status);
-		return(-EINTR);
+		return -EINTR;
 	}
-#endif
-	if (timeout <= 0)
-		return(-1);
-	else
-		return(0);
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	return 0;
 }
 
-/* 
+/*
  * This should perform the 'PCF8584 initialization sequence' as described
  * in the Philips IC12 data book (1995, Aug 29).
  * There should be a 30 clock cycle wait after reset, I assume this
@@ -164,18 +165,21 @@
 {
 	unsigned char temp;
 
-	DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", get_pcf(adap, 1)));
+	DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n",
+				get_pcf(adap, 1)));
 
 	/* S1=0x80: S0 selected, serial interface off */
 	set_pcf(adap, 1, I2C_PCF_PIN);
-	/* check to see S1 now used as R/W ctrl -
-	   PCF8584 does that when ESO is zero */
+	/*
+	 * check to see S1 now used as R/W ctrl -
+	 * PCF8584 does that when ESO is zero
+	 */
 	if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) {
 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
 		return -ENXIO; /* definetly not PCF8584 */
 	}
 
-	/* load own address in S0, effective address is (own << 1)	*/
+	/* load own address in S0, effective address is (own << 1) */
 	i2c_outb(adap, get_own(adap));
 	/* check it's really written */
 	if ((temp = i2c_inb(adap)) != get_own(adap)) {
@@ -183,7 +187,7 @@
 		return -ENXIO;
 	}
 
-	/* S1=0xA0, next byte in S2					*/
+	/* S1=0xA0, next byte in S2 */
 	set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1);
 	/* check to see S2 now selected */
 	if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) {
@@ -191,7 +195,7 @@
 		return -ENXIO;
 	}
 
-	/* load clock register S2					*/
+	/* load clock register S2 */
 	i2c_outb(adap, get_clock(adap));
 	/* check it's really written, the only 5 lowest bits does matter */
 	if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
@@ -199,7 +203,7 @@
 		return -ENXIO;
 	}
 
-	/* Enable serial interface, idle, S0 selected			*/
+	/* Enable serial interface, idle, S0 selected */
 	set_pcf(adap, 1, I2C_PCF_IDLE);
 
 	/* check to see PCF is really idled and we can access status register */
@@ -207,57 +211,47 @@
 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
 		return -ENXIO;
 	}
-	
+
 	printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
 
 	return 0;
 }
 
-
-/* ----- Utility functions
- */
-
 static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
-                         int count, int last)
+			 int count, int last)
 {
 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
 	int wrcount, status, timeout;
-    
+
 	for (wrcount=0; wrcount<count; ++wrcount) {
 		DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
-				buf[wrcount]&0xff));
+				buf[wrcount] & 0xff));
 		i2c_outb(adap, buf[wrcount]);
 		timeout = wait_for_pin(adap, &status);
 		if (timeout) {
-			if (timeout == -EINTR) {
-				/* arbitration lost */
-				return -EINTR;
-			}
+			if (timeout == -EINTR)
+				return -EINTR; /* arbitration lost */
+
 			i2c_stop(adap);
 			dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
 			return -EREMOTEIO; /* got a better one ?? */
 		}
-#ifndef STUB_I2C
 		if (status & I2C_PCF_LRB) {
 			i2c_stop(adap);
 			dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n");
 			return -EREMOTEIO; /* got a better one ?? */
 		}
-#endif
 	}
-	if (last) {
+	if (last)
 		i2c_stop(adap);
-	}
-	else {
+	else
 		i2c_repstart(adap);
-	}
 
-	return (wrcount);
+	return wrcount;
 }
 
-
 static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
-                         int count, int last)
+			 int count, int last)
 {
 	int i, status;
 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
@@ -267,42 +261,36 @@
 	for (i = 0; i <= count; i++) {
 
 		if ((wfp = wait_for_pin(adap, &status))) {
-			if (wfp == -EINTR) {
-				/* arbitration lost */
-				return -EINTR;
-			}
+			if (wfp == -EINTR)
+				return -EINTR; /* arbitration lost */
+
 			i2c_stop(adap);
 			dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
-			return (-1);
+			return -1;
 		}
 
-#ifndef STUB_I2C
 		if ((status & I2C_PCF_LRB) && (i != count)) {
 			i2c_stop(adap);
 			dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n");
-			return (-1);
+			return -1;
 		}
-#endif
-		
+
 		if (i == count - 1) {
 			set_pcf(adap, 1, I2C_PCF_ESO);
-		} else 
-		if (i == count) {
-			if (last) {
+		} else if (i == count) {
+			if (last)
 				i2c_stop(adap);
-			} else {
+			else
 				i2c_repstart(adap);
-			}
-		};
-
-		if (i) {
-			buf[i - 1] = i2c_inb(adap);
-		} else {
-			i2c_inb(adap); /* dummy read */
 		}
+
+		if (i)
+			buf[i - 1] = i2c_inb(adap);
+		else
+			i2c_inb(adap); /* dummy read */
 	}
 
-	return (i - 1);
+	return i - 1;
 }
 
 
@@ -323,14 +311,14 @@
 }
 
 static int pcf_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg *msgs, 
+		    struct i2c_msg *msgs,
 		    int num)
 {
 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
 	struct i2c_msg *pmsg;
 	int i;
 	int ret=0, timeout, status;
-    
+
 	if (adap->xfer_begin)
 		adap->xfer_begin(adap->data);
 
@@ -338,25 +326,24 @@
 	timeout = wait_for_bb(adap);
 	if (timeout) {
 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
-		            "Timeout waiting for BB in pcf_xfer\n");)
+			    "Timeout waiting for BB in pcf_xfer\n");)
 		i = -EIO;
 		goto out;
 	}
-	
+
 	for (i = 0;ret >= 0 && i < num; i++) {
 		pmsg = &msgs[i];
 
 		DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
 		     pmsg->flags & I2C_M_RD ? "read" : "write",
-                     pmsg->len, pmsg->addr, i + 1, num);)
-    
+		     pmsg->len, pmsg->addr, i + 1, num);)
+
 		ret = pcf_doAddress(adap, pmsg);
 
 		/* Send START */
-		if (i == 0) {
-			i2c_start(adap); 
-		}
-    
+		if (i == 0)
+			i2c_start(adap);
+
 		/* Wait for PIN (pending interrupt NOT) */
 		timeout = wait_for_pin(adap, &status);
 		if (timeout) {
@@ -371,8 +358,7 @@
 			i = -EREMOTEIO;
 			goto out;
 		}
-    
-#ifndef STUB_I2C
+
 		/* Check LRB (last rcvd bit - slave ack) */
 		if (status & I2C_PCF_LRB) {
 			i2c_stop(adap);
@@ -380,27 +366,24 @@
 			i = -EREMOTEIO;
 			goto out;
 		}
-#endif
-    
+
 		DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
 			    i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
-    
-		/* Read */
+
 		if (pmsg->flags & I2C_M_RD) {
-			/* read bytes into buffer*/
 			ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
-                                            (i + 1 == num));
-        
+					    (i + 1 == num));
+
 			if (ret != pmsg->len) {
 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
 					    "only read %d bytes.\n",ret));
 			} else {
 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret));
 			}
-		} else { /* Write */
+		} else {
 			ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
-                                            (i + 1 == num));
-        
+					    (i + 1 == num));
+
 			if (ret != pmsg->len) {
 				DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
 					    "only wrote %d bytes.\n",ret));
@@ -413,24 +396,23 @@
 out:
 	if (adap->xfer_end)
 		adap->xfer_end(adap->data);
-	return (i);
+	return i;
 }
 
 static u32 pcf_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
 	       I2C_FUNC_PROTOCOL_MANGLING;
 }
 
-/* -----exported algorithm data: -------------------------------------	*/
-
+/* exported algorithm data: */
 static const struct i2c_algorithm pcf_algo = {
 	.master_xfer	= pcf_xfer,
 	.functionality	= pcf_func,
 };
 
-/* 
- * registering functions to load algorithms at runtime 
+/*
+ * registering functions to load algorithms at runtime
  */
 int i2c_pcf_add_bus(struct i2c_adapter *adap)
 {
@@ -441,7 +423,6 @@
 
 	/* register new adapter to i2c module... */
 	adap->algo = &pcf_algo;
-	adap->timeout = 100;
 
 	if ((rval = pcf_init_8584(pcf_adap)))
 		return rval;
@@ -458,4 +439,4 @@
 
 module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(i2c_debug,
-        "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
+	"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 7f95905..da809ad 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -132,6 +132,7 @@
 	    Serverworks CSB5
 	    Serverworks CSB6
 	    Serverworks HT-1000
+	    Serverworks HT-1100
 	    SMSC Victory66
 
 	  This driver can also be built as a module.  If so, the module
@@ -617,12 +618,12 @@
 	  will be called i2c-elektor.
 
 config I2C_PCA_ISA
-	tristate "PCA9564 on an ISA bus"
+	tristate "PCA9564/PCA9665 on an ISA bus"
 	depends on ISA
 	select I2C_ALGOPCA
 	default n
 	help
-	  This driver supports ISA boards using the Philips PCA9564
+	  This driver supports ISA boards using the Philips PCA9564/PCA9665
 	  parallel bus to I2C bus controller.
 
 	  This driver can also be built as a module.  If so, the module
@@ -634,11 +635,11 @@
 	  time).  If unsure, say N.
 
 config I2C_PCA_PLATFORM
-	tristate "PCA9564 as platform device"
+	tristate "PCA9564/PCA9665 as platform device"
 	select I2C_ALGOPCA
 	default n
 	help
-	  This driver supports a memory mapped Philips PCA9564
+	  This driver supports a memory mapped Philips PCA9564/PCA9665
 	  parallel bus to I2C bus controller.
 
 	  This driver can also be built as a module.  If so, the module
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 9aefb5e..8679648 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -15,9 +15,9 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/hardware/ioc.h>
 #include <asm/system.h>
 
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 5d77898..3fae3a9 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -216,7 +216,7 @@
 {
 	unsigned long timeout;
 
-	timeout = jiffies + DAVINCI_I2C_TIMEOUT;
+	timeout = jiffies + dev->adapter.timeout;
 	while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)
 	       & DAVINCI_I2C_STR_BB) {
 		if (time_after(jiffies, timeout)) {
@@ -289,7 +289,7 @@
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
 	r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-						      DAVINCI_I2C_TIMEOUT);
+						      dev->adapter.timeout);
 	if (r == 0) {
 		dev_err(dev->dev, "controller timed out\n");
 		i2c_davinci_init(dev);
@@ -546,9 +546,7 @@
 	strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
 	adap->algo = &i2c_davinci_algo;
 	adap->dev.parent = &pdev->dev;
-
-	/* FIXME */
-	adap->timeout = 1;
+	adap->timeout = DAVINCI_I2C_TIMEOUT;
 
 	adap->nr = pdev->id;
 	r = i2c_add_numbered_adapter(adap);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 88f0db7..8b92a46 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -415,7 +415,7 @@
 	if (dev->irq >= 0){
 		/* Interrupt mode */
 		ret = wait_event_interruptible_timeout(dev->wq,
-			!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
+			!(in_8(&iic->sts) & STS_PT), dev->adap.timeout);
 
 		if (unlikely(ret < 0))
 			DBG("%d: wait interrupted\n", dev->idx);
@@ -426,7 +426,7 @@
 	}
 	else {
 		/* Polling mode */
-		unsigned long x = jiffies + dev->adap.timeout * HZ;
+		unsigned long x = jiffies + dev->adap.timeout;
 
 		while (in_8(&iic->sts) & STS_PT){
 			if (unlikely(time_after(jiffies, x))){
@@ -748,7 +748,7 @@
 	i2c_set_adapdata(adap, dev);
 	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
 	adap->algo = &iic_algo;
-	adap->timeout = 1;
+	adap->timeout = HZ;
 
 	ret = i2c_add_adapter(adap);
 	if (ret  < 0) {
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 3190690..a75c75e 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -488,7 +488,7 @@
 	/*
 	 * Default values...should these come in from board code?
 	 */
-	new_adapter->timeout = 100;	
+	new_adapter->timeout = HZ;
 	new_adapter->algo = &iop3xx_i2c_algo;
 
 	init_waitqueue_head(&adapter_data->waitq);
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index aedbbe6..26bf370 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -70,7 +70,7 @@
 		/* Read again to allow register to stabilise */
 		i2c->interrupt = readb(i2c->base + MPC_I2C_SR);
 		writeb(0, i2c->base + MPC_I2C_SR);
-		wake_up_interruptible(&i2c->queue);
+		wake_up(&i2c->queue);
 	}
 	return IRQ_HANDLED;
 }
@@ -115,13 +115,10 @@
 		writeb(0, i2c->base + MPC_I2C_SR);
 	} else {
 		/* Interrupt mode */
-		result = wait_event_interruptible_timeout(i2c->queue,
-			(i2c->interrupt & CSR_MIF), timeout * HZ);
+		result = wait_event_timeout(i2c->queue,
+			(i2c->interrupt & CSR_MIF), timeout);
 
-		if (unlikely(result < 0)) {
-			pr_debug("I2C: wait interrupted\n");
-			writeccr(i2c, 0);
-		} else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
+		if (unlikely(!(i2c->interrupt & CSR_MIF))) {
 			pr_debug("I2C: wait timeout\n");
 			writeccr(i2c, 0);
 			result = -ETIMEDOUT;
@@ -311,7 +308,7 @@
 	.owner = THIS_MODULE,
 	.name = "MPC adapter",
 	.algo = &mpc_algo,
-	.timeout = 1,
+	.timeout = HZ,
 };
 
 static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match)
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 7f186bb..5a4945d 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -358,7 +358,7 @@
 	char		abort = 0;
 
 	time_left = wait_event_interruptible_timeout(drv_data->waitq,
-		!drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout));
+		!drv_data->block, drv_data->adapter.timeout);
 
 	spin_lock_irqsave(&drv_data->lock, flags);
 	if (!time_left) { /* Timed out */
@@ -374,8 +374,7 @@
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 
 		time_left = wait_event_timeout(drv_data->waitq,
-			!drv_data->block,
-			msecs_to_jiffies(drv_data->adapter.timeout));
+			!drv_data->block, drv_data->adapter.timeout);
 
 		if ((time_left <= 0) && drv_data->block) {
 			drv_data->state = MV64XXX_I2C_STATE_IDLE;
@@ -530,7 +529,7 @@
 	drv_data->adapter.algo = &mv64xxx_i2c_algo;
 	drv_data->adapter.owner = THIS_MODULE;
 	drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
-	drv_data->adapter.timeout = pdata->timeout;
+	drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
 	drv_data->adapter.nr = pd->id;
 	platform_set_drvdata(pd, drv_data);
 	i2c_set_adapdata(&drv_data->adapter, drv_data);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 05af6cd..2ff4683 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -31,10 +31,14 @@
     nForce3 250Gb MCP		00E4
     nForce4 MCP			0052
     nForce4 MCP-04		0034
-    nForce4 MCP51		0264
-    nForce4 MCP55		0368
+    nForce MCP51		0264
+    nForce MCP55		0368
     nForce MCP61		03EB
     nForce MCP65		0446
+    nForce MCP67		0542
+    nForce MCP73		07D8
+    nForce MCP78S		0752
+    nForce MCP79		0AA2
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4/5xx chipsets.
@@ -315,6 +319,10 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) },
 	{ 0 }
 };
 
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index be8ee2c..ece0125 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -193,22 +193,24 @@
 
 static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
 {
-	if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-		dev->iclk = clk_get(dev->dev, "i2c_ick");
-		if (IS_ERR(dev->iclk)) {
-			dev->iclk = NULL;
-			return -ENODEV;
-		}
+	int ret;
+
+	dev->iclk = clk_get(dev->dev, "ick");
+	if (IS_ERR(dev->iclk)) {
+		ret = PTR_ERR(dev->iclk);
+		dev->iclk = NULL;
+		return ret;
 	}
 
-	dev->fclk = clk_get(dev->dev, "i2c_fck");
+	dev->fclk = clk_get(dev->dev, "fck");
 	if (IS_ERR(dev->fclk)) {
+		ret = PTR_ERR(dev->fclk);
 		if (dev->iclk != NULL) {
 			clk_put(dev->iclk);
 			dev->iclk = NULL;
 		}
 		dev->fclk = NULL;
-		return -ENODEV;
+		return ret;
 	}
 
 	return 0;
@@ -218,18 +220,15 @@
 {
 	clk_put(dev->fclk);
 	dev->fclk = NULL;
-	if (dev->iclk != NULL) {
-		clk_put(dev->iclk);
-		dev->iclk = NULL;
-	}
+	clk_put(dev->iclk);
+	dev->iclk = NULL;
 }
 
 static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 {
 	WARN_ON(!dev->idle);
 
-	if (dev->iclk != NULL)
-		clk_enable(dev->iclk);
+	clk_enable(dev->iclk);
 	clk_enable(dev->fclk);
 	dev->idle = 0;
 	if (dev->iestate)
@@ -254,8 +253,7 @@
 	}
 	dev->idle = 1;
 	clk_disable(dev->fclk);
-	if (dev->iclk != NULL)
-		clk_disable(dev->iclk);
+	clk_disable(dev->iclk);
 }
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
@@ -312,15 +310,14 @@
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 
 	if (cpu_class_is_omap1()) {
-		struct clk *armxor_ck;
+		/*
+		 * The I2C functional clock is the armxor_ck, so there's
+		 * no need to get "armxor_ck" separately.  Now, if OMAP2420
+		 * always returns 12MHz for the functional clock, we can
+		 * do this bit unconditionally.
+		 */
+		fclk_rate = clk_get_rate(dev->fclk);
 
-		armxor_ck = clk_get(NULL, "armxor_ck");
-		if (IS_ERR(armxor_ck))
-			dev_warn(dev->dev, "Could not get armxor_ck\n");
-		else {
-			fclk_rate = clk_get_rate(armxor_ck);
-			clk_put(armxor_ck);
-		}
 		/* TRM for 5912 says the I2C clock must be prescaled to be
 		 * between 7 - 12 MHz. The XOR input clock is typically
 		 * 12, 13 or 19.2 MHz. So we should have code that produces:
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 4aa8138..0ed68e2 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
@@ -41,15 +42,17 @@
 
 /* Data sheet recommends 59kHz for 100kHz operation due to variation
  * in the actual clock rate */
-static int clock  = I2C_PCA_CON_59kHz;
+static int clock  = 59000;
 
+static struct i2c_adapter pca_isa_ops;
 static wait_queue_head_t pca_wait;
 
 static void pca_isa_writebyte(void *pd, int reg, int val)
 {
 #ifdef DEBUG_IO
 	static char *names[] = { "T/O", "DAT", "ADR", "CON" };
-	printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val);
+	printk(KERN_DEBUG "*** write %s at %#lx <= %#04x\n", names[reg],
+	       base+reg, val);
 #endif
 	outb(val, base+reg);
 }
@@ -60,7 +63,7 @@
 #ifdef DEBUG_IO
 	{
 		static char *names[] = { "STA", "DAT", "ADR", "CON" };
-		printk("*** read  %s => %#04x\n", names[reg], res);
+		printk(KERN_DEBUG "*** read  %s => %#04x\n", names[reg], res);
 	}
 #endif
 	return res;
@@ -68,16 +71,22 @@
 
 static int pca_isa_waitforcompletion(void *pd)
 {
-	int ret = 0;
+	long ret = ~0;
+	unsigned long timeout;
 
 	if (irq > -1) {
-		ret = wait_event_interruptible(pca_wait,
-					       pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
+		ret = wait_event_interruptible_timeout(pca_wait,
+				pca_isa_readbyte(pd, I2C_PCA_CON)
+				& I2C_PCA_CON_SI, pca_isa_ops.timeout);
 	} else {
-		while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
+		/* Do polling */
+		timeout = jiffies + pca_isa_ops.timeout;
+		while (((pca_isa_readbyte(pd, I2C_PCA_CON)
+				& I2C_PCA_CON_SI) == 0)
+				&& (ret = time_before(jiffies, timeout)))
 			udelay(100);
 	}
-	return ret;
+	return ret > 0;
 }
 
 static void pca_isa_resetchip(void *pd)
@@ -102,8 +111,8 @@
 static struct i2c_adapter pca_isa_ops = {
 	.owner          = THIS_MODULE,
 	.algo_data	= &pca_isa_data,
-	.name		= "PCA9564 ISA Adapter",
-	.timeout	= 100,
+	.name		= "PCA9564/PCA9665 ISA Adapter",
+	.timeout	= HZ,
 };
 
 static int __devinit pca_isa_match(struct device *dev, unsigned int id)
@@ -195,7 +204,7 @@
 }
 
 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
-MODULE_DESCRIPTION("ISA base PCA9564 driver");
+MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver");
 MODULE_LICENSE("GPL");
 
 module_param(base, ulong, 0);
@@ -204,7 +213,13 @@
 module_param(irq, int, 0);
 MODULE_PARM_DESC(irq, "IRQ");
 module_param(clock, int, 0);
-MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
+MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t"
+		"For PCA9564: 330000,288000,217000,146000,"
+		"88000,59000,44000,36000\n"
+		"\t\tFor PCA9665:\tStandard: 60300 - 100099\n"
+		"\t\t\t\tFast: 100100 - 400099\n"
+		"\t\t\t\tFast+: 400100 - 10000099\n"
+		"\t\t\t\tTurbo: Up to 1265800");
 
 module_init(pca_isa_init);
 module_exit(pca_isa_exit);
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index 6bb15ad..7b23891 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -81,24 +82,23 @@
 static int i2c_pca_pf_waitforcompletion(void *pd)
 {
 	struct i2c_pca_pf_data *i2c = pd;
-	int ret = 0;
+	long ret = ~0;
+	unsigned long timeout;
 
 	if (i2c->irq) {
-		ret = wait_event_interruptible(i2c->wait,
+		ret = wait_event_interruptible_timeout(i2c->wait,
 			i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
-			& I2C_PCA_CON_SI);
+			& I2C_PCA_CON_SI, i2c->adap.timeout);
 	} else {
-		/*
-		 * Do polling...
-		 * XXX: Could get stuck in extreme cases!
-		 *      Maybe add timeout, but using irqs is preferred anyhow.
-		 */
-		while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
+		/* Do polling */
+		timeout = jiffies + i2c->adap.timeout;
+		while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
 				& I2C_PCA_CON_SI) == 0)
+				&& (ret = time_before(jiffies, timeout)))
 			udelay(100);
 	}
 
-	return ret;
+	return ret > 0;
 }
 
 static void i2c_pca_pf_dummyreset(void *pd)
@@ -172,14 +172,25 @@
 
 	i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
 	i2c->adap.owner = THIS_MODULE;
-	snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx",
-		(unsigned long) res->start);
+	snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+		 "PCA9564/PCA9665 at 0x%08lx",
+		 (unsigned long) res->start);
 	i2c->adap.algo_data = &i2c->algo_data;
 	i2c->adap.dev.parent = &pdev->dev;
-	i2c->adap.timeout = platform_data->timeout;
 
-	i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
+	if (platform_data) {
+		i2c->adap.timeout = platform_data->timeout;
+		i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
+		i2c->gpio = platform_data->gpio;
+	} else {
+		i2c->adap.timeout = HZ;
+		i2c->algo_data.i2c_clock = 59000;
+		i2c->gpio = -1;
+	}
+
 	i2c->algo_data.data = i2c;
+	i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
+	i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
 
 	switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
 	case IORESOURCE_MEM_32BIT:
@@ -197,11 +208,6 @@
 		break;
 	}
 
-	i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
-
-	i2c->gpio = platform_data->gpio;
-	i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
-
 	/* Use gpio_is_valid() when in mainline */
 	if (i2c->gpio > -1) {
 		ret = gpio_request(i2c->gpio, i2c->adap.name);
@@ -246,7 +252,7 @@
 e_alloc:
 	release_mem_region(res->start, res_len(res));
 e_print:
-	printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
+	printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret);
 	return ret;
 }
 
@@ -290,7 +296,7 @@
 }
 
 MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
-MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
+MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver");
 MODULE_LICENSE("GPL");
 
 module_init(i2c_pca_pf_init);
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 761f9dd..0249a7d 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -20,7 +20,7 @@
 /*
    Supports:
 	Intel PIIX4, 440MX
-	Serverworks OSB4, CSB5, CSB6, HT-1000
+	Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
 	ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
 	SMSC Victory66
 
@@ -226,6 +226,70 @@
 	return 0;
 }
 
+static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
+				const struct pci_device_id *id)
+{
+	unsigned short smba_idx = 0xcd6;
+	u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
+
+	/* SB800 SMBus does not support forcing address */
+	if (force || force_addr) {
+		dev_err(&PIIX4_dev->dev, "SB800 SMBus does not support "
+			"forcing address!\n");
+		return -EINVAL;
+	}
+
+	/* Determine the address of the SMBus areas */
+	if (!request_region(smba_idx, 2, "smba_idx")) {
+		dev_err(&PIIX4_dev->dev, "SMBus base address index region "
+			"0x%x already in use!\n", smba_idx);
+		return -EBUSY;
+	}
+	outb_p(smb_en, smba_idx);
+	smba_en_lo = inb_p(smba_idx + 1);
+	outb_p(smb_en + 1, smba_idx);
+	smba_en_hi = inb_p(smba_idx + 1);
+	release_region(smba_idx, 2);
+
+	if ((smba_en_lo & 1) == 0) {
+		dev_err(&PIIX4_dev->dev,
+			"Host SMBus controller not enabled!\n");
+		return -ENODEV;
+	}
+
+	piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
+	if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+		return -EBUSY;
+
+	if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
+		dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
+			piix4_smba);
+		return -EBUSY;
+	}
+
+	/* Request the SMBus I2C bus config region */
+	if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
+		dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
+			"0x%x already in use!\n", piix4_smba + i2ccfg_offset);
+		release_region(piix4_smba, SMBIOSIZE);
+		piix4_smba = 0;
+		return -EBUSY;
+	}
+	i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
+	release_region(piix4_smba + i2ccfg_offset, 1);
+
+	if (i2ccfg & 1)
+		dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n");
+	else
+		dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n");
+
+	dev_info(&PIIX4_dev->dev,
+		 "SMBus Host Controller at 0x%x, revision %d\n",
+		 piix4_smba, i2ccfg >> 4);
+
+	return 0;
+}
+
 static int piix4_transaction(void)
 {
 	int temp;
@@ -423,6 +487,8 @@
 		     PCI_DEVICE_ID_SERVERWORKS_CSB6) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
 		     PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+		     PCI_DEVICE_ID_SERVERWORKS_HT1100LD) },
 	{ 0, }
 };
 
@@ -433,7 +499,14 @@
 {
 	int retval;
 
-	retval = piix4_setup(dev, id);
+	if ((dev->vendor == PCI_VENDOR_ID_ATI) &&
+	    (dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) &&
+	    (dev->revision >= 0x40))
+		/* base address location etc changed in SB800 */
+		retval = piix4_setup_sb800(dev, id);
+	else
+		retval = piix4_setup(dev, id);
+
 	if (retval)
 		return retval;
 
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 60ca917..3c9d71f 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -191,7 +191,8 @@
 	i2c_set_adapdata(adapter, NULL);
 	/* We aren't that prepared to deal with this... */
 	if (rc)
-		printk("i2c-powermac.c: Failed to remove bus %s !\n",
+		printk(KERN_WARNING
+		       "i2c-powermac.c: Failed to remove bus %s !\n",
 		       adapter->name);
 	platform_set_drvdata(dev, NULL);
 	kfree(adapter);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index bdb1f751..c1405c8 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -210,11 +210,12 @@
 static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
 {
 	unsigned int i;
-	printk("i2c: error: %s\n", why);
-	printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
+	printk(KERN_ERR "i2c: error: %s\n", why);
+	printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
 		i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
-	printk("i2c: ICR: %08x ISR: %08x\n"
-	       "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
+	printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n",
+	       readl(_ICR(i2c)), readl(_ISR(i2c)));
+	printk(KERN_DEBUG "i2c: log: ");
 	for (i = 0; i < i2c->irqlogidx; i++)
 		printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
 	printk("\n");
diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c
index 4678bab..fede619 100644
--- a/drivers/i2c/busses/i2c-versatile.c
+++ b/drivers/i2c/busses/i2c-versatile.c
@@ -102,7 +102,13 @@
 	i2c->algo = i2c_versatile_algo;
 	i2c->algo.data = i2c;
 
-	ret = i2c_bit_add_bus(&i2c->adap);
+	if (dev->id >= 0) {
+		/* static bus numbering */
+		i2c->adap.nr = dev->id;
+		ret = i2c_bit_add_numbered_bus(&i2c->adap);
+	} else
+		/* dynamic bus numbering */
+		ret = i2c_bit_add_bus(&i2c->adap);
 	if (ret >= 0) {
 		platform_set_drvdata(dev, i2c);
 		return 0;
@@ -146,7 +152,7 @@
 	platform_driver_unregister(&i2c_versatile_driver);
 }
 
-module_init(i2c_versatile_init);
+subsys_initcall(i2c_versatile_init);
 module_exit(i2c_versatile_exit);
 
 MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index fbb9030..b6f3a0d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -152,7 +152,7 @@
 		driver->shutdown(to_i2c_client(dev));
 }
 
-static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
+static int i2c_device_suspend(struct device *dev, pm_message_t mesg)
 {
 	struct i2c_driver *driver;
 
@@ -164,7 +164,7 @@
 	return driver->suspend(to_i2c_client(dev), mesg);
 }
 
-static int i2c_device_resume(struct device * dev)
+static int i2c_device_resume(struct device *dev)
 {
 	struct i2c_driver *driver;
 
@@ -187,13 +187,15 @@
 	kfree(to_i2c_client(dev));
 }
 
-static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t
+show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	return sprintf(buf, "%s\n", client->name);
 }
 
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t
+show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
@@ -365,8 +367,7 @@
  * This returns the new i2c client, which should be saved for later use with
  * i2c_unregister_device(); or NULL to indicate an error.
  */
-struct i2c_client *
-i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
+struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
 {
 	struct i2c_board_info info = {
 		I2C_BOARD_INFO("dummy", address),
@@ -413,8 +414,8 @@
 		if (devinfo->busnum == adapter->nr
 				&& !i2c_new_device(adapter,
 						&devinfo->board_info))
-			printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n",
-				i2c_adapter_id(adapter),
+			dev_err(&adapter->dev,
+				"Can't create device at 0x%02x\n",
 				devinfo->board_info.addr);
 	}
 	mutex_unlock(&__i2c_board_lock);
@@ -459,6 +460,11 @@
 		pr_debug("I2C adapter driver [%s] forgot to specify "
 			 "physical device\n", adap->name);
 	}
+
+	/* Set default timeout to 1 second if not already set */
+	if (adap->timeout == 0)
+		adap->timeout = HZ;
+
 	dev_set_name(&adap->dev, "i2c-%d", adap->nr);
 	adap->dev.release = &i2c_adapter_dev_release;
 	adap->dev.class = &i2c_adapter_class;
@@ -581,7 +587,8 @@
 	struct i2c_client *client, *_n;
 	int res;
 
-	/* Remove the devices we created ourselves */
+	/* Remove the devices we created ourselves as the result of hardware
+	 * probing (using a driver's detect method) */
 	list_for_each_entry_safe(client, _n, &driver->clients, detected) {
 		if (client->adapter == adapter) {
 			dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
@@ -749,6 +756,8 @@
 	struct i2c_driver *driver = data;
 	struct i2c_client *client, *_n;
 
+	/* Remove the devices we created ourselves as the result of hardware
+	 * probing (using a driver's detect method) */
 	list_for_each_entry_safe(client, _n, &driver->clients, detected) {
 		dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
 			client->name, client->addr);
@@ -1012,7 +1021,7 @@
  * Note that there is no requirement that each message be sent to
  * the same slave address, although that is the most common model.
  */
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
+int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	int ret;
 
@@ -1519,8 +1528,7 @@
 /* The SMBus parts */
 
 #define POLY    (0x1070U << 3)
-static u8
-crc8(u16 data)
+static u8 crc8(u16 data)
 {
 	int i;
 
@@ -1984,9 +1992,9 @@
  * This executes an SMBus protocol operation, and returns a negative
  * errno code else zero on success.
  */
-s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
+s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
 		   char read_write, u8 command, int protocol,
-                   union i2c_smbus_data * data)
+		   union i2c_smbus_data *data)
 {
 	s32 res;
 
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index d3513b6..d516168 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -191,17 +191,18 @@
 /**
  *	ali15x3_dma_setup	-	begin a DMA phase
  *	@drive:	target device
+ *	@cmd: command
  *
  *	Returns 1 if the DMA cannot be performed, zero on success.
  */
 
-static int ali15x3_dma_setup(ide_drive_t *drive)
+static int ali15x3_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	if (m5229_revision < 0xC2 && drive->media != ide_disk) {
-		if (rq_data_dir(drive->hwif->rq))
+		if (cmd->tf_flags & IDE_TFLAG_WRITE)
 			return 1;	/* try PIO instead of DMA */
 	}
-	return ide_dma_setup(drive);
+	return ide_dma_setup(drive, cmd);
 }
 
 /**
@@ -503,11 +504,11 @@
 static const struct ide_dma_ops ali_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ali15x3_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
index 1bb50f4..2754712 100644
--- a/drivers/ide/at91_ide.c
+++ b/drivers/ide/at91_ide.c
@@ -143,7 +143,7 @@
 	set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy);
 }
 
-static void at91_ide_input_data(ide_drive_t *drive, struct request *rq,
+static void at91_ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 				void *buf, unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -156,11 +156,11 @@
 	len++;
 
 	enter_16bit(chipselect, mode);
-	__ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2);
+	readsw((void __iomem *)io_ports->data_addr, buf, len / 2);
 	leave_16bit(chipselect, mode);
 }
 
-static void at91_ide_output_data(ide_drive_t *drive, struct request *rq,
+static void at91_ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 				 void *buf, unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -171,7 +171,7 @@
 	pdbg("cs %u buf %p len %d\n", chipselect,  buf, len);
 
 	enter_16bit(chipselect, mode);
-	__ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2);
+	writesw((void __iomem *)io_ports->data_addr, buf, len / 2);
 	leave_16bit(chipselect, mode);
 }
 
@@ -185,55 +185,55 @@
 	writeb(value, (void __iomem *) port);
 }
 
-static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void at91_ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+	struct ide_taskfile *tf = &cmd->tf;
+	u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->tf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+	if (cmd->tf_flags & IDE_FTFLAG_OUT_DATA) {
 		u16 data = (tf->hob_data << 8) | tf->data;
 
 		at91_ide_output_data(drive, NULL, &data, 2);
 	}
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		ide_mm_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		ide_mm_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		ide_mm_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		ide_mm_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		ide_mm_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		ide_mm_outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
 		ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr);
 }
 
-static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void at91_ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->tf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data;
 
 		at91_ide_input_data(drive, NULL, &data, 2);
@@ -244,31 +244,31 @@
 	/* be sure we're looking at the low order bits */
 	ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = ide_mm_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = ide_mm_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = ide_mm_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = ide_mm_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = ide_mm_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = ide_mm_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature = ide_mm_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = ide_mm_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = ide_mm_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = ide_mm_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = ide_mm_inb(io_ports->lbah_addr);
 	}
 }
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 154ec2c..d3a9d6c 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -86,13 +86,13 @@
 	ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
 }
 
-static void au1xxx_input_data(ide_drive_t *drive, struct request *rq,
+static void au1xxx_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			      void *buf, unsigned int len)
 {
 	auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
 }
 
-static void au1xxx_output_data(ide_drive_t *drive, struct request *rq,
+static void au1xxx_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			       void *buf, unsigned int len)
 {
 	auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
@@ -209,23 +209,17 @@
  */
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static int auide_build_dmatable(ide_drive_t *drive)
+static int auide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	int i, iswrite, count = 0;
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
 	_auide_hwif *ahwif = &auide_hwif;
 	struct scatterlist *sg;
+	int i = cmd->sg_nents, count = 0;
+	int iswrite = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
 
-	iswrite = (rq_data_dir(rq) == WRITE);
 	/* Save for interrupt context */
 	ahwif->drive = drive;
 
-	hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-	if (!i)
-		return 0;
-
 	/* fill the descriptors */
 	sg = hwif->sg_table;
 	while (i && sg_dma_len(sg)) {
@@ -286,12 +280,7 @@
 
 static int auide_dma_end(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
-
-	if (hwif->sg_nents) {
-		ide_destroy_dmatable(drive);
-		hwif->sg_nents = 0;
-	}
+	ide_destroy_dmatable(drive);
 
 	return 0;
 }
@@ -301,19 +290,10 @@
 }
 
 
-static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+static int auide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	/* issue cmd to drive */
-	ide_execute_command(drive, command, &ide_dma_intr,
-			    (2*WAIT_CMD), NULL);
-}
-
-static int auide_dma_setup(ide_drive_t *drive)
-{
-	struct request *rq = drive->hwif->rq;
-
-	if (!auide_build_dmatable(drive)) {
-		ide_map_sg(drive, rq);
+	if (auide_build_dmatable(drive, cmd) == 0) {
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
@@ -369,7 +349,6 @@
 static const struct ide_dma_ops au1xxx_dma_ops = {
 	.dma_host_set		= auide_dma_host_set,
 	.dma_setup		= auide_dma_setup,
-	.dma_exec_cmd		= auide_dma_exec_cmd,
 	.dma_start		= auide_dma_start,
 	.dma_end		= auide_dma_end,
 	.dma_test_irq		= auide_dma_test_irq,
diff --git a/drivers/ide/buddha.c b/drivers/ide/buddha.c
index c5a3c9e..d028f88 100644
--- a/drivers/ide/buddha.c
+++ b/drivers/ide/buddha.c
@@ -143,6 +143,11 @@
 	hw->chipset = ide_generic;
 }
 
+static const struct ide_port_info buddha_port_info = {
+	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
+};
+
     /*
      *  Probe for a Buddha or Catweasel IDE interface
      */
@@ -172,10 +177,6 @@
 		
 		board = z->resource.start;
 
-/*
- * FIXME: we now have selectable mmio v/s iomio transports.
- */
-
 		if(type != BOARD_XSURF) {
 			if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
 				continue;
@@ -224,7 +225,7 @@
 			hws[i] = &hw[i];
 		}
 
-		ide_host_add(NULL, hws, NULL);
+		ide_host_add(&buddha_port_info, hws, NULL);
 	}
 
 	return 0;
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index aeee036..bf0e3f4 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -379,11 +379,11 @@
 static const struct ide_dma_ops cmd64x_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= cmd64x_dma_end,
 	.dma_test_irq		= cmd64x_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
@@ -391,11 +391,11 @@
 static const struct ide_dma_ops cmd646_rev1_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= cmd646_1_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
@@ -403,11 +403,11 @@
 static const struct ide_dma_ops cmd648_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= cmd648_dma_end,
 	.dma_test_irq		= cmd648_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c
index 7a62db7..d5dcf48 100644
--- a/drivers/ide/cs5536.c
+++ b/drivers/ide/cs5536.c
@@ -231,11 +231,11 @@
 static const struct ide_dma_ops cs5536_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= cs5536_dma_start,
 	.dma_end		= cs5536_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 };
 
diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c
index bacb119..f153b95 100644
--- a/drivers/ide/delkin_cb.c
+++ b/drivers/ide/delkin_cb.c
@@ -66,6 +66,7 @@
 	.port_ops		= &delkin_cb_port_ops,
 	.host_flags		= IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS |
 				  IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
 	.init_chipset		= delkin_cb_init_chipset,
 };
 
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 689b2e4..c6b1381 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -100,7 +100,8 @@
 				  IDE_HFLAG_IO_32BIT |
 				  /* disallow ->io_32bit changes */
 				  IDE_HFLAG_NO_IO_32BIT |
-				  IDE_HFLAG_NO_DMA,
+				  IDE_HFLAG_NO_DMA |
+				  IDE_HFLAG_DTC2278,
 	.pio_mask		= ATA_PIO4,
 };
 
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c
index a638e95..b368a5e 100644
--- a/drivers/ide/falconide.c
+++ b/drivers/ide/falconide.c
@@ -40,29 +40,48 @@
      *  which is shared between several drivers.
      */
 
-int falconide_intr_lock;
-EXPORT_SYMBOL(falconide_intr_lock);
+static int falconide_intr_lock;
 
-static void falconide_input_data(ide_drive_t *drive, struct request *rq,
+static void falconide_release_lock(void)
+{
+	if (falconide_intr_lock == 0) {
+		printk(KERN_ERR "%s: bug\n", __func__);
+		return;
+	}
+	falconide_intr_lock = 0;
+	stdma_release();
+}
+
+static void falconide_get_lock(irq_handler_t handler, void *data)
+{
+	if (falconide_intr_lock == 0) {
+		if (in_interrupt() > 0)
+			panic("Falcon IDE hasn't ST-DMA lock in interrupt");
+		stdma_lock(handler, data);
+		falconide_intr_lock = 1;
+	}
+}
+
+static void falconide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 				 void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 
-	if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS))
 		return insw(data_addr, buf, (len + 1) / 2);
 
-	insw_swapw(data_addr, buf, (len + 1) / 2);
+	raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 }
 
-static void falconide_output_data(ide_drive_t *drive, struct request *rq,
+static void falconide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 				  void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 
-	if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS))
 		return outsw(data_addr, buf, (len + 1) / 2);
 
-	outsw_swapw(data_addr, buf, (len + 1) / 2);
+	raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 }
 
 /* Atari has a byte-swapped IDE interface */
@@ -81,8 +100,12 @@
 };
 
 static const struct ide_port_info falconide_port_info = {
+	.get_lock		= falconide_get_lock,
+	.release_lock		= falconide_release_lock,
 	.tp_ops			= &falconide_tp_ops,
-	.host_flags		= IDE_HFLAG_NO_DMA | IDE_HFLAG_SERIALIZE,
+	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
+				  IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
 };
 
 static void __init falconide_setup_ports(hw_regs_t *hw)
@@ -132,9 +155,9 @@
 		goto err;
 	}
 
-	ide_get_lock(NULL, NULL);
+	falconide_get_lock(NULL, NULL);
 	rc = ide_host_register(host, &falconide_port_info, hws);
-	ide_release_lock();
+	falconide_release_lock();
 
 	if (rc)
 		goto err_free;
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 59bd0be..dc77825 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -118,7 +118,9 @@
 }
 
 static const struct ide_port_info gayle_port_info = {
-	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
+	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
+				  IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
 };
 
     /*
@@ -163,9 +165,6 @@
 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
 	    ack_intr = gayle_ack_intr_a1200;
 	}
-/*
- * FIXME: we now have selectable modes between mmio v/s iomio
- */
 
 	res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
 	res_n = GAYLE_IDEREG_SIZE;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index d3b3e82..dbaf184 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -1418,11 +1418,11 @@
 static const struct ide_dma_ops hpt37x_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= hpt374_dma_end,
 	.dma_test_irq		= hpt374_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
@@ -1430,11 +1430,11 @@
 static const struct ide_dma_ops hpt370_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= hpt370_dma_start,
 	.dma_end		= hpt370_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= hpt370_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
@@ -1442,11 +1442,11 @@
 static const struct ide_dma_ops hpt36x_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= hpt366_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 415d7e2..51ce404 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -307,15 +307,14 @@
 	enable_dma(ec->dma);
 }
 
-static int icside_dma_setup(ide_drive_t *drive)
+static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct expansion_card *ec = ECARD_DEV(hwif->dev);
 	struct icside_state *state = ecard_get_drvdata(ec);
-	struct request *rq = hwif->rq;
 	unsigned int dma_mode;
 
-	if (rq_data_dir(rq))
+	if (cmd->tf_flags & IDE_TFLAG_WRITE)
 		dma_mode = DMA_MODE_WRITE;
 	else
 		dma_mode = DMA_MODE_READ;
@@ -325,8 +324,6 @@
 	 */
 	BUG_ON(dma_channel_active(ec->dma));
 
-	hwif->sg_nents = ide_build_sglist(drive, rq);
-
 	/*
 	 * Ensure that we have the right interrupt routed.
 	 */
@@ -346,7 +343,7 @@
 	 * Tell the DMA engine about the SG table and
 	 * data direction.
 	 */
-	set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
+	set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents);
 	set_dma_mode(ec->dma, dma_mode);
 
 	drive->waiting_for_dma = 1;
@@ -354,12 +351,6 @@
 	return 0;
 }
 
-static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
-{
-	/* issue cmd to drive */
-	ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);
-}
-
 static int icside_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -383,7 +374,6 @@
 static const struct ide_dma_ops icside_v6_dma_ops = {
 	.dma_host_set		= icside_dma_host_set,
 	.dma_setup		= icside_dma_setup,
-	.dma_exec_cmd		= icside_dma_exec_cmd,
 	.dma_start		= icside_dma_start,
 	.dma_end		= icside_dma_end,
 	.dma_test_irq		= icside_dma_test_irq,
@@ -419,6 +409,10 @@
 	hw->chipset = ide_acorn;
 }
 
+static const struct ide_port_info icside_v5_port_info = {
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 static int __devinit
 icside_register_v5(struct icside_state *state, struct expansion_card *ec)
 {
@@ -445,7 +439,7 @@
 
 	icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
 
-	host = ide_host_alloc(NULL, hws);
+	host = ide_host_alloc(&icside_v5_port_info, hws);
 	if (host == NULL)
 		return -ENODEV;
 
@@ -453,7 +447,7 @@
 
 	ecard_set_drvdata(ec, state);
 
-	ret = ide_host_register(host, NULL, hws);
+	ret = ide_host_register(host, &icside_v5_port_info, hws);
 	if (ret)
 		goto err_free;
 
diff --git a/drivers/ide/ide-4drives.c b/drivers/ide/ide-4drives.c
index 9e85b1e..78aca75 100644
--- a/drivers/ide/ide-4drives.c
+++ b/drivers/ide/ide-4drives.c
@@ -23,7 +23,8 @@
 
 static const struct ide_port_info ide_4drives_port_info = {
 	.port_ops		= &ide_4drives_port_ops,
-	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
+	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA |
+				  IDE_HFLAG_4DRIVES,
 };
 
 static int __init ide_4drives_init(void)
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 5b704f1..12f4369 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -304,7 +304,7 @@
 	/* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */
 	for (ix = 0; ix < gtf_count; ix++) {
 		u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF);
-		ide_task_t task;
+		struct ide_cmd cmd;
 
 		DEBPRINT("(0x1f1-1f7): "
 			 "hex: %02x %02x %02x %02x %02x %02x %02x\n",
@@ -317,11 +317,11 @@
 		}
 
 		/* convert GTF to taskfile */
-		memset(&task, 0, sizeof(ide_task_t));
-		memcpy(&task.tf_array[7], gtf, REGS_PER_GTF);
-		task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+		memset(&cmd, 0, sizeof(cmd));
+		memcpy(&cmd.tf_array[7], gtf, REGS_PER_GTF);
+		cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-		err = ide_no_data_taskfile(drive, &task);
+		err = ide_no_data_taskfile(drive, &cmd);
 		if (err) {
 			printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
 					__func__, err);
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 6adc5b4..2fb5d28 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -302,16 +302,16 @@
 
 void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
-			IDE_TFLAG_IN_NSECT;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+		       IDE_TFLAG_IN_NSECT;
 
-	drive->hwif->tp_ops->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &cmd);
 
-	*bcount = (task.tf.lbah << 8) | task.tf.lbam;
-	*ireason = task.tf.nsect & 3;
+	*bcount = (cmd.tf.lbah << 8) | cmd.tf.lbam;
+	*ireason = cmd.tf.nsect & 3;
 }
 EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
 
@@ -336,11 +336,6 @@
 	timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
 					       : WAIT_TAPE_CMD;
 
-	if (pc->flags & PC_FLAG_TIMEDOUT) {
-		drive->pc_callback(drive, 0);
-		return ide_stopped;
-	}
-
 	/* Clear the interrupt */
 	stat = tp_ops->read_status(hwif);
 
@@ -362,6 +357,8 @@
 
 	/* No more interrupts */
 	if ((stat & ATA_DRQ) == 0) {
+		int uptodate;
+
 		debug_log("Packet command completed, %d bytes transferred\n",
 			  pc->xferred);
 
@@ -400,7 +397,22 @@
 			dsc = 1;
 
 		/* Command finished - Call the callback function */
-		drive->pc_callback(drive, dsc);
+		uptodate = drive->pc_callback(drive, dsc);
+
+		if (uptodate == 0)
+			drive->failed_pc = NULL;
+
+		if (blk_special_request(rq)) {
+			rq->errors = 0;
+			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
+		} else {
+			if (blk_fs_request(rq) == 0 && uptodate <= 0) {
+				if (rq->errors == 0)
+					rq->errors = -EIO;
+			}
+			ide_complete_rq(drive, uptodate ? 0 : -EIO,
+					ide_rq_bytes(rq));
+		}
 
 		return ide_stopped;
 	}
@@ -458,7 +470,8 @@
 
 		/* FIXME: don't do partial completions */
 		if (drive->media == ide_floppy)
-			ide_end_request(drive, 1, done >> 9);
+			ide_complete_rq(drive, 0,
+					done ? done : ide_rq_bytes(rq));
 	} else
 		xferfunc(drive, NULL, pc->cur_pos, bcount);
 
@@ -470,39 +483,32 @@
 		  rq->cmd[0], bcount);
 next_irq:
 	/* And set the interrupt handler again */
-	ide_set_handler(drive, ide_pc_intr, timeout, NULL);
+	ide_set_handler(drive, ide_pc_intr, timeout);
 	return ide_started;
 }
 
-static void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount)
+static void ide_init_packet_cmd(struct ide_cmd *cmd, u32 tf_flags,
+				u16 bcount, u8 dma)
 {
-	ide_hwif_t *hwif = drive->hwif;
-	ide_task_t task;
-	u8 dma = drive->dma;
-
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
-			IDE_TFLAG_OUT_FEATURE | tf_flags;
-	task.tf.feature = dma;		/* Use PIO/DMA */
-	task.tf.lbam    = bcount & 0xff;
-	task.tf.lbah    = (bcount >> 8) & 0xff;
-
-	ide_tf_dump(drive->name, &task.tf);
-	hwif->tp_ops->set_irq(hwif, 1);
-	SELECT_MASK(drive, 0);
-	hwif->tp_ops->tf_load(drive, &task);
+	cmd->protocol  = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO;
+	cmd->tf_flags |= IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
+			 IDE_TFLAG_OUT_FEATURE | tf_flags;
+	cmd->tf.command = ATA_CMD_PACKET;
+	cmd->tf.feature = dma;		/* Use PIO/DMA */
+	cmd->tf.lbam    = bcount & 0xff;
+	cmd->tf.lbah    = (bcount >> 8) & 0xff;
 }
 
 static u8 ide_read_ireason(ide_drive_t *drive)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_IN_NSECT;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_IN_NSECT;
 
-	drive->hwif->tp_ops->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &cmd);
 
-	return task.tf.nsect & 3;
+	return cmd.tf.nsect & 3;
 }
 
 static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
@@ -597,11 +603,13 @@
 		}
 	}
 
+	hwif->expiry = expiry;
+
 	/* Set the interrupt routine */
 	ide_set_handler(drive,
 			(dev_is_idecd(drive) ? drive->irq_handler
 					     : ide_pc_intr),
-			timeout, expiry);
+			timeout);
 
 	/* Begin DMA, if necessary */
 	if (dev_is_idecd(drive)) {
@@ -621,23 +629,30 @@
 	return ide_started;
 }
 
-ide_startstop_t ide_issue_pc(ide_drive_t *drive)
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	struct ide_atapi_pc *pc;
 	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_dma_ops *dma_ops = hwif->dma_ops;
 	ide_expiry_t *expiry = NULL;
+	struct request *rq = hwif->rq;
 	unsigned int timeout;
 	u32 tf_flags;
 	u16 bcount;
+	u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
 
 	if (dev_is_idecd(drive)) {
 		tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
-		bcount = ide_cd_get_xferlen(hwif->rq);
+		bcount = ide_cd_get_xferlen(rq);
 		expiry = ide_cd_expiry;
 		timeout = ATAPI_WAIT_PC;
 
-		if (drive->dma)
-			drive->dma = !hwif->dma_ops->dma_setup(drive);
+		if (drive->dma) {
+			if (ide_build_sglist(drive, cmd))
+				drive->dma = !dma_ops->dma_setup(drive, cmd);
+			else
+				drive->dma = 0;
+		}
 	} else {
 		pc = drive->pc;
 
@@ -656,8 +671,12 @@
 		}
 
 		if ((pc->flags & PC_FLAG_DMA_OK) &&
-		     (drive->dev_flags & IDE_DFLAG_USING_DMA))
-			drive->dma = !hwif->dma_ops->dma_setup(drive);
+		     (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
+			if (ide_build_sglist(drive, cmd))
+				drive->dma = !dma_ops->dma_setup(drive, cmd);
+			else
+				drive->dma = 0;
+		}
 
 		if (!drive->dma)
 			pc->flags &= ~PC_FLAG_DMA_OK;
@@ -666,18 +685,18 @@
 						       : WAIT_TAPE_CMD;
 	}
 
-	ide_pktcmd_tf_load(drive, tf_flags, bcount);
+	ide_init_packet_cmd(cmd, tf_flags, bcount, drive->dma);
 
-	/* Issue the packet command */
-	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+	(void)do_rw_taskfile(drive, cmd);
+
+	if (drq_int) {
 		if (drive->dma)
 			drive->waiting_for_dma = 0;
-		ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
-				    timeout, expiry);
-		return ide_started;
-	} else {
-		ide_execute_pkt_cmd(drive);
-		return ide_transfer_pc(drive);
+		hwif->expiry = expiry;
 	}
+
+	ide_execute_command(drive, cmd, ide_transfer_pc, timeout);
+
+	return drq_int ? ide_started : ide_transfer_pc(drive);
 }
 EXPORT_SYMBOL_GPL(ide_issue_pc);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 2177cd1..3f630e4 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -100,8 +100,7 @@
 {
 	int log = 0;
 
-	ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
-		      sense->sense_key);
+	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
 
 	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
 		return 0;
@@ -151,13 +150,12 @@
 	unsigned long bio_sectors;
 	struct cdrom_info *info = drive->driver_data;
 
-	ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
-			"sense_key: 0x%x\n", __func__, sense->error_code,
-			sense->sense_key);
+	ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x",
+				     sense->error_code, sense->sense_key);
 
 	if (failed_command)
-		ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
-				__func__, failed_command->cmd[0]);
+		ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x",
+					     failed_command->cmd[0]);
 
 	if (!cdrom_log_sense(drive, failed_command, sense))
 		return;
@@ -215,9 +213,9 @@
 				      struct request *failed_command)
 {
 	struct cdrom_info *info		= drive->driver_data;
-	struct request *rq		= &info->request_sense_request;
+	struct request *rq		= &drive->request_sense_rq;
 
-	ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_SENSE, "enter");
 
 	if (sense == NULL)
 		sense = &info->sense_data;
@@ -239,8 +237,8 @@
 	rq->buffer = (void *) failed_command;
 
 	if (failed_command)
-		ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
-			      failed_command->cmd[0]);
+		ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x",
+					     failed_command->cmd[0]);
 
 	drive->hwif->rq = NULL;
 
@@ -252,9 +250,8 @@
 	struct request *rq = drive->hwif->rq;
 	int nsectors = rq->hard_cur_sectors;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
-		      "nsectors: %d\n", __func__, rq->cmd[0], uptodate,
-		      nsectors);
+	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, uptodate: 0x%x, nsectors: %d",
+				    rq->cmd[0], uptodate, nsectors);
 
 	if (blk_sense_request(rq) && uptodate) {
 		/*
@@ -275,8 +272,8 @@
 			 * now end the failed request
 			 */
 			if (blk_fs_request(failed)) {
-				if (ide_end_dequeued_request(drive, failed, 0,
-						failed->hard_nr_sectors))
+				if (ide_end_rq(drive, failed, -EIO,
+						failed->hard_nr_sectors << 9))
 					BUG();
 			} else {
 				if (blk_end_request(failed, -EIO,
@@ -295,10 +292,13 @@
 	if (!nsectors)
 		nsectors = 1;
 
-	ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
-		      __func__, uptodate, nsectors);
+	ide_debug_log(IDE_DBG_FUNC, "uptodate: 0x%x, nsectors: %d",
+				    uptodate, nsectors);
 
-	ide_end_request(drive, uptodate, nsectors);
+	if (blk_fs_request(rq) == 0 && uptodate <= 0 && rq->errors == 0)
+		rq->errors = -EIO;
+
+	ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);
 }
 
 static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
@@ -338,9 +338,10 @@
 		return 1;
 	}
 
-	ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
-		      "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x, err: 0x%x\n",
-		      __func__, stat, good_stat, rq->cmd[0], rq->cmd_type, err);
+	ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, "
+				  "rq->cmd_type: 0x%x, err: 0x%x",
+				  stat, good_stat, rq->cmd[0], rq->cmd_type,
+				  err);
 
 	if (blk_sense_request(rq)) {
 		/*
@@ -530,8 +531,7 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
-		      __func__, ireason, rw);
+	ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw);
 
 	/*
 	 * ireason == 0: the drive wants to receive data from us
@@ -572,7 +572,7 @@
  */
 static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
 {
-	ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);
+	ide_debug_log(IDE_DBG_FUNC, "len: %d", len);
 
 	if ((len % SECTOR_SIZE) == 0)
 		return 0;
@@ -594,8 +594,7 @@
 static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
 						 struct request *rq)
 {
-	ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
-		      rq->cmd_flags);
+	ide_debug_log(IDE_DBG_RQ, "rq->cmd_flags: 0x%x", rq->cmd_flags);
 
 	if (rq_data_dir(rq) == READ) {
 		unsigned short sectors_per_frame =
@@ -639,7 +638,7 @@
 static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
 {
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	if (rq->buffer != bio_data(rq->bio)) {
 		sector_t n =
@@ -658,8 +657,7 @@
 
 static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
 {
-	ide_debug_log(IDE_DBG_FUNC, "Call %s, rq->cmd[0]: 0x%x\n",
-		      __func__, rq->cmd[0]);
+	ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]);
 
 	/*
 	 * Some of the trailing request sense fields are optional,
@@ -686,9 +684,9 @@
 	if (!sense)
 		sense = &local_sense;
 
-	ide_debug_log(IDE_DBG_PC, "Call %s, cmd[0]: 0x%x, write: 0x%x, "
-		      "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
-		      timeout, cmd_flags);
+	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, "
+				  "cmd_flags: 0x%x",
+				  cmd[0], write, timeout, cmd_flags);
 
 	/* start of retry loop */
 	do {
@@ -772,8 +770,8 @@
 	u16 len;
 	u8 ireason;
 
-	ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
-		      __func__, rq->cmd[0], write);
+	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x",
+				  rq->cmd[0], write);
 
 	/* check for errors */
 	dma = drive->dma;
@@ -795,10 +793,11 @@
 		if (dma_error)
 			return ide_error(drive, "dma error", stat);
 		if (blk_fs_request(rq)) {
-			ide_end_request(drive, 1, rq->nr_sectors);
+			ide_complete_rq(drive, 0, rq->nr_sectors
+				? (rq->nr_sectors << 9) : ide_rq_bytes(rq));
 			return ide_stopped;
 		} else if (rq->cmd_type == REQ_TYPE_ATA_PC && !rq->bio) {
-			ide_end_request(drive, 1, 1);
+			ide_complete_rq(drive, 0, 512);
 			return ide_stopped;
 		}
 		goto end_request;
@@ -810,8 +809,8 @@
 	if (thislen > len)
 		thislen = len;
 
-	ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
-		      __func__, stat, thislen);
+	ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d",
+				  stat, thislen);
 
 	/* If DRQ is clear, the command has completed. */
 	if ((stat & ATA_DRQ) == 0) {
@@ -876,8 +875,9 @@
 		xferfunc = hwif->tp_ops->input_data;
 	}
 
-	ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
-		      "ireason: 0x%x\n", __func__, rq->cmd_type, ireason);
+	ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, "
+				  "ireason: 0x%x",
+				  rq->cmd_type, ireason);
 
 	/* transfer data */
 	while (thislen > 0) {
@@ -959,7 +959,8 @@
 			expiry = ide_cd_expiry;
 	}
 
-	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
+	hwif->expiry = expiry;
+	ide_set_handler(drive, cdrom_newpc_intr, timeout);
 	return ide_started;
 
 end_request:
@@ -988,9 +989,9 @@
 	unsigned short sectors_per_frame =
 		queue_hardsect_size(drive->queue) >> SECTOR_BITS;
 
-	ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
-		      "secs_per_frame: %u\n",
-		      __func__, rq->cmd[0], write, sectors_per_frame);
+	ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, write: 0x%x, "
+				  "secs_per_frame: %u",
+				  rq->cmd[0], write, sectors_per_frame);
 
 	if (write) {
 		/* disk has become write protected */
@@ -1026,9 +1027,8 @@
 static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
 {
 
-	ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, "
-		      "rq->cmd_type: 0x%x\n", __func__, rq->cmd[0],
-		      rq->cmd_type);
+	ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x",
+				  rq->cmd[0], rq->cmd_type);
 
 	if (blk_pc_request(rq))
 		rq->cmd_flags |= REQ_QUIET;
@@ -1067,10 +1067,13 @@
 static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
 					sector_t block)
 {
-	ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, "
-		      "rq->cmd_type: 0x%x, block: %llu\n",
-		      __func__, rq->cmd[0], rq->cmd_type,
-		      (unsigned long long)block);
+	struct ide_cmd cmd;
+
+	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu",
+				  rq->cmd[0], (unsigned long long)block);
+
+	if (drive->debug_mask & IDE_DBG_RQ)
+		blk_dump_rq_flags(rq, "ide_cd_do_request");
 
 	if (blk_fs_request(rq)) {
 		if (cdrom_start_rw(drive, rq) == ide_stopped)
@@ -1094,7 +1097,14 @@
 		return ide_stopped;
 	}
 
-	return ide_issue_pc(drive);
+	memset(&cmd, 0, sizeof(cmd));
+
+	if (rq_data_dir(rq))
+		cmd.tf_flags |= IDE_TFLAG_WRITE;
+
+	cmd.rq = rq;
+
+	return ide_issue_pc(drive, &cmd);
 }
 
 /*
@@ -1119,7 +1129,7 @@
 	struct cdrom_device_info *cdi = &info->devinfo;
 	unsigned char cmd[BLK_MAX_CDB];
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	memset(cmd, 0, BLK_MAX_CDB);
 	cmd[0] = GPCMD_TEST_UNIT_READY;
@@ -1147,7 +1157,7 @@
 	unsigned len = sizeof(capbuf);
 	u32 blocklen;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	memset(cmd, 0, BLK_MAX_CDB);
 	cmd[0] = GPCMD_READ_CDVD_CAPACITY;
@@ -1179,8 +1189,8 @@
 	*capacity = 1 + be32_to_cpu(capbuf.lba);
 	*sectors_per_frame = blocklen >> SECTOR_BITS;
 
-	ide_debug_log(IDE_DBG_PROBE, "%s: cap: %lu, sectors_per_frame: %lu\n",
-		      __func__, *capacity, *sectors_per_frame);
+	ide_debug_log(IDE_DBG_PROBE, "cap: %lu, sectors_per_frame: %lu",
+				     *capacity, *sectors_per_frame);
 
 	return 0;
 }
@@ -1191,7 +1201,7 @@
 {
 	unsigned char cmd[BLK_MAX_CDB];
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	memset(cmd, 0, BLK_MAX_CDB);
 
@@ -1221,7 +1231,7 @@
 	long last_written;
 	unsigned long sectors_per_frame = SECTORS_PER_FRAME;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	if (toc == NULL) {
 		/* try to allocate space */
@@ -1383,7 +1393,7 @@
 	struct packet_command cgc;
 	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
 		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
@@ -1403,7 +1413,7 @@
 	struct cdrom_info *cd = drive->driver_data;
 	u16 curspeed, maxspeed;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
 		curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
@@ -1413,8 +1423,8 @@
 		maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
 	}
 
-	ide_debug_log(IDE_DBG_PROBE, "%s: curspeed: %u, maxspeed: %u\n",
-		      __func__, curspeed, maxspeed);
+	ide_debug_log(IDE_DBG_PROBE, "curspeed: %u, maxspeed: %u",
+				     curspeed, maxspeed);
 
 	cd->current_speed = (curspeed + (176/2)) / 176;
 	cd->max_speed = (maxspeed + (176/2)) / 176;
@@ -1448,7 +1458,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *devinfo = &info->devinfo;
 
-	ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);
+	ide_debug_log(IDE_DBG_PROBE, "nslots: %d", nslots);
 
 	devinfo->ops = &ide_cdrom_dops;
 	devinfo->speed = info->current_speed;
@@ -1471,9 +1481,8 @@
 	mechtype_t mechtype;
 	int nslots = 1;
 
-	ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
-		      "drive->atapi_flags: 0x%lx\n", __func__, drive->media,
-		      drive->atapi_flags);
+	ide_debug_log(IDE_DBG_PROBE, "media: 0x%x, atapi_flags: 0x%lx",
+				     drive->media, drive->atapi_flags);
 
 	cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
 		     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
@@ -1754,7 +1763,7 @@
 	char *fw_rev = (char *)&id[ATA_ID_FW_REV];
 	int nslots;
 
-	ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_PROBE, "enter");
 
 	blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
 	blk_queue_dma_alignment(drive->queue, 31);
@@ -1797,7 +1806,7 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	ide_proc_unregister_driver(drive, info->driver);
 	device_del(&info->dev);
@@ -1815,7 +1824,7 @@
 	ide_drive_t *drive = info->drive;
 	struct gendisk *g = info->disk;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	kfree(info->toc);
 	if (devinfo->handle == drive)
@@ -1839,7 +1848,6 @@
 	.remove			= ide_cd_remove,
 	.version		= IDECD_VERSION,
 	.do_request		= ide_cd_do_request,
-	.end_request		= ide_end_request,
 #ifdef CONFIG_IDE_PROC_FS
 	.proc_entries		= ide_cd_proc_entries,
 	.proc_devsets		= ide_cd_proc_devsets,
@@ -1974,9 +1982,8 @@
 	struct gendisk *g;
 	struct request_sense sense;
 
-	ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
-		      "drive->media: 0x%x\n", __func__, drive->driver_req,
-		      drive->media);
+	ide_debug_log(IDE_DBG_PROBE, "driver_req: %s, media: 0x%x",
+				     drive->driver_req, drive->media);
 
 	if (!strstr("ide-cdrom", drive->driver_req))
 		goto failed;
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index c878bfc..1d97101 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -11,7 +11,7 @@
 #define IDECD_DEBUG_LOG		0
 
 #if IDECD_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
 #else
 #define ide_debug_log(lvl, fmt, args...) do {} while (0)
 #endif
@@ -91,8 +91,6 @@
 	   on this device. */
 	struct request_sense sense_data;
 
-	struct request request_sense_request;
-
 	u8 max_speed;		/* Max speed of the drive. */
 	u8 current_speed;	/* Current speed of the drive. */
 
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index f50210f..9e47f35 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -154,6 +154,7 @@
 static const struct ide_port_info idecs_port_info = {
 	.port_ops		= &idecs_port_ops,
 	.host_flags		= IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
 };
 
 static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
index 7c39534..5bf958e 100644
--- a/drivers/ide/ide-devsets.c
+++ b/drivers/ide/ide-devsets.c
@@ -183,8 +183,6 @@
 	err = setfunc(drive, *(int *)&rq->cmd[1]);
 	if (err)
 		rq->errors = err;
-	else
-		err = 1;
-	ide_end_request(drive, err, 0);
+	ide_complete_rq(drive, err, ide_rq_bytes(rq));
 	return ide_stopped;
 }
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 806760d..ca934c8 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -28,7 +28,6 @@
 #include <linux/mutex.h>
 #include <linux/leds.h>
 #include <linux/ide.h>
-#include <linux/hdreg.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -53,33 +52,26 @@
 	ATA_CMD_WRITE_EXT,
 };
 
-static const u8 ide_data_phases[] = {
-	TASKFILE_MULTI_IN,
-	TASKFILE_MULTI_OUT,
-	TASKFILE_IN,
-	TASKFILE_OUT,
-	TASKFILE_IN_DMA,
-	TASKFILE_OUT_DMA,
-};
-
-static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
+static void ide_tf_set_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 dma)
 {
 	u8 index, lba48, write;
 
-	lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
-	write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
+	lba48 = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
+	write = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
 
-	if (dma)
+	if (dma) {
+		cmd->protocol = ATA_PROT_DMA;
 		index = 8;
-	else
-		index = drive->mult_count ? 0 : 4;
+	} else {
+		cmd->protocol = ATA_PROT_PIO;
+		if (drive->mult_count) {
+			cmd->tf_flags |= IDE_TFLAG_MULTI_PIO;
+			index = 0;
+		} else
+			index = 4;
+	}
 
-	task->tf.command = ide_rw_cmds[index + lba48 + write];
-
-	if (dma)
-		index = 8; /* fixup index */
-
-	task->data_phase = ide_data_phases[index / 2 + write];
+	cmd->tf.command = ide_rw_cmds[index + lba48 + write];
 }
 
 /*
@@ -93,8 +85,8 @@
 	u16 nsectors		= (u16)rq->nr_sectors;
 	u8 lba48		= !!(drive->dev_flags & IDE_DFLAG_LBA48);
 	u8 dma			= !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
-	ide_task_t		task;
-	struct ide_taskfile	*tf = &task.tf;
+	struct ide_cmd		cmd;
+	struct ide_taskfile	*tf = &cmd.tf;
 	ide_startstop_t		rc;
 
 	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
@@ -104,13 +96,8 @@
 			lba48 = 0;
 	}
 
-	if (!dma) {
-		ide_init_sg_cmd(drive, rq);
-		ide_map_sg(drive, rq);
-	}
-
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
 	if (drive->dev_flags & IDE_DFLAG_LBA) {
 		if (lba48) {
@@ -129,7 +116,7 @@
 			tf->lbam   = (u8)(block >>  8);
 			tf->lbah   = (u8)(block >> 16);
 
-			task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+			cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
 		} else {
 			tf->nsect  = nsectors & 0xff;
 			tf->lbal   = block;
@@ -156,23 +143,27 @@
 		tf->device = head;
 	}
 
+	cmd.tf_flags |= IDE_TFLAG_FS;
+
 	if (rq_data_dir(rq))
-		task.tf_flags |= IDE_TFLAG_WRITE;
+		cmd.tf_flags |= IDE_TFLAG_WRITE;
 
-	ide_tf_set_cmd(drive, &task, dma);
-	if (!dma)
-		hwif->data_phase = task.data_phase;
-	task.rq = rq;
+	ide_tf_set_cmd(drive, &cmd, dma);
+	cmd.rq = rq;
 
-	rc = do_rw_taskfile(drive, &task);
+	if (dma == 0) {
+		ide_init_sg_cmd(&cmd, nsectors << 9);
+		ide_map_sg(drive, &cmd);
+	}
+
+	rc = do_rw_taskfile(drive, &cmd);
 
 	if (rc == ide_stopped && dma) {
 		/* fallback to PIO */
-		task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
-		ide_tf_set_cmd(drive, &task, 0);
-		hwif->data_phase = task.data_phase;
-		ide_init_sg_cmd(drive, rq);
-		rc = do_rw_taskfile(drive, &task);
+		cmd.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
+		ide_tf_set_cmd(drive, &cmd, 0);
+		ide_init_sg_cmd(&cmd, nsectors << 9);
+		rc = do_rw_taskfile(drive, &cmd);
 	}
 
 	return rc;
@@ -193,7 +184,9 @@
 
 	if (!blk_fs_request(rq)) {
 		blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
-		ide_end_request(drive, 0, 0);
+		if (rq->errors == 0)
+			rq->errors = -EIO;
+		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
 		return ide_stopped;
 	}
 
@@ -216,22 +209,22 @@
  */
 static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
 {
-	ide_task_t args;
-	struct ide_taskfile *tf = &args.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 	u64 addr = 0;
 
-	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 	if (lba48)
 		tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
 	else
 		tf->command = ATA_CMD_READ_NATIVE_MAX;
 	tf->device  = ATA_LBA;
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 	if (lba48)
-		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
-	/* submit command request */
-	ide_no_data_taskfile(drive, &args);
+		cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+
+	ide_no_data_taskfile(drive, &cmd);
 
 	/* if OK, compute maximum address value */
 	if ((tf->status & 0x01) == 0)
@@ -246,13 +239,13 @@
  */
 static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
 {
-	ide_task_t args;
-	struct ide_taskfile *tf = &args.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 	u64 addr_set = 0;
 
 	addr_req--;
-	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
+
+	memset(&cmd, 0, sizeof(cmd));
 	tf->lbal     = (addr_req >>  0) & 0xff;
 	tf->lbam     = (addr_req >>= 8) & 0xff;
 	tf->lbah     = (addr_req >>= 8) & 0xff;
@@ -266,11 +259,13 @@
 		tf->command  = ATA_CMD_SET_MAX;
 	}
 	tf->device |= ATA_LBA;
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 	if (lba48)
-		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
-	/* submit command request */
-	ide_no_data_taskfile(drive, &args);
+		cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+
+	ide_no_data_taskfile(drive, &cmd);
+
 	/* if OK, compute maximum address value */
 	if ((tf->status & 0x01) == 0)
 		addr_set = ide_get_lba_addr(tf, lba48) + 1;
@@ -389,24 +384,24 @@
 static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 {
 	ide_drive_t *drive = q->queuedata;
-	ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC);
+	struct ide_cmd *cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
 
 	/* FIXME: map struct ide_taskfile on rq->cmd[] */
-	BUG_ON(task == NULL);
+	BUG_ON(cmd == NULL);
 
-	memset(task, 0, sizeof(*task));
+	memset(cmd, 0, sizeof(*cmd));
 	if (ata_id_flush_ext_enabled(drive->id) &&
 	    (drive->capacity64 >= (1UL << 28)))
-		task->tf.command = ATA_CMD_FLUSH_EXT;
+		cmd->tf.command = ATA_CMD_FLUSH_EXT;
 	else
-		task->tf.command = ATA_CMD_FLUSH;
-	task->tf_flags	 = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
-			   IDE_TFLAG_DYN;
-	task->data_phase = TASKFILE_NO_DATA;
+		cmd->tf.command = ATA_CMD_FLUSH;
+	cmd->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
+			IDE_TFLAG_DYN;
+	cmd->protocol = ATA_PROT_NODATA;
 
 	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
 	rq->cmd_flags |= REQ_SOFTBARRIER;
-	rq->special = task;
+	rq->special = cmd;
 }
 
 ide_devset_get(multcount, mult_count);
@@ -456,15 +451,15 @@
 
 static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 
-	memset(&task, 0, sizeof(task));
-	task.tf.feature = feature;
-	task.tf.nsect   = nsect;
-	task.tf.command = ATA_CMD_SET_FEATURES;
-	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf.feature = feature;
+	cmd.tf.nsect   = nsect;
+	cmd.tf.command = ATA_CMD_SET_FEATURES;
+	cmd.tf_flags   = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-	return ide_no_data_taskfile(drive, &task);
+	return ide_no_data_taskfile(drive, &cmd);
 }
 
 static void update_ordered(ide_drive_t *drive)
@@ -531,15 +526,16 @@
 
 static int do_idedisk_flushcache(ide_drive_t *drive)
 {
-	ide_task_t args;
+	struct ide_cmd cmd;
 
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 	if (ata_id_flush_ext_enabled(drive->id))
-		args.tf.command = ATA_CMD_FLUSH_EXT;
+		cmd.tf.command = ATA_CMD_FLUSH_EXT;
 	else
-		args.tf.command = ATA_CMD_FLUSH;
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	return ide_no_data_taskfile(drive, &args);
+		cmd.tf.command = ATA_CMD_FLUSH;
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+	return ide_no_data_taskfile(drive, &cmd);
 }
 
 ide_devset_get(acoustic, acoustic);
@@ -711,17 +707,17 @@
 static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk,
 				 int on)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 	int ret;
 
 	if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
 		return 0;
 
-	memset(&task, 0, sizeof(task));
-	task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
-	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
+	cmd.tf_flags   = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-	ret = ide_no_data_taskfile(drive, &task);
+	ret = ide_no_data_taskfile(drive, &cmd);
 
 	if (ret)
 		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
@@ -737,6 +733,5 @@
 	.init_media	= ide_disk_init_media,
 	.set_doorlock	= ide_disk_set_doorlock,
 	.do_request	= ide_do_rw_disk,
-	.end_request	= ide_end_request,
 	.ioctl		= ide_disk_ioctl,
 };
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
index 1f86dcb..eaea3be 100644
--- a/drivers/ide/ide-disk_proc.c
+++ b/drivers/ide/ide-disk_proc.c
@@ -1,38 +1,38 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
-#include <linux/hdreg.h>
 
 #include "ide-disk.h"
 
 static int smart_enable(ide_drive_t *drive)
 {
-	ide_task_t args;
-	struct ide_taskfile *tf = &args.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 	tf->feature = ATA_SMART_ENABLE;
 	tf->lbam    = ATA_SMART_LBAM_PASS;
 	tf->lbah    = ATA_SMART_LBAH_PASS;
 	tf->command = ATA_CMD_SMART;
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	return ide_no_data_taskfile(drive, &args);
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+	return ide_no_data_taskfile(drive, &cmd);
 }
 
 static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
 {
-	ide_task_t args;
-	struct ide_taskfile *tf = &args.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 	tf->feature = sub_cmd;
 	tf->nsect   = 0x01;
 	tf->lbam    = ATA_SMART_LBAM_PASS;
 	tf->lbah    = ATA_SMART_LBAH_PASS;
 	tf->command = ATA_CMD_SMART;
-	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	args.data_phase	= TASKFILE_IN;
-	(void) smart_enable(drive);
-	return ide_raw_taskfile(drive, &args, buf, 1);
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	cmd.protocol = ATA_PROT_PIO;
+
+	return ide_raw_taskfile(drive, &cmd, buf, 1);
 }
 
 static int proc_idedisk_read_cache
@@ -67,6 +67,8 @@
 	ide_drive_t	*drive = (ide_drive_t *)data;
 	int		len = 0, i = 0;
 
+	(void)smart_enable(drive);
+
 	if (get_smart_data(drive, page, sub_cmd) == 0) {
 		unsigned short *val = (unsigned short *) page;
 		char *out = (char *)val + SECTOR_SIZE;
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
index 123d393..75a9ea2 100644
--- a/drivers/ide/ide-dma-sff.c
+++ b/drivers/ide/ide-dma-sff.c
@@ -111,7 +111,7 @@
  *	May also be invoked from trm290.c
  */
 
-int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+int ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	__le32 *table = (__le32 *)hwif->dmatable_cpu;
@@ -120,11 +120,7 @@
 	struct scatterlist *sg;
 	u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290);
 
-	hwif->sg_nents = ide_build_sglist(drive, rq);
-	if (hwif->sg_nents == 0)
-		return 0;
-
-	for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+	for_each_sg(hwif->sg_table, sg, cmd->sg_nents, i) {
 		u32 cur_addr, cur_len, xcount, bcount;
 
 		cur_addr = sg_dma_address(sg);
@@ -179,6 +175,7 @@
 /**
  *	ide_dma_setup	-	begin a DMA phase
  *	@drive: target device
+ *	@cmd: command
  *
  *	Build an IDE DMA PRD (IDE speak for scatter gather table)
  *	and then set up the DMA transfer registers for a device
@@ -189,17 +186,16 @@
  *	is returned.
  */
 
-int ide_dma_setup(ide_drive_t *drive)
+int ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
-	unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR;
 	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+	u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
 	u8 dma_stat;
 
 	/* fall back to pio! */
-	if (!ide_build_dmatable(drive, rq)) {
-		ide_map_sg(drive, rq);
+	if (ide_build_dmatable(drive, cmd) == 0) {
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
@@ -212,9 +208,9 @@
 
 	/* specify r/w */
 	if (mmio)
-		writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+		writeb(rw, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
 	else
-		outb(reading, hwif->dma_base + ATA_DMA_CMD);
+		outb(rw, hwif->dma_base + ATA_DMA_CMD);
 
 	/* read DMA status for INTR & ERROR flags */
 	dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
@@ -228,7 +224,7 @@
 EXPORT_SYMBOL_GPL(ide_dma_setup);
 
 /**
- *	dma_timer_expiry	-	handle a DMA timeout
+ *	ide_dma_sff_timer_expiry	-	handle a DMA timeout
  *	@drive: Drive that timed out
  *
  *	An IDE DMA transfer timed out. In the event of an error we ask
@@ -241,7 +237,7 @@
  *	This can occur if an interrupt is lost or due to hang or bugs.
  */
 
-static int dma_timer_expiry(ide_drive_t *drive)
+int ide_dma_sff_timer_expiry(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
@@ -265,14 +261,7 @@
 
 	return 0;	/* Status is unknown -- reset the bus */
 }
-
-void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-	/* issue cmd to drive */
-	ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
-			    dma_timer_expiry);
-}
-EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+EXPORT_SYMBOL_GPL(ide_dma_sff_timer_expiry);
 
 void ide_dma_start(ide_drive_t *drive)
 {
@@ -346,10 +335,10 @@
 const struct ide_dma_ops sff_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_lost_irq		= ide_dma_lost_irq,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index a878f47..3dbf80c 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -96,9 +96,13 @@
 
 	if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
 		if (!dma_stat) {
-			struct request *rq = hwif->rq;
+			struct ide_cmd *cmd = &hwif->cmd;
 
-			task_end_request(drive, rq, stat);
+			if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
+				ide_finish_cmd(drive, cmd, stat);
+			else
+				ide_complete_rq(drive, 0,
+						cmd->rq->nr_sectors << 9);
 			return ide_stopped;
 		}
 		printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
@@ -106,7 +110,6 @@
 	}
 	return ide_error(drive, "dma_intr", stat);
 }
-EXPORT_SYMBOL_GPL(ide_dma_intr);
 
 int ide_dma_good_drive(ide_drive_t *drive)
 {
@@ -116,7 +119,7 @@
 /**
  *	ide_build_sglist	-	map IDE scatter gather for DMA I/O
  *	@drive: the drive to build the DMA table for
- *	@rq: the request holding the sg list
+ *	@cmd: command
  *
  *	Perform the DMA mapping magic necessary to access the source or
  *	target buffers of a request via DMA.  The lower layers of the
@@ -124,28 +127,29 @@
  *	operate in a portable fashion.
  */
 
-int ide_build_sglist(ide_drive_t *drive, struct request *rq)
+int ide_build_sglist(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
 	int i;
 
-	ide_map_sg(drive, rq);
+	ide_map_sg(drive, cmd);
 
-	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = DMA_FROM_DEVICE;
+	if (cmd->tf_flags & IDE_TFLAG_WRITE)
+		cmd->sg_dma_direction = DMA_TO_DEVICE;
 	else
-		hwif->sg_dma_direction = DMA_TO_DEVICE;
+		cmd->sg_dma_direction = DMA_FROM_DEVICE;
 
-	i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
-	if (i) {
-		hwif->orig_sg_nents = hwif->sg_nents;
-		hwif->sg_nents = i;
+	i = dma_map_sg(hwif->dev, sg, cmd->sg_nents, cmd->sg_dma_direction);
+	if (i == 0)
+		ide_map_sg(drive, cmd);
+	else {
+		cmd->orig_sg_nents = cmd->sg_nents;
+		cmd->sg_nents = i;
 	}
 
 	return i;
 }
-EXPORT_SYMBOL_GPL(ide_build_sglist);
 
 /**
  *	ide_destroy_dmatable	-	clean up DMA mapping
@@ -161,9 +165,10 @@
 void ide_destroy_dmatable(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct ide_cmd *cmd = &hwif->cmd;
 
-	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents,
-		     hwif->sg_dma_direction);
+	dma_unmap_sg(hwif->dev, hwif->sg_table, cmd->orig_sg_nents,
+		     cmd->sg_dma_direction);
 }
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
 
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c
index 1231b5e..1166497 100644
--- a/drivers/ide/ide-eh.c
+++ b/drivers/ide/ide-eh.c
@@ -123,8 +123,18 @@
 
 	/* retry only "normal" I/O: */
 	if (!blk_fs_request(rq)) {
-		rq->errors = 1;
-		ide_end_drive_cmd(drive, stat, err);
+		if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+			struct ide_cmd *cmd = rq->special;
+
+			if (cmd)
+				ide_complete_cmd(drive, cmd, stat, err);
+		} else if (blk_pm_request(rq)) {
+			rq->errors = 1;
+			ide_complete_pm_rq(drive, rq);
+			return ide_stopped;
+		}
+		rq->errors = err;
+		ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq));
 		return ide_stopped;
 	}
 
@@ -136,8 +146,11 @@
 {
 	struct request *rq = drive->hwif->rq;
 
-	if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
-		ide_end_request(drive, err ? err : 1, 0);
+	if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) {
+		if (err <= 0 && rq->errors == 0)
+			rq->errors = -EIO;
+		ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq));
+	}
 }
 
 /* needed below */
@@ -162,8 +175,7 @@
 		printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name);
 	else {
 		if (time_before(jiffies, hwif->poll_timeout)) {
-			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20,
-					NULL);
+			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20);
 			/* continue polling */
 			return ide_started;
 		}
@@ -225,7 +237,7 @@
 
 	if (!OK_STAT(tmp, 0, ATA_BUSY)) {
 		if (time_before(jiffies, hwif->poll_timeout)) {
-			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+			ide_set_handler(drive, &reset_pollfunc, HZ/20);
 			/* continue polling */
 			return ide_started;
 		}
@@ -342,7 +354,7 @@
 		ndelay(400);
 		hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
 		hwif->polling = 1;
-		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
+		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20);
 		spin_unlock_irqrestore(&hwif->lock, flags);
 		return ide_started;
 	}
@@ -402,7 +414,7 @@
 	udelay(10);
 	hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
 	hwif->polling = 1;
-	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+	__ide_set_handler(drive, &reset_pollfunc, HZ/20);
 
 	/*
 	 * Some weird controller like resetting themselves to a strange
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 317ec62..7ae6623 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -61,50 +61,6 @@
  */
 #define IDEFLOPPY_PC_DELAY	(HZ/20)	/* default delay for ZIP 100 (50ms) */
 
-/* Error code returned in rq->errors to the higher part of the driver. */
-#define	IDEFLOPPY_ERROR_GENERAL		101
-
-/*
- * Used to finish servicing a request. For read/write requests, we will call
- * ide_end_request to pass to the next buffer.
- */
-static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
-{
-	struct ide_disk_obj *floppy = drive->driver_data;
-	struct request *rq = drive->hwif->rq;
-	int error;
-
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
-	switch (uptodate) {
-	case 0:
-		error = IDEFLOPPY_ERROR_GENERAL;
-		break;
-
-	case 1:
-		error = 0;
-		break;
-
-	default:
-		error = uptodate;
-	}
-
-	if (error)
-		floppy->failed_pc = NULL;
-	/* Why does this happen? */
-	if (!rq)
-		return 0;
-	if (!blk_special_request(rq)) {
-		/* our real local end request function */
-		ide_end_request(drive, uptodate, nsecs);
-		return 0;
-	}
-	rq->errors = error;
-	/* fixme: need to move this local also */
-	ide_end_drive_cmd(drive, 0, 0);
-	return 0;
-}
-
 static void idefloppy_update_buffers(ide_drive_t *drive,
 				struct ide_atapi_pc *pc)
 {
@@ -112,22 +68,23 @@
 	struct bio *bio = rq->bio;
 
 	while ((bio = rq->bio) != NULL)
-		ide_floppy_end_request(drive, 1, 0);
+		ide_complete_rq(drive, 0, ide_rq_bytes(rq));
 }
 
-static void ide_floppy_callback(ide_drive_t *drive, int dsc)
+static int ide_floppy_callback(ide_drive_t *drive, int dsc)
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
 	struct ide_atapi_pc *pc = drive->pc;
+	struct request *rq = pc->rq;
 	int uptodate = pc->error ? 0 : 1;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
-	if (floppy->failed_pc == pc)
-		floppy->failed_pc = NULL;
+	if (drive->failed_pc == pc)
+		drive->failed_pc = NULL;
 
 	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
-	    (pc->rq && blk_pc_request(pc->rq)))
+	    (rq && blk_pc_request(rq)))
 		uptodate = 1; /* FIXME */
 	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
 		u8 *buf = pc->buf;
@@ -139,19 +96,22 @@
 			floppy->progress_indication = buf[15] & 0x80 ?
 				(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
 
-			if (floppy->failed_pc)
-				ide_debug_log(IDE_DBG_PC, "pc = %x, ",
-					      floppy->failed_pc->c[0]);
+			if (drive->failed_pc)
+				ide_debug_log(IDE_DBG_PC, "pc = %x",
+					      drive->failed_pc->c[0]);
 
 			ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
-				      "ascq = %x\n", floppy->sense_key,
+				      "ascq = %x", floppy->sense_key,
 				      floppy->asc, floppy->ascq);
 		} else
 			printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
 			       "Aborting request!\n");
 	}
 
-	ide_floppy_end_request(drive, uptodate, 0);
+	if (blk_special_request(rq))
+		rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
+
+	return uptodate;
 }
 
 static void ide_floppy_report_error(struct ide_disk_obj *floppy,
@@ -170,14 +130,15 @@
 
 }
 
-static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
-		struct ide_atapi_pc *pc)
+static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
+					   struct ide_cmd *cmd,
+					   struct ide_atapi_pc *pc)
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
 
-	if (floppy->failed_pc == NULL &&
+	if (drive->failed_pc == NULL &&
 	    pc->c[0] != GPCMD_REQUEST_SENSE)
-		floppy->failed_pc = pc;
+		drive->failed_pc = pc;
 
 	/* Set the current packet command */
 	drive->pc = pc;
@@ -186,18 +147,18 @@
 		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
 			ide_floppy_report_error(floppy, pc);
 		/* Giving up */
-		pc->error = IDEFLOPPY_ERROR_GENERAL;
+		pc->error = IDE_DRV_ERROR_GENERAL;
 
-		floppy->failed_pc = NULL;
+		drive->failed_pc = NULL;
 		drive->pc_callback(drive, 0);
 		return ide_stopped;
 	}
 
-	ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries);
+	ide_debug_log(IDE_DBG_FUNC, "retry #%d", pc->retries);
 
 	pc->retries++;
 
-	return ide_issue_pc(drive);
+	return ide_issue_pc(drive, cmd);
 }
 
 void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
@@ -242,8 +203,7 @@
 	int blocks = rq->nr_sectors / floppy->bs_factor;
 	int cmd = rq_data_dir(rq);
 
-	ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__,
-		      block, blocks);
+	ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks);
 
 	ide_init_pc(pc);
 	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
@@ -285,34 +245,34 @@
 {
 	struct ide_disk_obj *floppy = drive->driver_data;
 	ide_hwif_t *hwif = drive->hwif;
+	struct ide_cmd cmd;
 	struct ide_atapi_pc *pc;
 
-	ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
-		      "errors: %d\n",
-		      __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
-		      rq->cmd[0], rq->cmd_type, rq->errors);
-
-	ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
-		      "current_nr_sectors: %d\n",
-		      __func__, (long)rq->sector, rq->nr_sectors,
-		      rq->current_nr_sectors);
+	if (drive->debug_mask & IDE_DBG_RQ)
+		blk_dump_rq_flags(rq, (rq->rq_disk
+					? rq->rq_disk->disk_name
+					: "dev?"));
 
 	if (rq->errors >= ERROR_MAX) {
-		if (floppy->failed_pc)
-			ide_floppy_report_error(floppy, floppy->failed_pc);
-		else
+		if (drive->failed_pc) {
+			ide_floppy_report_error(floppy, drive->failed_pc);
+			drive->failed_pc = NULL;
+		} else
 			printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
 
-		ide_floppy_end_request(drive, 0, 0);
-		return ide_stopped;
+		if (blk_special_request(rq)) {
+			rq->errors = 0;
+			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
+			return ide_stopped;
+		} else
+			goto out_end;
 	}
 	if (blk_fs_request(rq)) {
 		if (((long)rq->sector % floppy->bs_factor) ||
 		    (rq->nr_sectors % floppy->bs_factor)) {
 			printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
 				drive->name);
-			ide_floppy_end_request(drive, 0, 0);
-			return ide_stopped;
+			goto out_end;
 		}
 		pc = &floppy->queued_pc;
 		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
@@ -323,21 +283,33 @@
 		idefloppy_blockpc_cmd(floppy, pc, rq);
 	} else {
 		blk_dump_rq_flags(rq, PFX "unsupported command in queue");
-		ide_floppy_end_request(drive, 0, 0);
-		return ide_stopped;
+		goto out_end;
 	}
 
+	memset(&cmd, 0, sizeof(cmd));
+
+	if (rq_data_dir(rq))
+		cmd.tf_flags |= IDE_TFLAG_WRITE;
+
+	cmd.rq = rq;
+
 	if (blk_fs_request(rq) || pc->req_xfer) {
-		ide_init_sg_cmd(drive, rq);
-		ide_map_sg(drive, rq);
+		ide_init_sg_cmd(&cmd, rq->nr_sectors << 9);
+		ide_map_sg(drive, &cmd);
 	}
 
 	pc->sg = hwif->sg_table;
-	pc->sg_cnt = hwif->sg_nents;
+	pc->sg_cnt = cmd.sg_nents;
 
 	pc->rq = rq;
 
-	return idefloppy_issue_pc(drive, pc);
+	return ide_floppy_issue_pc(drive, &cmd, pc);
+out_end:
+	drive->failed_pc = NULL;
+	if (blk_fs_request(rq) == 0 && rq->errors == 0)
+		rq->errors = -EIO;
+	ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
+	return ide_stopped;
 }
 
 /*
@@ -438,8 +410,9 @@
 		length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
 
 		ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
-			      "%d sector size\n",
-			      i, blocks * length / 1024, blocks, length);
+					     "%d sector size",
+					     i, blocks * length / 1024,
+					     blocks, length);
 
 		if (i)
 			continue;
@@ -495,8 +468,8 @@
 				"in drive\n", drive->name);
 			break;
 		}
-		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n",
-			      pc.buf[desc_start + 4] & 0x03);
+		ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d",
+					     pc.buf[desc_start + 4] & 0x03);
 	}
 
 	/* Clik! disk does not support get_flexible_disk_page */
@@ -575,6 +548,5 @@
 	.init_media	= ide_floppy_init_media,
 	.set_doorlock	= ide_set_media_lock,
 	.do_request	= ide_floppy_do_request,
-	.end_request	= ide_floppy_end_request,
 	.ioctl		= ide_floppy_ioctl,
 };
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 0471094..1aebdf1 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -145,11 +145,6 @@
 	return drive->disk_ops->do_request(drive, rq, sector);
 }
 
-static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs)
-{
-	return drive->disk_ops->end_request(drive, uptodate, nrsecs);
-}
-
 static struct ide_driver ide_gd_driver = {
 	.gen_driver = {
 		.owner		= THIS_MODULE,
@@ -162,7 +157,6 @@
 	.shutdown		= ide_gd_shutdown,
 	.version		= IDE_GD_VERSION,
 	.do_request		= ide_gd_do_request,
-	.end_request		= ide_gd_end_request,
 #ifdef CONFIG_IDE_PROC_FS
 	.proc_entries		= ide_disk_proc_entries,
 	.proc_devsets		= ide_disk_proc_devsets,
@@ -182,7 +176,7 @@
 
 	drive = idkp->drive;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	idkp->openers++;
 
@@ -232,7 +226,7 @@
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
 
-	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+	ide_debug_log(IDE_DBG_FUNC, "enter");
 
 	if (idkp->openers == 1)
 		drive->disk_ops->flush(drive);
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h
index b604bdd..5597077 100644
--- a/drivers/ide/ide-gd.h
+++ b/drivers/ide/ide-gd.h
@@ -8,7 +8,7 @@
 #define IDE_GD_DEBUG_LOG	0
 
 #if IDE_GD_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
 #else
 #define ide_debug_log(lvl, fmt, args...) do {} while (0)
 #endif
@@ -20,8 +20,6 @@
 	struct device		dev;
 	unsigned int		openers;	/* protected by BKL for now */
 
-	/* Last failed packet command */
-	struct ide_atapi_pc *failed_pc;
 	/* used for blk_{fs,pc}_request() requests */
 	struct ide_atapi_pc queued_pc;
 
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 81a5282..9d03e82 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -32,6 +32,10 @@
 module_param(probe_mask, int, 0);
 MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
 
+static const struct ide_port_info ide_generic_port_info = {
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 static ssize_t store_add(struct class *cls, const char *buf, size_t n)
 {
 	unsigned int base, ctl;
@@ -46,7 +50,7 @@
 	hw.irq = irq;
 	hw.chipset = ide_generic;
 
-	rc = ide_host_add(NULL, hws, NULL);
+	rc = ide_host_add(&ide_generic_port_info, hws, NULL);
 	if (rc)
 		return rc;
 
@@ -184,7 +188,7 @@
 #endif
 			hw.chipset = ide_generic;
 
-			rc = ide_host_add(NULL, hws, NULL);
+			rc = ide_host_add(&ide_generic_port_info, hws, NULL);
 			if (rc) {
 				release_region(io_addr + 0x206, 1);
 				release_region(io_addr, 8);
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c
index 9270d32..ff8339e 100644
--- a/drivers/ide/ide-h8300.c
+++ b/drivers/ide/ide-h8300.c
@@ -44,53 +44,53 @@
 	return r;
 }
 
-static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void h8300_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+	struct ide_taskfile *tf = &cmd->tf;
+	u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+	if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA)
 		mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
 		outb((tf->device & HIHI) | drive->select,
 		     io_ports->device_addr);
 }
 
-static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void h8300_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data = mm_inw(io_ports->data_addr);
 
 		tf->data = data & 0xff;
@@ -100,31 +100,31 @@
 	/* be sure we're looking at the low order bits */
 	outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature = inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = inb(io_ports->lbah_addr);
 	}
 }
@@ -143,13 +143,13 @@
 		*bp = bswap(*(volatile u16 *)addr);
 }
 
-static void h8300_input_data(ide_drive_t *drive, struct request *rq,
+static void h8300_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			     void *buf, unsigned int len)
 {
 	mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
 }
 
-static void h8300_output_data(ide_drive_t *drive, struct request *rq,
+static void h8300_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			      void *buf, unsigned int len)
 {
 	mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c
index 45b43dd..2d9c6dc 100644
--- a/drivers/ide/ide-io-std.c
+++ b/drivers/ide/ide-io-std.c
@@ -2,6 +2,13 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 
+#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
+    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
+#include <asm/ide.h>
+#else
+#include <asm-generic/ide_iops.h>
+#endif
+
 /*
  *	Conventional PIO operations for ATA devices
  */
@@ -75,24 +82,24 @@
 }
 EXPORT_SYMBOL_GPL(ide_set_irq);
 
-void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 	void (*tf_outb)(u8 addr, unsigned long port);
 	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+	u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
 	if (mmio)
 		tf_outb = ide_mm_outb;
 	else
 		tf_outb = ide_outb;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
 		u16 data = (tf->hob_data << 8) | tf->data;
 
 		if (mmio)
@@ -101,39 +108,39 @@
 			outw(data, io_ports->data_addr);
 	}
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		tf_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		tf_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		tf_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		tf_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		tf_outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		tf_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		tf_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		tf_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		tf_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		tf_outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
 		tf_outb((tf->device & HIHI) | drive->select,
 			 io_ports->device_addr);
 }
 EXPORT_SYMBOL_GPL(ide_tf_load);
 
-void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 	void (*tf_outb)(u8 addr, unsigned long port);
 	u8 (*tf_inb)(unsigned long port);
 	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
@@ -146,7 +153,7 @@
 		tf_inb  = ide_inb;
 	}
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data;
 
 		if (mmio)
@@ -161,31 +168,31 @@
 	/* be sure we're looking at the low order bits */
 	tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = tf_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = tf_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = tf_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = tf_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = tf_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = tf_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature = tf_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
 	}
 }
@@ -212,7 +219,7 @@
  * so if an odd len is specified, be sure that there's at least one
  * extra byte allocated for the buffer.
  */
-void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
 		    unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
@@ -258,7 +265,7 @@
 /*
  * This is used for most PIO data transfers *to* the IDE interface
  */
-void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
 		     unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 2e92497..1adc5e2 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -40,7 +40,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
-#include <linux/hdreg.h>
 #include <linux/completion.h>
 #include <linux/reboot.h>
 #include <linux/cdrom.h>
@@ -55,25 +54,9 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static int __ide_end_request(ide_drive_t *drive, struct request *rq,
-			     int uptodate, unsigned int nr_bytes, int dequeue)
+int ide_end_rq(ide_drive_t *drive, struct request *rq, int error,
+	       unsigned int nr_bytes)
 {
-	int ret = 1;
-	int error = 0;
-
-	if (uptodate <= 0)
-		error = uptodate ? uptodate : -EIO;
-
-	/*
-	 * if failfast is set on a request, override number of sectors and
-	 * complete the whole request right now
-	 */
-	if (blk_noretry_request(rq) && error)
-		nr_bytes = rq->hard_nr_sectors << 9;
-
-	if (!blk_fs_request(rq) && error && !rq->errors)
-		rq->errors = -EIO;
-
 	/*
 	 * decide whether to reenable DMA -- 3 is a random magic for now,
 	 * if we DMA timeout more than 3 times, just stay in PIO
@@ -84,127 +67,86 @@
 		ide_dma_on(drive);
 	}
 
-	if (!blk_end_request(rq, error, nr_bytes))
-		ret = 0;
-
-	if (ret == 0 && dequeue)
-		drive->hwif->rq = NULL;
-
-	return ret;
+	return blk_end_request(rq, error, nr_bytes);
 }
+EXPORT_SYMBOL_GPL(ide_end_rq);
 
-/**
- *	ide_end_request		-	complete an IDE I/O
- *	@drive: IDE device for the I/O
- *	@uptodate:
- *	@nr_sectors: number of sectors completed
- *
- *	This is our end_request wrapper function. We complete the I/O
- *	update random number input and dequeue the request, which if
- *	it was tagged may be out of order.
- */
-
-int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
 {
-	unsigned int nr_bytes = nr_sectors << 9;
-	struct request *rq = drive->hwif->rq;
+	struct ide_taskfile *tf = &cmd->tf;
+	struct request *rq = cmd->rq;
+	u8 tf_cmd = tf->command;
 
-	if (!nr_bytes) {
-		if (blk_pc_request(rq))
-			nr_bytes = rq->data_len;
-		else
-			nr_bytes = rq->hard_cur_sectors << 9;
+	tf->error = err;
+	tf->status = stat;
+
+	drive->hwif->tp_ops->tf_read(drive, cmd);
+
+	if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) &&
+	    tf_cmd == ATA_CMD_IDLEIMMEDIATE) {
+		if (tf->lbal != 0xc4) {
+			printk(KERN_ERR "%s: head unload failed!\n",
+			       drive->name);
+			ide_tf_dump(drive->name, tf);
+		} else
+			drive->dev_flags |= IDE_DFLAG_PARKED;
 	}
 
-	return __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
+	if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+		memcpy(rq->special, cmd, sizeof(*cmd));
+
+	if (cmd->tf_flags & IDE_TFLAG_DYN)
+		kfree(cmd);
 }
-EXPORT_SYMBOL(ide_end_request);
 
-/**
- *	ide_end_dequeued_request	-	complete an IDE I/O
- *	@drive: IDE device for the I/O
- *	@uptodate:
- *	@nr_sectors: number of sectors completed
- *
- *	Complete an I/O that is no longer on the request queue. This
- *	typically occurs when we pull the request and issue a REQUEST_SENSE.
- *	We must still finish the old request but we must not tamper with the
- *	queue in the meantime.
- *
- *	NOTE: This path does not handle barrier, but barrier is not supported
- *	on ide-cd anyway.
- */
-
-int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
-			     int uptodate, int nr_sectors)
+/* obsolete, blk_rq_bytes() should be used instead */
+unsigned int ide_rq_bytes(struct request *rq)
 {
-	BUG_ON(!blk_rq_started(rq));
-
-	return __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
+	if (blk_pc_request(rq))
+		return rq->data_len;
+	else
+		return rq->hard_cur_sectors << 9;
 }
-EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
+EXPORT_SYMBOL_GPL(ide_rq_bytes);
 
-/**
- *	ide_end_drive_cmd	-	end an explicit drive command
- *	@drive: command 
- *	@stat: status bits
- *	@err: error bits
- *
- *	Clean up after success/failure of an explicit drive command.
- *	These get thrown onto the queue so they are synchronized with
- *	real I/O operations on the drive.
- *
- *	In LBA48 mode we have to read the register set twice to get
- *	all the extra information out.
- */
- 
-void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq = hwif->rq;
+	int rc;
 
-	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-		ide_task_t *task = (ide_task_t *)rq->special;
+	/*
+	 * if failfast is set on a request, override number of sectors
+	 * and complete the whole request right now
+	 */
+	if (blk_noretry_request(rq) && error <= 0)
+		nr_bytes = rq->hard_nr_sectors << 9;
 
-		if (task) {
-			struct ide_taskfile *tf = &task->tf;
+	rc = ide_end_rq(drive, rq, error, nr_bytes);
+	if (rc == 0)
+		hwif->rq = NULL;
 
-			tf->error = err;
-			tf->status = stat;
-
-			drive->hwif->tp_ops->tf_read(drive, task);
-
-			if (task->tf_flags & IDE_TFLAG_DYN)
-				kfree(task);
-		}
-	} else if (blk_pm_request(rq)) {
-		struct request_pm_state *pm = rq->data;
-
-		ide_complete_power_step(drive, rq);
-		if (pm->pm_step == IDE_PM_COMPLETED)
-			ide_complete_pm_request(drive, rq);
-		return;
-	}
-
-	hwif->rq = NULL;
-
-	rq->errors = err;
-
-	if (unlikely(blk_end_request(rq, (rq->errors ? -EIO : 0),
-				     blk_rq_bytes(rq))))
-		BUG();
+	return rc;
 }
-EXPORT_SYMBOL(ide_end_drive_cmd);
+EXPORT_SYMBOL(ide_complete_rq);
 
 void ide_kill_rq(ide_drive_t *drive, struct request *rq)
 {
-	if (rq->rq_disk) {
-		struct ide_driver *drv;
+	u8 drv_req = blk_special_request(rq) && rq->rq_disk;
+	u8 media = drive->media;
 
-		drv = *(struct ide_driver **)rq->rq_disk->private_data;
-		drv->end_request(drive, 0, 0);
-	} else
-		ide_end_request(drive, 0, 0);
+	drive->failed_pc = NULL;
+
+	if ((media == ide_floppy || media == ide_tape) && drv_req) {
+		rq->errors = 0;
+		ide_complete_rq(drive, 0, blk_rq_bytes(rq));
+	} else {
+		if (media == ide_tape)
+			rq->errors = IDE_DRV_ERROR_GENERAL;
+		else if (blk_fs_request(rq) == 0 && rq->errors == 0)
+			rq->errors = -EIO;
+		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
+	}
 }
 
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
@@ -232,20 +174,20 @@
 static ide_startstop_t ide_disk_special(ide_drive_t *drive)
 {
 	special_t *s = &drive->special;
-	ide_task_t args;
+	struct ide_cmd cmd;
 
-	memset(&args, 0, sizeof(ide_task_t));
-	args.data_phase = TASKFILE_NO_DATA;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.protocol = ATA_PROT_NODATA;
 
 	if (s->b.set_geometry) {
 		s->b.set_geometry = 0;
-		ide_tf_set_specify_cmd(drive, &args.tf);
+		ide_tf_set_specify_cmd(drive, &cmd.tf);
 	} else if (s->b.recalibrate) {
 		s->b.recalibrate = 0;
-		ide_tf_set_restore_cmd(drive, &args.tf);
+		ide_tf_set_restore_cmd(drive, &cmd.tf);
 	} else if (s->b.set_multmode) {
 		s->b.set_multmode = 0;
-		ide_tf_set_setmult_cmd(drive, &args.tf);
+		ide_tf_set_setmult_cmd(drive, &cmd.tf);
 	} else if (s->all) {
 		int special = s->all;
 		s->all = 0;
@@ -253,10 +195,10 @@
 		return ide_stopped;
 	}
 
-	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
-			IDE_TFLAG_CUSTOM_HANDLER;
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
+		       IDE_TFLAG_CUSTOM_HANDLER;
 
-	do_rw_taskfile(drive, &args);
+	do_rw_taskfile(drive, &cmd);
 
 	return ide_started;
 }
@@ -286,33 +228,29 @@
 	return ide_stopped;
 }
 
-void ide_map_sg(ide_drive_t *drive, struct request *rq)
+void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
+	struct request *rq = cmd->rq;
 
 	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
 		sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
-		hwif->sg_nents = 1;
+		cmd->sg_nents = 1;
 	} else if (!rq->bio) {
 		sg_init_one(sg, rq->data, rq->data_len);
-		hwif->sg_nents = 1;
-	} else {
-		hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
-	}
+		cmd->sg_nents = 1;
+	} else
+		cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
 }
-
 EXPORT_SYMBOL_GPL(ide_map_sg);
 
-void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq)
+void ide_init_sg_cmd(struct ide_cmd *cmd, unsigned int nr_bytes)
 {
-	ide_hwif_t *hwif = drive->hwif;
-
-	hwif->nsect = hwif->nleft = rq->nr_sectors;
-	hwif->cursg_ofs = 0;
-	hwif->cursg = NULL;
+	cmd->nbytes = cmd->nleft = nr_bytes;
+	cmd->cursg_ofs = 0;
+	cmd->cursg = NULL;
 }
-
 EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
 
 /**
@@ -330,24 +268,15 @@
 static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
 		struct request *rq)
 {
-	ide_hwif_t *hwif = drive->hwif;
-	ide_task_t *task = rq->special;
+	struct ide_cmd *cmd = rq->special;
 
-	if (task) {
-		hwif->data_phase = task->data_phase;
-
-		switch (hwif->data_phase) {
-		case TASKFILE_MULTI_OUT:
-		case TASKFILE_OUT:
-		case TASKFILE_MULTI_IN:
-		case TASKFILE_IN:
-			ide_init_sg_cmd(drive, rq);
-			ide_map_sg(drive, rq);
-		default:
-			break;
+	if (cmd) {
+		if (cmd->protocol == ATA_PROT_PIO) {
+			ide_init_sg_cmd(cmd, rq->nr_sectors << 9);
+			ide_map_sg(drive, cmd);
 		}
 
-		return do_rw_taskfile(drive, task);
+		return do_rw_taskfile(drive, cmd);
 	}
 
  	/*
@@ -357,8 +286,8 @@
 #ifdef DEBUG
  	printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
-	ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
-			  ide_read_error(drive));
+	rq->errors = 0;
+	ide_complete_rq(drive, 0, blk_rq_bytes(rq));
 
  	return ide_stopped;
 }
@@ -376,9 +305,7 @@
 	case REQ_DRIVE_RESET:
 		return ide_do_reset(drive);
 	default:
-		blk_dump_rq_flags(rq, "ide_special_rq - bad request");
-		ide_end_request(drive, 0, 0);
-		return ide_stopped;
+		BUG();
 	}
 }
 
@@ -438,7 +365,7 @@
 			startstop = ide_start_power_step(drive, rq);
 			if (startstop == ide_stopped &&
 			    pm->pm_step == IDE_PM_COMPLETED)
-				ide_complete_pm_request(drive, rq);
+				ide_complete_pm_rq(drive, rq);
 			return startstop;
 		} else if (!rq->rq_disk && blk_special_request(rq))
 			/*
@@ -501,8 +428,8 @@
 	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
 		rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);
 		if (rc == 0) {
-			/* for atari only */
-			ide_get_lock(ide_intr, hwif);
+			if (host->get_lock)
+				host->get_lock(ide_intr, hwif);
 		}
 	}
 	return rc;
@@ -511,8 +438,8 @@
 static inline void ide_unlock_host(struct ide_host *host)
 {
 	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
-		/* for atari only */
-		ide_release_lock();
+		if (host->release_lock)
+			host->release_lock();
 		clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);
 	}
 }
@@ -724,6 +651,7 @@
 			}
 		}
 		hwif->handler = NULL;
+		hwif->expiry = NULL;
 		/*
 		 * We need to simulate a real interrupt when invoking
 		 * the handler() function, which means we need to
@@ -739,7 +667,8 @@
 		} else if (drive_is_ready(drive)) {
 			if (drive->waiting_for_dma)
 				hwif->dma_ops->dma_lost_irq(drive);
-			(void)ide_ack_intr(hwif);
+			if (hwif->ack_intr)
+				hwif->ack_intr(hwif);
 			printk(KERN_WARNING "%s: lost interrupt\n",
 				drive->name);
 			startstop = handler(drive);
@@ -840,6 +769,7 @@
 irqreturn_t ide_intr (int irq, void *dev_id)
 {
 	ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
+	struct ide_host *host = hwif->host;
 	ide_drive_t *uninitialized_var(drive);
 	ide_handler_t *handler;
 	unsigned long flags;
@@ -847,14 +777,14 @@
 	irqreturn_t irq_ret = IRQ_NONE;
 	int plug_device = 0;
 
-	if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
-		if (hwif != hwif->host->cur_port)
+	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
+		if (hwif != host->cur_port)
 			goto out_early;
 	}
 
 	spin_lock_irqsave(&hwif->lock, flags);
 
-	if (!ide_ack_intr(hwif))
+	if (hwif->ack_intr && hwif->ack_intr(hwif) == 0)
 		goto out;
 
 	handler = hwif->handler;
@@ -871,27 +801,19 @@
 		 *
 		 * For PCI, we cannot tell the difference,
 		 * so in that case we just ignore it and hope it goes away.
-		 *
-		 * FIXME: unexpected_intr should be hwif-> then we can
-		 * remove all the ifdef PCI crap
 		 */
-#ifdef CONFIG_BLK_DEV_IDEPCI
-		if (hwif->chipset != ide_pci)
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-		{
+		if ((host->irq_flags & IRQF_SHARED) == 0) {
 			/*
 			 * Probably not a shared PCI interrupt,
 			 * so we can safely try to do something about it:
 			 */
 			unexpected_intr(irq, hwif);
-#ifdef CONFIG_BLK_DEV_IDEPCI
 		} else {
 			/*
 			 * Whack the status register, just in case
 			 * we have a leftover pending IRQ.
 			 */
 			(void)hwif->tp_ops->read_status(hwif);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
 		}
 		goto out;
 	}
@@ -909,6 +831,7 @@
 		goto out;
 
 	hwif->handler = NULL;
+	hwif->expiry = NULL;
 	hwif->req_gen++;
 	del_timer(&hwif->timer);
 	spin_unlock(&hwif->lock);
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index 1be263e..7701427 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -111,13 +111,13 @@
 	return 0;
 }
 
-static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
 {
 	u8 *buf = NULL;
 	int bufsize = 0, err = 0;
 	u8 args[4], xfer_rate = 0;
-	ide_task_t tfargs;
-	struct ide_taskfile *tf = &tfargs.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 	u16 *id = drive->id;
 
 	if (NULL == (void *) arg) {
@@ -134,24 +134,24 @@
 	if (copy_from_user(args, (void __user *)arg, 4))
 		return -EFAULT;
 
-	memset(&tfargs, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 	tf->feature = args[2];
 	if (args[0] == ATA_CMD_SMART) {
 		tf->nsect = args[3];
 		tf->lbal  = args[1];
 		tf->lbam  = 0x4f;
 		tf->lbah  = 0xc2;
-		tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
+		cmd.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
 	} else {
 		tf->nsect = args[1];
-		tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
-				  IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
+		cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
+			       IDE_TFLAG_IN_NSECT;
 	}
 	tf->command = args[0];
-	tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
+	cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA;
 
 	if (args[3]) {
-		tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+		cmd.tf_flags |= IDE_TFLAG_IO_16BIT;
 		bufsize = SECTOR_SIZE * args[3];
 		buf = kzalloc(bufsize, GFP_KERNEL);
 		if (buf == NULL)
@@ -172,7 +172,7 @@
 		}
 	}
 
-	err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
+	err = ide_raw_taskfile(drive, &cmd, buf, args[3]);
 
 	args[0] = tf->status;
 	args[1] = tf->error;
@@ -194,25 +194,25 @@
 	return err;
 }
 
-static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg)
 {
 	void __user *p = (void __user *)arg;
 	int err = 0;
 	u8 args[7];
-	ide_task_t task;
+	struct ide_cmd cmd;
 
 	if (copy_from_user(args, p, 7))
 		return -EFAULT;
 
-	memset(&task, 0, sizeof(task));
-	memcpy(&task.tf_array[7], &args[1], 6);
-	task.tf.command = args[0];
-	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	memcpy(&cmd.tf_array[7], &args[1], 6);
+	cmd.tf.command = args[0];
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-	err = ide_no_data_taskfile(drive, &task);
+	err = ide_no_data_taskfile(drive, &cmd);
 
-	args[0] = task.tf.command;
-	memcpy(&args[1], &task.tf_array[7], 6);
+	args[0] = cmd.tf.command;
+	memcpy(&args[1], &cmd.tf_array[7], 6);
 
 	if (copy_to_user(p, args, 7))
 		err = -EFAULT;
@@ -262,17 +262,17 @@
 		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 			return -EACCES;
 		if (drive->media == ide_disk)
-			return ide_taskfile_ioctl(drive, cmd, arg);
+			return ide_taskfile_ioctl(drive, arg);
 		return -ENOMSG;
 #endif
 	case HDIO_DRIVE_CMD:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EACCES;
-		return ide_cmd_ioctl(drive, cmd, arg);
+		return ide_cmd_ioctl(drive, arg);
 	case HDIO_DRIVE_TASK:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EACCES;
-		return ide_task_ioctl(drive, cmd, arg);
+		return ide_task_ioctl(drive, arg);
 	case HDIO_DRIVE_RESET:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 317c5da..5403e4a 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -31,15 +31,15 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_port_ops *port_ops = hwif->port_ops;
-	ide_task_t task;
+	struct ide_cmd cmd;
 
 	if (port_ops && port_ops->selectproc)
 		port_ops->selectproc(drive);
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_OUT_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_OUT_DEVICE;
 
-	drive->hwif->tp_ops->tf_load(drive, &task);
+	drive->hwif->tp_ops->tf_load(drive, &cmd);
 }
 
 void SELECT_MASK(ide_drive_t *drive, int mask)
@@ -52,14 +52,14 @@
 
 u8 ide_read_error(ide_drive_t *drive)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_IN_FEATURE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_IN_FEATURE;
 
-	drive->hwif->tp_ops->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &cmd);
 
-	return task.tf.error;
+	return cmd.tf.error;
 }
 EXPORT_SYMBOL_GPL(ide_read_error);
 
@@ -329,7 +329,7 @@
 	u16 *id = drive->id, i;
 	int error = 0;
 	u8 stat;
-	ide_task_t task;
+	struct ide_cmd cmd;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_ops)	/* check if host supports DMA */
@@ -361,12 +361,12 @@
 	udelay(1);
 	tp_ops->set_irq(hwif, 0);
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
-	task.tf.feature = SETFEATURES_XFER;
-	task.tf.nsect   = speed;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
+	cmd.tf.feature = SETFEATURES_XFER;
+	cmd.tf.nsect   = speed;
 
-	tp_ops->tf_load(drive, &task);
+	tp_ops->tf_load(drive, &cmd);
 
 	tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
 
@@ -425,26 +425,25 @@
  * See also ide_execute_command
  */
 void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
-		       unsigned int timeout, ide_expiry_t *expiry)
+		       unsigned int timeout)
 {
 	ide_hwif_t *hwif = drive->hwif;
 
 	BUG_ON(hwif->handler);
 	hwif->handler		= handler;
-	hwif->expiry		= expiry;
 	hwif->timer.expires	= jiffies + timeout;
 	hwif->req_gen_timer	= hwif->req_gen;
 	add_timer(&hwif->timer);
 }
 
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
-		      unsigned int timeout, ide_expiry_t *expiry)
+void ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
+		     unsigned int timeout)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hwif->lock, flags);
-	__ide_set_handler(drive, handler, timeout, expiry);
+	__ide_set_handler(drive, handler, timeout);
 	spin_unlock_irqrestore(&hwif->lock, flags);
 }
 EXPORT_SYMBOL(ide_set_handler);
@@ -452,10 +451,9 @@
 /**
  *	ide_execute_command	-	execute an IDE command
  *	@drive: IDE drive to issue the command against
- *	@command: command byte to write
+ *	@cmd: command
  *	@handler: handler for next phase
  *	@timeout: timeout for command
- *	@expiry:  handler to run on timeout
  *
  *	Helper function to issue an IDE command. This handles the
  *	atomicity requirements, command timing and ensures that the
@@ -463,15 +461,18 @@
  *	should go via this function or do equivalent locking.
  */
 
-void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
-			 unsigned timeout, ide_expiry_t *expiry)
+void ide_execute_command(ide_drive_t *drive, struct ide_cmd *cmd,
+			 ide_handler_t *handler, unsigned timeout)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hwif->lock, flags);
-	__ide_set_handler(drive, handler, timeout, expiry);
-	hwif->tp_ops->exec_command(hwif, cmd);
+	if ((cmd->protocol != ATAPI_PROT_DMA &&
+	     cmd->protocol != ATAPI_PROT_PIO) ||
+	    (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT))
+		__ide_set_handler(drive, handler, timeout);
+	hwif->tp_ops->exec_command(hwif, cmd->tf.command);
 	/*
 	 * Drive takes 400nS to respond, we must avoid the IRQ being
 	 * serviced before that.
@@ -481,19 +482,6 @@
 	ndelay(400);
 	spin_unlock_irqrestore(&hwif->lock, flags);
 }
-EXPORT_SYMBOL(ide_execute_command);
-
-void ide_execute_pkt_cmd(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hwif->lock, flags);
-	hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
-	ndelay(400);
-	spin_unlock_irqrestore(&hwif->lock, flags);
-}
-EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
 
 /*
  * ide_wait_not_busy() waits for the currently selected device on the hwif
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index f6c683d..217b7fd 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -34,19 +34,19 @@
 static void ide_dump_opcode(ide_drive_t *drive)
 {
 	struct request *rq = drive->hwif->rq;
-	ide_task_t *task = NULL;
+	struct ide_cmd *cmd = NULL;
 
 	if (!rq)
 		return;
 
 	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
-		task = rq->special;
+		cmd = rq->special;
 
 	printk(KERN_ERR "ide: failed opcode was: ");
-	if (task == NULL)
+	if (cmd == NULL)
 		printk(KERN_CONT "unknown\n");
 	else
-		printk(KERN_CONT "0x%02x\n", task->tf.command);
+		printk(KERN_CONT "0x%02x\n", cmd->tf.command);
 }
 
 u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
@@ -66,18 +66,18 @@
 
 static void ide_dump_sector(ide_drive_t *drive)
 {
-	ide_task_t task;
-	struct ide_taskfile *tf = &task.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 	u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
 
-	memset(&task, 0, sizeof(task));
+	memset(&cmd, 0, sizeof(cmd));
 	if (lba48)
-		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
+		cmd.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
 				IDE_TFLAG_LBA48;
 	else
-		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
+		cmd.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
 
-	drive->hwif->tp_ops->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &cmd);
 
 	if (lba48 || (tf->device & ATA_LBA))
 		printk(KERN_CONT ", LBAsect=%llu",
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index f30e521..9490b44 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -1,6 +1,5 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
-#include <linux/hdreg.h>
 #include <linux/jiffies.h>
 #include <linux/blkdev.h>
 
@@ -63,10 +62,10 @@
 
 ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq)
 {
-	ide_task_t task;
-	struct ide_taskfile *tf = &task.tf;
+	struct ide_cmd cmd;
+	struct ide_taskfile *tf = &cmd.tf;
 
-	memset(&task, 0, sizeof(task));
+	memset(&cmd, 0, sizeof(cmd));
 	if (rq->cmd[0] == REQ_PARK_HEADS) {
 		drive->sleep = *(unsigned long *)rq->special;
 		drive->dev_flags |= IDE_DFLAG_SLEEPING;
@@ -75,14 +74,16 @@
 		tf->lbal = 0x4c;
 		tf->lbam = 0x4e;
 		tf->lbah = 0x55;
-		task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+		cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 	} else		/* cmd == REQ_UNPARK_HEADS */
 		tf->command = ATA_CMD_CHK_POWER;
 
-	task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	task.rq = rq;
-	drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
-	return do_rw_taskfile(drive, &task);
+	cmd.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+	cmd.protocol = ATA_PROT_NODATA;
+
+	cmd.rq = rq;
+
+	return do_rw_taskfile(drive, &cmd);
 }
 
 ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 60538d9..ebf2d21 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -1,6 +1,5 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
-#include <linux/hdreg.h>
 
 int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
@@ -8,7 +7,7 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq;
 	struct request_pm_state rqpm;
-	ide_task_t args;
+	struct ide_cmd cmd;
 	int ret;
 
 	/* call ACPI _GTM only once */
@@ -16,10 +15,10 @@
 		ide_acpi_get_timing(hwif);
 
 	memset(&rqpm, 0, sizeof(rqpm));
-	memset(&args, 0, sizeof(args));
+	memset(&cmd, 0, sizeof(cmd));
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_PM_SUSPEND;
-	rq->special = &args;
+	rq->special = &cmd;
 	rq->data = &rqpm;
 	rqpm.pm_step = IDE_PM_START_SUSPEND;
 	if (mesg.event == PM_EVENT_PRETHAW)
@@ -42,7 +41,7 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq;
 	struct request_pm_state rqpm;
-	ide_task_t args;
+	struct ide_cmd cmd;
 	int err;
 
 	/* call ACPI _PS0 / _STM only once */
@@ -54,11 +53,11 @@
 	ide_acpi_exec_tfs(drive);
 
 	memset(&rqpm, 0, sizeof(rqpm));
-	memset(&args, 0, sizeof(args));
+	memset(&cmd, 0, sizeof(cmd));
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_PM_RESUME;
 	rq->cmd_flags |= REQ_PREEMPT;
-	rq->special = &args;
+	rq->special = &cmd;
 	rq->data = &rqpm;
 	rqpm.pm_step = IDE_PM_START_RESUME;
 	rqpm.pm_state = PM_EVENT_ON;
@@ -109,9 +108,9 @@
 ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
 {
 	struct request_pm_state *pm = rq->data;
-	ide_task_t *args = rq->special;
+	struct ide_cmd *cmd = rq->special;
 
-	memset(args, 0, sizeof(*args));
+	memset(cmd, 0, sizeof(*cmd));
 
 	switch (pm->pm_step) {
 	case IDE_PM_FLUSH_CACHE:	/* Suspend step 1 (flush cache) */
@@ -124,12 +123,12 @@
 			return ide_stopped;
 		}
 		if (ata_id_flush_ext_enabled(drive->id))
-			args->tf.command = ATA_CMD_FLUSH_EXT;
+			cmd->tf.command = ATA_CMD_FLUSH_EXT;
 		else
-			args->tf.command = ATA_CMD_FLUSH;
+			cmd->tf.command = ATA_CMD_FLUSH;
 		goto out_do_tf;
 	case IDE_PM_STANDBY:		/* Suspend step 2 (standby) */
-		args->tf.command = ATA_CMD_STANDBYNOW1;
+		cmd->tf.command = ATA_CMD_STANDBYNOW1;
 		goto out_do_tf;
 	case IDE_PM_RESTORE_PIO:	/* Resume step 1 (restore PIO) */
 		ide_set_max_pio(drive);
@@ -142,7 +141,7 @@
 			ide_complete_power_step(drive, rq);
 		return ide_stopped;
 	case IDE_PM_IDLE:		/* Resume step 2 (idle) */
-		args->tf.command = ATA_CMD_IDLEIMMEDIATE;
+		cmd->tf.command = ATA_CMD_IDLEIMMEDIATE;
 		goto out_do_tf;
 	case IDE_PM_RESTORE_DMA:	/* Resume step 3 (restore DMA) */
 		/*
@@ -160,27 +159,34 @@
 	}
 
 	pm->pm_step = IDE_PM_COMPLETED;
+
 	return ide_stopped;
 
 out_do_tf:
-	args->tf_flags	 = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	args->data_phase = TASKFILE_NO_DATA;
-	return do_rw_taskfile(drive, args);
+	cmd->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	cmd->protocol = ATA_PROT_NODATA;
+
+	return do_rw_taskfile(drive, cmd);
 }
 
 /**
- *	ide_complete_pm_request - end the current Power Management request
+ *	ide_complete_pm_rq - end the current Power Management request
  *	@drive: target drive
  *	@rq: request
  *
  *	This function cleans up the current PM request and stops the queue
  *	if necessary.
  */
-void ide_complete_pm_request(ide_drive_t *drive, struct request *rq)
+void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
 {
 	struct request_queue *q = drive->queue;
+	struct request_pm_state *pm = rq->data;
 	unsigned long flags;
 
+	ide_complete_power_step(drive, rq);
+	if (pm->pm_step != IDE_PM_COMPLETED)
+		return;
+
 #ifdef DEBUG_PM
 	printk("%s: completing PM request, %s\n", drive->name,
 	       blk_pm_suspend_request(rq) ? "suspend" : "resume");
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index bac9b39..6e80b77 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -27,6 +27,10 @@
 	{.id = ""}
 };
 
+static const struct ide_port_info ide_pnp_port_info = {
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	struct ide_host *host;
@@ -60,7 +64,7 @@
 	hw.irq = pnp_irq(dev, 0);
 	hw.chipset = ide_generic;
 
-	rc = ide_host_add(NULL, hws, &host);
+	rc = ide_host_add(&ide_pnp_port_info, hws, &host);
 	if (rc)
 		goto out;
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 9740670..5488645 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -228,15 +228,9 @@
 	m[ATA_ID_PROD_LEN - 1] = '\0';
 
 	if (strstr(m, "E X A B Y T E N E S T"))
-		goto err_misc;
-
-	drive->dev_flags |= IDE_DFLAG_PRESENT;
-	drive->dev_flags &= ~IDE_DFLAG_DEAD;
-
-	return;
-err_misc:
-	kfree(id);
-	drive->dev_flags &= ~IDE_DFLAG_PRESENT;
+		drive->dev_flags &= ~IDE_DFLAG_PRESENT;
+	else
+		drive->dev_flags |= IDE_DFLAG_PRESENT;
 }
 
 /**
@@ -289,13 +283,13 @@
 	 * identify command to be sure of reply
 	 */
 	if (cmd == ATA_CMD_ID_ATAPI) {
-		ide_task_t task;
+		struct ide_cmd cmd;
 
-		memset(&task, 0, sizeof(task));
+		memset(&cmd, 0, sizeof(cmd));
 		/* disable DMA & overlap */
-		task.tf_flags = IDE_TFLAG_OUT_FEATURE;
+		cmd.tf_flags = IDE_TFLAG_OUT_FEATURE;
 
-		tp_ops->tf_load(drive, &task);
+		tp_ops->tf_load(drive, &cmd);
 	}
 
 	/* ask drive for ID */
@@ -343,14 +337,14 @@
 
 static u8 ide_read_device(ide_drive_t *drive)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 
-	memset(&task, 0, sizeof(task));
-	task.tf_flags = IDE_TFLAG_IN_DEVICE;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf_flags = IDE_TFLAG_IN_DEVICE;
 
-	drive->hwif->tp_ops->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &cmd);
 
-	return task.tf.device;
+	return cmd.tf.device;
 }
 
 /**
@@ -505,8 +499,7 @@
 		}
 
 		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-			/* drive not found */
-			return 0;
+			goto out_free;
 
 		/* identification failed? */
 		if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -530,7 +523,7 @@
 	}
 
 	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
-		return 0;
+		goto out_free;
 
 	/* The drive wasn't being helpful. Add generic info only */
 	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -543,7 +536,10 @@
 		ide_disk_init_mult_count(drive);
 	}
 
-	return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
+	return 1;
+out_free:
+	kfree(drive->id);
+	return 0;
 }
 
 static void hwif_release_dev(struct device *dev)
@@ -841,34 +837,19 @@
 static int init_irq (ide_hwif_t *hwif)
 {
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	irq_handler_t irq_handler;
-	int sa = 0;
+	struct ide_host *host = hwif->host;
+	irq_handler_t irq_handler = host->irq_handler;
+	int sa = host->irq_flags;
 
-	irq_handler = hwif->host->irq_handler;
 	if (irq_handler == NULL)
 		irq_handler = ide_intr;
 
-#if defined(__mc68000__)
-	sa = IRQF_SHARED;
-#endif /* __mc68000__ */
-
-	if (hwif->chipset == ide_pci)
-		sa = IRQF_SHARED;
-
 	if (io_ports->ctl_addr)
 		hwif->tp_ops->set_irq(hwif, 1);
 
 	if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
 		goto out_up;
 
-	if (!hwif->rqsize) {
-		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
-		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
-			hwif->rqsize = 256;
-		else
-			hwif->rqsize = 65536;
-	}
-
 #if !defined(__mc68000__)
 	printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
 		io_ports->data_addr, io_ports->status_addr,
@@ -1080,7 +1061,7 @@
 		hwif->tp_ops = d->tp_ops;
 
 	/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
-	if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
+	if ((hwif->host_flags & IDE_HFLAG_DTC2278) == 0 || hwif->channel == 0)
 		hwif->port_ops = d->port_ops;
 
 	hwif->swdma_mask = d->swdma_mask;
@@ -1114,6 +1095,13 @@
 
 	if (d->max_sectors)
 		hwif->rqsize = d->max_sectors;
+	else {
+		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
+			hwif->rqsize = 256;
+		else
+			hwif->rqsize = 65536;
+	}
 
 	/* call chipset specific routine for each enabled port */
 	if (d->init_hwif)
@@ -1326,6 +1314,8 @@
 
 	if (d) {
 		host->init_chipset = d->init_chipset;
+		host->get_lock     = d->get_lock;
+		host->release_lock = d->release_lock;
 		host->host_flags = d->host_flags;
 	}
 
@@ -1372,20 +1362,15 @@
 		ide_init_port_hw(hwif, hws[i]);
 		ide_port_apply_params(hwif);
 
-		if (d == NULL) {
-			mate = NULL;
-		} else {
-			if ((i & 1) && mate) {
-				hwif->mate = mate;
-				mate->mate = hwif;
-			}
-
-			mate = (i & 1) ? NULL : hwif;
-
-			ide_init_port(hwif, i & 1, d);
-			ide_port_cable_detect(hwif);
+		if ((i & 1) && mate) {
+			hwif->mate = mate;
+			mate->mate = hwif;
 		}
 
+		mate = (i & 1) ? NULL : hwif;
+
+		ide_init_port(hwif, i & 1, d);
+		ide_port_cable_detect(hwif);
 		ide_port_init_devices(hwif);
 	}
 
@@ -1396,8 +1381,8 @@
 		if (ide_probe_port(hwif) == 0)
 			hwif->present = 1;
 
-		if (hwif->chipset != ide_4drives || !hwif->mate ||
-		    !hwif->mate->present) {
+		if ((hwif->host_flags & IDE_HFLAG_4DRIVES) == 0 ||
+		    hwif->mate == NULL || hwif->mate->present == 0) {
 			if (ide_register_port(hwif)) {
 				ide_disable_port(hwif);
 				continue;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 417cde5..10a88bf 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -194,20 +194,20 @@
 
 static int set_xfer_rate (ide_drive_t *drive, int arg)
 {
-	ide_task_t task;
+	struct ide_cmd cmd;
 	int err;
 
 	if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
 		return -EINVAL;
 
-	memset(&task, 0, sizeof(task));
-	task.tf.command = ATA_CMD_SET_FEATURES;
-	task.tf.feature = SETFEATURES_XFER;
-	task.tf.nsect   = (u8)arg;
-	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
-			IDE_TFLAG_IN_NSECT;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf.command = ATA_CMD_SET_FEATURES;
+	cmd.tf.feature = SETFEATURES_XFER;
+	cmd.tf.nsect   = (u8)arg;
+	cmd.tf_flags   = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
+			 IDE_TFLAG_IN_NSECT;
 
-	err = ide_no_data_taskfile(drive, &task);
+	err = ide_no_data_taskfile(drive, &cmd);
 
 	if (!err) {
 		ide_set_xfer_rate(drive, (u8) arg);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 4e6181c..64dfa74 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -152,11 +152,6 @@
 #define IDETAPE_LU_RETENSION_MASK	2
 #define IDETAPE_LU_EOT_MASK		4
 
-/* Error codes returned in rq->errors to the higher part of the driver. */
-#define IDETAPE_ERROR_GENERAL		101
-#define IDETAPE_ERROR_FILEMARK		102
-#define IDETAPE_ERROR_EOD		103
-
 /* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
 #define IDETAPE_BLOCK_DESCRIPTOR	0
 #define IDETAPE_CAPABILITIES_PAGE	0x2a
@@ -171,14 +166,6 @@
 	struct gendisk		*disk;
 	struct device		dev;
 
-	/*
-	 *	failed_pc points to the last failed packet command, or contains
-	 *	NULL if we do not need to retry any packet command. This is
-	 *	required since an additional packet command is needed before the
-	 *	retry, to get detailed information on what went wrong.
-	 */
-	/* Last failed packet command */
-	struct ide_atapi_pc *failed_pc;
 	/* used by REQ_IDETAPE_{READ,WRITE} requests */
 	struct ide_atapi_pc queued_pc;
 
@@ -245,9 +232,6 @@
 	/* Wasted space in each stage */
 	int excess_bh_size;
 
-	/* protects the ide-tape queue */
-	spinlock_t lock;
-
 	/* Measures average tape speed */
 	unsigned long avg_time;
 	int avg_size;
@@ -400,7 +384,7 @@
 static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	struct ide_atapi_pc *pc = tape->failed_pc;
+	struct ide_atapi_pc *pc = drive->failed_pc;
 
 	tape->sense_key = sense[2] & 0xF;
 	tape->asc       = sense[12];
@@ -433,19 +417,19 @@
 		}
 	}
 	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
-		pc->error = IDETAPE_ERROR_FILEMARK;
+		pc->error = IDE_DRV_ERROR_FILEMARK;
 		pc->flags |= PC_FLAG_ABORT;
 	}
 	if (pc->c[0] == WRITE_6) {
 		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
 		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
-			pc->error = IDETAPE_ERROR_EOD;
+			pc->error = IDE_DRV_ERROR_EOD;
 			pc->flags |= PC_FLAG_ABORT;
 		}
 	}
 	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
 		if (tape->sense_key == 8) {
-			pc->error = IDETAPE_ERROR_EOD;
+			pc->error = IDE_DRV_ERROR_EOD;
 			pc->flags |= PC_FLAG_ABORT;
 		}
 		if (!(pc->flags & PC_FLAG_ABORT) &&
@@ -477,52 +461,23 @@
 	}
 }
 
-static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
-{
-	struct request *rq = drive->hwif->rq;
-	idetape_tape_t *tape = drive->driver_data;
-	unsigned long flags;
-	int error;
-
-	debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
-	switch (uptodate) {
-	case 0:	error = IDETAPE_ERROR_GENERAL; break;
-	case 1: error = 0; break;
-	default: error = uptodate;
-	}
-	rq->errors = error;
-	if (error)
-		tape->failed_pc = NULL;
-
-	if (!blk_special_request(rq)) {
-		ide_end_request(drive, uptodate, nr_sects);
-		return 0;
-	}
-
-	spin_lock_irqsave(&tape->lock, flags);
-
-	ide_end_drive_cmd(drive, 0, 0);
-
-	spin_unlock_irqrestore(&tape->lock, flags);
-	return 0;
-}
-
 static void ide_tape_handle_dsc(ide_drive_t *);
 
-static void ide_tape_callback(ide_drive_t *drive, int dsc)
+static int ide_tape_callback(ide_drive_t *drive, int dsc)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc = drive->pc;
+	struct request *rq = drive->hwif->rq;
 	int uptodate = pc->error ? 0 : 1;
+	int err = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
 
 	debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
 	if (dsc)
 		ide_tape_handle_dsc(drive);
 
-	if (tape->failed_pc == pc)
-		tape->failed_pc = NULL;
+	if (drive->failed_pc == pc)
+		drive->failed_pc = NULL;
 
 	if (pc->c[0] == REQUEST_SENSE) {
 		if (uptodate)
@@ -531,7 +486,6 @@
 			printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
 					"itself - Aborting request!\n");
 	} else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
-		struct request *rq = drive->hwif->rq;
 		int blocks = pc->xferred / tape->blk_size;
 
 		tape->avg_size += blocks * tape->blk_size;
@@ -546,8 +500,10 @@
 		tape->first_frame += blocks;
 		rq->current_nr_sectors -= blocks;
 
-		if (pc->error)
-			uptodate = pc->error;
+		if (pc->error) {
+			uptodate = 0;
+			err = pc->error;
+		}
 	} else if (pc->c[0] == READ_POSITION && uptodate) {
 		u8 *readpos = pc->buf;
 
@@ -561,6 +517,7 @@
 					 "to the tape\n");
 			clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
 			uptodate = 0;
+			err = IDE_DRV_ERROR_GENERAL;
 		} else {
 			debug_log(DBG_SENSE, "Block Location - %u\n",
 					be32_to_cpup((__be32 *)&readpos[4]));
@@ -571,7 +528,9 @@
 		}
 	}
 
-	idetape_end_request(drive, uptodate, 0);
+	rq->errors = err;
+
+	return uptodate;
 }
 
 /*
@@ -621,7 +580,7 @@
  *
  * The handling will be done in three stages:
  *
- * 1. idetape_issue_pc will send the packet command to the drive, and will set
+ * 1. ide_tape_issue_pc will send the packet command to the drive, and will set
  * the interrupt handler to ide_pc_intr.
  *
  * 2. On each interrupt, ide_pc_intr will be called. This step will be
@@ -649,8 +608,9 @@
  * request.
  */
 
-static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
-		struct ide_atapi_pc *pc)
+static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
+					 struct ide_cmd *cmd,
+					 struct ide_atapi_pc *pc)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
@@ -660,8 +620,8 @@
 			"Two request sense in serial were issued\n");
 	}
 
-	if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
-		tape->failed_pc = pc;
+	if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
+		drive->failed_pc = pc;
 
 	/* Set the current packet command */
 	drive->pc = pc;
@@ -685,9 +645,9 @@
 						tape->ascq);
 			}
 			/* Giving up */
-			pc->error = IDETAPE_ERROR_GENERAL;
+			pc->error = IDE_DRV_ERROR_GENERAL;
 		}
-		tape->failed_pc = NULL;
+		drive->failed_pc = NULL;
 		drive->pc_callback(drive, 0);
 		return ide_stopped;
 	}
@@ -695,7 +655,7 @@
 
 	pc->retries++;
 
-	return ide_issue_pc(drive);
+	return ide_issue_pc(drive, cmd);
 }
 
 /* A mode sense command is used to "sense" tape parameters. */
@@ -746,8 +706,8 @@
 		}
 		pc->error = 0;
 	} else {
-		pc->error = IDETAPE_ERROR_GENERAL;
-		tape->failed_pc = NULL;
+		pc->error = IDE_DRV_ERROR_GENERAL;
+		drive->failed_pc = NULL;
 	}
 	drive->pc_callback(drive, 0);
 	return ide_stopped;
@@ -790,6 +750,7 @@
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc = NULL;
 	struct request *postponed_rq = tape->postponed_rq;
+	struct ide_cmd cmd;
 	u8 stat;
 
 	debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
@@ -801,13 +762,15 @@
 		/* We do not support buffer cache originated requests. */
 		printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
 			"request queue (%d)\n", drive->name, rq->cmd_type);
-		ide_end_request(drive, 0, 0);
+		if (blk_fs_request(rq) == 0 && rq->errors == 0)
+			rq->errors = -EIO;
+		ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
 		return ide_stopped;
 	}
 
 	/* Retry a failed packet command */
-	if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
-		pc = tape->failed_pc;
+	if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
+		pc = drive->failed_pc;
 		goto out;
 	}
 
@@ -815,7 +778,9 @@
 		if (rq != postponed_rq) {
 			printk(KERN_ERR "ide-tape: ide-tape.c bug - "
 					"Two DSC requests were queued\n");
-			idetape_end_request(drive, 0, 0);
+			drive->failed_pc = NULL;
+			rq->errors = 0;
+			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
 			return ide_stopped;
 		}
 
@@ -881,7 +846,14 @@
 	BUG();
 
 out:
-	return idetape_issue_pc(drive, pc);
+	memset(&cmd, 0, sizeof(cmd));
+
+	if (rq_data_dir(rq))
+		cmd.tf_flags |= IDE_TFLAG_WRITE;
+
+	cmd.rq = rq;
+
+	return ide_tape_issue_pc(drive, &cmd, pc);
 }
 
 /*
@@ -1226,7 +1198,7 @@
 
 	if (tape->merge_bh)
 		idetape_init_merge_buffer(tape);
-	if (errors == IDETAPE_ERROR_GENERAL)
+	if (errors == IDE_DRV_ERROR_GENERAL)
 		return -EIO;
 	return ret;
 }
@@ -2192,8 +2164,6 @@
 	drive->pc_update_buffers = idetape_update_buffers;
 	drive->pc_io_buffers	 = ide_tape_io_buffers;
 
-	spin_lock_init(&tape->lock);
-
 	drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
 
 	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
@@ -2325,7 +2295,6 @@
 	.remove			= ide_tape_remove,
 	.version		= IDETAPE_VERSION,
 	.do_request		= idetape_do_request,
-	.end_request		= idetape_end_request,
 #ifdef CONFIG_IDE_PROC_FS
 	.proc_entries		= ide_tape_proc_entries,
 	.proc_devsets		= ide_tape_proc_devsets,
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 16138bc..84532be 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -39,88 +39,86 @@
 
 int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
 {
-	ide_task_t args;
+	struct ide_cmd cmd;
 
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tf.nsect = 0x01;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.tf.nsect = 0x01;
 	if (drive->media == ide_disk)
-		args.tf.command = ATA_CMD_ID_ATA;
+		cmd.tf.command = ATA_CMD_ID_ATA;
 	else
-		args.tf.command = ATA_CMD_ID_ATAPI;
-	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-	args.data_phase	= TASKFILE_IN;
-	return ide_raw_taskfile(drive, &args, buf, 1);
+		cmd.tf.command = ATA_CMD_ID_ATAPI;
+	cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+	cmd.protocol = ATA_PROT_PIO;
+
+	return ide_raw_taskfile(drive, &cmd, buf, 1);
 }
 
 static ide_startstop_t task_no_data_intr(ide_drive_t *);
-static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
-static ide_startstop_t task_in_intr(ide_drive_t *);
+static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct ide_cmd *);
+static ide_startstop_t task_pio_intr(ide_drive_t *);
 
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_cmd *cmd = &hwif->cmd;
+	struct ide_taskfile *tf = &cmd->tf;
 	ide_handler_t *handler = NULL;
 	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	const struct ide_dma_ops *dma_ops = hwif->dma_ops;
 
-	if (task->data_phase == TASKFILE_MULTI_IN ||
-	    task->data_phase == TASKFILE_MULTI_OUT) {
-		if (!drive->mult_count) {
-			printk(KERN_ERR "%s: multimode not set!\n",
-					drive->name);
-			return ide_stopped;
-		}
+	if (orig_cmd->protocol == ATA_PROT_PIO &&
+	    (orig_cmd->tf_flags & IDE_TFLAG_MULTI_PIO) &&
+	    drive->mult_count == 0) {
+		printk(KERN_ERR "%s: multimode not set!\n", drive->name);
+		return ide_stopped;
 	}
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
-		task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
+	if (orig_cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
+		orig_cmd->ftf_flags |= IDE_FTFLAG_SET_IN_FLAGS;
 
-	memcpy(&hwif->task, task, sizeof(*task));
+	memcpy(cmd, orig_cmd, sizeof(*cmd));
 
-	if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
+	if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
 		ide_tf_dump(drive->name, tf);
 		tp_ops->set_irq(hwif, 1);
 		SELECT_MASK(drive, 0);
-		tp_ops->tf_load(drive, task);
+		tp_ops->tf_load(drive, cmd);
 	}
 
-	switch (task->data_phase) {
-	case TASKFILE_MULTI_OUT:
-	case TASKFILE_OUT:
-		tp_ops->exec_command(hwif, tf->command);
-		ndelay(400);	/* FIXME */
-		return pre_task_out_intr(drive, task->rq);
-	case TASKFILE_MULTI_IN:
-	case TASKFILE_IN:
-		handler = task_in_intr;
+	switch (cmd->protocol) {
+	case ATA_PROT_PIO:
+		if (cmd->tf_flags & IDE_TFLAG_WRITE) {
+			tp_ops->exec_command(hwif, tf->command);
+			ndelay(400);	/* FIXME */
+			return pre_task_out_intr(drive, cmd);
+		}
+		handler = task_pio_intr;
 		/* fall-through */
-	case TASKFILE_NO_DATA:
+	case ATA_PROT_NODATA:
 		if (handler == NULL)
 			handler = task_no_data_intr;
-		ide_execute_command(drive, tf->command, handler,
-				    WAIT_WORSTCASE, NULL);
+		ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE);
 		return ide_started;
-	default:
+	case ATA_PROT_DMA:
 		if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
-		    dma_ops->dma_setup(drive))
+		    ide_build_sglist(drive, cmd) == 0 ||
+		    dma_ops->dma_setup(drive, cmd))
 			return ide_stopped;
-		dma_ops->dma_exec_cmd(drive, tf->command);
+		hwif->expiry = dma_ops->dma_timer_expiry;
+		ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD);
 		dma_ops->dma_start(drive);
+	default:
 		return ide_started;
 	}
 }
 EXPORT_SYMBOL_GPL(do_rw_taskfile);
 
-/*
- * Handler for commands without a data phase
- */
 static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	ide_task_t *task = &hwif->task;
-	struct ide_taskfile *tf = &task->tf;
-	int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
+	struct ide_cmd *cmd = &hwif->cmd;
+	struct ide_taskfile *tf = &cmd->tf;
+	int custom = (cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
 	int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
 	u8 stat;
 
@@ -142,28 +140,26 @@
 		} else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
 			if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
 				ide_set_handler(drive, &task_no_data_intr,
-						WAIT_WORSTCASE, NULL);
+						WAIT_WORSTCASE);
 				return ide_started;
 			}
 		}
 		return ide_error(drive, "task_no_data_intr", stat);
-		/* calls ide_end_drive_cmd */
 	}
 
-	if (!custom)
-		ide_end_drive_cmd(drive, stat, ide_read_error(drive));
-	else if (tf->command == ATA_CMD_IDLEIMMEDIATE) {
-		hwif->tp_ops->tf_read(drive, task);
-		if (tf->lbal != 0xc4) {
-			printk(KERN_ERR "%s: head unload failed!\n",
-			       drive->name);
-			ide_tf_dump(drive->name, tf);
-		} else
-			drive->dev_flags |= IDE_DFLAG_PARKED;
-		ide_end_drive_cmd(drive, stat, ide_read_error(drive));
-	} else if (tf->command == ATA_CMD_SET_MULTI)
+	if (custom && tf->command == ATA_CMD_SET_MULTI)
 		drive->mult_count = drive->mult_req;
 
+	if (custom == 0 || tf->command == ATA_CMD_IDLEIMMEDIATE ||
+	    tf->command == ATA_CMD_CHK_POWER) {
+		struct request *rq = hwif->rq;
+
+		if (blk_pm_request(rq))
+			ide_complete_pm_rq(drive, rq);
+		else
+			ide_finish_cmd(drive, cmd, stat);
+	}
+
 	return ide_stopped;
 }
 
@@ -192,12 +188,12 @@
 	return stat;
 }
 
-static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
-			   unsigned int write)
+static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
+			  unsigned int write, unsigned int nr_bytes)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
-	struct scatterlist *cursg = hwif->cursg;
+	struct scatterlist *cursg = cmd->cursg;
 	struct page *page;
 #ifdef CONFIG_HIGHMEM
 	unsigned long flags;
@@ -205,14 +201,14 @@
 	unsigned int offset;
 	u8 *buf;
 
-	cursg = hwif->cursg;
+	cursg = cmd->cursg;
 	if (!cursg) {
 		cursg = sg;
-		hwif->cursg = sg;
+		cmd->cursg = sg;
 	}
 
 	page = sg_page(cursg);
-	offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE;
+	offset = cursg->offset + cmd->cursg_ofs;
 
 	/* get the current page and offset */
 	page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -223,19 +219,19 @@
 #endif
 	buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
 
-	hwif->nleft--;
-	hwif->cursg_ofs++;
+	cmd->nleft -= nr_bytes;
+	cmd->cursg_ofs += nr_bytes;
 
-	if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) {
-		hwif->cursg = sg_next(hwif->cursg);
-		hwif->cursg_ofs = 0;
+	if (cmd->cursg_ofs == cursg->length) {
+		cmd->cursg = sg_next(cmd->cursg);
+		cmd->cursg_ofs = 0;
 	}
 
 	/* do the actual data transfer */
 	if (write)
-		hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
+		hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes);
 	else
-		hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
+		hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes);
 
 	kunmap_atomic(buf, KM_BIO_SRC_IRQ);
 #ifdef CONFIG_HIGHMEM
@@ -243,188 +239,137 @@
 #endif
 }
 
-static void ide_pio_multi(ide_drive_t *drive, struct request *rq,
+static void ide_pio_multi(ide_drive_t *drive, struct ide_cmd *cmd,
 			  unsigned int write)
 {
 	unsigned int nsect;
 
-	nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
+	nsect = min_t(unsigned int, cmd->nleft >> 9, drive->mult_count);
 	while (nsect--)
-		ide_pio_sector(drive, rq, write);
+		ide_pio_bytes(drive, cmd, write, SECTOR_SIZE);
 }
 
-static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
-				     unsigned int write)
+static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
+			      unsigned int write)
 {
 	u8 saved_io_32bit = drive->io_32bit;
 
-	if (rq->bio)	/* fs request */
-		rq->errors = 0;
+	if (cmd->tf_flags & IDE_TFLAG_FS)
+		cmd->rq->errors = 0;
 
-	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-		ide_task_t *task = rq->special;
-
-		if (task->tf_flags & IDE_TFLAG_IO_16BIT)
-			drive->io_32bit = 0;
-	}
+	if (cmd->tf_flags & IDE_TFLAG_IO_16BIT)
+		drive->io_32bit = 0;
 
 	touch_softlockup_watchdog();
 
-	switch (drive->hwif->data_phase) {
-	case TASKFILE_MULTI_IN:
-	case TASKFILE_MULTI_OUT:
-		ide_pio_multi(drive, rq, write);
-		break;
-	default:
-		ide_pio_sector(drive, rq, write);
-		break;
-	}
+	if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
+		ide_pio_multi(drive, cmd, write);
+	else
+		ide_pio_bytes(drive, cmd, write, SECTOR_SIZE);
 
 	drive->io_32bit = saved_io_32bit;
 }
 
-static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
-				  const char *s, u8 stat)
+static void ide_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	if (rq->bio) {
-		ide_hwif_t *hwif = drive->hwif;
-		int sectors = hwif->nsect - hwif->nleft;
+	if (cmd->tf_flags & IDE_TFLAG_FS) {
+		int nr_bytes = cmd->nbytes - cmd->nleft;
 
-		switch (hwif->data_phase) {
-		case TASKFILE_IN:
-			if (hwif->nleft)
-				break;
-			/* fall through */
-		case TASKFILE_OUT:
-			sectors--;
-			break;
-		case TASKFILE_MULTI_IN:
-			if (hwif->nleft)
-				break;
-			/* fall through */
-		case TASKFILE_MULTI_OUT:
-			sectors -= drive->mult_count;
-		default:
-			break;
+		if (cmd->protocol == ATA_PROT_PIO &&
+		    ((cmd->tf_flags & IDE_TFLAG_WRITE) || cmd->nleft == 0)) {
+			if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO)
+				nr_bytes -= drive->mult_count << 9;
+			else
+				nr_bytes -= SECTOR_SIZE;
 		}
 
-		if (sectors > 0) {
-			struct ide_driver *drv;
-
-			drv = *(struct ide_driver **)rq->rq_disk->private_data;
-			drv->end_request(drive, 1, sectors);
-		}
+		if (nr_bytes > 0)
+			ide_complete_rq(drive, 0, nr_bytes);
 	}
-	return ide_error(drive, s, stat);
 }
 
-void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
+void ide_finish_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat)
 {
-	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-		u8 err = ide_read_error(drive);
+	struct request *rq = drive->hwif->rq;
+	u8 err = ide_read_error(drive);
 
-		ide_end_drive_cmd(drive, stat, err);
-		return;
-	}
-
-	if (rq->rq_disk) {
-		struct ide_driver *drv;
-
-		drv = *(struct ide_driver **)rq->rq_disk->private_data;;
-		drv->end_request(drive, 1, rq->nr_sectors);
-	} else
-		ide_end_request(drive, 1, rq->nr_sectors);
+	ide_complete_cmd(drive, cmd, stat, err);
+	rq->errors = err;
+	ide_complete_rq(drive, err ? -EIO : 0, blk_rq_bytes(rq));
 }
 
 /*
- * We got an interrupt on a task_in case, but no errors and no DRQ.
- *
- * It might be a spurious irq (shared irq), but it might be a
- * command that had no output.
+ * Handler for command with PIO data phase.
  */
-static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat)
-{
-	/* Command all done? */
-	if (OK_STAT(stat, ATA_DRDY, ATA_BUSY)) {
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Assume it was a spurious irq */
-	ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
-	return ide_started;
-}
-
-/*
- * Handler for command with PIO data-in phase (Read/Read Multiple).
- */
-static ide_startstop_t task_in_intr(ide_drive_t *drive)
+static ide_startstop_t task_pio_intr(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
+	struct ide_cmd *cmd = &drive->hwif->cmd;
 	u8 stat = hwif->tp_ops->read_status(hwif);
+	u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
 
-	/* Error? */
-	if (stat & ATA_ERR)
-		return task_error(drive, rq, __func__, stat);
+	if (write == 0) {
+		/* Error? */
+		if (stat & ATA_ERR)
+			goto out_err;
 
-	/* Didn't want any data? Odd. */
-	if ((stat & ATA_DRQ) == 0)
-		return task_in_unexpected(drive, rq, stat);
+		/* Didn't want any data? Odd. */
+		if ((stat & ATA_DRQ) == 0) {
+			/* Command all done? */
+			if (OK_STAT(stat, ATA_DRDY, ATA_BUSY))
+				goto out_end;
 
-	ide_pio_datablock(drive, rq, 0);
+			/* Assume it was a spurious irq */
+			goto out_wait;
+		}
+	} else {
+		if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
+			goto out_err;
+
+		/* Deal with unexpected ATA data phase. */
+		if (((stat & ATA_DRQ) == 0) ^ (cmd->nleft == 0))
+			goto out_err;
+	}
+
+	if (write && cmd->nleft == 0)
+		goto out_end;
+
+	/* Still data left to transfer. */
+	ide_pio_datablock(drive, cmd, write);
 
 	/* Are we done? Check status and finish transfer. */
-	if (!hwif->nleft) {
+	if (write == 0 && cmd->nleft == 0) {
 		stat = wait_drive_not_busy(drive);
 		if (!OK_STAT(stat, 0, BAD_STAT))
-			return task_error(drive, rq, __func__, stat);
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
+			goto out_err;
+
+		goto out_end;
 	}
-
+out_wait:
 	/* Still data left to transfer. */
-	ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
-
+	ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
 	return ide_started;
+out_end:
+	if ((cmd->tf_flags & IDE_TFLAG_FS) == 0)
+		ide_finish_cmd(drive, cmd, stat);
+	else
+		ide_complete_rq(drive, 0, cmd->rq->nr_sectors << 9);
+	return ide_stopped;
+out_err:
+	ide_error_cmd(drive, cmd);
+	return ide_error(drive, __func__, stat);
 }
 
-/*
- * Handler for command with PIO data-out phase (Write/Write Multiple).
- */
-static ide_startstop_t task_out_intr (ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
-	u8 stat = hwif->tp_ops->read_status(hwif);
-
-	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-		return task_error(drive, rq, __func__, stat);
-
-	/* Deal with unexpected ATA data phase. */
-	if (((stat & ATA_DRQ) == 0) ^ !hwif->nleft)
-		return task_error(drive, rq, __func__, stat);
-
-	if (!hwif->nleft) {
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Still data left to transfer. */
-	ide_pio_datablock(drive, rq, 1);
-	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
-
-	return ide_started;
-}
-
-static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
+static ide_startstop_t pre_task_out_intr(ide_drive_t *drive,
+					 struct ide_cmd *cmd)
 {
 	ide_startstop_t startstop;
 
 	if (ide_wait_stat(&startstop, drive, ATA_DRQ,
 			  drive->bad_wstat, WAIT_DRQ)) {
 		printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
-			drive->name, drive->hwif->data_phase ? "MULT" : "",
+			drive->name,
+			(cmd->tf_flags & IDE_TFLAG_MULTI_PIO) ? "MULT" : "",
 			(drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
 		return startstop;
 	}
@@ -432,13 +377,15 @@
 	if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
 		local_irq_disable();
 
-	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
-	ide_pio_datablock(drive, rq, 1);
+	ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE);
+
+	ide_pio_datablock(drive, cmd, 1);
 
 	return ide_started;
 }
 
-int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
+int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
+		     u16 nsect)
 {
 	struct request *rq;
 	int error;
@@ -456,11 +403,11 @@
 	rq->hard_nr_sectors = rq->nr_sectors = nsect;
 	rq->hard_cur_sectors = rq->current_nr_sectors = nsect;
 
-	if (task->tf_flags & IDE_TFLAG_WRITE)
+	if (cmd->tf_flags & IDE_TFLAG_WRITE)
 		rq->cmd_flags |= REQ_RW;
 
-	rq->special = task;
-	task->rq = rq;
+	rq->special = cmd;
+	cmd->rq = rq;
 
 	error = blk_execute_rq(drive->queue, NULL, rq, 0);
 	blk_put_request(rq);
@@ -470,19 +417,19 @@
 
 EXPORT_SYMBOL(ide_raw_taskfile);
 
-int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
+int ide_no_data_taskfile(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	task->data_phase = TASKFILE_NO_DATA;
+	cmd->protocol = ATA_PROT_NODATA;
 
-	return ide_raw_taskfile(drive, task, NULL, 0);
+	return ide_raw_taskfile(drive, cmd, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
 
 #ifdef CONFIG_IDE_TASK_IOCTL
-int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg)
 {
 	ide_task_request_t	*req_task;
-	ide_task_t		args;
+	struct ide_cmd		cmd;
 	u8 *outbuf		= NULL;
 	u8 *inbuf		= NULL;
 	u8 *data_buf		= NULL;
@@ -536,53 +483,63 @@
 		}
 	}
 
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&cmd, 0, sizeof(cmd));
 
-	memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
-	memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
+	memcpy(&cmd.tf_array[0], req_task->hob_ports,
+	       HDIO_DRIVE_HOB_HDR_SIZE - 2);
+	memcpy(&cmd.tf_array[6], req_task->io_ports,
+	       HDIO_DRIVE_TASK_HDR_SIZE);
 
-	args.data_phase = req_task->data_phase;
+	cmd.tf_flags   = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
+			 IDE_TFLAG_IN_TF;
 
-	args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
-			IDE_TFLAG_IN_TF;
 	if (drive->dev_flags & IDE_DFLAG_LBA48)
-		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
+		cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
 
 	if (req_task->out_flags.all) {
-		args.tf_flags |= IDE_TFLAG_FLAGGED;
+		cmd.ftf_flags |= IDE_FTFLAG_FLAGGED;
 
 		if (req_task->out_flags.b.data)
-			args.tf_flags |= IDE_TFLAG_OUT_DATA;
+			cmd.ftf_flags |= IDE_FTFLAG_OUT_DATA;
 
 		if (req_task->out_flags.b.nsector_hob)
-			args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
+			cmd.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
 		if (req_task->out_flags.b.sector_hob)
-			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
+			cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
 		if (req_task->out_flags.b.lcyl_hob)
-			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
+			cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
 		if (req_task->out_flags.b.hcyl_hob)
-			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
+			cmd.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
 
 		if (req_task->out_flags.b.error_feature)
-			args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
+			cmd.tf_flags |= IDE_TFLAG_OUT_FEATURE;
 		if (req_task->out_flags.b.nsector)
-			args.tf_flags |= IDE_TFLAG_OUT_NSECT;
+			cmd.tf_flags |= IDE_TFLAG_OUT_NSECT;
 		if (req_task->out_flags.b.sector)
-			args.tf_flags |= IDE_TFLAG_OUT_LBAL;
+			cmd.tf_flags |= IDE_TFLAG_OUT_LBAL;
 		if (req_task->out_flags.b.lcyl)
-			args.tf_flags |= IDE_TFLAG_OUT_LBAM;
+			cmd.tf_flags |= IDE_TFLAG_OUT_LBAM;
 		if (req_task->out_flags.b.hcyl)
-			args.tf_flags |= IDE_TFLAG_OUT_LBAH;
+			cmd.tf_flags |= IDE_TFLAG_OUT_LBAH;
 	} else {
-		args.tf_flags |= IDE_TFLAG_OUT_TF;
-		if (args.tf_flags & IDE_TFLAG_LBA48)
-			args.tf_flags |= IDE_TFLAG_OUT_HOB;
+		cmd.tf_flags |= IDE_TFLAG_OUT_TF;
+		if (cmd.tf_flags & IDE_TFLAG_LBA48)
+			cmd.tf_flags |= IDE_TFLAG_OUT_HOB;
 	}
 
 	if (req_task->in_flags.b.data)
-		args.tf_flags |= IDE_TFLAG_IN_DATA;
+		cmd.ftf_flags |= IDE_FTFLAG_IN_DATA;
 
-	switch(req_task->data_phase) {
+	if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE) {
+		/* fixup data phase if needed */
+		if (req_task->data_phase == TASKFILE_IN_DMAQ ||
+		    req_task->data_phase == TASKFILE_IN_DMA)
+			cmd.tf_flags |= IDE_TFLAG_WRITE;
+	}
+
+	cmd.protocol = ATA_PROT_DMA;
+
+	switch (req_task->data_phase) {
 		case TASKFILE_MULTI_OUT:
 			if (!drive->mult_count) {
 				/* (hs): give up if multcount is not set */
@@ -592,11 +549,14 @@
 				err = -EPERM;
 				goto abort;
 			}
+			cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
 			/* fall through */
 		case TASKFILE_OUT:
+			cmd.protocol = ATA_PROT_PIO;
 			/* fall through */
 		case TASKFILE_OUT_DMAQ:
 		case TASKFILE_OUT_DMA:
+			cmd.tf_flags |= IDE_TFLAG_WRITE;
 			nsect = taskout / SECTOR_SIZE;
 			data_buf = outbuf;
 			break;
@@ -609,8 +569,10 @@
 				err = -EPERM;
 				goto abort;
 			}
+			cmd.tf_flags |= IDE_TFLAG_MULTI_PIO;
 			/* fall through */
 		case TASKFILE_IN:
+			cmd.protocol = ATA_PROT_PIO;
 			/* fall through */
 		case TASKFILE_IN_DMAQ:
 		case TASKFILE_IN_DMA:
@@ -618,6 +580,7 @@
 			data_buf = inbuf;
 			break;
 		case TASKFILE_NO_DATA:
+			cmd.protocol = ATA_PROT_NODATA;
 			break;
 		default:
 			err = -EFAULT;
@@ -627,7 +590,7 @@
 	if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
 		nsect = 0;
 	else if (!nsect) {
-		nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
+		nsect = (cmd.tf.hob_nsect << 8) | cmd.tf.nsect;
 
 		if (!nsect) {
 			printk(KERN_ERR "%s: in/out command without data\n",
@@ -637,15 +600,14 @@
 		}
 	}
 
-	if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
-		args.tf_flags |= IDE_TFLAG_WRITE;
+	err = ide_raw_taskfile(drive, &cmd, data_buf, nsect);
 
-	err = ide_raw_taskfile(drive, &args, data_buf, nsect);
+	memcpy(req_task->hob_ports, &cmd.tf_array[0],
+	       HDIO_DRIVE_HOB_HDR_SIZE - 2);
+	memcpy(req_task->io_ports, &cmd.tf_array[6],
+	       HDIO_DRIVE_TASK_HDR_SIZE);
 
-	memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
-	memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
-
-	if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
+	if ((cmd.ftf_flags & IDE_FTFLAG_SET_IN_FLAGS) &&
 	    req_task->in_flags.all == 0) {
 		req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
 		if (drive->dev_flags & IDE_DFLAG_LBA48)
diff --git a/drivers/ide/ide_arm.c b/drivers/ide/ide_arm.c
index bdcac94..cf63854 100644
--- a/drivers/ide/ide_arm.c
+++ b/drivers/ide/ide_arm.c
@@ -18,6 +18,10 @@
 #define IDE_ARM_IO	0x1f0
 #define IDE_ARM_IRQ	IRQ_HARDDISK
 
+static const struct ide_port_info ide_arm_port_info = {
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 static int __init ide_arm_init(void)
 {
 	unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
@@ -41,7 +45,7 @@
 	hw.irq = IDE_ARM_IRQ;
 	hw.chipset = ide_generic;
 
-	return ide_host_add(NULL, hws, NULL);
+	return ide_host_add(&ide_arm_port_info, hws, NULL);
 }
 
 module_init(ide_arm_init);
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 6b9fc95..0d4ac65 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -508,10 +508,10 @@
 static struct ide_dma_ops it821x_pass_through_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= it821x_dma_start,
 	.dma_end		= it821x_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_lost_irq		= ide_dma_lost_irq,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
diff --git a/drivers/ide/macide.c b/drivers/ide/macide.c
index 3c60064..4b1718e 100644
--- a/drivers/ide/macide.c
+++ b/drivers/ide/macide.c
@@ -80,6 +80,11 @@
 	hw->chipset = ide_generic;
 }
 
+static const struct ide_port_info macide_port_info = {
+	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
+};
+
 static const char *mac_ide_name[] =
 	{ "Quadra", "Powerbook", "Powerbook Baboon" };
 
@@ -122,7 +127,7 @@
 
 	macide_setup_ports(&hw, base, irq, ack_intr);
 
-	return ide_host_add(NULL, hws, NULL);
+	return ide_host_add(&macide_port_info, hws, NULL);
 }
 
 module_init(macide_init);
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index ea48a3e..7b65fe5 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -61,12 +61,12 @@
 	return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
 }
 
-static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void superio_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data = inw(io_ports->data_addr);
 
 		tf->data = data & 0xff;
@@ -76,31 +76,31 @@
 	/* be sure we're looking at the low order bits */
 	outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = superio_ide_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature = inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = inb(io_ports->lbah_addr);
 	}
 }
@@ -216,11 +216,11 @@
 	return (dma_stat & 7) != 4;
 }
 
-static int ns87415_dma_setup(ide_drive_t *drive)
+static int ns87415_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	/* select DMA xfer */
 	ns87415_prepare_drive(drive, 1);
-	if (!ide_dma_setup(drive))
+	if (ide_dma_setup(drive, cmd) == 0)
 		return 0;
 	/* DMA failed: select PIO xfer */
 	ns87415_prepare_drive(drive, 0);
@@ -301,11 +301,11 @@
 static const struct ide_dma_ops ns87415_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ns87415_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ns87415_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= superio_dma_sff_read_status,
 };
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index f38aac7..c7acca0 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -347,7 +347,7 @@
 	struct clk *clk;
 	struct resource *mem, *irq;
 	void __iomem *base;
-	unsigned long rate;
+	unsigned long rate, mem_size;
 	int i, rc;
 	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
@@ -374,13 +374,18 @@
 		return -ENODEV;
 	}
 
-	if (request_mem_region(mem->start, mem->end - mem->start + 1,
-			       "palm_bk3710") == NULL) {
+	mem_size = mem->end - mem->start + 1;
+	if (request_mem_region(mem->start, mem_size, "palm_bk3710") == NULL) {
 		printk(KERN_ERR "failed to request memory region\n");
 		return -EBUSY;
 	}
 
-	base = IO_ADDRESS(mem->start);
+	base = ioremap(mem->start, mem_size);
+	if (!base) {
+		printk(KERN_ERR "failed to map IO memory\n");
+		release_mem_region(mem->start, mem_size);
+		return -ENOMEM;
+	}
 
 	/* Configure the Palm Chip controller */
 	palm_bk3710_chipinit(base);
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index cba66eb..f7536d1 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -331,11 +331,11 @@
 static const struct ide_dma_ops pdc20246_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= pdc202xx_dma_test_irq,
 	.dma_lost_irq		= pdc202xx_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= pdc202xx_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
@@ -343,11 +343,11 @@
 static const struct ide_dma_ops pdc2026x_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= pdc202xx_dma_start,
 	.dma_end		= pdc202xx_dma_end,
 	.dma_test_irq		= pdc202xx_dma_test_irq,
 	.dma_lost_irq		= pdc202xx_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= pdc202xx_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 74625e8..2bfcfed 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -404,7 +404,6 @@
 #define IDE_WAKEUP_DELAY	(1*HZ)
 
 static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *);
-static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
 static void pmac_ide_selectproc(ide_drive_t *drive);
 static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
 
@@ -1422,17 +1421,16 @@
  * pmac_ide_build_dmatable builds the DBDMA command list
  * for a transfer and sets the DBDMA channel to point to it.
  */
-static int
-pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	pmac_ide_hwif_t *pmif =
 		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct dbdma_cmd *table;
-	int i, count = 0;
 	volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
 	struct scatterlist *sg;
-	int wr = (rq_data_dir(rq) == WRITE);
+	int wr = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
+	int i = cmd->sg_nents, count = 0;
 
 	/* DMA table is already aligned */
 	table = (struct dbdma_cmd *) pmif->dma_table_cpu;
@@ -1442,11 +1440,6 @@
 	while (readl(&dma->status) & RUN)
 		udelay(1);
 
-	hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-	if (!i)
-		return 0;
-
 	/* Build DBDMA commands list */
 	sg = hwif->sg_table;
 	while (i && sg_dma_len(sg)) {
@@ -1509,23 +1502,22 @@
  * Prepare a DMA transfer. We build the DMA table, adjust the timings for
  * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
  */
-static int
-pmac_ide_dma_setup(ide_drive_t *drive)
+static int pmac_ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	pmac_ide_hwif_t *pmif =
 		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-	struct request *rq = hwif->rq;
 	u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
+	u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
 
-	if (!pmac_ide_build_dmatable(drive, rq)) {
-		ide_map_sg(drive, rq);
+	if (pmac_ide_build_dmatable(drive, cmd) == 0) {
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
 	/* Apple adds 60ns to wrDataSetup on reads */
 	if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
-		writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0),
+		writel(pmif->timings[unit] + (write ? 0 : 0x00800000UL),
 			PMAC_IDE_REG(IDE_TIMING_CONFIG));
 		(void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 	}
@@ -1535,13 +1527,6 @@
 	return 0;
 }
 
-static void
-pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-	/* issue cmd to drive */
-	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL);
-}
-
 /*
  * Kick the DMA controller into life after the DMA command has been issued
  * to the drive.
@@ -1662,7 +1647,6 @@
 static const struct ide_dma_ops pmac_dma_ops = {
 	.dma_host_set		= pmac_ide_dma_host_set,
 	.dma_setup		= pmac_ide_dma_setup,
-	.dma_exec_cmd		= pmac_ide_dma_exec_cmd,
 	.dma_start		= pmac_ide_dma_start,
 	.dma_end		= pmac_ide_dma_end,
 	.dma_test_irq		= pmac_ide_dma_test_irq,
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c
index 9f9c0b3..2a43a2f 100644
--- a/drivers/ide/q40ide.c
+++ b/drivers/ide/q40ide.c
@@ -72,26 +72,26 @@
 	hw->chipset = ide_generic;
 }
 
-static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
+static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			      void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 
-	if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS))
 		return insw(data_addr, buf, (len + 1) / 2);
 
-	insw_swapw(data_addr, buf, (len + 1) / 2);
+	raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 }
 
-static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
+static void q40ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			       void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
 
-	if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
+	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS))
 		return outsw(data_addr, buf, (len + 1) / 2);
 
-	outsw_swapw(data_addr, buf, (len + 1) / 2);
+	raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
 }
 
 /* Q40 has a byte-swapped IDE interface */
@@ -111,7 +111,8 @@
 
 static const struct ide_port_info q40ide_port_info = {
 	.tp_ops			= &q40ide_tp_ops,
-	.host_flags		= IDE_HFLAG_NO_DMA,
+	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+	.irq_flags		= IRQF_SHARED,
 };
 
 /* 
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
index dbdd298..1c3a829 100644
--- a/drivers/ide/sc1200.c
+++ b/drivers/ide/sc1200.c
@@ -286,11 +286,11 @@
 static const struct ide_dma_ops sc1200_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= sc1200_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c
index 8d2314b..0cc137c 100644
--- a/drivers/ide/scc_pata.c
+++ b/drivers/ide/scc_pata.c
@@ -303,8 +303,9 @@
 }
 
 /**
- *	scc_ide_dma_setup	-	begin a DMA phase
+ *	scc_dma_setup	-	begin a DMA phase
  *	@drive: target device
+ *	@cmd: command
  *
  *	Build an IDE DMA PRD (IDE speak for scatter gather table)
  *	and then set up the DMA transfer registers.
@@ -313,21 +314,15 @@
  *	is returned.
  */
 
-static int scc_dma_setup(ide_drive_t *drive)
+static int scc_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
-	unsigned int reading;
+	u32 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
 	u8 dma_stat;
 
-	if (rq_data_dir(rq))
-		reading = 0;
-	else
-		reading = 1 << 3;
-
 	/* fall back to pio! */
-	if (!ide_build_dmatable(drive, rq)) {
-		ide_map_sg(drive, rq);
+	if (ide_build_dmatable(drive, cmd) == 0) {
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
@@ -335,7 +330,7 @@
 	out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
 
 	/* specify r/w */
-	out_be32((void __iomem *)hwif->dma_base, reading);
+	out_be32((void __iomem *)hwif->dma_base, rw);
 
 	/* read DMA status for INTR & ERROR flags */
 	dma_stat = scc_dma_sff_read_status(hwif);
@@ -666,52 +661,52 @@
 	return rc;
 }
 
-static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void scc_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+	struct ide_taskfile *tf = &cmd->tf;
+	u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA)
+	if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA)
 		out_be32((void *)io_ports->data_addr,
 			 (tf->hob_data << 8) | tf->data);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		scc_ide_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		scc_ide_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		scc_ide_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		scc_ide_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		scc_ide_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		scc_ide_outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
 		scc_ide_outb((tf->device & HIHI) | drive->select,
 			     io_ports->device_addr);
 }
 
-static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void scc_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data = (u16)in_be32((void *)io_ports->data_addr);
 
 		tf->data = data & 0xff;
@@ -721,36 +716,36 @@
 	/* be sure we're looking at the low order bits */
 	scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = scc_ide_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = scc_ide_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = scc_ide_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = scc_ide_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = scc_ide_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = scc_ide_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = scc_ide_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = scc_ide_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = scc_ide_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = scc_ide_inb(io_ports->lbah_addr);
 	}
 }
 
-static void scc_input_data(ide_drive_t *drive, struct request *rq,
+static void scc_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
 			   void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
@@ -766,7 +761,7 @@
 		scc_ide_insw(data_addr, buf, len / 2);
 }
 
-static void scc_output_data(ide_drive_t *drive,  struct request *rq,
+static void scc_output_data(ide_drive_t *drive,  struct ide_cmd *cmd,
 			    void *buf, unsigned int len)
 {
 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
@@ -873,30 +868,26 @@
 static const struct ide_dma_ops scc_dma_ops = {
 	.dma_host_set		= scc_dma_host_set,
 	.dma_setup		= scc_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= scc_dma_start,
 	.dma_end		= scc_dma_end,
 	.dma_test_irq		= scc_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
 	.dma_timeout		= ide_dma_timeout,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_sff_read_status	= scc_dma_sff_read_status,
 };
 
-#define DECLARE_SCC_DEV(name_str)			\
-  {							\
-      .name		= name_str,			\
-      .init_iops	= init_iops_scc,		\
-      .init_dma		= scc_init_dma,			\
-      .init_hwif	= init_hwif_scc,		\
-      .tp_ops		= &scc_tp_ops,		\
-      .port_ops		= &scc_port_ops,		\
-      .dma_ops		= &scc_dma_ops,			\
-      .host_flags	= IDE_HFLAG_SINGLE,		\
-      .pio_mask		= ATA_PIO4,			\
-  }
-
-static const struct ide_port_info scc_chipsets[] __devinitdata = {
-	/* 0 */ DECLARE_SCC_DEV("sccIDE"),
+static const struct ide_port_info scc_chipset __devinitdata = {
+	.name		= "sccIDE",
+	.init_iops	= init_iops_scc,
+	.init_dma	= scc_init_dma,
+	.init_hwif	= init_hwif_scc,
+	.tp_ops		= &scc_tp_ops,
+	.port_ops	= &scc_port_ops,
+	.dma_ops	= &scc_dma_ops,
+	.host_flags	= IDE_HFLAG_SINGLE,
+	.irq_flags	= IRQF_SHARED,
+	.pio_mask	= ATA_PIO4,
 };
 
 /**
@@ -910,7 +901,7 @@
 
 static int __devinit scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	return init_setup_scc(dev, &scc_chipsets[id->driver_data]);
+	return init_setup_scc(dev, &scc_chipset);
 }
 
 /**
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 24bc884..a19dbcc 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -558,6 +558,8 @@
 
 	host->host_priv = priv;
 
+	host->irq_flags = IRQF_SHARED;
+
 	pci_set_drvdata(dev, host);
 
 	ret = do_ide_setup_pci_device(dev, d, 1);
@@ -606,6 +608,8 @@
 
 	host->host_priv = priv;
 
+	host->irq_flags = IRQF_SHARED;
+
 	pci_set_drvdata(pdev[0], host);
 	pci_set_drvdata(pdev[1], host);
 
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
index fdb9d70..b12de83 100644
--- a/drivers/ide/sgiioc4.c
+++ b/drivers/ide/sgiioc4.c
@@ -424,20 +424,13 @@
 /* | Upper 32 bits - Zero	    |EOL| 15 unused     | 16 Bit Length| */
 /* --------------------------------------------------------------------- */
 /* Creates the scatter gather list, DMA Table */
-static unsigned int
-sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
+static int sgiioc4_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	unsigned int *table = hwif->dmatable_cpu;
-	unsigned int count = 0, i = 1;
-	struct scatterlist *sg;
+	unsigned int count = 0, i = cmd->sg_nents;
+	struct scatterlist *sg = hwif->sg_table;
 
-	hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-	if (!i)
-		return 0;	/* sglist of length Zero */
-
-	sg = hwif->sg_table;
 	while (i && sg_dma_len(sg)) {
 		dma_addr_t cur_addr;
 		int cur_len;
@@ -490,24 +483,18 @@
 	return 0;		/* revert to PIO for this request */
 }
 
-static int sgiioc4_dma_setup(ide_drive_t *drive)
+static int sgiioc4_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	struct request *rq = drive->hwif->rq;
-	unsigned int count = 0;
 	int ddir;
+	u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
 
-	if (rq_data_dir(rq))
-		ddir = PCI_DMA_TODEVICE;
-	else
-		ddir = PCI_DMA_FROMDEVICE;
-
-	if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) {
+	if (sgiioc4_build_dmatable(drive, cmd) == 0) {
 		/* try PIO instead of DMA */
-		ide_map_sg(drive, rq);
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
-	if (rq_data_dir(rq))
+	if (write)
 		/* Writes TO the IOC4 FROM Main Memory */
 		ddir = IOC4_DMA_READ;
 	else
@@ -557,6 +544,7 @@
 	.port_ops		= &sgiioc4_port_ops,
 	.dma_ops		= &sgiioc4_dma_ops,
 	.host_flags		= IDE_HFLAG_MMIO,
+	.irq_flags		= IRQF_SHARED,
 	.mwdma_mask		= ATA_MWDMA2_ONLY,
 };
 
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index 1811ae9..075cb12 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -711,10 +711,10 @@
 static const struct ide_dma_ops sil_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= siimage_dma_test_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_lost_irq		= ide_dma_lost_irq,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index dba213c..d25137b 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -293,11 +293,11 @@
 static const struct ide_dma_ops sl82c105_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= sl82c105_dma_start,
 	.dma_end		= sl82c105_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= sl82c105_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= sl82c105_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c
index 84109f5..427d4b3 100644
--- a/drivers/ide/tc86c001.c
+++ b/drivers/ide/tc86c001.c
@@ -182,11 +182,11 @@
 static const struct ide_dma_ops tc86c001_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= tc86c001_dma_start,
 	.dma_end		= ide_dma_end,
 	.dma_test_irq		= ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 1c09e54..ed14968 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -176,18 +176,12 @@
 	trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
 }
 
-static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-	ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
-}
-
-static int trm290_dma_setup(ide_drive_t *drive)
+static int trm290_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = hwif->rq;
 	unsigned int count, rw;
 
-	if (rq_data_dir(rq)) {
+	if (cmd->tf_flags & IDE_TFLAG_WRITE) {
 #ifdef TRM290_NO_DMA_WRITES
 		/* always use PIO for writes */
 		trm290_prepare_drive(drive, 0);	/* select PIO xfer */
@@ -197,7 +191,9 @@
 	} else
 		rw = 2;
 
-	if (!(count = ide_build_dmatable(drive, rq))) {
+	count = ide_build_dmatable(drive, cmd);
+	if (count == 0) {
+		ide_map_sg(drive, cmd);
 		/* try PIO instead of DMA */
 		trm290_prepare_drive(drive, 0); /* select PIO xfer */
 		return 1;
@@ -314,7 +310,6 @@
 static struct ide_dma_ops trm290_dma_ops = {
 	.dma_host_set		= trm290_dma_host_set,
 	.dma_setup 		= trm290_dma_setup,
-	.dma_exec_cmd		= trm290_dma_exec_cmd,
 	.dma_start 		= trm290_dma_start,
 	.dma_end		= trm290_dma_end,
 	.dma_test_irq		= trm290_dma_test_irq,
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index d909534..657a618 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -15,6 +15,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+
+#include <asm/ide.h>
 #include <asm/txx9/tx4938.h>
 
 static void tx4938ide_tune_ebusc(unsigned int ebus_ch,
@@ -80,57 +82,57 @@
 	__raw_writeb(value, (void __iomem *)port);
 }
 
-static void tx4938ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void tx4938ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
+	struct ide_taskfile *tf = &cmd->tf;
+	u8 HIHI = cmd->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
 		u16 data = (tf->hob_data << 8) | tf->data;
 
 		/* no endian swap */
 		__raw_writew(data, (void __iomem *)io_ports->data_addr);
 	}
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		tx4938ide_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		tx4938ide_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		tx4938ide_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		tx4938ide_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		tx4938ide_outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		tx4938ide_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		tx4938ide_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		tx4938ide_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		tx4938ide_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		tx4938ide_outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
 		tx4938ide_outb((tf->device & HIHI) | drive->select,
 			       io_ports->device_addr);
 }
 
-static void tx4938ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void tx4938ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data;
 
 		/* no endian swap */
@@ -142,37 +144,37 @@
 	/* be sure we're looking at the low order bits */
 	tx4938ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = tx4938ide_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = tx4938ide_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = tx4938ide_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = tx4938ide_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = tx4938ide_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = tx4938ide_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		tx4938ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature =
 				tx4938ide_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = tx4938ide_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = tx4938ide_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = tx4938ide_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = tx4938ide_inb(io_ports->lbah_addr);
 	}
 }
 
-static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq,
+static void tx4938ide_input_data_swap(ide_drive_t *drive, struct ide_cmd *cmd,
 				void *buf, unsigned int len)
 {
 	unsigned long port = drive->hwif->io_ports.data_addr;
@@ -184,7 +186,7 @@
 	__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
 }
 
-static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
+static void tx4938ide_output_data_swap(ide_drive_t *drive, struct ide_cmd *cmd,
 				void *buf, unsigned int len)
 {
 	unsigned long port = drive->hwif->io_ports.data_addr;
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index 40b0812..e0e0a80 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -18,6 +18,8 @@
 #include <linux/io.h>
 #include <linux/scatterlist.h>
 
+#include <asm/ide.h>
+
 #define MODNAME	"tx4939ide"
 
 /* ATA Shadow Registers (8-bit except for Data which is 16-bit) */
@@ -230,7 +232,7 @@
 
 #ifdef __BIG_ENDIAN
 /* custom ide_build_dmatable to handle swapped layout */
-static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+static int tx4939ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	u32 *table = (u32 *)hwif->dmatable_cpu;
@@ -238,11 +240,7 @@
 	int i;
 	struct scatterlist *sg;
 
-	hwif->sg_nents = ide_build_sglist(drive, rq);
-	if (hwif->sg_nents == 0)
-		return 0;
-
-	for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+	for_each_sg(hwif->sg_table, sg, cmd->sg_nents, i) {
 		u32 cur_addr, cur_len, bcount;
 
 		cur_addr = sg_dma_address(sg);
@@ -289,23 +287,15 @@
 #define tx4939ide_build_dmatable	ide_build_dmatable
 #endif
 
-static int tx4939ide_dma_setup(ide_drive_t *drive)
+static int tx4939ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	void __iomem *base = TX4939IDE_BASE(hwif);
-	struct request *rq = hwif->rq;
-	u8 reading;
-	int nent;
-
-	if (rq_data_dir(rq))
-		reading = 0;
-	else
-		reading = ATA_DMA_WR;
+	u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
 
 	/* fall back to PIO! */
-	nent = tx4939ide_build_dmatable(drive, rq);
-	if (!nent) {
-		ide_map_sg(drive, rq);
+	if (tx4939ide_build_dmatable(drive, cmd) == 0) {
+		ide_map_sg(drive, cmd);
 		return 1;
 	}
 
@@ -313,7 +303,7 @@
 	tx4939ide_writel(hwif->dmatable_dma, base, TX4939IDE_PRD_Ptr);
 
 	/* specify r/w */
-	tx4939ide_writeb(reading, base, TX4939IDE_DMA_Cmd);
+	tx4939ide_writeb(rw, base, TX4939IDE_DMA_Cmd);
 
 	/* clear INTR & ERROR flags */
 	tx4939ide_clear_dma_status(base);
@@ -322,7 +312,9 @@
 
 	tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ?
 			 TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1);
-	tx4939ide_writew(rq->nr_sectors, base, TX4939IDE_Sec_Cnt);
+
+	tx4939ide_writew(cmd->rq->nr_sectors, base, TX4939IDE_Sec_Cnt);
+
 	return 0;
 }
 
@@ -437,7 +429,7 @@
 	return ide_allocate_dma_engine(hwif);
 }
 
-static void tx4939ide_tf_load_fixup(ide_drive_t *drive, ide_task_t *task)
+static void tx4939ide_tf_load_fixup(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	void __iomem *base = TX4939IDE_BASE(hwif);
@@ -465,59 +457,59 @@
 	__raw_writeb(value, (void __iomem *)port);
 }
 
-static void tx4939ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
-	u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
+	struct ide_taskfile *tf = &cmd->tf;
+	u8 HIHI = cmd->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF;
 
-	if (task->tf_flags & IDE_TFLAG_FLAGGED)
+	if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
 		HIHI = 0xFF;
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
 		u16 data = (tf->hob_data << 8) | tf->data;
 
 		/* no endian swap */
 		__raw_writew(data, (void __iomem *)io_ports->data_addr);
 	}
 
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
 		tx4939ide_outb(tf->hob_feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
 		tx4939ide_outb(tf->hob_nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
 		tx4939ide_outb(tf->hob_lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
 		tx4939ide_outb(tf->hob_lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
 		tx4939ide_outb(tf->hob_lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
 		tx4939ide_outb(tf->feature, io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
 		tx4939ide_outb(tf->nsect, io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
 		tx4939ide_outb(tf->lbal, io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
 		tx4939ide_outb(tf->lbam, io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
 		tx4939ide_outb(tf->lbah, io_ports->lbah_addr);
 
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) {
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) {
 		tx4939ide_outb((tf->device & HIHI) | drive->select,
 			       io_ports->device_addr);
-		tx4939ide_tf_load_fixup(drive, task);
+		tx4939ide_tf_load_fixup(drive);
 	}
 }
 
-static void tx4939ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+static void tx4939ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
-	struct ide_taskfile *tf = &task->tf;
+	struct ide_taskfile *tf = &cmd->tf;
 
-	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
 		u16 data;
 
 		/* no endian swap */
@@ -529,32 +521,32 @@
 	/* be sure we're looking at the low order bits */
 	tx4939ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
-	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
 		tf->feature = tx4939ide_inb(io_ports->feature_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+	if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = tx4939ide_inb(io_ports->nsect_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
 		tf->lbal   = tx4939ide_inb(io_ports->lbal_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
 		tf->lbam   = tx4939ide_inb(io_ports->lbam_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+	if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
 		tf->lbah   = tx4939ide_inb(io_ports->lbah_addr);
-	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+	if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
 		tf->device = tx4939ide_inb(io_ports->device_addr);
 
-	if (task->tf_flags & IDE_TFLAG_LBA48) {
+	if (cmd->tf_flags & IDE_TFLAG_LBA48) {
 		tx4939ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
 
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
 			tf->hob_feature =
 				tx4939ide_inb(io_ports->feature_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
 			tf->hob_nsect   = tx4939ide_inb(io_ports->nsect_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
 			tf->hob_lbal    = tx4939ide_inb(io_ports->lbal_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
 			tf->hob_lbam    = tx4939ide_inb(io_ports->lbam_addr);
-		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+		if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
 			tf->hob_lbah    = tx4939ide_inb(io_ports->lbah_addr);
 	}
 }
@@ -601,11 +593,12 @@
 
 #else	/* __LITTLE_ENDIAN */
 
-static void tx4939ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
 {
-	ide_tf_load(drive, task);
-	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-		tx4939ide_tf_load_fixup(drive, task);
+	ide_tf_load(drive, cmd);
+
+	if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
+		tx4939ide_tf_load_fixup(drive);
 }
 
 static const struct ide_tp_ops tx4939ide_tp_ops = {
@@ -634,11 +627,11 @@
 static const struct ide_dma_ops tx4939ide_dma_ops = {
 	.dma_host_set		= tx4939ide_dma_host_set,
 	.dma_setup		= tx4939ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
 	.dma_start		= ide_dma_start,
 	.dma_end		= tx4939ide_dma_end,
 	.dma_test_irq		= tx4939ide_dma_test_irq,
 	.dma_lost_irq		= ide_dma_lost_irq,
+	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
 	.dma_timeout		= ide_dma_timeout,
 	.dma_sff_read_status	= tx4939ide_dma_sff_read_status,
 };
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index abb04c8..634af6a 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -21,8 +21,6 @@
 #include <linux/slab.h>
 
 #include <mach/corgi.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-gpio.h>
 #include <asm/hardware/scoop.h>
 
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 9d1781a..1396742 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -21,8 +21,6 @@
 #include <linux/slab.h>
 
 #include <mach/spitz.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-gpio.h>
 
 #define KB_ROWS			7
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 56c079e..272dedd 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -22,10 +22,10 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/hardware/iomd.h>
 
 MODULE_AUTHOR("Vojtech Pavlik, Russell King");
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 7f36edd3..ed045c9 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -33,10 +33,10 @@
 #include <linux/serio.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/hardware/iomd.h>
 #include <asm/system.h>
 
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 3fb51b5..94a1919 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -21,7 +21,6 @@
 
 #include <mach/sharpsl.h>
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-gpio.h>
 
 
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 82607ad..c0621d5 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -498,8 +498,8 @@
 #define BUILD_STORE_FUNC_INT(name, data)			\
 static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
 {								\
-	u32 val;						\
-	val = simple_strtoul(buf, NULL, 10);			\
+	int val;						\
+	val = simple_strtol(buf, NULL, 10);			\
 	if (val < 0 || val > 255)				\
 		return -EINVAL;					\
 	printk(KERN_INFO "Setting specified fan speed to %d\n", val);	\
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 93ea201..223c36e 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -117,7 +117,7 @@
 config DAB
 	boolean "DAB adapters"
 	---help---
-	  Allow selecting support for for Digital Audio Broadcasting (DAB)
+	  Allow selecting support for Digital Audio Broadcasting (DAB)
 	  Receiver adapters.
 
 if DAB
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index d8229a0..3fe158a 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -153,6 +153,65 @@
 };
 EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a);
 
+/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = {
+	[0x00] = KEY_POWER,
+	[0x01] = KEY_TUNER,		/* TV/FM */
+	[0x03] = KEY_TEXT,		/* Teletext */
+	[0x04] = KEY_EPG,
+	[0x05] = KEY_1,
+	[0x06] = KEY_2,
+	[0x07] = KEY_3,
+	[0x08] = KEY_AUDIO,
+	[0x09] = KEY_4,
+	[0x0a] = KEY_5,
+	[0x0b] = KEY_6,
+	[0x0c] = KEY_ZOOM,		/* Full screen */
+	[0x0d] = KEY_7,
+	[0x0e] = KEY_8,
+	[0x0f] = KEY_9,
+	[0x10] = KEY_PAGEUP,		/* 16-CH PREV */
+	[0x11] = KEY_0,
+	[0x12] = KEY_INFO,
+	[0x13] = KEY_AGAIN,		/* CH RTN - channel return */
+	[0x14] = KEY_MUTE,
+	[0x15] = KEY_EDIT,		/* Autoscan */
+	[0x17] = KEY_SAVE,		/* Screenshot */
+	[0x18] = KEY_PLAYPAUSE,
+	[0x19] = KEY_RECORD,
+	[0x1a] = KEY_PLAY,
+	[0x1b] = KEY_STOP,
+	[0x1c] = KEY_FASTFORWARD,
+	[0x1d] = KEY_REWIND,
+	[0x1e] = KEY_VOLUMEDOWN,
+	[0x1f] = KEY_VOLUMEUP,
+	[0x22] = KEY_SLEEP,		/* Sleep */
+	[0x23] = KEY_ZOOM,		/* Aspect */
+	[0x26] = KEY_SCREEN,		/* Pos */
+	[0x27] = KEY_ANGLE,		/* Size */
+	[0x28] = KEY_SELECT,		/* Select */
+	[0x29] = KEY_BLUE,		/* Blue/Picture */
+	[0x2a] = KEY_BACKSPACE,	/* Back */
+	[0x2b] = KEY_MEDIA,		/* PIP (Picture-in-picture) */
+	[0x2c] = KEY_DOWN,
+	[0x2e] = KEY_DOT,
+	[0x2f] = KEY_TV,		/* Live TV */
+	[0x32] = KEY_LEFT,
+	[0x33] = KEY_CLEAR,		/* Clear */
+	[0x35] = KEY_RED,		/* Red/TV */
+	[0x36] = KEY_UP,
+	[0x37] = KEY_HOME,		/* Home */
+	[0x39] = KEY_GREEN,		/* Green/Video */
+	[0x3d] = KEY_YELLOW,		/* Yellow/Music */
+	[0x3e] = KEY_OK,		/* Ok */
+	[0x3f] = KEY_RIGHT,
+	[0x40] = KEY_NEXT,		/* Next */
+	[0x41] = KEY_PREVIOUS,	/* Previous */
+	[0x42] = KEY_CHANNELDOWN,	/* Channel down */
+	[0x43] = KEY_CHANNELUP	/* Channel up */
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus);
+
 /* Attila Kondoros <attila.kondoros@chello.hu> */
 IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
 
@@ -2452,6 +2511,55 @@
 };
 EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog);
 
+/* Kaiomy TVnPC U2
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = {
+	[0x43] = KEY_POWER2,
+	[0x01] = KEY_LIST,
+	[0x0b] = KEY_ZOOM,
+	[0x03] = KEY_POWER,
+
+	[0x04] = KEY_1,
+	[0x08] = KEY_2,
+	[0x02] = KEY_3,
+
+	[0x0f] = KEY_4,
+	[0x05] = KEY_5,
+	[0x06] = KEY_6,
+
+	[0x0c] = KEY_7,
+	[0x0d] = KEY_8,
+	[0x0a] = KEY_9,
+
+	[0x11] = KEY_0,
+
+	[0x09] = KEY_CHANNELUP,
+	[0x07] = KEY_CHANNELDOWN,
+
+	[0x0e] = KEY_VOLUMEUP,
+	[0x13] = KEY_VOLUMEDOWN,
+
+	[0x10] = KEY_HOME,
+	[0x12] = KEY_ENTER,
+
+	[0x14] = KEY_RECORD,
+	[0x15] = KEY_STOP,
+	[0x16] = KEY_PLAY,
+	[0x17] = KEY_MUTE,
+
+	[0x18] = KEY_UP,
+	[0x19] = KEY_DOWN,
+	[0x1a] = KEY_LEFT,
+	[0x1b] = KEY_RIGHT,
+
+	[0x1c] = KEY_RED,
+	[0x1d] = KEY_GREEN,
+	[0x1e] = KEY_YELLOW,
+	[0x1f] = KEY_BLUE,
+};
+EXPORT_SYMBOL_GPL(ir_codes_kaiomy);
+
 IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
 	[0x20] = KEY_LIST,
 	[0x00] = KEY_POWER,
@@ -2604,3 +2712,41 @@
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600);
+
+/* DVBWorld remotes
+   Igor M. Liplianin <liplianin@me.by>
+ */
+IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = {
+	[0x0a] = KEY_Q,		/*power*/
+	[0x0c] = KEY_M,		/*mute*/
+	[0x11] = KEY_1,
+	[0x12] = KEY_2,
+	[0x13] = KEY_3,
+	[0x14] = KEY_4,
+	[0x15] = KEY_5,
+	[0x16] = KEY_6,
+	[0x17] = KEY_7,
+	[0x18] = KEY_8,
+	[0x19] = KEY_9,
+	[0x10] = KEY_0,
+	[0x1c] = KEY_PAGEUP,	/*ch+*/
+	[0x0f] = KEY_PAGEDOWN,	/*ch-*/
+	[0x1a] = KEY_O,		/*vol+*/
+	[0x0e] = KEY_Z,		/*vol-*/
+	[0x04] = KEY_R,		/*rec*/
+	[0x09] = KEY_D,		/*fav*/
+	[0x08] = KEY_BACKSPACE,	/*rewind*/
+	[0x07] = KEY_A,		/*fast*/
+	[0x0b] = KEY_P,		/*pause*/
+	[0x02] = KEY_ESC,	/*cancel*/
+	[0x03] = KEY_G,		/*tab*/
+	[0x00] = KEY_UP,	/*up*/
+	[0x1f] = KEY_ENTER,	/*ok*/
+	[0x01] = KEY_DOWN,	/*down*/
+	[0x05] = KEY_C,		/*cap*/
+	[0x06] = KEY_S,		/*stop*/
+	[0x40] = KEY_F,		/*full*/
+	[0x1e] = KEY_W,		/*tvmode*/
+	[0x1b] = KEY_B,		/*recall*/
+};
+EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index d599d36..982f000 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -452,8 +452,6 @@
 	INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
 	dev->ext = ext;
 
-	pci_set_drvdata(pci, dev);
-
 	mutex_init(&dev->lock);
 	spin_lock_init(&dev->int_slock);
 	spin_lock_init(&dev->slock);
@@ -477,8 +475,12 @@
 
 	if (ext->attach(dev, pci_ext)) {
 		DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
-		goto err_unprobe;
+		goto err_free_i2c;
 	}
+	/* V4L extensions will set the pci drvdata to the v4l2_device in the
+	   attach() above. So for those cards that do not use V4L we have to
+	   set it explicitly. */
+	pci_set_drvdata(pci, &dev->v4l2_dev);
 
 	INIT_LIST_HEAD(&dev->item);
 	list_add_tail(&dev->item,&saa7146_devices);
@@ -488,8 +490,6 @@
 out:
 	return err;
 
-err_unprobe:
-	pci_set_drvdata(pci, NULL);
 err_free_i2c:
 	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
 			    dev->d_i2c.dma_handle);
@@ -514,7 +514,8 @@
 
 static void saa7146_remove_one(struct pci_dev *pdev)
 {
-	struct saa7146_dev* dev = pci_get_drvdata(pdev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+	struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev);
 	struct {
 		void *addr;
 		dma_addr_t dma;
@@ -528,6 +529,8 @@
 	DEB_EE(("dev:%p\n",dev));
 
 	dev->ext->detach(dev);
+	/* Zero the PCI drvdata after use. */
+	pci_set_drvdata(pdev, NULL);
 
 	/* shut down all video dma transfers */
 	saa7146_write(dev, MC1, 0x00ff0000);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cf06f4d..620f655 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -308,14 +308,6 @@
 	return 0;
 }
 
-static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-/*
-	DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
-*/
-	return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
-}
-
 static int fops_mmap(struct file *file, struct vm_area_struct * vma)
 {
 	struct saa7146_fh *fh = file->private_data;
@@ -425,7 +417,7 @@
 	.write		= fops_write,
 	.poll		= fops_poll,
 	.mmap		= fops_mmap,
-	.ioctl		= fops_ioctl,
+	.ioctl		= video_ioctl2,
 };
 
 static void vv_callback(struct saa7146_dev *dev, unsigned long status)
@@ -452,19 +444,22 @@
 	}
 }
 
-static struct video_device device_template =
-{
-	.fops		= &video_fops,
-	.minor		= -1,
-};
-
 int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 {
-	struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
-	if( NULL == vv ) {
+	struct saa7146_vv *vv;
+	int err;
+
+	err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
+	if (err)
+		return err;
+
+	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
+	if (vv == NULL) {
 		ERR(("out of memory. aborting.\n"));
-		return -1;
+		return -ENOMEM;
 	}
+	ext_vv->ops = saa7146_video_ioctl_ops;
+	ext_vv->core_ops = &saa7146_video_ioctl_ops;
 
 	DEB_EE(("dev:%p\n",dev));
 
@@ -507,6 +502,7 @@
 
 	DEB_EE(("dev:%p\n",dev));
 
+	v4l2_device_unregister(&dev->v4l2_dev);
 	pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
 	kfree(vv);
 	dev->vv_data = NULL;
@@ -521,6 +517,8 @@
 {
 	struct saa7146_vv *vv = dev->vv_data;
 	struct video_device *vfd;
+	int err;
+	int i;
 
 	DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
 
@@ -529,16 +527,20 @@
 	if (vfd == NULL)
 		return -ENOMEM;
 
-	memcpy(vfd, &device_template, sizeof(struct video_device));
-	strlcpy(vfd->name, name, sizeof(vfd->name));
+	vfd->fops = &video_fops;
+	vfd->ioctl_ops = &dev->ext_vv_data->ops;
 	vfd->release = video_device_release;
+	vfd->tvnorms = 0;
+	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
+		vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
+	strlcpy(vfd->name, name, sizeof(vfd->name));
 	video_set_drvdata(vfd, dev);
 
-	// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
-	if (video_register_device(vfd, type, -1) < 0) {
+	err = video_register_device(vfd, type, -1);
+	if (err < 0) {
 		ERR(("cannot register v4l2 device. skipping.\n"));
 		video_device_release(vfd);
-		return -1;
+		return err;
 	}
 
 	if( VFL_TYPE_GRABBER == type ) {
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index c11da4d..7e8f568 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -293,7 +293,6 @@
 	int i = 0, count = 0;
 	__le32 *buffer = dev->d_i2c.cpu_addr;
 	int err = 0;
-	int address_err = 0;
 	int short_delay = 0;
 
 	if (mutex_lock_interruptible(&dev->i2c_lock))
@@ -333,17 +332,10 @@
 				   i2c address probing, however, and address errors indicate that a
 				   device is really *not* there. retrying in that case
 				   increases the time the device needs to probe greatly, so
-				   it should be avoided. because of the fact, that only
-				   analog based cards use irq based i2c transactions (for dvb
-				   cards, this screwes up other interrupt sources), we bail out
-				   completely for analog cards after an address error and trust
-				   the saa7146 address error detection. */
-				if ( -EREMOTEIO == err ) {
-					if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
-						goto out;
-					}
-					address_err++;
-				}
+				   it should be avoided. So we bail out in irq mode after an
+				   address error and trust the saa7146 address error detection. */
+				if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
+					goto out;
 				DEB_I2C(("error while sending message(s). starting again.\n"));
 				break;
 			}
@@ -358,10 +350,9 @@
 
 	} while (err != num && retries--);
 
-	/* if every retry had an address error, exit right away */
-	if (address_err == retries) {
+	/* quit if any error occurred */
+	if (err != num)
 		goto out;
-	}
 
 	/* if any things had to be read, get the results */
 	if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
@@ -390,7 +381,8 @@
 /* utility functions */
 static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
 {
-	struct saa7146_dev* dev = i2c_get_adapdata(adapter);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
+	struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev);
 
 	/* use helper function to transfer data */
 	return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
@@ -417,9 +409,8 @@
 	dev->i2c_bitrate = bitrate;
 	saa7146_i2c_reset(dev);
 
-	if( NULL != i2c_adapter ) {
-		BUG_ON(!i2c_adapter->class);
-		i2c_set_adapdata(i2c_adapter,dev);
+	if (i2c_adapter) {
+		i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev);
 		i2c_adapter->dev.parent    = &dev->pci->dev;
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 47fee05..552dab4 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -1,4 +1,5 @@
 #include <media/saa7146_vv.h>
+#include <media/v4l2-chip-ident.h>
 
 static int max_memory = 32;
 
@@ -97,172 +98,13 @@
 	return NULL;
 }
 
-static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
-{
-	struct saa7146_dev *dev = fh->dev;
-	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
-
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		f->fmt.pix = fh->video_fmt;
-		return 0;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		f->fmt.win = fh->ov.win;
-		return 0;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-	{
-		f->fmt.vbi = fh->vbi_fmt;
-		return 0;
-	}
-	default:
-		DEB_D(("invalid format type '%d'.\n",f->type));
-		return -EINVAL;
-	}
-}
-
-static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	enum v4l2_field field;
-	int maxw, maxh;
-
-	DEB_EE(("dev:%p\n",dev));
-
-	if (NULL == vv->ov_fb.base) {
-		DEB_D(("no fb base set.\n"));
-		return -EINVAL;
-	}
-	if (NULL == vv->ov_fmt) {
-		DEB_D(("no fb fmt set.\n"));
-		return -EINVAL;
-	}
-	if (win->w.width < 48 || win->w.height <  32) {
-		DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
-		return -EINVAL;
-	}
-	if (win->clipcount > 16) {
-		DEB_D(("clipcount too big.\n"));
-		return -EINVAL;
-	}
-
-	field = win->field;
-	maxw  = vv->standard->h_max_out;
-	maxh  = vv->standard->v_max_out;
-
-	if (V4L2_FIELD_ANY == field) {
-		field = (win->w.height > maxh/2)
-			? V4L2_FIELD_INTERLACED
-			: V4L2_FIELD_TOP;
-		}
-	switch (field) {
-	case V4L2_FIELD_TOP:
-	case V4L2_FIELD_BOTTOM:
-	case V4L2_FIELD_ALTERNATE:
-		maxh = maxh / 2;
-		break;
-	case V4L2_FIELD_INTERLACED:
-		break;
-	default: {
-		DEB_D(("no known field mode '%d'.\n",field));
-		return -EINVAL;
-	}
-	}
-
-	win->field = field;
-	if (win->w.width > maxw)
-		win->w.width = maxw;
-	if (win->w.height > maxh)
-		win->w.height = maxh;
-
-	return 0;
-}
-
-static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	int err;
-
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-	{
-		struct saa7146_format *fmt;
-		enum v4l2_field field;
-		int maxw, maxh;
-		int calc_bpl;
-
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
-
-		fmt = format_by_fourcc(dev,f->fmt.pix.pixelformat);
-		if (NULL == fmt) {
-			return -EINVAL;
-		}
-
-		field = f->fmt.pix.field;
-		maxw  = vv->standard->h_max_out;
-		maxh  = vv->standard->v_max_out;
-
-		if (V4L2_FIELD_ANY == field) {
-			field = (f->fmt.pix.height > maxh/2)
-				? V4L2_FIELD_INTERLACED
-				: V4L2_FIELD_BOTTOM;
-		}
-		switch (field) {
-		case V4L2_FIELD_ALTERNATE: {
-			vv->last_field = V4L2_FIELD_TOP;
-			maxh = maxh / 2;
-			break;
-		}
-		case V4L2_FIELD_TOP:
-		case V4L2_FIELD_BOTTOM:
-			vv->last_field = V4L2_FIELD_INTERLACED;
-			maxh = maxh / 2;
-			break;
-		case V4L2_FIELD_INTERLACED:
-			vv->last_field = V4L2_FIELD_INTERLACED;
-			break;
-		default: {
-			DEB_D(("no known field mode '%d'.\n",field));
-			return -EINVAL;
-		}
-		}
-
-		f->fmt.pix.field = field;
-		if (f->fmt.pix.width > maxw)
-			f->fmt.pix.width = maxw;
-		if (f->fmt.pix.height > maxh)
-			f->fmt.pix.height = maxh;
-
-		calc_bpl = (f->fmt.pix.width * fmt->depth)/8;
-
-		if (f->fmt.pix.bytesperline < calc_bpl)
-			f->fmt.pix.bytesperline = calc_bpl;
-
-		if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
-			f->fmt.pix.bytesperline = calc_bpl;
-
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
-		DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
-
-		return 0;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
-		err = try_win(dev,&f->fmt.win);
-		if (0 != err) {
-			return err;
-		}
-		return 0;
-	default:
-		DEB_EE(("unknown format type '%d'\n",f->type));
-		return -EINVAL;
-	}
-}
+static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f);
 
 int saa7146_start_preview(struct saa7146_fh *fh)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
+	struct v4l2_format fmt;
 	int ret = 0, err = 0;
 
 	DEB_EE(("dev:%p, fh:%p\n",dev,fh));
@@ -294,12 +136,13 @@
 		return -EBUSY;
 	}
 
-	err = try_win(dev,&fh->ov.win);
+	fmt.fmt.win = fh->ov.win;
+	err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
 	if (0 != err) {
 		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
 		return -EBUSY;
 	}
-
+	fh->ov.win = fmt.fmt.win;
 	vv->ov_data = &fh->ov;
 
 	DEB_D(("%dx%d+%d+%d %s field=%s\n",
@@ -355,58 +198,6 @@
 }
 EXPORT_SYMBOL_GPL(saa7146_stop_preview);
 
-static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	int err;
-
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
-		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_EE(("streaming capture is active\n"));
-			return -EBUSY;
-		}
-		err = try_fmt(fh,f);
-		if (0 != err)
-			return err;
-		fh->video_fmt = f->fmt.pix;
-		DEB_EE(("set to pixelformat '%4.4s'\n",(char *)&fh->video_fmt.pixelformat));
-		return 0;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n",dev,fh));
-		err = try_win(dev,&f->fmt.win);
-		if (0 != err)
-			return err;
-		mutex_lock(&dev->lock);
-		fh->ov.win    = f->fmt.win;
-		fh->ov.nclips = f->fmt.win.clipcount;
-		if (fh->ov.nclips > 16)
-			fh->ov.nclips = 16;
-		if (copy_from_user(fh->ov.clips,f->fmt.win.clips,sizeof(struct v4l2_clip)*fh->ov.nclips)) {
-			mutex_unlock(&dev->lock);
-			return -EFAULT;
-		}
-
-		/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
-		fh->ov.fh = fh;
-
-		mutex_unlock(&dev->lock);
-
-		/* check if our current overlay is active */
-		if (IS_OVERLAY_ACTIVE(fh) != 0) {
-			saa7146_stop_preview(fh);
-			saa7146_start_preview(fh);
-		}
-		return 0;
-	default:
-		DEB_D(("unknown format type '%d'\n",f->type));
-		return -EINVAL;
-	}
-}
-
 /********************************************************************************/
 /* device controls */
 
@@ -419,6 +210,7 @@
 		.step		= 1,
 		.default_value	= 128,
 		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.flags 		= V4L2_CTRL_FLAG_SLIDER,
 	},{
 		.id		= V4L2_CID_CONTRAST,
 		.name		= "Contrast",
@@ -427,6 +219,7 @@
 		.step		= 1,
 		.default_value	= 64,
 		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.flags 		= V4L2_CTRL_FLAG_SLIDER,
 	},{
 		.id		= V4L2_CID_SATURATION,
 		.name		= "Saturation",
@@ -435,15 +228,16 @@
 		.step		= 1,
 		.default_value	= 64,
 		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.flags 		= V4L2_CTRL_FLAG_SLIDER,
 	},{
 		.id		= V4L2_CID_VFLIP,
-		.name		= "Vertical flip",
+		.name		= "Vertical Flip",
 		.minimum	= 0,
 		.maximum	= 1,
 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
 	},{
 		.id		= V4L2_CID_HFLIP,
-		.name		= "Horizontal flip",
+		.name		= "Horizontal Flip",
 		.minimum	= 0,
 		.maximum	= 1,
 		.type		= V4L2_CTRL_TYPE_BOOLEAN,
@@ -463,132 +257,6 @@
 	return NULL;
 }
 
-static int get_control(struct saa7146_fh *fh, struct v4l2_control *c)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	const struct v4l2_queryctrl* ctrl;
-	u32 value = 0;
-
-	ctrl = ctrl_by_id(c->id);
-	if (NULL == ctrl)
-		return -EINVAL;
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		value = saa7146_read(dev, BCS_CTRL);
-		c->value = 0xff & (value >> 24);
-		DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value));
-		break;
-	case V4L2_CID_CONTRAST:
-		value = saa7146_read(dev, BCS_CTRL);
-		c->value = 0x7f & (value >> 16);
-		DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value));
-		break;
-	case V4L2_CID_SATURATION:
-		value = saa7146_read(dev, BCS_CTRL);
-		c->value = 0x7f & (value >> 0);
-		DEB_D(("V4L2_CID_SATURATION: %d\n",c->value));
-		break;
-	case V4L2_CID_VFLIP:
-		c->value = vv->vflip;
-		DEB_D(("V4L2_CID_VFLIP: %d\n",c->value));
-		break;
-	case V4L2_CID_HFLIP:
-		c->value = vv->hflip;
-		DEB_D(("V4L2_CID_HFLIP: %d\n",c->value));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	const struct v4l2_queryctrl* ctrl;
-
-	ctrl = ctrl_by_id(c->id);
-	if (NULL == ctrl) {
-		DEB_D(("unknown control %d\n",c->id));
-		return -EINVAL;
-	}
-
-	mutex_lock(&dev->lock);
-
-	switch (ctrl->type) {
-	case V4L2_CTRL_TYPE_BOOLEAN:
-	case V4L2_CTRL_TYPE_MENU:
-	case V4L2_CTRL_TYPE_INTEGER:
-		if (c->value < ctrl->minimum)
-			c->value = ctrl->minimum;
-		if (c->value > ctrl->maximum)
-			c->value = ctrl->maximum;
-		break;
-	default:
-		/* nothing */;
-	};
-
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS: {
-		u32 value = saa7146_read(dev, BCS_CTRL);
-		value &= 0x00ffffff;
-		value |= (c->value << 24);
-		saa7146_write(dev, BCS_CTRL, value);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
-		break;
-	}
-	case V4L2_CID_CONTRAST: {
-		u32 value = saa7146_read(dev, BCS_CTRL);
-		value &= 0xff00ffff;
-		value |= (c->value << 16);
-		saa7146_write(dev, BCS_CTRL, value);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
-		break;
-	}
-	case V4L2_CID_SATURATION: {
-		u32 value = saa7146_read(dev, BCS_CTRL);
-		value &= 0xffffff00;
-		value |= (c->value << 0);
-		saa7146_write(dev, BCS_CTRL, value);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06 );
-		break;
-	}
-	case V4L2_CID_HFLIP:
-		/* fixme: we can support changing VFLIP and HFLIP here... */
-		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
-			mutex_unlock(&dev->lock);
-			return -EINVAL;
-		}
-		vv->hflip = c->value;
-		break;
-	case V4L2_CID_VFLIP:
-		if (IS_CAPTURE_ACTIVE(fh) != 0) {
-			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
-			mutex_unlock(&dev->lock);
-			return -EINVAL;
-		}
-		vv->vflip = c->value;
-		break;
-	default: {
-		mutex_unlock(&dev->lock);
-		return -EINVAL;
-	}
-	}
-	mutex_unlock(&dev->lock);
-
-	if (IS_OVERLAY_ACTIVE(fh) != 0) {
-		saa7146_stop_preview(fh);
-		saa7146_start_preview(fh);
-	}
-	return 0;
-}
-
 /********************************************************************************/
 /* common pagetable functions */
 
@@ -829,231 +497,446 @@
 	return 0;
 }
 
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel pointer.
- */
-
-long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 {
-	struct saa7146_fh *fh  = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+
+	strcpy((char *)cap->driver, "saa7146 v4l2");
+	strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
+	sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
+	cap->version = SAA7146_VERSION_CODE;
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_VIDEO_OVERLAY |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	cap->capabilities |= dev->ext_vv_data->capabilities;
+	return 0;
+}
+
+static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	long err = 0;
-	int result = 0, ee = 0;
+	*fb = vv->ov_fb;
+	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	return 0;
+}
 
-	struct saa7146_use_ops *ops;
-	struct videobuf_queue *q;
+static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt;
 
-	/* check if extension handles the command */
-	for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) {
-		if( cmd == dev->ext_vv_data->ioctls[ee].cmd )
-			break;
-	}
+	DEB_EE(("VIDIOC_S_FBUF\n"));
 
-	if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
-		DEB_D(("extension handles ioctl exclusive.\n"));
-		result = dev->ext_vv_data->ioctl(fh, cmd, arg);
-		return result;
-	}
-	if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
-		DEB_D(("extension handles ioctl before.\n"));
-		result = dev->ext_vv_data->ioctl(fh, cmd, arg);
-		if( -EAGAIN != result ) {
-			return result;
+	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/* check args */
+	fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	/* planar formats are not allowed for overlay video, clipping and video dma would clash */
+	if (fmt->flags & FORMAT_IS_PLANAR)
+		DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
+					(char *)&fmt->pixelformat));
+
+	/* check if overlay is running */
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		if (vv->video_fh != fh) {
+			DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
+			return -EBUSY;
 		}
 	}
 
-	/* fixme: add handle "after" case (is it still needed?) */
+	mutex_lock(&dev->lock);
 
-	switch (fh->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		ops = &saa7146_video_uops;
-		q = &fh->video_q;
+	/* ok, accept it */
+	vv->ov_fb = *fb;
+	vv->ov_fmt = fmt;
+	if (0 == vv->ov_fb.fmt.bytesperline)
+		vv->ov_fb.fmt.bytesperline =
+			vv->ov_fb.fmt.width * fmt->depth / 8;
+
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	if (f->index >= NUM_FORMATS)
+		return -EINVAL;
+	strlcpy((char *)f->description, formats[f->index].name,
+			sizeof(f->description));
+	f->pixelformat = formats[f->index].pixelformat;
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
+{
+	const struct v4l2_queryctrl *ctrl;
+
+	if ((c->id <  V4L2_CID_BASE ||
+	     c->id >= V4L2_CID_LASTP1) &&
+	    (c->id <  V4L2_CID_PRIVATE_BASE ||
+	     c->id >= V4L2_CID_PRIVATE_LASTP1))
+		return -EINVAL;
+
+	ctrl = ctrl_by_id(c->id);
+	if (ctrl == NULL)
+		return -EINVAL;
+
+	DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
+	*c = *ctrl;
+	return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	const struct v4l2_queryctrl *ctrl;
+	u32 value = 0;
+
+	ctrl = ctrl_by_id(c->id);
+	if (NULL == ctrl)
+		return -EINVAL;
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		value = saa7146_read(dev, BCS_CTRL);
+		c->value = 0xff & (value >> 24);
+		DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
 		break;
-		}
-	case V4L2_BUF_TYPE_VBI_CAPTURE: {
-		ops = &saa7146_vbi_uops;
-		q = &fh->vbi_q;
+	case V4L2_CID_CONTRAST:
+		value = saa7146_read(dev, BCS_CTRL);
+		c->value = 0x7f & (value >> 16);
+		DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
 		break;
-		}
+	case V4L2_CID_SATURATION:
+		value = saa7146_read(dev, BCS_CTRL);
+		c->value = 0x7f & (value >> 0);
+		DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
+		break;
+	case V4L2_CID_VFLIP:
+		c->value = vv->vflip;
+		DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
+		break;
+	case V4L2_CID_HFLIP:
+		c->value = vv->hflip;
+		DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
+		break;
 	default:
-		BUG();
-		return 0;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	const struct v4l2_queryctrl *ctrl;
+
+	ctrl = ctrl_by_id(c->id);
+	if (NULL == ctrl) {
+		DEB_D(("unknown control %d\n", c->id));
+		return -EINVAL;
 	}
 
-	switch (cmd) {
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
-		memset(cap,0,sizeof(*cap));
+	mutex_lock(&dev->lock);
 
-		DEB_EE(("VIDIOC_QUERYCAP\n"));
-
-		strcpy((char *)cap->driver, "saa7146 v4l2");
-		strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
-		sprintf((char *)cap->bus_info,"PCI:%s", pci_name(dev->pci));
-		cap->version = SAA7146_VERSION_CODE;
-		cap->capabilities =
-			V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_VIDEO_OVERLAY |
-			V4L2_CAP_READWRITE |
-			V4L2_CAP_STREAMING;
-		cap->capabilities |= dev->ext_vv_data->capabilities;
-		return 0;
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER:
+		if (c->value < ctrl->minimum)
+			c->value = ctrl->minimum;
+		if (c->value > ctrl->maximum)
+			c->value = ctrl->maximum;
+		break;
+	default:
+		/* nothing */;
 	}
-	case VIDIOC_G_FBUF:
-	{
-		struct v4l2_framebuffer *fb = arg;
 
-		DEB_EE(("VIDIOC_G_FBUF\n"));
-
-		*fb = vv->ov_fb;
-		fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-		return 0;
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS: {
+		u32 value = saa7146_read(dev, BCS_CTRL);
+		value &= 0x00ffffff;
+		value |= (c->value << 24);
+		saa7146_write(dev, BCS_CTRL, value);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
 	}
-	case VIDIOC_S_FBUF:
-	{
-		struct v4l2_framebuffer *fb = arg;
-		struct saa7146_format *fmt;
-
-		DEB_EE(("VIDIOC_S_FBUF\n"));
-
-		if(!capable(CAP_SYS_ADMIN) &&
-		   !capable(CAP_SYS_RAWIO))
-			return -EPERM;
-
-		/* check args */
-		fmt = format_by_fourcc(dev,fb->fmt.pixelformat);
-		if (NULL == fmt) {
-			return -EINVAL;
+	case V4L2_CID_CONTRAST: {
+		u32 value = saa7146_read(dev, BCS_CTRL);
+		value &= 0xff00ffff;
+		value |= (c->value << 16);
+		saa7146_write(dev, BCS_CTRL, value);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
+	}
+	case V4L2_CID_SATURATION: {
+		u32 value = saa7146_read(dev, BCS_CTRL);
+		value &= 0xffffff00;
+		value |= (c->value << 0);
+		saa7146_write(dev, BCS_CTRL, value);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
+	}
+	case V4L2_CID_HFLIP:
+		/* fixme: we can support changing VFLIP and HFLIP here... */
+		if (IS_CAPTURE_ACTIVE(fh) != 0) {
+			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
+			mutex_unlock(&dev->lock);
+			return -EBUSY;
 		}
-
-		/* planar formats are not allowed for overlay video, clipping and video dma would clash */
-		if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
-			DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
+		vv->hflip = c->value;
+		break;
+	case V4L2_CID_VFLIP:
+		if (IS_CAPTURE_ACTIVE(fh) != 0) {
+			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
+			mutex_unlock(&dev->lock);
+			return -EBUSY;
 		}
-
-		/* check if overlay is running */
-		if (IS_OVERLAY_ACTIVE(fh) != 0) {
-			if (vv->video_fh != fh) {
-				DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
-				return -EBUSY;
-			}
-		}
-
-		mutex_lock(&dev->lock);
-
-		/* ok, accept it */
-		vv->ov_fb = *fb;
-		vv->ov_fmt = fmt;
-		if (0 == vv->ov_fb.fmt.bytesperline)
-			vv->ov_fb.fmt.bytesperline =
-				vv->ov_fb.fmt.width*fmt->depth/8;
-
+		vv->vflip = c->value;
+		break;
+	default:
 		mutex_unlock(&dev->lock);
-
-		return 0;
+		return -EINVAL;
 	}
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *f = arg;
+	mutex_unlock(&dev->lock);
 
-		switch (f->type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-			if (f->index >= NUM_FORMATS)
-				return -EINVAL;
-			strlcpy((char *)f->description, formats[f->index].name,
-					sizeof(f->description));
-			f->pixelformat = formats[f->index].pixelformat;
-			f->flags = 0;
-			memset(f->reserved, 0, sizeof(f->reserved));
-			break;
-		default:
-			return -EINVAL;
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		saa7146_stop_preview(fh);
+		saa7146_start_preview(fh);
+	}
+	return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *fh,
+		struct v4l2_streamparm *parm)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	parm->parm.capture.readbuffers = 1;
+	v4l2_video_std_frame_period(vv->standard->id,
+				    &parm->parm.capture.timeperframe);
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	f->fmt.pix = ((struct saa7146_fh *)fh)->video_fmt;
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
+{
+	f->fmt.win = ((struct saa7146_fh *)fh)->ov.win;
+	return 0;
+}
+
+static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	f->fmt.vbi = ((struct saa7146_fh *)fh)->vbi_fmt;
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt;
+	enum v4l2_field field;
+	int maxw, maxh;
+	int calc_bpl;
+
+	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+
+	fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw  = vv->standard->h_max_out;
+	maxh  = vv->standard->v_max_out;
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (f->fmt.pix.height > maxh / 2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+	switch (field) {
+	case V4L2_FIELD_ALTERNATE:
+		vv->last_field = V4L2_FIELD_TOP;
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		vv->last_field = V4L2_FIELD_INTERLACED;
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		vv->last_field = V4L2_FIELD_INTERLACED;
+		break;
+	default:
+		DEB_D(("no known field mode '%d'.\n", field));
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	if (f->fmt.pix.width > maxw)
+		f->fmt.pix.width = maxw;
+	if (f->fmt.pix.height > maxh)
+		f->fmt.pix.height = maxh;
+
+	calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
+
+	if (f->fmt.pix.bytesperline < calc_bpl)
+		f->fmt.pix.bytesperline = calc_bpl;
+
+	if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
+		f->fmt.pix.bytesperline = calc_bpl;
+
+	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+	DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
+			f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
+
+	return 0;
+}
+
+
+static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct v4l2_window *win = &f->fmt.win;
+	enum v4l2_field field;
+	int maxw, maxh;
+
+	DEB_EE(("dev:%p\n", dev));
+
+	if (NULL == vv->ov_fb.base) {
+		DEB_D(("no fb base set.\n"));
+		return -EINVAL;
+	}
+	if (NULL == vv->ov_fmt) {
+		DEB_D(("no fb fmt set.\n"));
+		return -EINVAL;
+	}
+	if (win->w.width < 48 || win->w.height < 32) {
+		DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
+		return -EINVAL;
+	}
+	if (win->clipcount > 16) {
+		DEB_D(("clipcount too big.\n"));
+		return -EINVAL;
+	}
+
+	field = win->field;
+	maxw  = vv->standard->h_max_out;
+	maxh  = vv->standard->v_max_out;
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (win->w.height > maxh / 2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_TOP;
 		}
-
-		DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index));
-		return 0;
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_ALTERNATE:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		DEB_D(("no known field mode '%d'.\n", field));
+		return -EINVAL;
 	}
-	case VIDIOC_QUERYCTRL:
-	{
-		const struct v4l2_queryctrl *ctrl;
-		struct v4l2_queryctrl *c = arg;
 
-		if ((c->id <  V4L2_CID_BASE ||
-		     c->id >= V4L2_CID_LASTP1) &&
-		    (c->id <  V4L2_CID_PRIVATE_BASE ||
-		     c->id >= V4L2_CID_PRIVATE_LASTP1))
-			return -EINVAL;
+	win->field = field;
+	if (win->w.width > maxw)
+		win->w.width = maxw;
+	if (win->w.height > maxh)
+		win->w.height = maxh;
 
-		ctrl = ctrl_by_id(c->id);
-		if( NULL == ctrl ) {
-			return -EINVAL;
-/*
-			c->flags = V4L2_CTRL_FLAG_DISABLED;
-			return 0;
-*/
-		}
+	return 0;
+}
 
-		DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id));
-		*c = *ctrl;
-		return 0;
+static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
+{
+	struct saa7146_fh *fh = __fh;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	int err;
+
+	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
+	if (IS_CAPTURE_ACTIVE(fh) != 0) {
+		DEB_EE(("streaming capture is active\n"));
+		return -EBUSY;
 	}
-	case VIDIOC_G_CTRL: {
-		DEB_EE(("VIDIOC_G_CTRL\n"));
-		return get_control(fh,arg);
-	}
-	case VIDIOC_S_CTRL:
-	{
-		DEB_EE(("VIDIOC_S_CTRL\n"));
-		err = set_control(fh,arg);
+	err = vidioc_try_fmt_vid_cap(file, fh, f);
+	if (0 != err)
 		return err;
+	fh->video_fmt = f->fmt.pix;
+	DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
+{
+	struct saa7146_fh *fh = __fh;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	int err;
+
+	DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
+	err = vidioc_try_fmt_vid_overlay(file, fh, f);
+	if (0 != err)
+		return err;
+	mutex_lock(&dev->lock);
+	fh->ov.win    = f->fmt.win;
+	fh->ov.nclips = f->fmt.win.clipcount;
+	if (fh->ov.nclips > 16)
+		fh->ov.nclips = 16;
+	if (copy_from_user(fh->ov.clips, f->fmt.win.clips,
+				sizeof(struct v4l2_clip) * fh->ov.nclips)) {
+		mutex_unlock(&dev->lock);
+		return -EFAULT;
 	}
-	case VIDIOC_G_PARM:
-	{
-		struct v4l2_streamparm *parm = arg;
-		if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
-			return -EINVAL;
-		}
-		memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));
-		parm->parm.capture.readbuffers = 1;
-		// fixme: only for PAL!
-		parm->parm.capture.timeperframe.numerator = 1;
-		parm->parm.capture.timeperframe.denominator = 25;
-		return 0;
+
+	/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
+	fh->ov.fh = fh;
+
+	mutex_unlock(&dev->lock);
+
+	/* check if our current overlay is active */
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		saa7146_stop_preview(fh);
+		saa7146_start_preview(fh);
 	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = arg;
-		DEB_EE(("VIDIOC_G_FMT\n"));
-		return g_fmt(fh,f);
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-		DEB_EE(("VIDIOC_S_FMT\n"));
-		return s_fmt(fh,f);
-	}
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *f = arg;
-		DEB_EE(("VIDIOC_TRY_FMT\n"));
-		return try_fmt(fh,f);
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *id = arg;
-		DEB_EE(("VIDIOC_G_STD\n"));
-		*id = vv->standard->id;
-		return 0;
-	}
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	*norm = vv->standard->id;
+	return 0;
+}
+
 	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
 	   PAL / NTSC / SECAM. if your hardware does not (or does more)
 	   -- override this function in your extension */
+/*
 	case VIDIOC_ENUMSTD:
 	{
 		struct v4l2_standard *e = arg;
@@ -1066,163 +949,246 @@
 		}
 		return -EINVAL;
 	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *id = arg;
-		int found = 0;
-		int i;
+	*/
 
-		DEB_EE(("VIDIOC_S_STD\n"));
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	int found = 0;
+	int err, i;
 
-		if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
-			DEB_D(("cannot change video standard while streaming capture is active\n"));
-			return -EBUSY;
-		}
+	DEB_EE(("VIDIOC_S_STD\n"));
 
-		if ((vv->video_status & STATUS_OVERLAY) != 0) {
-			vv->ov_suspend = vv->video_fh;
-			err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
-			if (0 != err) {
-				DEB_D(("suspending video failed. aborting\n"));
-				return err;
-			}
-		}
-
-		mutex_lock(&dev->lock);
-
-		for(i = 0; i < dev->ext_vv_data->num_stds; i++)
-			if (*id & dev->ext_vv_data->stds[i].id)
-				break;
-		if (i != dev->ext_vv_data->num_stds) {
-			vv->standard = &dev->ext_vv_data->stds[i];
-			if( NULL != dev->ext_vv_data->std_callback )
-				dev->ext_vv_data->std_callback(dev, vv->standard);
-			found = 1;
-		}
-
-		mutex_unlock(&dev->lock);
-
-		if (vv->ov_suspend != NULL) {
-			saa7146_start_preview(vv->ov_suspend);
-			vv->ov_suspend = NULL;
-		}
-
-		if( 0 == found ) {
-			DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
-			return -EINVAL;
-		}
-
-		DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name));
-		return 0;
+	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
+		DEB_D(("cannot change video standard while streaming capture is active\n"));
+		return -EBUSY;
 	}
-	case VIDIOC_OVERLAY:
-	{
-		int on = *(int *)arg;
 
-		DEB_D(("VIDIOC_OVERLAY on:%d\n",on));
-		if (on != 0) {
-			err = saa7146_start_preview(fh);
-		} else {
-			err = saa7146_stop_preview(fh);
-		}
-		return err;
-	}
-	case VIDIOC_REQBUFS: {
-		struct v4l2_requestbuffers *req = arg;
-		DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
-		return videobuf_reqbufs(q,req);
-	}
-	case VIDIOC_QUERYBUF: {
-		struct v4l2_buffer *buf = arg;
-		DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
-		return videobuf_querybuf(q,buf);
-	}
-	case VIDIOC_QBUF: {
-		struct v4l2_buffer *buf = arg;
-		int ret = 0;
-		ret = videobuf_qbuf(q,buf);
-		DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
-		return ret;
-	}
-	case VIDIOC_DQBUF: {
-		struct v4l2_buffer *buf = arg;
-		int ret = 0;
-		ret = videobuf_dqbuf(q,buf,file->f_flags & O_NONBLOCK);
-		DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
-		return ret;
-	}
-	case VIDIOC_STREAMON: {
-		int *type = arg;
-		DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
-
-		err = video_begin(fh);
-		if( 0 != err) {
-			return err;
-		}
-		err = videobuf_streamon(q);
-		return err;
-	}
-	case VIDIOC_STREAMOFF: {
-		int *type = arg;
-
-		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
-
-		/* ugly: we need to copy some checks from video_end(),
-		   because videobuf_streamoff() relies on the capture running.
-		   check and fix this */
-		if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
-			DEB_S(("not capturing.\n"));
-			return 0;
-		}
-
-		if (vv->video_fh != fh) {
-			DEB_S(("capturing, but in another open.\n"));
-			return -EBUSY;
-		}
-
-		err = videobuf_streamoff(q);
+	if ((vv->video_status & STATUS_OVERLAY) != 0) {
+		vv->ov_suspend = vv->video_fh;
+		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (0 != err) {
-			DEB_D(("warning: videobuf_streamoff() failed.\n"));
-			video_end(fh, file);
-		} else {
-			err = video_end(fh, file);
-		}
-		return err;
-	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *mbuf = arg;
-		int i;
-
-		/* fixme: number of capture buffers and sizes for v4l apps */
-		int gbuffers = 2;
-		int gbufsize = 768*576*4;
-
-		DEB_D(("VIDIOCGMBUF \n"));
-
-		q = &fh->video_q;
-		err = videobuf_mmap_setup(q,gbuffers,gbufsize,
-					  V4L2_MEMORY_MMAP);
-		if (err < 0)
+			DEB_D(("suspending video failed. aborting\n"));
 			return err;
+		}
+	}
 
-		gbuffers = err;
-		memset(mbuf,0,sizeof(*mbuf));
-		mbuf->frames = gbuffers;
-		mbuf->size   = gbuffers * gbufsize;
-		for (i = 0; i < gbuffers; i++)
-			mbuf->offsets[i] = i * gbufsize;
-		return 0;
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
+		if (*id & dev->ext_vv_data->stds[i].id)
+			break;
+	if (i != dev->ext_vv_data->num_stds) {
+		vv->standard = &dev->ext_vv_data->stds[i];
+		if (NULL != dev->ext_vv_data->std_callback)
+			dev->ext_vv_data->std_callback(dev, vv->standard);
+		found = 1;
 	}
-#endif
-	default:
-		return v4l_compat_translate_ioctl(file, cmd, arg,
-						  saa7146_video_do_ioctl);
+
+	mutex_unlock(&dev->lock);
+
+	if (vv->ov_suspend != NULL) {
+		saa7146_start_preview(vv->ov_suspend);
+		vv->ov_suspend = NULL;
 	}
+
+	if (!found) {
+		DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
+		return -EINVAL;
+	}
+
+	DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
 	return 0;
 }
 
+static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
+{
+	int err;
+
+	DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
+	if (on)
+		err = saa7146_start_preview(fh);
+	else
+		err = saa7146_stop_preview(fh);
+	return err;
+}
+
+static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
+{
+	struct saa7146_fh *fh = __fh;
+
+	if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return videobuf_reqbufs(&fh->video_q, b);
+	if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return videobuf_reqbufs(&fh->vbi_q, b);
+	return -EINVAL;
+}
+
+static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct saa7146_fh *fh = __fh;
+
+	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return videobuf_querybuf(&fh->video_q, buf);
+	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return videobuf_querybuf(&fh->vbi_q, buf);
+	return -EINVAL;
+}
+
+static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct saa7146_fh *fh = __fh;
+
+	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return videobuf_qbuf(&fh->video_q, buf);
+	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return videobuf_qbuf(&fh->vbi_q, buf);
+	return -EINVAL;
+}
+
+static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct saa7146_fh *fh = __fh;
+
+	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
+	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
+	return -EINVAL;
+}
+
+static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+	struct saa7146_fh *fh = __fh;
+	int err;
+
+	DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
+
+	err = video_begin(fh);
+	if (err)
+		return err;
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return videobuf_streamon(&fh->video_q);
+	if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return videobuf_streamon(&fh->vbi_q);
+	return -EINVAL;
+}
+
+static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+	struct saa7146_fh *fh = __fh;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	int err;
+
+	DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
+
+	/* ugly: we need to copy some checks from video_end(),
+	   because videobuf_streamoff() relies on the capture running.
+	   check and fix this */
+	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
+		DEB_S(("not capturing.\n"));
+		return 0;
+	}
+
+	if (vv->video_fh != fh) {
+		DEB_S(("capturing, but in another open.\n"));
+		return -EBUSY;
+	}
+
+	err = -EINVAL;
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		err = videobuf_streamoff(&fh->video_q);
+	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		err = videobuf_streamoff(&fh->vbi_q);
+	if (0 != err) {
+		DEB_D(("warning: videobuf_streamoff() failed.\n"));
+		video_end(fh, file);
+	} else {
+		err = video_end(fh, file);
+	}
+	return err;
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *__fh,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	struct saa7146_fh *fh = __fh;
+	struct saa7146_dev *dev = fh->dev;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type == V4L2_CHIP_MATCH_HOST && !chip->match.addr) {
+		chip->ident = V4L2_IDENT_SAA7146;
+		return 0;
+	}
+	return v4l2_device_call_until_err(&dev->v4l2_dev, 0,
+			core, g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf)
+{
+	struct saa7146_fh *fh = __fh;
+	struct videobuf_queue *q = &fh->video_q;
+	int err, i;
+
+	/* fixme: number of capture buffers and sizes for v4l apps */
+	int gbuffers = 2;
+	int gbufsize = 768 * 576 * 4;
+
+	DEB_D(("VIDIOCGMBUF \n"));
+
+	q = &fh->video_q;
+	err = videobuf_mmap_setup(q, gbuffers, gbufsize,
+			V4L2_MEMORY_MMAP);
+	if (err < 0)
+		return err;
+
+	gbuffers = err;
+	memset(mbuf, 0, sizeof(*mbuf));
+	mbuf->frames = gbuffers;
+	mbuf->size   = gbuffers * gbufsize;
+	for (i = 0; i < gbuffers; i++)
+		mbuf->offsets[i] = i * gbufsize;
+	return 0;
+}
+#endif
+
+const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
+	.vidioc_querycap             = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
+	.vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
+	.vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
+	.vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
+	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
+	.vidioc_g_chip_ident         = vidioc_g_chip_ident,
+
+	.vidioc_overlay 	     = vidioc_overlay,
+	.vidioc_g_fbuf  	     = vidioc_g_fbuf,
+	.vidioc_s_fbuf  	     = vidioc_s_fbuf,
+	.vidioc_reqbufs              = vidioc_reqbufs,
+	.vidioc_querybuf             = vidioc_querybuf,
+	.vidioc_qbuf                 = vidioc_qbuf,
+	.vidioc_dqbuf                = vidioc_dqbuf,
+	.vidioc_g_std                = vidioc_g_std,
+	.vidioc_s_std                = vidioc_s_std,
+	.vidioc_queryctrl            = vidioc_queryctrl,
+	.vidioc_g_ctrl               = vidioc_g_ctrl,
+	.vidioc_s_ctrl               = vidioc_s_ctrl,
+	.vidioc_streamon             = vidioc_streamon,
+	.vidioc_streamoff            = vidioc_streamoff,
+	.vidioc_g_parm 		     = vidioc_g_parm,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidiocgmbuf                 = vidiocgmbuf,
+#endif
+};
+
 /*********************************************************************************/
 /* buffer handling functions                                                  */
 
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 6f92bea..52c3f65 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -21,16 +21,17 @@
 	tristate
 	default VIDEO_MEDIA && I2C
 	depends on VIDEO_MEDIA && I2C
-	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
 
-menuconfig MEDIA_TUNER_CUSTOMIZE
+menuconfig MEDIA_TUNER_CUSTOMISE
 	bool "Customize analog and hybrid tuner modules to build"
 	depends on MEDIA_TUNER
 	default n
@@ -43,13 +44,13 @@
 
 	  If unsure say N.
 
-if MEDIA_TUNER_CUSTOMIZE
+if MEDIA_TUNER_CUSTOMISE
 
 config MEDIA_TUNER_SIMPLE
 	tristate "Simple tuner support"
 	depends on VIDEO_MEDIA && I2C
 	select MEDIA_TUNER_TDA9887
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for various simple tuners.
 
@@ -58,28 +59,28 @@
 	depends on VIDEO_MEDIA && I2C
 	select MEDIA_TUNER_TDA827X
 	select MEDIA_TUNER_TDA18271
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for Philips TDA8290+8275(a) tuner.
 
 config MEDIA_TUNER_TDA827X
 	tristate "Philips TDA827X silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A DVB-T silicon tuner module. Say Y when you want to support this tuner.
 
 config MEDIA_TUNER_TDA18271
 	tristate "NXP TDA18271 silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A silicon tuner module. Say Y when you want to support this tuner.
 
 config MEDIA_TUNER_TDA9887
 	tristate "TDA 9885/6/7 analog IF demodulator"
 	depends on VIDEO_MEDIA && I2C
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for Philips TDA9885/6/7
 	  analog IF demodulator.
@@ -88,63 +89,63 @@
 	tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
 	depends on VIDEO_MEDIA && I2C
 	depends on EXPERIMENTAL
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for the Philips TEA5761 radio tuner.
 
 config MEDIA_TUNER_TEA5767
 	tristate "TEA 5767 radio tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for the Philips TEA5767 radio tuner.
 
 config MEDIA_TUNER_MT20XX
 	tristate "Microtune 2032 / 2050 tuners"
 	depends on VIDEO_MEDIA && I2C
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for the MT2032 / MT2050 tuner.
 
 config MEDIA_TUNER_MT2060
 	tristate "Microtune MT2060 silicon IF tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon IF tuner MT2060 from Microtune.
 
 config MEDIA_TUNER_MT2266
 	tristate "Microtune MT2266 silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon baseband tuner MT2266 from Microtune.
 
 config MEDIA_TUNER_MT2131
 	tristate "Microtune MT2131 silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon baseband tuner MT2131 from Microtune.
 
 config MEDIA_TUNER_QT1010
 	tristate "Quantek QT1010 silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon tuner QT1010 from Quantek.
 
 config MEDIA_TUNER_XC2028
 	tristate "XCeive xc2028/xc3028 tuners"
 	depends on VIDEO_MEDIA && I2C
-	default m if MEDIA_TUNER_CUSTOMIZE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to include support for the xc2028/xc3028 tuners.
 
 config MEDIA_TUNER_XC5000
 	tristate "Xceive XC5000 silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon tuner XC5000 from Xceive.
 	  This device is only used inside a SiP called togther with a
@@ -153,15 +154,22 @@
 config MEDIA_TUNER_MXL5005S
 	tristate "MaxLinear MSL5005S silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon tuner MXL5005S from MaxLinear.
 
 config MEDIA_TUNER_MXL5007T
 	tristate "MaxLinear MxL5007T silicon tuner"
 	depends on VIDEO_MEDIA && I2C
-	default m if DVB_FE_CUSTOMISE
+	default m if MEDIA_TUNER_CUSTOMISE
 	help
 	  A driver for the silicon tuner MxL5007T from MaxLinear.
 
-endif # MEDIA_TUNER_CUSTOMIZE
+config MEDIA_TUNER_MC44S803
+	tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  Say Y here to support the Freescale MC44S803 based tuners
+
+endif # MEDIA_TUNER_CUSTOMISE
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
index 4dfbe5b..4132b2b 100644
--- a/drivers/media/common/tuners/Makefile
+++ b/drivers/media/common/tuners/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
+obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/common/tuners/mc44s803.c b/drivers/media/common/tuners/mc44s803.c
new file mode 100644
index 0000000..20c4485
--- /dev/null
+++ b/drivers/media/common/tuners/mc44s803.c
@@ -0,0 +1,371 @@
+/*
+ *  Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
+ *
+ *  Copyright (c) 2009 Jochen Friedrich <jochen@scram.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 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/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "mc44s803.h"
+#include "mc44s803_priv.h"
+
+#define mc_printk(level, format, arg...)	\
+	printk(level "mc44s803: " format , ## arg)
+
+/* Writes a single register */
+static int mc44s803_writereg(struct mc44s803_priv *priv, u32 val)
+{
+	u8 buf[3];
+	struct i2c_msg msg = {
+		.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 3
+	};
+
+	buf[0] = (val & 0xff0000) >> 16;
+	buf[1] = (val & 0xff00) >> 8;
+	buf[2] = (val & 0xff);
+
+	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+		mc_printk(KERN_WARNING, "I2C write failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* Reads a single register */
+static int mc44s803_readreg(struct mc44s803_priv *priv, u8 reg, u32 *val)
+{
+	u32 wval;
+	u8 buf[3];
+	int ret;
+	struct i2c_msg msg[] = {
+		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
+		  .buf = buf, .len = 3 },
+	};
+
+	wval = MC44S803_REG_SM(MC44S803_REG_DATAREG, MC44S803_ADDR) |
+	       MC44S803_REG_SM(reg, MC44S803_D);
+
+	ret = mc44s803_writereg(priv, wval);
+	if (ret)
+		return ret;
+
+	if (i2c_transfer(priv->i2c, msg, 1) != 1) {
+		mc_printk(KERN_WARNING, "I2C read failed\n");
+		return -EREMOTEIO;
+	}
+
+	*val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+
+	return 0;
+}
+
+static int mc44s803_release(struct dvb_frontend *fe)
+{
+	struct mc44s803_priv *priv = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(priv);
+
+	return 0;
+}
+
+static int mc44s803_init(struct dvb_frontend *fe)
+{
+	struct mc44s803_priv *priv = fe->tuner_priv;
+	u32 val;
+	int err;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+/* Reset chip */
+	val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_RS);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+/* Power Up and Start Osc */
+
+	val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) |
+	      MC44S803_REG_SM(0xC0, MC44S803_REFOSC) |
+	      MC44S803_REG_SM(1, MC44S803_OSCSEL);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_POWER, MC44S803_ADDR) |
+	      MC44S803_REG_SM(0x200, MC44S803_POWER);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	msleep(10);
+
+	val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) |
+	      MC44S803_REG_SM(0x40, MC44S803_REFOSC) |
+	      MC44S803_REG_SM(1, MC44S803_OSCSEL);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	msleep(20);
+
+/* Setup Mixer */
+
+	val = MC44S803_REG_SM(MC44S803_REG_MIXER, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_TRI_STATE) |
+	      MC44S803_REG_SM(0x7F, MC44S803_MIXER_RES);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+/* Setup Cirquit Adjust */
+
+	val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_G1) |
+	      MC44S803_REG_SM(1, MC44S803_G3) |
+	      MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) |
+	      MC44S803_REG_SM(1, MC44S803_G6) |
+	      MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) |
+	      MC44S803_REG_SM(0x3, MC44S803_LP) |
+	      MC44S803_REG_SM(1, MC44S803_CLRF) |
+	      MC44S803_REG_SM(1, MC44S803_CLIF);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_G1) |
+	      MC44S803_REG_SM(1, MC44S803_G3) |
+	      MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) |
+	      MC44S803_REG_SM(1, MC44S803_G6) |
+	      MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) |
+	      MC44S803_REG_SM(0x3, MC44S803_LP);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+/* Setup Digtune */
+
+	val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
+	      MC44S803_REG_SM(3, MC44S803_XOD);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+/* Setup AGC */
+
+	val = MC44S803_REG_SM(MC44S803_REG_LNAAGC, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_AT1) |
+	      MC44S803_REG_SM(1, MC44S803_AT2) |
+	      MC44S803_REG_SM(1, MC44S803_AGC_AN_DIG) |
+	      MC44S803_REG_SM(1, MC44S803_AGC_READ_EN) |
+	      MC44S803_REG_SM(1, MC44S803_LNA0);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	return 0;
+
+exit:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	mc_printk(KERN_WARNING, "I/O Error\n");
+	return err;
+}
+
+static int mc44s803_set_params(struct dvb_frontend *fe,
+			       struct dvb_frontend_parameters *params)
+{
+	struct mc44s803_priv *priv = fe->tuner_priv;
+	u32 r1, r2, n1, n2, lo1, lo2, freq, val;
+	int err;
+
+	priv->frequency = params->frequency;
+
+	r1 = MC44S803_OSC / 1000000;
+	r2 = MC44S803_OSC /  100000;
+
+	n1 = (params->frequency + MC44S803_IF1 + 500000) / 1000000;
+	freq = MC44S803_OSC / r1 * n1;
+	lo1 = ((60 * n1) + (r1 / 2)) / r1;
+	freq = freq - params->frequency;
+
+	n2 = (freq - MC44S803_IF2 + 50000) / 100000;
+	lo2 = ((60 * n2) + (r2 / 2)) / r2;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	val = MC44S803_REG_SM(MC44S803_REG_REFDIV, MC44S803_ADDR) |
+	      MC44S803_REG_SM(r1-1, MC44S803_R1) |
+	      MC44S803_REG_SM(r2-1, MC44S803_R2) |
+	      MC44S803_REG_SM(1, MC44S803_REFBUF_EN);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_LO1, MC44S803_ADDR) |
+	      MC44S803_REG_SM(n1-2, MC44S803_LO1);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_LO2, MC44S803_ADDR) |
+	      MC44S803_REG_SM(n2-2, MC44S803_LO2);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
+	      MC44S803_REG_SM(1, MC44S803_DA) |
+	      MC44S803_REG_SM(lo1, MC44S803_LO_REF) |
+	      MC44S803_REG_SM(1, MC44S803_AT);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
+	      MC44S803_REG_SM(2, MC44S803_DA) |
+	      MC44S803_REG_SM(lo2, MC44S803_LO_REF) |
+	      MC44S803_REG_SM(1, MC44S803_AT);
+
+	err = mc44s803_writereg(priv, val);
+	if (err)
+		goto exit;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return 0;
+
+exit:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	mc_printk(KERN_WARNING, "I/O Error\n");
+	return err;
+}
+
+static int mc44s803_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct mc44s803_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static const struct dvb_tuner_ops mc44s803_tuner_ops = {
+	.info = {
+		.name           = "Freescale MC44S803",
+		.frequency_min  =   48000000,
+		.frequency_max  = 1000000000,
+		.frequency_step =     100000,
+	},
+
+	.release       = mc44s803_release,
+	.init          = mc44s803_init,
+	.set_params    = mc44s803_set_params,
+	.get_frequency = mc44s803_get_frequency
+};
+
+/* This functions tries to identify a MC44S803 tuner by reading the ID
+   register. This is hasty. */
+struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
+	 struct i2c_adapter *i2c, struct mc44s803_config *cfg)
+{
+	struct mc44s803_priv *priv;
+	u32 reg;
+	u8 id;
+	int ret;
+
+	reg = 0;
+
+	priv = kzalloc(sizeof(struct mc44s803_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->cfg = cfg;
+	priv->i2c = i2c;
+	priv->fe  = fe;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	ret = mc44s803_readreg(priv, MC44S803_REG_ID, &reg);
+	if (ret)
+		goto error;
+
+	id = MC44S803_REG_MS(reg, MC44S803_ID);
+
+	if (id != 0x14) {
+		mc_printk(KERN_ERR, "unsupported ID "
+		       "(%x should be 0x14)\n", id);
+		goto error;
+	}
+
+	mc_printk(KERN_INFO, "successfully identified (ID = %x)\n", id);
+	memcpy(&fe->ops.tuner_ops, &mc44s803_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = priv;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	return fe;
+
+error:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(mc44s803_attach);
+
+MODULE_AUTHOR("Jochen Friedrich");
+MODULE_DESCRIPTION("Freescale MC44S803 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mc44s803.h b/drivers/media/common/tuners/mc44s803.h
new file mode 100644
index 0000000..34f3892
--- /dev/null
+++ b/drivers/media/common/tuners/mc44s803.h
@@ -0,0 +1,46 @@
+/*
+ *  Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
+ *
+ *  Copyright (c) 2009 Jochen Friedrich <jochen@scram.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 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.=
+ */
+
+#ifndef MC44S803_H
+#define MC44S803_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct mc44s803_config {
+	u8 i2c_address;
+	u8 dig_out;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_MC44S803) || \
+    (defined(CONFIG_MEDIA_TUNER_MC44S803_MODULE) && defined(MODULE))
+extern struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
+	 struct i2c_adapter *i2c, struct mc44s803_config *cfg);
+#else
+static inline struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
+	 struct i2c_adapter *i2c, struct mc44s803_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_MEDIA_TUNER_MC44S803 */
+
+#endif
diff --git a/drivers/media/common/tuners/mc44s803_priv.h b/drivers/media/common/tuners/mc44s803_priv.h
new file mode 100644
index 0000000..14a9278
--- /dev/null
+++ b/drivers/media/common/tuners/mc44s803_priv.h
@@ -0,0 +1,208 @@
+/*
+ *  Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
+ *
+ *  Copyright (c) 2009 Jochen Friedrich <jochen@scram.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 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.=
+ */
+
+#ifndef MC44S803_PRIV_H
+#define MC44S803_PRIV_H
+
+/* This driver is based on the information available in the datasheet
+   http://www.freescale.com/files/rf_if/doc/data_sheet/MC44S803.pdf
+
+   SPI or I2C Address : 0xc0-0xc6
+
+   Reg.No | Function
+   -------------------------------------------
+       00 | Power Down
+       01 | Reference Oszillator
+       02 | Reference Dividers
+       03 | Mixer and Reference Buffer
+       04 | Reset/Serial Out
+       05 | LO 1
+       06 | LO 2
+       07 | Circuit Adjust
+       08 | Test
+       09 | Digital Tune
+       0A | LNA AGC
+       0B | Data Register Address
+       0C | Regulator Test
+       0D | VCO Test
+       0E | LNA Gain/Input Power
+       0F | ID Bits
+
+*/
+
+#define MC44S803_OSC 26000000	/* 26 MHz */
+#define MC44S803_IF1 1086000000 /* 1086 MHz */
+#define MC44S803_IF2 36125000	/* 36.125 MHz */
+
+#define MC44S803_REG_POWER	0
+#define MC44S803_REG_REFOSC	1
+#define MC44S803_REG_REFDIV	2
+#define MC44S803_REG_MIXER	3
+#define MC44S803_REG_RESET	4
+#define MC44S803_REG_LO1	5
+#define MC44S803_REG_LO2	6
+#define MC44S803_REG_CIRCADJ	7
+#define MC44S803_REG_TEST	8
+#define MC44S803_REG_DIGTUNE	9
+#define MC44S803_REG_LNAAGC	0x0A
+#define MC44S803_REG_DATAREG	0x0B
+#define MC44S803_REG_REGTEST	0x0C
+#define MC44S803_REG_VCOTEST	0x0D
+#define MC44S803_REG_LNAGAIN	0x0E
+#define MC44S803_REG_ID		0x0F
+
+/* Register definitions */
+#define MC44S803_ADDR		0x0F
+#define MC44S803_ADDR_S		0
+/* REG_POWER */
+#define MC44S803_POWER		0xFFFFF0
+#define MC44S803_POWER_S	4
+/* REG_REFOSC */
+#define MC44S803_REFOSC		0x1FF0
+#define MC44S803_REFOSC_S	4
+#define MC44S803_OSCSEL		0x2000
+#define MC44S803_OSCSEL_S	13
+/* REG_REFDIV */
+#define MC44S803_R2		0x1FF0
+#define MC44S803_R2_S		4
+#define MC44S803_REFBUF_EN	0x2000
+#define MC44S803_REFBUF_EN_S	13
+#define MC44S803_R1		0x7C000
+#define MC44S803_R1_S		14
+/* REG_MIXER */
+#define MC44S803_R3		0x70
+#define MC44S803_R3_S		4
+#define MC44S803_MUX3		0x80
+#define MC44S803_MUX3_S		7
+#define MC44S803_MUX4		0x100
+#define MC44S803_MUX4_S		8
+#define MC44S803_OSC_SCR	0x200
+#define MC44S803_OSC_SCR_S	9
+#define MC44S803_TRI_STATE	0x400
+#define MC44S803_TRI_STATE_S	10
+#define MC44S803_BUF_GAIN	0x800
+#define MC44S803_BUF_GAIN_S	11
+#define MC44S803_BUF_IO		0x1000
+#define MC44S803_BUF_IO_S	12
+#define MC44S803_MIXER_RES	0xFE000
+#define MC44S803_MIXER_RES_S	13
+/* REG_RESET */
+#define MC44S803_RS		0x10
+#define MC44S803_RS_S		4
+#define MC44S803_SO		0x20
+#define MC44S803_SO_S		5
+/* REG_LO1 */
+#define MC44S803_LO1		0xFFF0
+#define MC44S803_LO1_S		4
+/* REG_LO2 */
+#define MC44S803_LO2		0x7FFF0
+#define MC44S803_LO2_S		4
+/* REG_CIRCADJ */
+#define MC44S803_G1		0x20
+#define MC44S803_G1_S		5
+#define MC44S803_G3		0x80
+#define MC44S803_G3_S		7
+#define MC44S803_CIRCADJ_RES	0x300
+#define MC44S803_CIRCADJ_RES_S	8
+#define MC44S803_G6		0x400
+#define MC44S803_G6_S		10
+#define MC44S803_G7		0x800
+#define MC44S803_G7_S		11
+#define MC44S803_S1		0x1000
+#define MC44S803_S1_S		12
+#define MC44S803_LP		0x7E000
+#define MC44S803_LP_S		13
+#define MC44S803_CLRF		0x80000
+#define MC44S803_CLRF_S		19
+#define MC44S803_CLIF		0x100000
+#define MC44S803_CLIF_S		20
+/* REG_TEST */
+/* REG_DIGTUNE */
+#define MC44S803_DA		0xF0
+#define MC44S803_DA_S		4
+#define MC44S803_XOD		0x300
+#define MC44S803_XOD_S		8
+#define MC44S803_RST		0x10000
+#define MC44S803_RST_S		16
+#define MC44S803_LO_REF		0x1FFF00
+#define MC44S803_LO_REF_S	8
+#define MC44S803_AT		0x200000
+#define MC44S803_AT_S		21
+#define MC44S803_MT		0x400000
+#define MC44S803_MT_S		22
+/* REG_LNAAGC */
+#define MC44S803_G		0x3F0
+#define MC44S803_G_S		4
+#define MC44S803_AT1		0x400
+#define MC44S803_AT1_S		10
+#define MC44S803_AT2		0x800
+#define MC44S803_AT2_S		11
+#define MC44S803_HL_GR_EN	0x8000
+#define MC44S803_HL_GR_EN_S	15
+#define MC44S803_AGC_AN_DIG	0x10000
+#define MC44S803_AGC_AN_DIG_S	16
+#define MC44S803_ATTEN_EN	0x20000
+#define MC44S803_ATTEN_EN_S	17
+#define MC44S803_AGC_READ_EN	0x40000
+#define MC44S803_AGC_READ_EN_S	18
+#define MC44S803_LNA0		0x80000
+#define MC44S803_LNA0_S		19
+#define MC44S803_AGC_SEL	0x100000
+#define MC44S803_AGC_SEL_S	20
+#define MC44S803_AT0		0x200000
+#define MC44S803_AT0_S		21
+#define MC44S803_B		0xC00000
+#define MC44S803_B_S		22
+/* REG_DATAREG */
+#define MC44S803_D		0xF0
+#define MC44S803_D_S		4
+/* REG_REGTEST */
+/* REG_VCOTEST */
+/* REG_LNAGAIN */
+#define MC44S803_IF_PWR		0x700
+#define MC44S803_IF_PWR_S	8
+#define MC44S803_RF_PWR		0x3800
+#define MC44S803_RF_PWR_S	11
+#define MC44S803_LNA_GAIN	0xFC000
+#define MC44S803_LNA_GAIN_S	14
+/* REG_ID */
+#define MC44S803_ID		0x3E00
+#define MC44S803_ID_S		9
+
+/* Some macros to read/write fields */
+
+/* First shift, then mask */
+#define MC44S803_REG_SM(_val, _reg)					\
+	(((_val) << _reg##_S) & (_reg))
+
+/* First mask, then shift */
+#define MC44S803_REG_MS(_val, _reg)					\
+	(((_val) & (_reg)) >> _reg##_S)
+
+struct mc44s803_priv {
+	struct mc44s803_config *cfg;
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+
+	u32 frequency;
+};
+
+#endif
diff --git a/drivers/media/common/tuners/mt2060.c b/drivers/media/common/tuners/mt2060.c
index 12206d7..c7abe3d 100644
--- a/drivers/media/common/tuners/mt2060.c
+++ b/drivers/media/common/tuners/mt2060.c
@@ -278,7 +278,7 @@
 	while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
 		msleep(20);
 
-	if (i < 10) {
+	if (i <= 10) {
 		mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
 		dprintk("calibration was successful: %d", (int)priv->fmfreq);
 	} else
diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c
index 35b763a..44608ad 100644
--- a/drivers/media/common/tuners/mt20xx.c
+++ b/drivers/media/common/tuners/mt20xx.c
@@ -6,7 +6,7 @@
  */
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include "tuner-i2c.h"
 #include "mt20xx.h"
 
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 31522d2..0803dab 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -4003,12 +4003,11 @@
 	/* Change tuner for new modulation type if reqd */
 	if (req_mode != state->current_mode) {
 		switch (req_mode) {
-		case VSB_8:
-		case QAM_64:
-		case QAM_256:
-		case QAM_AUTO:
+		case MXL_ATSC:
+		case MXL_QAM:
 			req_bw  = MXL5005S_BANDWIDTH_6MHZ;
 			break;
+		case MXL_DVBT:
 		default:
 			/* Assume DVB-T */
 			switch (params->u.ofdm.bandwidth) {
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index 3ec2894..2d02698 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -1,7 +1,7 @@
 /*
  *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
  *
- *  Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *  Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.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
@@ -66,22 +66,17 @@
 #define MHz 1000000
 
 enum mxl5007t_mode {
-	MxL_MODE_OTA_DVBT_ATSC        =    0,
-	MxL_MODE_OTA_NTSC_PAL_GH      =    1,
-	MxL_MODE_OTA_PAL_IB           =    2,
-	MxL_MODE_OTA_PAL_D_SECAM_KL   =    3,
-	MxL_MODE_OTA_ISDBT            =    4,
-	MxL_MODE_CABLE_DIGITAL        = 0x10,
-	MxL_MODE_CABLE_NTSC_PAL_GH    = 0x11,
-	MxL_MODE_CABLE_PAL_IB         = 0x12,
-	MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,
-	MxL_MODE_CABLE_SCTE40         = 0x14,
+	MxL_MODE_ISDBT     =    0,
+	MxL_MODE_DVBT      =    1,
+	MxL_MODE_ATSC      =    2,
+	MxL_MODE_CABLE     = 0x10,
 };
 
 enum mxl5007t_chip_version {
 	MxL_UNKNOWN_ID     = 0x00,
 	MxL_5007_V1_F1     = 0x11,
 	MxL_5007_V1_F2     = 0x12,
+	MxL_5007_V4        = 0x14,
 	MxL_5007_V2_100_F1 = 0x21,
 	MxL_5007_V2_100_F2 = 0x22,
 	MxL_5007_V2_200_F1 = 0x23,
@@ -96,67 +91,61 @@
 /* ------------------------------------------------------------------------- */
 
 static struct reg_pair_t init_tab[] = {
-	{ 0x0b, 0x44 }, /* XTAL */
-	{ 0x0c, 0x60 }, /* IF */
-	{ 0x10, 0x00 }, /* MISC */
-	{ 0x12, 0xca }, /* IDAC */
-	{ 0x16, 0x90 }, /* MODE */
-	{ 0x32, 0x38 }, /* MODE Analog/Digital */
-	{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
-	{ 0x2c, 0x34 }, /* OVERRIDE */
-	{ 0x4d, 0x40 }, /* OVERRIDE */
-	{ 0x7f, 0x02 }, /* OVERRIDE */
-	{ 0x9a, 0x52 }, /* OVERRIDE */
-	{ 0x48, 0x5a }, /* OVERRIDE */
-	{ 0x76, 0x1a }, /* OVERRIDE */
-	{ 0x6a, 0x48 }, /* OVERRIDE */
-	{ 0x64, 0x28 }, /* OVERRIDE */
-	{ 0x66, 0xe6 }, /* OVERRIDE */
-	{ 0x35, 0x0e }, /* OVERRIDE */
-	{ 0x7e, 0x01 }, /* OVERRIDE */
-	{ 0x83, 0x00 }, /* OVERRIDE */
-	{ 0x04, 0x0b }, /* OVERRIDE */
-	{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+	{ 0x02, 0x06 },
+	{ 0x03, 0x48 },
+	{ 0x05, 0x04 },
+	{ 0x06, 0x10 },
+	{ 0x2e, 0x15 }, /* OVERRIDE */
+	{ 0x30, 0x10 }, /* OVERRIDE */
+	{ 0x45, 0x58 }, /* OVERRIDE */
+	{ 0x48, 0x19 }, /* OVERRIDE */
+	{ 0x52, 0x03 }, /* OVERRIDE */
+	{ 0x53, 0x44 }, /* OVERRIDE */
+	{ 0x6a, 0x4b }, /* OVERRIDE */
+	{ 0x76, 0x00 }, /* OVERRIDE */
+	{ 0x78, 0x18 }, /* OVERRIDE */
+	{ 0x7a, 0x17 }, /* OVERRIDE */
+	{ 0x85, 0x06 }, /* OVERRIDE */
+	{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
 	{ 0, 0 }
 };
 
 static struct reg_pair_t init_tab_cable[] = {
-	{ 0x0b, 0x44 }, /* XTAL */
-	{ 0x0c, 0x60 }, /* IF */
-	{ 0x10, 0x00 }, /* MISC */
-	{ 0x12, 0xca }, /* IDAC */
-	{ 0x16, 0x90 }, /* MODE */
-	{ 0x32, 0x38 }, /* MODE A/D */
-	{ 0x71, 0x3f }, /* TOP1 */
-	{ 0x72, 0x3f }, /* TOP2 */
-	{ 0x74, 0x3f }, /* TOP3 */
-	{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
-	{ 0x2c, 0x34 }, /* OVERRIDE */
-	{ 0x4d, 0x40 }, /* OVERRIDE */
-	{ 0x7f, 0x02 }, /* OVERRIDE */
-	{ 0x9a, 0x52 }, /* OVERRIDE */
-	{ 0x48, 0x5a }, /* OVERRIDE */
-	{ 0x76, 0x1a }, /* OVERRIDE */
-	{ 0x6a, 0x48 }, /* OVERRIDE */
-	{ 0x64, 0x28 }, /* OVERRIDE */
-	{ 0x66, 0xe6 }, /* OVERRIDE */
-	{ 0x35, 0x0e }, /* OVERRIDE */
-	{ 0x7e, 0x01 }, /* OVERRIDE */
-	{ 0x04, 0x0b }, /* OVERRIDE */
-	{ 0x68, 0xb4 }, /* OVERRIDE */
-	{ 0x36, 0x00 }, /* OVERRIDE */
-	{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+	{ 0x02, 0x06 },
+	{ 0x03, 0x48 },
+	{ 0x05, 0x04 },
+	{ 0x06, 0x10 },
+	{ 0x09, 0x3f },
+	{ 0x0a, 0x3f },
+	{ 0x0b, 0x3f },
+	{ 0x2e, 0x15 }, /* OVERRIDE */
+	{ 0x30, 0x10 }, /* OVERRIDE */
+	{ 0x45, 0x58 }, /* OVERRIDE */
+	{ 0x48, 0x19 }, /* OVERRIDE */
+	{ 0x52, 0x03 }, /* OVERRIDE */
+	{ 0x53, 0x44 }, /* OVERRIDE */
+	{ 0x6a, 0x4b }, /* OVERRIDE */
+	{ 0x76, 0x00 }, /* OVERRIDE */
+	{ 0x78, 0x18 }, /* OVERRIDE */
+	{ 0x7a, 0x17 }, /* OVERRIDE */
+	{ 0x85, 0x06 }, /* OVERRIDE */
+	{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
 	{ 0, 0 }
 };
 
 /* ------------------------------------------------------------------------- */
 
 static struct reg_pair_t reg_pair_rftune[] = {
-	{ 0x11, 0x00 }, /* abort tune */
-	{ 0x13, 0x15 },
-	{ 0x14, 0x40 },
-	{ 0x15, 0x0e },
-	{ 0x11, 0x02 }, /* start tune */
+	{ 0x0f, 0x00 }, /* abort tune */
+	{ 0x0c, 0x15 },
+	{ 0x0d, 0x40 },
+	{ 0x0e, 0x0e },
+	{ 0x1f, 0x87 }, /* OVERRIDE */
+	{ 0x20, 0x1f }, /* OVERRIDE */
+	{ 0x21, 0x87 }, /* OVERRIDE */
+	{ 0x22, 0x1f }, /* OVERRIDE */
+	{ 0x80, 0x01 }, /* freq dependent */
+	{ 0x0f, 0x01 }, /* start tune */
 	{ 0, 0 }
 };
 
@@ -227,63 +216,20 @@
 				   s32 if_diff_out_level)
 {
 	switch (mode) {
-	case MxL_MODE_OTA_DVBT_ATSC:
-		set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
-		set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);
+	case MxL_MODE_ATSC:
+		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x12);
 		break;
-	case MxL_MODE_OTA_ISDBT:
-		set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
-		set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);
+	case MxL_MODE_DVBT:
+		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x11);
 		break;
-	case MxL_MODE_OTA_NTSC_PAL_GH:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+	case MxL_MODE_ISDBT:
+		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x10);
 		break;
-	case MxL_MODE_OTA_PAL_IB:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
-		break;
-	case MxL_MODE_OTA_PAL_D_SECAM_KL:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
-		break;
-	case MxL_MODE_CABLE_DIGITAL:
-		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
-		set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+	case MxL_MODE_CABLE:
+		set_reg_bits(state->tab_init_cable, 0x09, 0xff, 0xc1);
+		set_reg_bits(state->tab_init_cable, 0x0a, 0xff,
 			     8 - if_diff_out_level);
-		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
-		break;
-	case MxL_MODE_CABLE_NTSC_PAL_GH:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
-		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
-		set_reg_bits(state->tab_init_cable, 0x72, 0xff,
-			     8 - if_diff_out_level);
-		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
-		break;
-	case MxL_MODE_CABLE_PAL_IB:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
-		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
-		set_reg_bits(state->tab_init_cable, 0x72, 0xff,
-			     8 - if_diff_out_level);
-		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
-		break;
-	case MxL_MODE_CABLE_PAL_D_SECAM_KL:
-		set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
-		set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
-		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
-		set_reg_bits(state->tab_init_cable, 0x72, 0xff,
-			     8 - if_diff_out_level);
-		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
-		break;
-	case MxL_MODE_CABLE_SCTE40:
-		set_reg_bits(state->tab_init_cable, 0x36, 0xff, 0x08);
-		set_reg_bits(state->tab_init_cable, 0x68, 0xff, 0xbc);
-		set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
-		set_reg_bits(state->tab_init_cable, 0x72, 0xff,
-			     8 - if_diff_out_level);
-		set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+		set_reg_bits(state->tab_init_cable, 0x0b, 0xff, 0x17);
 		break;
 	default:
 		mxl_fail(-EINVAL);
@@ -302,43 +248,43 @@
 		val = 0x00;
 		break;
 	case MxL_IF_4_5_MHZ:
-		val = 0x20;
+		val = 0x02;
 		break;
 	case MxL_IF_4_57_MHZ:
-		val = 0x30;
+		val = 0x03;
 		break;
 	case MxL_IF_5_MHZ:
-		val = 0x40;
+		val = 0x04;
 		break;
 	case MxL_IF_5_38_MHZ:
-		val = 0x50;
+		val = 0x05;
 		break;
 	case MxL_IF_6_MHZ:
-		val = 0x60;
+		val = 0x06;
 		break;
 	case MxL_IF_6_28_MHZ:
-		val = 0x70;
+		val = 0x07;
 		break;
 	case MxL_IF_9_1915_MHZ:
-		val = 0x80;
+		val = 0x08;
 		break;
 	case MxL_IF_35_25_MHZ:
-		val = 0x90;
+		val = 0x09;
 		break;
 	case MxL_IF_36_15_MHZ:
-		val = 0xa0;
+		val = 0x0a;
 		break;
 	case MxL_IF_44_MHZ:
-		val = 0xb0;
+		val = 0x0b;
 		break;
 	default:
 		mxl_fail(-EINVAL);
 		return;
 	}
-	set_reg_bits(state->tab_init, 0x0c, 0xf0, val);
+	set_reg_bits(state->tab_init, 0x02, 0x0f, val);
 
 	/* set inverted IF or normal IF */
-	set_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00);
+	set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
 
 	return;
 }
@@ -346,56 +292,68 @@
 static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
 					enum mxl5007t_xtal_freq xtal_freq)
 {
-	u8 val;
-
 	switch (xtal_freq) {
 	case MxL_XTAL_16_MHZ:
-		val = 0x00; /* select xtal freq & Ref Freq */
+		/* select xtal freq & ref freq */
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x00);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x00);
 		break;
 	case MxL_XTAL_20_MHZ:
-		val = 0x11;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x10);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x01);
 		break;
 	case MxL_XTAL_20_25_MHZ:
-		val = 0x22;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x20);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x02);
 		break;
 	case MxL_XTAL_20_48_MHZ:
-		val = 0x33;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x30);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x03);
 		break;
 	case MxL_XTAL_24_MHZ:
-		val = 0x44;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x40);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x04);
 		break;
 	case MxL_XTAL_25_MHZ:
-		val = 0x55;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x50);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x05);
 		break;
 	case MxL_XTAL_25_14_MHZ:
-		val = 0x66;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x60);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x06);
 		break;
 	case MxL_XTAL_27_MHZ:
-		val = 0x77;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x70);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x07);
 		break;
 	case MxL_XTAL_28_8_MHZ:
-		val = 0x88;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x80);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x08);
 		break;
 	case MxL_XTAL_32_MHZ:
-		val = 0x99;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x90);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x09);
 		break;
 	case MxL_XTAL_40_MHZ:
-		val = 0xaa;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xa0);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0a);
 		break;
 	case MxL_XTAL_44_MHZ:
-		val = 0xbb;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xb0);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0b);
 		break;
 	case MxL_XTAL_48_MHZ:
-		val = 0xcc;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xc0);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0c);
 		break;
 	case MxL_XTAL_49_3811_MHZ:
-		val = 0xdd;
+		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xd0);
+		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0d);
 		break;
 	default:
 		mxl_fail(-EINVAL);
 		return;
 	}
-	set_reg_bits(state->tab_init, 0x0b, 0xff, val);
 
 	return;
 }
@@ -412,16 +370,11 @@
 	mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
 	mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
 
-	set_reg_bits(state->tab_init, 0x10, 0x40, cfg->loop_thru_enable << 6);
+	set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable);
+	set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
+	set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
 
-	set_reg_bits(state->tab_init, 0xd8, 0x08, cfg->clk_out_enable << 3);
-
-	set_reg_bits(state->tab_init, 0x10, 0x07, cfg->clk_out_amp);
-
-	/* set IDAC to automatic mode control by AGC */
-	set_reg_bits(state->tab_init, 0x12, 0x80, 0x00);
-
-	if (mode >= MxL_MODE_CABLE_DIGITAL) {
+	if (mode >= MxL_MODE_CABLE) {
 		copy_reg_bits(state->tab_init, state->tab_init_cable);
 		return state->tab_init_cable;
 	} else
@@ -447,7 +400,7 @@
 			     * and DIG_MODEINDEX_CSF */
 		break;
 	case MxL_BW_7MHz:
-		val = 0x21;
+		val = 0x2a;
 		break;
 	case MxL_BW_8MHz:
 		val = 0x3f;
@@ -456,7 +409,7 @@
 		mxl_fail(-EINVAL);
 		return;
 	}
-	set_reg_bits(state->tab_rftune, 0x13, 0x3f, val);
+	set_reg_bits(state->tab_rftune, 0x0c, 0x3f, val);
 
 	return;
 }
@@ -493,8 +446,11 @@
 	if (temp > 7812)
 		dig_rf_freq++;
 
-	set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq);
-	set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8));
+	set_reg_bits(state->tab_rftune, 0x0d, 0xff, (u8) dig_rf_freq);
+	set_reg_bits(state->tab_rftune, 0x0e, 0xff, (u8) (dig_rf_freq >> 8));
+
+	if (rf_freq >= 333000000)
+		set_reg_bits(state->tab_rftune, 0x80, 0x40, 0x40);
 
 	return state->tab_rftune;
 }
@@ -551,9 +507,10 @@
 static int mxl5007t_soft_reset(struct mxl5007t_state *state)
 {
 	u8 d = 0xff;
-	struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
-			       .buf = &d, .len = 1 };
-
+	struct i2c_msg msg = {
+		.addr = state->i2c_props.addr, .flags = 0,
+		.buf = &d, .len = 1
+	};
 	int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
 
 	if (ret != 1) {
@@ -580,9 +537,6 @@
 	if (mxl_fail(ret))
 		goto fail;
 	mdelay(1);
-
-	ret = mxl5007t_write_reg(state, 0x2c, 0x35);
-	mxl_fail(ret);
 fail:
 	return ret;
 }
@@ -615,7 +569,7 @@
 	*rf_locked = 0;
 	*ref_locked = 0;
 
-	ret = mxl5007t_read_reg(state, 0xcf, &d);
+	ret = mxl5007t_read_reg(state, 0xd8, &d);
 	if (mxl_fail(ret))
 		goto fail;
 
@@ -628,37 +582,14 @@
 	return ret;
 }
 
-static int mxl5007t_check_rf_input_power(struct mxl5007t_state *state,
-					 s32 *rf_input_level)
-{
-	u8 d1, d2;
-	int ret;
-
-	ret = mxl5007t_read_reg(state, 0xb7, &d1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl5007t_read_reg(state, 0xbf, &d2);
-	if (mxl_fail(ret))
-		goto fail;
-
-	d2 = d2 >> 4;
-	if (d2 > 7)
-		d2 += 0xf0;
-
-	*rf_input_level = (s32)(d1 + d2 - 113);
-fail:
-	return ret;
-}
-
 /* ------------------------------------------------------------------------- */
 
 static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
 {
 	struct mxl5007t_state *state = fe->tuner_priv;
-	int rf_locked, ref_locked;
-	s32 rf_input_level = 0;
-	int ret;
+	int rf_locked, ref_locked, ret;
+
+	*status = 0;
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
@@ -669,10 +600,8 @@
 	mxl_debug("%s%s", rf_locked ? "rf locked " : "",
 		  ref_locked ? "ref locked" : "");
 
-	ret = mxl5007t_check_rf_input_power(state, &rf_input_level);
-	if (mxl_fail(ret))
-		goto fail;
-	mxl_debug("rf input power: %d", rf_input_level);
+	if ((rf_locked) || (ref_locked))
+		*status |= TUNER_STATUS_LOCKED;
 fail:
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
@@ -695,11 +624,11 @@
 		switch (params->u.vsb.modulation) {
 		case VSB_8:
 		case VSB_16:
-			mode = MxL_MODE_OTA_DVBT_ATSC;
+			mode = MxL_MODE_ATSC;
 			break;
 		case QAM_64:
 		case QAM_256:
-			mode = MxL_MODE_CABLE_DIGITAL;
+			mode = MxL_MODE_CABLE;
 			break;
 		default:
 			mxl_err("modulation not set!");
@@ -721,7 +650,7 @@
 			mxl_err("bandwidth not set!");
 			return -EINVAL;
 		}
-		mode = MxL_MODE_OTA_DVBT_ATSC;
+		mode = MxL_MODE_DVBT;
 	} else {
 		mxl_err("modulation type not supported!");
 		return -EINVAL;
@@ -752,96 +681,20 @@
 	return ret;
 }
 
-static int mxl5007t_set_analog_params(struct dvb_frontend *fe,
-				      struct analog_parameters *params)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-	enum mxl5007t_bw_mhz bw = 0; /* FIXME */
-	enum mxl5007t_mode cbl_mode;
-	enum mxl5007t_mode ota_mode;
-	char *mode_name;
-	int ret;
-	u32 freq = params->frequency * 62500;
-
-#define cable 1
-	if (params->std & V4L2_STD_MN) {
-		cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
-		ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
-		mode_name = "MN";
-	} else if (params->std & V4L2_STD_B) {
-		cbl_mode = MxL_MODE_CABLE_PAL_IB;
-		ota_mode = MxL_MODE_OTA_PAL_IB;
-		mode_name = "B";
-	} else if (params->std & V4L2_STD_GH) {
-		cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
-		ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
-		mode_name = "GH";
-	} else if (params->std & V4L2_STD_PAL_I) {
-		cbl_mode = MxL_MODE_CABLE_PAL_IB;
-		ota_mode = MxL_MODE_OTA_PAL_IB;
-		mode_name = "I";
-	} else if (params->std & V4L2_STD_DK) {
-		cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
-		ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
-		mode_name = "DK";
-	} else if (params->std & V4L2_STD_SECAM_L) {
-		cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
-		ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
-		mode_name = "L";
-	} else if (params->std & V4L2_STD_SECAM_LC) {
-		cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
-		ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
-		mode_name = "L'";
-	} else {
-		mode_name = "xx";
-		/* FIXME */
-		cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
-		ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
-	}
-	mxl_debug("setting mxl5007 to system %s", mode_name);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	mutex_lock(&state->lock);
-
-	ret = mxl5007t_tuner_init(state, cable ? cbl_mode : ota_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl5007t_tuner_rf_tune(state, freq, bw);
-	if (mxl_fail(ret))
-		goto fail;
-
-	state->frequency = freq;
-	state->bandwidth = 0;
-fail:
-	mutex_unlock(&state->lock);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
 /* ------------------------------------------------------------------------- */
 
 static int mxl5007t_init(struct dvb_frontend *fe)
 {
 	struct mxl5007t_state *state = fe->tuner_priv;
 	int ret;
-	u8 d;
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 
-	ret = mxl5007t_read_reg(state, 0x05, &d);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl5007t_write_reg(state, 0x05, d | 0x01);
+	/* wake from standby */
+	ret = mxl5007t_write_reg(state, 0x01, 0x01);
 	mxl_fail(ret);
-fail:
+
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
@@ -852,18 +705,16 @@
 {
 	struct mxl5007t_state *state = fe->tuner_priv;
 	int ret;
-	u8 d;
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 
-	ret = mxl5007t_read_reg(state, 0x05, &d);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl5007t_write_reg(state, 0x05, d & ~0x01);
+	/* enter standby mode */
+	ret = mxl5007t_write_reg(state, 0x01, 0x00);
 	mxl_fail(ret);
-fail:
+	ret = mxl5007t_write_reg(state, 0x0f, 0x00);
+	mxl_fail(ret);
+
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 0);
 
@@ -911,7 +762,6 @@
 	.init              = mxl5007t_init,
 	.sleep             = mxl5007t_sleep,
 	.set_params        = mxl5007t_set_params,
-	.set_analog_params = mxl5007t_set_analog_params,
 	.get_status        = mxl5007t_get_status,
 	.get_frequency     = mxl5007t_get_frequency,
 	.get_bandwidth     = mxl5007t_get_bandwidth,
@@ -924,7 +774,7 @@
 	int ret;
 	u8 id;
 
-	ret = mxl5007t_read_reg(state, 0xd3, &id);
+	ret = mxl5007t_read_reg(state, 0xd9, &id);
 	if (mxl_fail(ret))
 		goto fail;
 
@@ -947,8 +797,12 @@
 	case MxL_5007_V2_200_F2:
 		name = "MxL5007.v2.200.f2";
 		break;
+	case MxL_5007_V4:
+		name = "MxL5007T.v4";
+		break;
 	default:
 		name = "MxL5007T";
+		printk(KERN_WARNING "%s: unknown rev (%02x)\n", __func__, id);
 		id = MxL_UNKNOWN_ID;
 	}
 	state->chip_id = id;
@@ -975,7 +829,7 @@
 	mutex_lock(&mxl5007t_list_mutex);
 	instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
 					      hybrid_tuner_instance_list,
-					      i2c, addr, "mxl5007");
+					      i2c, addr, "mxl5007t");
 	switch (instance) {
 	case 0:
 		goto fail;
@@ -1018,7 +872,7 @@
 MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1");
+MODULE_VERSION("0.2");
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
index 6fb5b45..fc76c30 100644
--- a/drivers/media/common/tuners/tda18271-common.c
+++ b/drivers/media/common/tuners/tda18271-common.c
@@ -490,9 +490,9 @@
 		tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
 
 	regs[R_EP3]  &= ~0xe0; /* clear sm, sm_lt, sm_xt */
-	regs[R_EP3]  |= sm    ? (1 << 7) : 0 |
-			sm_lt ? (1 << 6) : 0 |
-			sm_xt ? (1 << 5) : 0;
+	regs[R_EP3]  |= (sm    ? (1 << 7) : 0) |
+			(sm_lt ? (1 << 6) : 0) |
+			(sm_xt ? (1 << 5) : 0);
 
 	return tda18271_write_regs(fe, R_EP3, 1);
 }
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 1b48b5d..b109356 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -818,6 +818,38 @@
 	return ret;
 }
 
+/* ------------------------------------------------------------------ */
+
+static int tda18271_agc(struct dvb_frontend *fe)
+{
+	struct tda18271_priv *priv = fe->tuner_priv;
+	int ret = 0;
+
+	switch (priv->config) {
+	case 0:
+		/* no LNA */
+		tda_dbg("no agc configuration provided\n");
+		break;
+	case 3:
+		/* switch with GPIO of saa713x */
+		tda_dbg("invoking callback\n");
+		if (fe->callback)
+			ret = fe->callback(priv->i2c_props.adap->algo_data,
+					   DVB_FRONTEND_COMPONENT_TUNER,
+					   TDA18271_CALLBACK_CMD_AGC_ENABLE,
+					   priv->mode);
+		break;
+	case 1:
+	case 2:
+	default:
+		/* n/a - currently not supported */
+		tda_err("unsupported configuration: %d\n", priv->config);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
 static int tda18271_tune(struct dvb_frontend *fe,
 			 struct tda18271_std_map_item *map, u32 freq, u32 bw)
 {
@@ -827,6 +859,10 @@
 	tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
 		freq, map->if_freq, bw, map->agc_mode, map->std);
 
+	ret = tda18271_agc(fe);
+	if (tda_fail(ret))
+		tda_warn("failed to configure agc\n");
+
 	ret = tda18271_init(fe);
 	if (tda_fail(ret))
 		goto fail;
@@ -1159,6 +1195,7 @@
 		/* new tuner instance */
 		priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
 		priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
+		priv->config = (cfg) ? cfg->config : 0;
 		priv->cal_initialized = false;
 		mutex_init(&priv->lock);
 
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
index 81a7393..74beb28 100644
--- a/drivers/media/common/tuners/tda18271-priv.h
+++ b/drivers/media/common/tuners/tda18271-priv.h
@@ -91,11 +91,6 @@
 	TDA18271_CAL_PLL,
 };
 
-enum tda18271_mode {
-	TDA18271_ANALOG,
-	TDA18271_DIGITAL,
-};
-
 struct tda18271_map_layout;
 
 enum tda18271_ver {
@@ -114,6 +109,7 @@
 	enum tda18271_i2c_gate gate;
 	enum tda18271_ver id;
 
+	unsigned int config; /* interface to saa713x / tda829x */
 	unsigned int tm_rfcal;
 	unsigned int cal_initialized:1;
 	unsigned int small_i2c:1;
diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h
index 7db9831..53a9892 100644
--- a/drivers/media/common/tuners/tda18271.h
+++ b/drivers/media/common/tuners/tda18271.h
@@ -79,6 +79,16 @@
 
 	/* some i2c providers cant write all 39 registers at once */
 	unsigned int small_i2c:1;
+
+	/* interface to saa713x / tda829x */
+	unsigned int config;
+};
+
+#define TDA18271_CALLBACK_CMD_AGC_ENABLE 0
+
+enum tda18271_mode {
+	TDA18271_ANALOG = 0,
+	TDA18271_DIGITAL,
 };
 
 #if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE))
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index f4d931f..36a7bc7 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -132,11 +132,31 @@
 	{ .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
 };
 
+static int tuner_transfer(struct dvb_frontend *fe,
+			  struct i2c_msg *msg,
+			  const int size)
+{
+	int rc;
+	struct tda827x_priv *priv = fe->tuner_priv;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	rc = i2c_transfer(priv->i2c_adap, msg, size);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (rc >= 0 && rc != size)
+		return -EIO;
+
+	return rc;
+}
+
 static int tda827xo_set_params(struct dvb_frontend *fe,
 			       struct dvb_frontend_parameters *params)
 {
 	struct tda827x_priv *priv = fe->tuner_priv;
 	u8 buf[14];
+	int rc;
 
 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
 			       .buf = buf, .len = sizeof(buf) };
@@ -183,27 +203,29 @@
 	buf[13] = 0x40;
 
 	msg.len = 14;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
-		printk("%s: could not write to tuner at addr: 0x%02x\n",
-		       __func__, priv->i2c_addr << 1);
-		return -EIO;
-	}
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
+
 	msleep(500);
 	/* correct CP value */
 	buf[0] = 0x30;
 	buf[1] = 0x50 + tda827x_table[i].cp;
 	msg.len = 2;
 
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	priv->frequency = params->frequency;
 	priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
 
 	return 0;
+
+err:
+	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
+	       __func__, priv->i2c_addr << 1);
+	return rc;
 }
 
 static int tda827xo_sleep(struct dvb_frontend *fe)
@@ -214,9 +236,7 @@
 			       .buf = buf, .len = sizeof(buf) };
 
 	dprintk("%s:\n", __func__);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	if (priv->cfg && priv->cfg->sleep)
 		priv->cfg->sleep(fe);
@@ -266,44 +286,44 @@
 
 	msg.buf = tuner_reg;
 	msg.len = 8;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msg.buf = reg2;
 	msg.len = 2;
 	reg2[0] = 0x80;
 	reg2[1] = 0;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	reg2[0] = 0x60;
 	reg2[1] = 0xbf;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	reg2[0] = 0x30;
 	reg2[1] = tuner_reg[4] + 0x80;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msleep(1);
 	reg2[0] = 0x30;
 	reg2[1] = tuner_reg[4] + 4;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msleep(1);
 	reg2[0] = 0x30;
 	reg2[1] = tuner_reg[4];
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msleep(550);
 	reg2[0] = 0x30;
 	reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	reg2[0] = 0x60;
 	reg2[1] = 0x3f;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	reg2[0] = 0x80;
 	reg2[1] = 0x08;   /* Vsync en */
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	priv->frequency = params->frequency;
 
@@ -317,7 +337,7 @@
 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
 			       .buf = data, .len = 2};
 
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 }
 
 /* ------------------------------------------------------------------ */
@@ -331,7 +351,7 @@
 	u8  gc3;
 };
 
-static const struct tda827xa_data tda827xa_dvbt[] = {
+static struct tda827xa_data tda827xa_dvbt[] = {
 	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
 	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
 	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
@@ -361,6 +381,36 @@
 	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
 };
 
+static struct tda827xa_data tda827xa_dvbc[] = {
+	{ .lomax =  50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
+	{ .lomax =  58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
+	{ .lomax =  69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
+	{ .lomax =  83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
+	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
+	{ .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
+	{ .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
+	{ .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
+	{ .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
+	{ .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
+	{ .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
+	{ .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
+	{ .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
+	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
+	{ .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
+	{ .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
+	{ .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
+	{ .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
+	{ .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
+	{ .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
+	{ .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
+	{ .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
+	{ .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
+	{ .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
+	{ .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
+	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
+	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
+};
+
 static struct tda827xa_data tda827xa_analog[] = {
 	{ .lomax =  56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
 	{ .lomax =  67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
@@ -398,13 +448,8 @@
 			       .buf = buf, .len = sizeof(buf) };
 
 	dprintk("%s:\n", __func__);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
 
-	i2c_transfer(priv->i2c_adap, &msg, 1);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
+	tuner_transfer(fe, &msg, 1);
 
 	if (priv->cfg && priv->cfg->sleep)
 		priv->cfg->sleep(fe);
@@ -455,7 +500,7 @@
 		buf[1] = high ? 0 : 1;
 		if (priv->cfg->config == 2)
 			buf[1] = high ? 1 : 0;
-		i2c_transfer(priv->i2c_adap, &msg, 1);
+		tuner_transfer(fe, &msg, 1);
 		break;
 	case 3: /* switch with GPIO of saa713x */
 		if (fe->callback)
@@ -469,12 +514,13 @@
 			       struct dvb_frontend_parameters *params)
 {
 	struct tda827x_priv *priv = fe->tuner_priv;
+	struct tda827xa_data *frequency_map = tda827xa_dvbt;
 	u8 buf[11];
 
 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
 			       .buf = buf, .len = sizeof(buf) };
 
-	int i, tuner_freq, if_freq;
+	int i, tuner_freq, if_freq, rc;
 	u32 N;
 
 	dprintk("%s:\n", __func__);
@@ -495,56 +541,58 @@
 	}
 	tuner_freq = params->frequency + if_freq;
 
+	if (fe->ops.info.type == FE_QAM) {
+		dprintk("%s select tda827xa_dvbc\n", __func__);
+		frequency_map = tda827xa_dvbc;
+	}
+
 	i = 0;
-	while (tda827xa_dvbt[i].lomax < tuner_freq) {
-		if(tda827xa_dvbt[i + 1].lomax == 0)
+	while (frequency_map[i].lomax < tuner_freq) {
+		if (frequency_map[i + 1].lomax == 0)
 			break;
 		i++;
 	}
 
-	N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
+	N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
 	buf[0] = 0;            // subaddress
 	buf[1] = N >> 8;
 	buf[2] = N & 0xff;
 	buf[3] = 0;
 	buf[4] = 0x16;
-	buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
-			tda827xa_dvbt[i].sbs;
-	buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
+	buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
+			frequency_map[i].sbs;
+	buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
 	buf[7] = 0x1c;
 	buf[8] = 0x06;
 	buf[9] = 0x24;
 	buf[10] = 0x00;
 	msg.len = 11;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
-		printk("%s: could not write to tuner at addr: 0x%02x\n",
-		       __func__, priv->i2c_addr << 1);
-		return -EIO;
-	}
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
+
 	buf[0] = 0x90;
 	buf[1] = 0xff;
 	buf[2] = 0x60;
 	buf[3] = 0x00;
 	buf[4] = 0x59;  // lpsel, for 6MHz + 2
 	msg.len = 5;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	buf[0] = 0xa0;
 	buf[1] = 0x40;
 	msg.len = 2;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	msleep(11);
 	msg.flags = I2C_M_RD;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 	msg.flags = 0;
 
 	buf[1] >>= 4;
@@ -553,49 +601,55 @@
 		tda827xa_lna_gain(fe, 0, NULL);
 		buf[0] = 0x60;
 		buf[1] = 0x0c;
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		i2c_transfer(priv->i2c_adap, &msg, 1);
+		rc = tuner_transfer(fe, &msg, 1);
+		if (rc < 0)
+			goto err;
 	}
 
 	buf[0] = 0xc0;
 	buf[1] = 0x99;    // lpsel, for 6MHz + 2
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	buf[0] = 0x60;
 	buf[1] = 0x3c;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	/* correct CP value */
 	buf[0] = 0x30;
-	buf[1] = 0x10 + tda827xa_dvbt[i].scr;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	buf[1] = 0x10 + frequency_map[i].scr;
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	msleep(163);
 	buf[0] = 0xc0;
 	buf[1] = 0x39;  // lpsel, for 6MHz + 2
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	msleep(3);
 	/* freeze AGC1 */
 	buf[0] = 0x50;
-	buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
+	rc = tuner_transfer(fe, &msg, 1);
+	if (rc < 0)
+		goto err;
 
 	priv->frequency = params->frequency;
 	priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
 
+
 	return 0;
+
+err:
+	printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
+	       __func__, priv->i2c_addr << 1);
+	return rc;
 }
 
 
@@ -643,7 +697,7 @@
 	tuner_reg[9] = 0x20;
 	tuner_reg[10] = 0x00;
 	msg.len = 11;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0x90;
 	tuner_reg[1] = 0xff;
@@ -651,19 +705,19 @@
 	tuner_reg[3] = 0;
 	tuner_reg[4] = 0x99 + (priv->lpsel << 1);
 	msg.len = 5;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0xa0;
 	tuner_reg[1] = 0xc0;
 	msg.len = 2;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0x30;
 	tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msg.flags = I2C_M_RD;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 	msg.flags = 0;
 	tuner_reg[1] >>= 4;
 	dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
@@ -673,24 +727,24 @@
 	msleep(100);
 	tuner_reg[0] = 0x60;
 	tuner_reg[1] = 0x3c;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	msleep(163);
 	tuner_reg[0] = 0x50;
 	tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0x80;
 	tuner_reg[1] = 0x28;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0xb0;
 	tuner_reg[1] = 0x01;
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	tuner_reg[0] = 0xc0;
 	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 
 	priv->frequency = params->frequency;
 
@@ -703,7 +757,7 @@
 	unsigned char data[] = {0x80, 0x2c};
 	struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
 			      .buf = data, .len = 2};
-	i2c_transfer(priv->i2c_adap, &msg, 1);
+	tuner_transfer(fe, &msg, 1);
 }
 
 /* ------------------------------------------------------------------ */
@@ -792,16 +846,19 @@
 };
 
 static int tda827x_probe_version(struct dvb_frontend *fe)
-{	u8 data;
+{
+	u8 data;
+	int rc;
 	struct tda827x_priv *priv = fe->tuner_priv;
 	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
 			       .buf = &data, .len = 1 };
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
+
+	rc = tuner_transfer(fe, &msg, 1);
+
+	if (rc < 0) {
 		printk("%s: could not read from tuner at addr: 0x%02x\n",
 		       __func__, msg.addr << 1);
-		return -EIO;
+		return rc;
 	}
 	if ((data & 0x3c) == 0) {
 		dprintk("tda827x tuner found\n");
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
index 4b8662e..064d14c 100644
--- a/drivers/media/common/tuners/tda8290.c
+++ b/drivers/media/common/tuners/tda8290.c
@@ -22,7 +22,7 @@
 
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include "tuner-i2c.h"
 #include "tda8290.h"
 #include "tda827x.h"
@@ -566,8 +566,11 @@
 	u8 data;
 	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
 
-	if (NULL == analog_ops->i2c_gate_ctrl)
+	if (!analog_ops->i2c_gate_ctrl) {
+		printk(KERN_ERR "tda8290: no gate control were provided!\n");
+
 		return -EINVAL;
+	}
 
 	analog_ops->i2c_gate_ctrl(fe, 1);
 
@@ -615,11 +618,13 @@
 
 	if (ret != 1) {
 		tuner_warn("tuner access failed!\n");
+		analog_ops->i2c_gate_ctrl(fe, 0);
 		return -EREMOTEIO;
 	}
 
 	if ((data == 0x83) || (data == 0x84)) {
 		priv->ver |= TDA18271;
+		tda829x_tda18271_config.config = priv->cfg.config;
 		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
 			   priv->i2c_props.adap, &tda829x_tda18271_config);
 	} else {
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c
index b23dade..60ed872 100644
--- a/drivers/media/common/tuners/tea5761.c
+++ b/drivers/media/common/tuners/tea5761.c
@@ -9,7 +9,7 @@
 
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/tuner.h>
 #include "tuner-i2c.h"
 #include "tea5761.h"
diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c
index 1f56463..223a226 100644
--- a/drivers/media/common/tuners/tea5767.c
+++ b/drivers/media/common/tuners/tea5767.c
@@ -12,7 +12,7 @@
 
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include "tuner-i2c.h"
 #include "tea5767.h"
 
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 493ce93..b545985 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -739,7 +739,10 @@
 	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
 		__func__, params->frequency);
 
-	priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
+	/* Fix me: it could be air. */
+	priv->rf_mode = params->mode;
+	if (params->mode > XC_RF_MODE_CABLE)
+		priv->rf_mode = XC_RF_MODE_CABLE;
 
 	/* params->frequency is in units of 62.5khz */
 	priv->freq_hz = params->frequency * 62500;
@@ -970,8 +973,6 @@
 	case 1:
 		/* new tuner instance */
 		priv->bandwidth = BANDWIDTH_6_MHZ;
-		priv->if_khz = cfg->if_khz;
-
 		fe->tuner_priv = priv;
 		break;
 	default:
@@ -980,6 +981,13 @@
 		break;
 	}
 
+	if (priv->if_khz == 0) {
+		/* If the IF hasn't been set yet, use the value provided by
+		   the caller (occurs in hybrid devices where the analog
+		   call to xc5000_attach occurs before the digital side) */
+		priv->if_khz = cfg->if_khz;
+	}
+
 	/* Check if firmware has been loaded. It is possible that another
 	   instance of the driver has loaded the firmware.
 	 */
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index a8c6249..9e57814 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -13,7 +13,7 @@
 	select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
 	select DVB_CX24123 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
 	select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE
 	help
 	  Support for the digital TV receiver chip made by B2C2 Inc. included in
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index d9db066..b97cf72 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -2,7 +2,6 @@
 	flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
 
-
 ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
 b2c2-flexcop-objs += flexcop-dma.o
 endif
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
index 8ce0633..3e1c472 100644
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -28,11 +28,14 @@
 
 /* Steal from usb.h */
 #undef err
-#define err(format,  arg...) printk(KERN_ERR     FC_LOG_PREFIX ": " format "\n" , ## arg)
+#define err(format, arg...) \
+	printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg)
 #undef info
-#define info(format, arg...) printk(KERN_INFO    FC_LOG_PREFIX ": " format "\n" , ## arg)
+#define info(format, arg...) \
+	printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg)
 #undef warn
-#define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
+#define warn(format, arg...) \
+	printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
 
 struct flexcop_dma {
 	struct pci_dev *pdev;
@@ -91,16 +94,14 @@
 	int fullts_streaming_state;
 
 	/* bus specific callbacks */
-	flexcop_ibi_value (*read_ibi_reg)  (struct flexcop_device *, flexcop_ibi_register);
-	int               (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
-
-
-	int (*i2c_request) (struct flexcop_i2c_adapter*,
+	flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *,
+			flexcop_ibi_register);
+	int (*write_ibi_reg) (struct flexcop_device *,
+			flexcop_ibi_register, flexcop_ibi_value);
+	int (*i2c_request) (struct flexcop_i2c_adapter *,
 		flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
-	int (*stream_control) (struct flexcop_device*, int);
-
+	int (*stream_control) (struct flexcop_device *, int);
 	int (*get_mac_addr) (struct flexcop_device *fc, int extended);
-
 	void *bus_specific;
 };
 
@@ -111,22 +112,28 @@
 void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
 
 struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
-void flexcop_device_kfree(struct flexcop_device*);
+void flexcop_device_kfree(struct flexcop_device *);
 
-int  flexcop_device_initialize(struct flexcop_device*);
+int flexcop_device_initialize(struct flexcop_device *);
 void flexcop_device_exit(struct flexcop_device *fc);
-
 void flexcop_reset_block_300(struct flexcop_device *fc);
 
 /* from flexcop-dma.c */
-int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size);
+int flexcop_dma_allocate(struct pci_dev *pdev,
+		struct flexcop_dma *dma, u32 size);
 void flexcop_dma_free(struct flexcop_dma *dma);
 
-int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
-int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
-int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
+		flexcop_dma_index_t no, int onoff);
+int flexcop_dma_control_size_irq(struct flexcop_device *fc,
+		flexcop_dma_index_t no, int onoff);
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma,
+		flexcop_dma_index_t dma_idx);
+int flexcop_dma_xfer_control(struct flexcop_device *fc,
+		flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index,
+		int onoff);
+int flexcop_dma_config_timer(struct flexcop_device *fc,
+		flexcop_dma_index_t dma_idx, u8 cycles);
 
 /* from flexcop-eeprom.c */
 /* the PCI part uses this call to get the MAC address, the USB part has its own */
@@ -141,13 +148,15 @@
 	u8 chipaddr, u8 addr, u8 *buf, u16 len);
 
 /* from flexcop-sram.c */
-int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
+	flexcop_sram_dest_target_t target);
 void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
-void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill);
+void flexcop_sram_ctrl(struct flexcop_device *fc,
+		int usb_wan, int sramdma, int maximumfill);
 
 /* global prototypes for the flexcop-chip */
 /* from flexcop-fe-tuner.c */
-int flexcop_frontend_init(struct flexcop_device *card);
+int flexcop_frontend_init(struct flexcop_device *fc);
 void flexcop_frontend_exit(struct flexcop_device *fc);
 
 /* from flexcop-i2c.c */
@@ -159,11 +168,14 @@
 
 /* from flexcop-misc.c */
 void flexcop_determine_revision(struct flexcop_device *fc);
-void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix);
-void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num);
+void flexcop_device_name(struct flexcop_device *fc,
+		const char *prefix, const char *suffix);
+void flexcop_dump_reg(struct flexcop_device *fc,
+		flexcop_ibi_register reg, int num);
 
 /* from flexcop-hw-filter.c */
-int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff);
+int flexcop_pid_feed_control(struct flexcop_device *fc,
+		struct dvb_demux_feed *dvbdmxfeed, int onoff);
 void flexcop_hw_filter_init(struct flexcop_device *fc);
 
 void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
index 26f0011..2881e0d 100644
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -1,13 +1,12 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-dma.c - configuring and controlling the DMA of the FlexCop
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
-int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
+int flexcop_dma_allocate(struct pci_dev *pdev,
+		struct flexcop_dma *dma, u32 size)
 {
 	u8 *tcpu;
 	dma_addr_t tdma = 0;
@@ -32,7 +31,8 @@
 
 void flexcop_dma_free(struct flexcop_dma *dma)
 {
-	pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0);
+	pci_free_consistent(dma->pdev, dma->size*2,
+			dma->cpu_addr0, dma->dma_addr0);
 	memset(dma,0,sizeof(struct flexcop_dma));
 }
 EXPORT_SYMBOL(flexcop_dma_free);
@@ -44,8 +44,8 @@
 	flexcop_ibi_value v0x0,v0x4,v0xc;
 	v0x0.raw = v0x4.raw = v0xc.raw = 0;
 
-	v0x0.dma_0x0.dma_address0        = dma->dma_addr0 >> 2;
-	v0xc.dma_0xc.dma_address1        = dma->dma_addr1 >> 2;
+	v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
+	v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
 	v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
 
 	if ((dma_idx & FC_DMA_1) == dma_idx) {
@@ -57,7 +57,8 @@
 		fc->write_ibi_reg(fc,dma2_014,v0x4);
 		fc->write_ibi_reg(fc,dma2_01c,v0xc);
 	} else {
-		err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call.");
+		err("either DMA1 or DMA2 can be configured within one "
+			"flexcop_dma_config call.");
 		return -EINVAL;
 	}
 
@@ -81,7 +82,8 @@
 		r0x0 = dma2_010;
 		r0xc = dma2_01c;
 	} else {
-		err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call.");
+		err("either transfer DMA1 or DMA2 can be started within one "
+			"flexcop_dma_xfer_control call.");
 		return -EINVAL;
 	}
 
@@ -154,8 +156,7 @@
 
 /* 1 cycles = 1.97 msec */
 int flexcop_dma_config_timer(struct flexcop_device *fc,
-		flexcop_dma_index_t dma_idx,
-		u8 cycles)
+		flexcop_dma_index_t dma_idx, u8 cycles)
 {
 	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
 	flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
index 8a8ae8a..a25373a 100644
--- a/drivers/media/dvb/b2c2/flexcop-eeprom.c
+++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
@@ -1,9 +1,7 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used)
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading)
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
@@ -14,17 +12,17 @@
 	return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
 }
 
-static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries)
+static int eeprom_lrc_write(struct adapter *adapter, u32 addr,
+		u32 len, u8 *wbuf, u8 *rbuf, int retries)
 {
-	int i;
+int i;
 
-	for (i = 0; i < retries; i++) {
-		if (eeprom_write(adapter, addr, wbuf, len) == len) {
-			if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
-				return 1;
+for (i = 0; i < retries; i++) {
+	if (eeprom_write(adapter, addr, wbuf, len) == len) {
+		if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
+			return 1;
 		}
 	}
-
 	return 0;
 }
 
@@ -39,12 +37,10 @@
 		return 0;
 
 	memcpy(wbuf, key, len);
-
 	wbuf[16] = 0;
 	wbuf[17] = 0;
 	wbuf[18] = 0;
 	wbuf[19] = calc_lrc(wbuf, 19);
-
 	return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
 }
 
@@ -59,7 +55,6 @@
 		return 0;
 
 	memcpy(key, buf, len);
-
 	return 1;
 }
 
@@ -74,9 +69,7 @@
 		tmp[3] = mac[5];
 		tmp[4] = mac[6];
 		tmp[5] = mac[7];
-
 	} else {
-
 		tmp[0] = mac[0];
 		tmp[1] = mac[1];
 		tmp[2] = mac[2];
@@ -90,11 +83,11 @@
 
 	if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
 		return 1;
-
 	return 0;
 }
 
-static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len)
+static int flexcop_eeprom_read(struct flexcop_device *fc,
+		u16 addr, u8 *buf, u16 len)
 {
 	return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
 }
@@ -110,7 +103,8 @@
 	return sum;
 }
 
-static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
+static int flexcop_eeprom_request(struct flexcop_device *fc,
+	flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
 {
 	int i,ret = 0;
 	u8 chipaddr =  0x50 | ((addr >> 8) & 3);
@@ -123,7 +117,8 @@
 	return ret;
 }
 
-static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr,
+		u8 *buf, u16 len, int retries)
 {
 	int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
 	if (ret == 0)
@@ -133,8 +128,7 @@
 }
 
 /* JJ's comment about extended == 1: it is not presently used anywhere but was
- * added to the low-level functions for possible support of EUI64
- */
+ * added to the low-level functions for possible support of EUI64 */
 int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
 {
 	u8 buf[8];
@@ -142,12 +136,9 @@
 
 	if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
 		if (extended != 0) {
-			err("TODO: extended (EUI64) MAC addresses aren't completely supported yet");
+			err("TODO: extended (EUI64) MAC addresses aren't "
+				"completely supported yet");
 			ret = -EINVAL;
-/*			memcpy(fc->dvb_adapter.proposed_mac,buf,3);
-			mac[3] = 0xfe;
-			mac[4] = 0xff;
-			memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */
 		} else
 			memcpy(fc->dvb_adapter.proposed_mac,buf,6);
 	}
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 5cded37..f7afab5 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -592,14 +592,14 @@
 		fc->fe_sleep = ops->sleep;
 		ops->sleep = flexcop_sleep;
 
-		fc->dev_type = FC_SKY;
+		fc->dev_type = FC_SKY_REV26;
 		goto fe_found;
 	}
 
 	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
 	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
 	if (fc->fe != NULL) {
-		fc->dev_type = FC_AIR_DVB;
+		fc->dev_type = FC_AIR_DVBT;
 		fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
 		goto fe_found;
 	}
@@ -653,7 +653,7 @@
 		fc->fe_sleep                = ops->sleep;
 		ops->sleep                  = flexcop_sleep;
 
-		fc->dev_type                = FC_SKY_OLD;
+		fc->dev_type                = FC_SKY_REV23;
 		goto fe_found;
 	}
 
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
index 451974b..77e4547 100644
--- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c
+++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
@@ -1,33 +1,30 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-hw-filter.c - pid and mac address filtering and control functions
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
 static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
 {
-	flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
-
-	deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off");
+	flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff);
+	deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off");
 }
 
 void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
 {
-	flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
+	flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff);
 }
 
 static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
 {
-	flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
+	flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff);
 }
 
 void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
 {
-	flexcop_ibi_value v418,v41c;
-	v41c = fc->read_ibi_reg(fc,mac_address_41c);
+	flexcop_ibi_value v418, v41c;
+	v41c = fc->read_ibi_reg(fc, mac_address_41c);
 
 	v418.mac_address_418.MAC1 = mac[0];
 	v418.mac_address_418.MAC2 = mac[1];
@@ -36,27 +33,28 @@
 	v41c.mac_address_41c.MAC7 = mac[4];
 	v41c.mac_address_41c.MAC8 = mac[5];
 
-	fc->write_ibi_reg(fc,mac_address_418,v418);
-	fc->write_ibi_reg(fc,mac_address_41c,v41c);
+	fc->write_ibi_reg(fc, mac_address_418, v418);
+	fc->write_ibi_reg(fc, mac_address_41c, v41c);
 }
 
 void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
 {
-	flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff);
+	flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff);
 }
 
-static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask)
+static void flexcop_pid_group_filter(struct flexcop_device *fc,
+		u16 pid, u16 mask)
 {
 	/* index_reg_310.extra_index_reg need to 0 or 7 to work */
 	flexcop_ibi_value v30c;
 	v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
 	v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
-	fc->write_ibi_reg(fc,pid_filter_30c,v30c);
+	fc->write_ibi_reg(fc, pid_filter_30c, v30c);
 }
 
 static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
 {
-	flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
+	flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff);
 }
 
 /* this fancy define reduces the code size of the quite similar PID controlling of
@@ -65,91 +63,112 @@
 
 #define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
 	flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
-					  v208 = fc->read_ibi_reg(fc, ctrl_208); \
-\
-	vpid.vregname.field = onoff ? pid : 0x1fff; \
-	vpid.vregname.trans_field = transval; \
-	v208.ctrl_208.enablefield = onoff; \
-\
-	fc->write_ibi_reg(fc,vregname,vpid); \
-	fc->write_ibi_reg(fc,ctrl_208,v208);
+v208 = fc->read_ibi_reg(fc, ctrl_208); \
+vpid.vregname.field = onoff ? pid : 0x1fff; \
+vpid.vregname.trans_field = transval; \
+v208.ctrl_208.enablefield = onoff; \
+fc->write_ibi_reg(fc, vregname, vpid); \
+fc->write_ibi_reg(fc, ctrl_208, v208);
 
-static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0);
+	pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig,
+			Stream1_trans, 0);
 }
 
-static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0);
+	pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig,
+			Stream2_trans, 0);
 }
 
-static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0);
+	pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0);
 }
 
-static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0);
+	pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0);
 }
 
-static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0);
+	pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0);
 }
 
-static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc,
+		u16 pid, int onoff)
 {
-	pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0);
+	pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0);
 }
 
-static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff)
+static void flexcop_pid_control(struct flexcop_device *fc,
+		int index, u16 pid, int onoff)
 {
 	if (pid == 0x2000)
 		return;
 
-	deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off");
+	deb_ts("setting pid: %5d %04x at index %d '%s'\n",
+			pid, pid, index, onoff ? "on" : "off");
 
 	/* We could use bit magic here to reduce source code size.
 	 * I decided against it, but to use the real register names */
 	switch (index) {
-		case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
-		case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break;
-		case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break;
-		case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break;
-		case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break;
-		case 5:	flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break;
-		default:
-			if (fc->has_32_hw_pid_filter && index < 38) {
-				flexcop_ibi_value vpid,vid;
+	case 0:
+		flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff);
+		break;
+	case 1:
+		flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff);
+		break;
+	case 2:
+		flexcop_pid_PCR_PID_ctrl(fc, pid, onoff);
+		break;
+	case 3:
+		flexcop_pid_PMT_PID_ctrl(fc, pid, onoff);
+		break;
+	case 4:
+		flexcop_pid_EMM_PID_ctrl(fc, pid, onoff);
+		break;
+	case 5:
+		flexcop_pid_ECM_PID_ctrl(fc, pid, onoff);
+		break;
+	default:
+		if (fc->has_32_hw_pid_filter && index < 38) {
+			flexcop_ibi_value vpid, vid;
 
-				/* set the index */
-				vid = fc->read_ibi_reg(fc,index_reg_310);
-				vid.index_reg_310.index_reg = index - 6;
-				fc->write_ibi_reg(fc,index_reg_310, vid);
+			/* set the index */
+			vid = fc->read_ibi_reg(fc, index_reg_310);
+			vid.index_reg_310.index_reg = index - 6;
+			fc->write_ibi_reg(fc, index_reg_310, vid);
 
-				vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
-				vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
-				vpid.pid_n_reg_314.PID_enable_bit = onoff;
-				fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
-			}
-			break;
+			vpid = fc->read_ibi_reg(fc, pid_n_reg_314);
+			vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
+			vpid.pid_n_reg_314.PID_enable_bit = onoff;
+			fc->write_ibi_reg(fc, pid_n_reg_314, vpid);
+		}
+		break;
 	}
 }
 
-static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff)
 {
 	if (fc->fullts_streaming_state != onoff) {
 		deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
 		flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
-		flexcop_pid_group_filter_ctrl(fc,onoff);
+		flexcop_pid_group_filter_ctrl(fc, onoff);
 		fc->fullts_streaming_state = onoff;
 	}
 	return 0;
 }
 
-int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff)
+int flexcop_pid_feed_control(struct flexcop_device *fc,
+		struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
 	int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
 
@@ -164,24 +183,25 @@
 	 *   - or the requested pid is 0x2000 */
 
 	if (!fc->pid_filtering && fc->feedcount == onoff)
-		flexcop_toggle_fullts_streaming(fc,onoff);
+		flexcop_toggle_fullts_streaming(fc, onoff);
 
 	if (fc->pid_filtering) {
-		flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+		flexcop_pid_control \
+			(fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
 
 		if (fc->extra_feedcount > 0)
-			flexcop_toggle_fullts_streaming(fc,1);
+			flexcop_toggle_fullts_streaming(fc, 1);
 		else if (dvbdmxfeed->pid == 0x2000)
-			flexcop_toggle_fullts_streaming(fc,onoff);
+			flexcop_toggle_fullts_streaming(fc, onoff);
 		else
-			flexcop_toggle_fullts_streaming(fc,0);
+			flexcop_toggle_fullts_streaming(fc, 0);
 	}
 
 	/* if it was the first or last feed request change the stream-status */
 	if (fc->feedcount == onoff) {
-		flexcop_rcv_data_ctrl(fc,onoff);
+		flexcop_rcv_data_ctrl(fc, onoff);
 		if (fc->stream_control) /* device specific stream control */
-			fc->stream_control(fc,onoff);
+			fc->stream_control(fc, onoff);
 
 		/* feeding stopped -> reset the flexcop filter*/
 		if (onoff == 0) {
@@ -189,7 +209,6 @@
 			flexcop_hw_filter_init(fc);
 		}
 	}
-
 	return 0;
 }
 EXPORT_SYMBOL(flexcop_pid_feed_control);
@@ -199,15 +218,15 @@
 	int i;
 	flexcop_ibi_value v;
 	for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
-		flexcop_pid_control(fc,i,0x1fff,0);
+		flexcop_pid_control(fc, i, 0x1fff, 0);
 
 	flexcop_pid_group_filter(fc, 0, 0x1fe0);
-	flexcop_pid_group_filter_ctrl(fc,0);
+	flexcop_pid_group_filter_ctrl(fc, 0);
 
-	v = fc->read_ibi_reg(fc,pid_filter_308);
+	v = fc->read_ibi_reg(fc, pid_filter_308);
 	v.pid_filter_308.EMM_filter_4 = 1;
 	v.pid_filter_308.EMM_filter_6 = 0;
-	fc->write_ibi_reg(fc,pid_filter_308,v);
+	fc->write_ibi_reg(fc, pid_filter_308, v);
 
 	flexcop_null_filter_ctrl(fc, 1);
 }
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index f13783f..e2bed50 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -1,17 +1,14 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
- *
- * see flexcop.c for copyright information.
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
 #define FC_MAX_I2C_RETRIES 100000
 
-/* #define DUMP_I2C_MESSAGES */
-
-static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
+static int flexcop_i2c_operation(struct flexcop_device *fc,
+		flexcop_ibi_value *r100)
 {
 	int i;
 	flexcop_ibi_value r;
@@ -26,7 +23,7 @@
 		r = fc->read_ibi_reg(fc, tw_sm_c_100);
 
 		if (!r.tw_sm_c_100.no_base_addr_ack_error) {
-			if (r.tw_sm_c_100.st_done) {  /* && !r.tw_sm_c_100.working_start */
+			if (r.tw_sm_c_100.st_done) {
 				*r100 = r;
 				deb_i2c("i2c success\n");
 				return 0;
@@ -36,17 +33,31 @@
 			return -EREMOTEIO;
 		}
 	}
-	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i);
+	deb_i2c("tried %d times i2c operation, "
+			"never finished or too many ack errors.\n", i);
 	return -EREMOTEIO;
 }
 
 static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
-	flexcop_ibi_value r100, u8 *buf)
+		flexcop_ibi_value r100, u8 *buf)
 {
 	flexcop_ibi_value r104;
-	int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
+	int len = r100.tw_sm_c_100.total_bytes,
+		/* remember total_bytes is buflen-1 */
 		ret;
 
+	/* work-around to have CableStar2 and SkyStar2 rev 2.7 work
+	 * correctly:
+	 *
+	 * the ITD1000 is behind an i2c-gate which closes automatically
+	 * after an i2c-transaction the STV0297 needs 2 consecutive reads
+	 * one with no_base_addr = 0 and one with 1
+	 *
+	 * those two work-arounds are conflictin: we check for the card
+	 * type, it is set when probing the ITD1000 */
+	if (i2c->fc->dev_type == FC_SKY_REV27)
+		r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
+
 	ret = flexcop_i2c_operation(i2c->fc, &r100);
 	if (ret != 0) {
 		deb_i2c("Retrying operation\n");
@@ -69,11 +80,11 @@
 		if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
 		if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
 	}
-
 	return 0;
 }
 
-static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
+static int flexcop_i2c_write4(struct flexcop_device *fc,
+		flexcop_ibi_value r100, u8 *buf)
 {
 	flexcop_ibi_value r104;
 	int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
@@ -81,7 +92,6 @@
 
 	/* there is at least one byte, otherwise we wouldn't be here */
 	r100.tw_sm_c_100.data1_reg = buf[0];
-
 	r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
 	r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
 	r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
@@ -94,7 +104,7 @@
 }
 
 int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
-	flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+		flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
 	int ret;
 
@@ -117,7 +127,6 @@
 		printk("rd(");
 	else
 		printk("wr(");
-
 	printk("%02x): %02x ", chipaddr, addr);
 #endif
 
@@ -163,7 +172,8 @@
 EXPORT_SYMBOL(flexcop_i2c_request);
 
 /* master xfer callback for demodulator */
-static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msgs[], int num)
 {
 	struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
 	int i, ret = 0;
@@ -182,12 +192,13 @@
 		/* reading */
 		if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
 			ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
-				msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len);
+					msgs[i].buf[0], msgs[i+1].buf,
+					msgs[i+1].len);
 			i++; /* skip the following message */
 		} else /* writing */
 			ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
-				msgs[i].buf[0], &msgs[i].buf[1],
-				msgs[i].len - 1);
+					msgs[i].buf[0], &msgs[i].buf[1],
+					msgs[i].len - 1);
 		if (ret < 0) {
 			err("i2c master_xfer failed");
 			break;
@@ -214,23 +225,21 @@
 int flexcop_i2c_init(struct flexcop_device *fc)
 {
 	int ret;
-
 	mutex_init(&fc->i2c_mutex);
 
 	fc->fc_i2c_adap[0].fc = fc;
 	fc->fc_i2c_adap[1].fc = fc;
 	fc->fc_i2c_adap[2].fc = fc;
-
 	fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
 	fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
 	fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
 
 	strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
-		sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
+			sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
 	strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
-		sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
+			sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
 	strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
-		sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
+			sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
 
 	i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
 	i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
@@ -268,7 +277,6 @@
 	i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
 adap_1_failed:
 	i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
-
 	return ret;
 }
 
@@ -279,6 +287,5 @@
 		i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
 		i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
 	}
-
 	fc->init_state &= ~FC_STATE_I2C_INIT;
 }
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 93d20e5..e56627d 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -1,9 +1,7 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-misc.c - miscellaneous functions.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-misc.c - miscellaneous functions
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
@@ -12,39 +10,43 @@
 	flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
 
 	switch (v.misc_204.Rev_N_sig_revision_hi) {
-		case 0x2:
-			deb_info("found a FlexCopII.\n");
-			fc->rev = FLEXCOP_II;
-			break;
-		case 0x3:
-			deb_info("found a FlexCopIIb.\n");
-			fc->rev = FLEXCOP_IIB;
-			break;
-		case 0x0:
-			deb_info("found a FlexCopIII.\n");
-			fc->rev = FLEXCOP_III;
-			break;
-		default:
-			err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi);
-			break;
+	case 0x2:
+		deb_info("found a FlexCopII.\n");
+		fc->rev = FLEXCOP_II;
+		break;
+	case 0x3:
+		deb_info("found a FlexCopIIb.\n");
+		fc->rev = FLEXCOP_IIB;
+		break;
+	case 0x0:
+		deb_info("found a FlexCopIII.\n");
+		fc->rev = FLEXCOP_III;
+		break;
+	default:
+		err("unknown FlexCop Revision: %x. Please report this to "
+				"linux-dvb@linuxtv.org.",
+				v.misc_204.Rev_N_sig_revision_hi);
+		break;
 	}
 
 	if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
-		deb_info("this FlexCop has the additional 32 hardware pid filter.\n");
+		deb_info("this FlexCop has "
+				"the additional 32 hardware pid filter.\n");
 	else
-		deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n");
+		deb_info("this FlexCop has "
+				"the 6 basic main hardware pid filter.\n");
 	/* bus parts have to decide if hw pid filtering is used or not. */
 }
 
 static const char *flexcop_revision_names[] = {
-	"Unkown chip",
+	"Unknown chip",
 	"FlexCopII",
 	"FlexCopIIb",
 	"FlexCopIII",
 };
 
 static const char *flexcop_device_names[] = {
-	"Unkown device",
+	"Unknown device",
 	"Air2PC/AirStar 2 DVB-T",
 	"Air2PC/AirStar 2 ATSC 1st generation",
 	"Air2PC/AirStar 2 ATSC 2nd generation",
@@ -61,21 +63,23 @@
 	"PCI",
 };
 
-void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
-		char *suffix)
+void flexcop_device_name(struct flexcop_device *fc,
+		const char *prefix, const char *suffix)
 {
-	info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix,
-			flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
-			flexcop_revision_names[fc->rev],suffix);
+	info("%s '%s' at the '%s' bus controlled by a '%s' %s",
+			prefix,	flexcop_device_names[fc->dev_type],
+			flexcop_bus_names[fc->bus_type],
+			flexcop_revision_names[fc->rev], suffix);
 }
 
-void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num)
+void flexcop_dump_reg(struct flexcop_device *fc,
+		flexcop_ibi_register reg, int num)
 {
 	flexcop_ibi_value v;
 	int i;
 	for (i = 0; i < num; i++) {
-		v = fc->read_ibi_reg(fc,reg+4*i);
-		deb_rdump("0x%03x: %08x, ",reg+4*i, v.raw);
+		v = fc->read_ibi_reg(fc, reg+4*i);
+		deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw);
 	}
 	deb_rdump("\n");
 }
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 76e37fd..227c020 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -1,9 +1,7 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-pci.c - covers the PCI part including DMA transfers.
- *
- * see flexcop.c for copyright information.
+ * Linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-pci.c - covers the PCI part including DMA transfers
+ * see flexcop.c for copyright information
  */
 
 #define FC_LOG_PREFIX "flexcop-pci"
@@ -11,7 +9,8 @@
 
 static int enable_pid_filtering = 1;
 module_param(enable_pid_filtering, int, 0444);
-MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
+MODULE_PARM_DESC(enable_pid_filtering,
+	"enable hardware pid filtering: supported values: 0 (fullts), 1");
 
 static int irq_chk_intv = 100;
 module_param(irq_chk_intv, int, 0644);
@@ -26,17 +25,17 @@
 #define DEBSTATUS " (debugging is not enabled)"
 #endif
 
-#define deb_info(args...)  dprintk(0x01,args)
-#define deb_reg(args...)   dprintk(0x02,args)
-#define deb_ts(args...)    dprintk(0x04,args)
-#define deb_irq(args...)   dprintk(0x08,args)
-#define deb_chk(args...)   dprintk(0x10,args)
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_reg(args...) dprintk(0x02, args)
+#define deb_ts(args...) dprintk(0x04, args)
+#define deb_irq(args...) dprintk(0x08, args)
+#define deb_chk(args...) dprintk(0x10, args)
 
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug,
 	"set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))."
-	 DEBSTATUS);
+	DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
 #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
@@ -51,30 +50,30 @@
 
 	void __iomem *io_mem;
 	u32 irq;
-/* buffersize (at least for DMA1, need to be % 188 == 0,
- * this logic is required */
+	/* buffersize (at least for DMA1, need to be % 188 == 0,
+	 * this logic is required */
 #define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)
 #define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
 	struct flexcop_dma dma[2];
 
 	int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
-	u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
+	u32 last_dma1_cur_pos;
+	/* position of the pointer last time the timer/packet irq occured */
 	int count;
 	int count_prev;
 	int stream_problem;
 
 	spinlock_t irq_lock;
-
 	unsigned long last_irq;
 
 	struct delayed_work irq_check_work;
-
 	struct flexcop_device *fc_dev;
 };
 
-static int lastwreg,lastwval,lastrreg,lastrval;
+static int lastwreg, lastwval, lastrreg, lastrval;
 
-static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, flexcop_ibi_register r)
+static flexcop_ibi_value flexcop_pci_read_ibi_reg(struct flexcop_device *fc,
+		flexcop_ibi_register r)
 {
 	struct flexcop_pci *fc_pci = fc->bus_specific;
 	flexcop_ibi_value v;
@@ -82,19 +81,20 @@
 
 	if (lastrreg != r || lastrval != v.raw) {
 		lastrreg = r; lastrval = v.raw;
-		deb_reg("new rd: %3x: %08x\n",r,v.raw);
+		deb_reg("new rd: %3x: %08x\n", r, v.raw);
 	}
 
 	return v;
 }
 
-static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register r, flexcop_ibi_value v)
+static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc,
+		flexcop_ibi_register r, flexcop_ibi_value v)
 {
 	struct flexcop_pci *fc_pci = fc->bus_specific;
 
 	if (lastwreg != r || lastwval != v.raw) {
 		lastwreg = r; lastwval = v.raw;
-		deb_reg("new wr: %3x: %08x\n",r,v.raw);
+		deb_reg("new wr: %3x: %08x\n", r, v.raw);
 	}
 
 	writel(v.raw, fc_pci->io_mem + r);
@@ -113,15 +113,16 @@
 			deb_chk("no IRQ since the last check\n");
 			if (fc_pci->stream_problem++ == 3) {
 				struct dvb_demux_feed *feed;
+				deb_info("flexcop-pci: stream problem, resetting pid filter\n");
 
 				spin_lock_irq(&fc->demux.lock);
 				list_for_each_entry(feed, &fc->demux.feed_list,
-					list_head) {
+						list_head) {
 					flexcop_pid_feed_control(fc, feed, 0);
 				}
 
 				list_for_each_entry(feed, &fc->demux.feed_list,
-					list_head) {
+						list_head) {
 					flexcop_pid_feed_control(fc, feed, 1);
 				}
 				spin_unlock_irq(&fc->demux.lock);
@@ -149,11 +150,10 @@
 	flexcop_ibi_value v;
 	irqreturn_t ret = IRQ_HANDLED;
 
-	spin_lock_irqsave(&fc_pci->irq_lock,flags);
+	spin_lock_irqsave(&fc_pci->irq_lock, flags);
+	v = fc->read_ibi_reg(fc, irq_20c);
 
-	v = fc->read_ibi_reg(fc,irq_20c);
-
-   /* errors */
+	/* errors */
 	if (v.irq_20c.Data_receiver_error)
 		deb_chk("data receiver error\n");
 	if (v.irq_20c.Continuity_error_flag)
@@ -164,24 +164,29 @@
 		deb_chk("Transport error\n");
 
 	if ((fc_pci->count % 1000) == 0)
-		deb_chk("%d valid irq took place so far\n",fc_pci->count);
+		deb_chk("%d valid irq took place so far\n", fc_pci->count);
 
 	if (v.irq_20c.DMA1_IRQ_Status == 1) {
 		if (fc_pci->active_dma1_addr == 0)
-			flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188);
+			flexcop_pass_dmx_packets(fc_pci->fc_dev,
+					fc_pci->dma[0].cpu_addr0,
+					fc_pci->dma[0].size / 188);
 		else
-			flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188);
+			flexcop_pass_dmx_packets(fc_pci->fc_dev,
+					fc_pci->dma[0].cpu_addr1,
+					fc_pci->dma[0].size / 188);
 
 		deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr);
 		fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr;
-	} else if (v.irq_20c.DMA1_Timer_Status == 1) {
 		/* for the timer IRQ we only can use buffer dmx feeding, because we don't have
 		 * complete TS packets when reading from the DMA memory */
+	} else if (v.irq_20c.DMA1_Timer_Status == 1) {
 		dma_addr_t cur_addr =
 			fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
 		u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
 
-		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
+		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, "
+			"last_cur_pos: %08x ",
 				jiffies_to_usecs(jiffies - fc_pci->last_irq),
 				v.raw, (unsigned long long)cur_addr, cur_pos,
 				fc_pci->last_dma1_cur_pos);
@@ -191,30 +196,36 @@
 		 * pass the data from last_cur_pos to the buffer end to the demux
 		 */
 		if (cur_pos < fc_pci->last_dma1_cur_pos) {
-			deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos);
+			deb_irq(" end was reached: passing %d bytes ",
+				(fc_pci->dma[0].size*2 - 1) -
+				fc_pci->last_dma1_cur_pos);
 			flexcop_pass_dmx_data(fc_pci->fc_dev,
-					fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
-					(fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos);
+				fc_pci->dma[0].cpu_addr0 +
+					fc_pci->last_dma1_cur_pos,
+				(fc_pci->dma[0].size*2) -
+					fc_pci->last_dma1_cur_pos);
 			fc_pci->last_dma1_cur_pos = 0;
 		}
 
 		if (cur_pos > fc_pci->last_dma1_cur_pos) {
-			deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos);
+			deb_irq(" passing %d bytes ",
+				cur_pos - fc_pci->last_dma1_cur_pos);
 			flexcop_pass_dmx_data(fc_pci->fc_dev,
-					fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
-					cur_pos - fc_pci->last_dma1_cur_pos);
+				fc_pci->dma[0].cpu_addr0 +
+					fc_pci->last_dma1_cur_pos,
+				cur_pos - fc_pci->last_dma1_cur_pos);
 		}
 		deb_irq("\n");
 
 		fc_pci->last_dma1_cur_pos = cur_pos;
 		fc_pci->count++;
 	} else {
-		deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw);
+		deb_irq("isr for flexcop called, "
+			"apparently without reason (%08x)\n", v.raw);
 		ret = IRQ_NONE;
 	}
 
-	spin_unlock_irqrestore(&fc_pci->irq_lock,flags);
-
+	spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
 	return ret;
 }
 
@@ -222,52 +233,48 @@
 {
 	struct flexcop_pci *fc_pci = fc->bus_specific;
 	if (onoff) {
-		flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1);
-		flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2);
-
-		flexcop_dma_config_timer(fc,FC_DMA_1,0);
-
-		flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,1);
+		flexcop_dma_config(fc, &fc_pci->dma[0], FC_DMA_1);
+		flexcop_dma_config(fc, &fc_pci->dma[1], FC_DMA_2);
+		flexcop_dma_config_timer(fc, FC_DMA_1, 0);
+		flexcop_dma_xfer_control(fc, FC_DMA_1,
+				FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 1);
 		deb_irq("DMA xfer enabled\n");
 
 		fc_pci->last_dma1_cur_pos = 0;
-		flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
+		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1);
 		deb_irq("IRQ enabled\n");
-
 		fc_pci->count_prev = fc_pci->count;
-
-//		fc_pci->active_dma1_addr = 0;
-//		flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
-
 	} else {
-		flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
+		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0);
 		deb_irq("IRQ disabled\n");
 
-//		flexcop_dma_control_size_irq(fc,FC_DMA_1,0);
-
-		flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,0);
+		flexcop_dma_xfer_control(fc, FC_DMA_1,
+			 FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 0);
 		deb_irq("DMA xfer disabled\n");
 	}
-
 	return 0;
 }
 
 static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
 {
 	int ret;
-	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
+	ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0],
+			FC_DEFAULT_DMA1_BUFSIZE);
+	if (ret != 0)
 		return ret;
 
-	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
+	ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[1],
+			FC_DEFAULT_DMA2_BUFSIZE);
+	if (ret != 0) {
 		flexcop_dma_free(&fc_pci->dma[0]);
 		return ret;
 	}
 
-	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
-	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
-
+	flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_MEDIA |
+			FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
+	flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_CAO |
+			FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 	fc_pci->init_state |= FC_PCI_DMA_INIT;
-
 	return ret;
 }
 
@@ -290,12 +297,8 @@
 
 	if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
 		return ret;
-
 	pci_set_master(fc_pci->pdev);
 
-	/* enable interrupts */
-	// pci_write_config_dword(pdev, 0x6c, 0x8000);
-
 	if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
 		goto err_pci_disable_device;
 
@@ -338,8 +341,8 @@
 	fc_pci->init_state &= ~FC_PCI_INIT;
 }
 
-
-static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int flexcop_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
 {
 	struct flexcop_device *fc;
 	struct flexcop_pci *fc_pci;
@@ -350,7 +353,7 @@
 		return -ENOMEM;
 	}
 
-/* general flexcop init */
+	/* general flexcop init */
 	fc_pci = fc->bus_specific;
 	fc_pci->fc_dev = fc;
 
@@ -358,7 +361,6 @@
 	fc->write_ibi_reg = flexcop_pci_write_ibi_reg;
 	fc->i2c_request = flexcop_i2c_request;
 	fc->get_mac_addr = flexcop_eeprom_check_mac_addr;
-
 	fc->stream_control = flexcop_pci_stream_control;
 
 	if (enable_pid_filtering)
@@ -368,29 +370,29 @@
 
 	fc->pid_filtering = enable_pid_filtering;
 	fc->bus_type = FC_PCI;
-
 	fc->dev = &pdev->dev;
 	fc->owner = THIS_MODULE;
 
-/* bus specific part */
+	/* bus specific part */
 	fc_pci->pdev = pdev;
 	if ((ret = flexcop_pci_init(fc_pci)) != 0)
 		goto err_kfree;
 
-/* init flexcop */
+	/* init flexcop */
 	if ((ret = flexcop_device_initialize(fc)) != 0)
 		goto err_pci_exit;
 
-/* init dma */
+	/* init dma */
 	if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
 		goto err_fc_exit;
 
 	INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work);
 
-		if (irq_chk_intv > 0)
-			schedule_delayed_work(&fc_pci->irq_check_work,
-		msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
-
+	if (irq_chk_intv > 0)
+		schedule_delayed_work(&fc_pci->irq_check_work,
+				msecs_to_jiffies(irq_chk_intv < 100 ?
+					100 :
+					irq_chk_intv));
 	return ret;
 
 err_fc_exit:
@@ -420,7 +422,6 @@
 
 static struct pci_device_id flexcop_pci_tbl[] = {
 	{ PCI_DEVICE(0x13d0, 0x2103) },
-/*	{ PCI_DEVICE(0x13d0, 0x2200) }, ? */
 	{ },
 };
 
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 7599fcc..dc4528d 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -1,14 +1,11 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
- *
- * see flexcop.c for copyright information.
+ * see flexcop.c for copyright information
  */
 #ifndef __FLEXCOP_REG_H__
 #define __FLEXCOP_REG_H__
 
-
 typedef enum {
 	FLEXCOP_UNK = 0,
 	FLEXCOP_II,
@@ -18,13 +15,13 @@
 
 typedef enum {
 	FC_UNK = 0,
-	FC_AIR_DVB,
+	FC_CABLE,
+	FC_AIR_DVBT,
 	FC_AIR_ATSC1,
 	FC_AIR_ATSC2,
-	FC_SKY,
-	FC_SKY_OLD,
-	FC_CABLE,
 	FC_AIR_ATSC3,
+	FC_SKY_REV23,
+	FC_SKY_REV26,
 	FC_SKY_REV27,
 	FC_SKY_REV28,
 } flexcop_device_type_t;
@@ -36,12 +33,12 @@
 
 /* FlexCop IBI Registers */
 #if defined(__LITTLE_ENDIAN)
-	#include "flexcop_ibi_value_le.h"
+#include "flexcop_ibi_value_le.h"
 #else
 #if defined(__BIG_ENDIAN)
-	#include "flexcop_ibi_value_be.h"
+#include "flexcop_ibi_value_be.h"
 #else
-	#error no endian defined
+#error no endian defined
 #endif
 #endif
 
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
index cda6952..f2199e4 100644
--- a/drivers/media/dvb/b2c2/flexcop-sram.c
+++ b/drivers/media/dvb/b2c2/flexcop-sram.c
@@ -1,45 +1,43 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-sram.c - functions for controlling the SRAM.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-sram.c - functions for controlling the SRAM
+ * see flexcop.c for copyright information
  */
 #include "flexcop.h"
 
-static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type)
+static void flexcop_sram_set_chip(struct flexcop_device *fc,
+		flexcop_sram_type_t type)
 {
-	flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type);
+	flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type);
 }
 
 int flexcop_sram_init(struct flexcop_device *fc)
 {
 	switch (fc->rev) {
-		case FLEXCOP_II:
-		case FLEXCOP_IIB:
-			flexcop_sram_set_chip(fc,FC_SRAM_1_32KB);
-			break;
-		case FLEXCOP_III:
-			flexcop_sram_set_chip(fc,FC_SRAM_1_48KB);
-			break;
-		default:
-			return -EINVAL;
+	case FLEXCOP_II:
+	case FLEXCOP_IIB:
+		flexcop_sram_set_chip(fc, FC_SRAM_1_32KB);
+		break;
+	case FLEXCOP_III:
+		flexcop_sram_set_chip(fc, FC_SRAM_1_48KB);
+		break;
+	default:
+		return -EINVAL;
 	}
 	return 0;
 }
 
-int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target)
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
+		 flexcop_sram_dest_target_t target)
 {
 	flexcop_ibi_value v;
-
-	v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+	v = fc->read_ibi_reg(fc, sram_dest_reg_714);
 
 	if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
 		err("SRAM destination target to available on FlexCopII(b)\n");
 		return -EINVAL;
 	}
-
-	deb_sram("sram dest: %x target: %x\n",dest, target);
+	deb_sram("sram dest: %x target: %x\n", dest, target);
 
 	if (dest & FC_SRAM_DEST_NET)
 		v.sram_dest_reg_714.NET_Dest = target;
@@ -154,14 +152,12 @@
 		else
 			bank = 0x10000000;
 	}
-
 	flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
 }
 
 static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
 {
 	u32 bank;
-
 	bank = 0;
 
 	if (adapter->dw_sram_type == 0x20000) {
@@ -174,26 +170,22 @@
 		else
 			bank = 0x10000000;
 	}
-
 	flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
 }
 
 static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
 {
 	u32 length;
-
 	while (len != 0) {
 		length = len;
-
-		// check if the address range belongs to the same
-		// 32K memory chip. If not, the data is read from
-		// one chip at a time.
+		/* check if the address range belongs to the same
+		 * 32K memory chip. If not, the data is read
+		 * from one chip at a time */
 		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
 			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
 		}
 
 		sram_read_chunk(adapter, addr, buf, length);
-
 		addr = addr + length;
 		buf = buf + length;
 		len = len - length;
@@ -203,19 +195,17 @@
 static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
 {
 	u32 length;
-
 	while (len != 0) {
 		length = len;
 
-		// check if the address range belongs to the same
-		// 32K memory chip. If not, the data is written to
-		// one chip at a time.
+		/* check if the address range belongs to the same
+		 * 32K memory chip. If not, the data is
+		 * written to one chip at a time */
 		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
 			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
 		}
 
 		sram_write_chunk(adapter, addr, buf, length);
-
 		addr = addr + length;
 		buf = buf + length;
 		len = len - length;
@@ -224,39 +214,29 @@
 
 static void sram_set_size(struct adapter *adapter, u32 mask)
 {
-	write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
+	write_reg_dw(adapter, 0x71c,
+			(mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
 }
 
 static void sram_init(struct adapter *adapter)
 {
 	u32 tmp;
-
 	tmp = read_reg_dw(adapter, 0x71c);
-
 	write_reg_dw(adapter, 0x71c, 1);
 
 	if (read_reg_dw(adapter, 0x71c) != 0) {
 		write_reg_dw(adapter, 0x71c, tmp);
-
 		adapter->dw_sram_type = tmp & 0x30000;
-
 		ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
-
 	} else {
-
 		adapter->dw_sram_type = 0x10000;
-
 		ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
 	}
-
-	/* return value is never used? */
-/*	return adapter->dw_sram_type; */
 }
 
 static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
 {
 	u8 tmp1, tmp2;
-
 	dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
 
 	sram_set_size(adapter, mask);
@@ -269,7 +249,6 @@
 	sram_write(adapter, addr + 4, &tmp1, 1);
 
 	tmp2 = 0;
-
 	mdelay(20);
 
 	sram_read(adapter, addr, &tmp2, 1);
@@ -287,7 +266,6 @@
 	sram_write(adapter, addr + 4, &tmp1, 1);
 
 	tmp2 = 0;
-
 	mdelay(20);
 
 	sram_read(adapter, addr, &tmp2, 1);
@@ -297,26 +275,24 @@
 
 	if (tmp2 != 0x5a)
 		return 0;
-
 	return 1;
 }
 
 static u32 sram_length(struct adapter *adapter)
 {
 	if (adapter->dw_sram_type == 0x10000)
-		return 32768;	//  32K
+		return 32768; /* 32K */
 	if (adapter->dw_sram_type == 0x00000)
-		return 65536;	//  64K
+		return 65536; /* 64K */
 	if (adapter->dw_sram_type == 0x20000)
-		return 131072;	// 128K
-
-	return 32768;		// 32K
+		return 131072; /* 128K */
+	return 32768; /* 32K */
 }
 
 /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
-    - for 128K there are 4x32K chips at bank 0,1,2,3.
-    - for  64K there are 2x32K chips at bank 1,2.
-    - for  32K there is one 32K chip at bank 0.
+   - for 128K there are 4x32K chips at bank 0,1,2,3.
+   - for  64K there are 2x32K chips at bank 1,2.
+   - for  32K there is one 32K chip at bank 0.
 
    FlexCop works only with one bank at a time. The bank is selected
    by bits 28-29 of the 0x700 register.
@@ -324,24 +300,18 @@
    bank 0 covers addresses 0x00000-0x07fff
    bank 1 covers addresses 0x08000-0x0ffff
    bank 2 covers addresses 0x10000-0x17fff
-   bank 3 covers addresses 0x18000-0x1ffff
-*/
+   bank 3 covers addresses 0x18000-0x1ffff */
 
 static int flexcop_sram_detect(struct flexcop_device *fc)
 {
-	flexcop_ibi_value r208,r71c_0,vr71c_1;
-
+	flexcop_ibi_value r208, r71c_0, vr71c_1;
 	r208 = fc->read_ibi_reg(fc, ctrl_208);
 	fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
 
 	r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
-
 	write_reg_dw(adapter, 0x71c, 1);
-
 	tmp3 = read_reg_dw(adapter, 0x71c);
-
 	dprintk("%s: tmp3 = %x\n", __func__, tmp3);
-
 	write_reg_dw(adapter, 0x71c, tmp2);
 
 	// check for internal SRAM ???
@@ -350,9 +320,7 @@
 		sram_set_size(adapter, 0x10000);
 		sram_init(adapter);
 		write_reg_dw(adapter, 0x208, tmp);
-
 		dprintk("%s: sram size = 32K\n", __func__);
-
 		return 32;
 	}
 
@@ -360,9 +328,7 @@
 		sram_set_size(adapter, 0x20000);
 		sram_init(adapter);
 		write_reg_dw(adapter, 0x208, tmp);
-
 		dprintk("%s: sram size = 128K\n", __func__);
-
 		return 128;
 	}
 
@@ -370,9 +336,7 @@
 		sram_set_size(adapter, 0x00000);
 		sram_init(adapter);
 		write_reg_dw(adapter, 0x208, tmp);
-
 		dprintk("%s: sram size = 64K\n", __func__);
-
 		return 64;
 	}
 
@@ -380,18 +344,14 @@
 		sram_set_size(adapter, 0x10000);
 		sram_init(adapter);
 		write_reg_dw(adapter, 0x208, tmp);
-
 		dprintk("%s: sram size = 32K\n", __func__);
-
 		return 32;
 	}
 
 	sram_set_size(adapter, 0x10000);
 	sram_init(adapter);
 	write_reg_dw(adapter, 0x208, tmp);
-
 	dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
-
 	return 0;
 }
 
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index ae0d76a..bedcfb6 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -1,11 +1,8 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop-usb.c - covers the USB part.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-usb.c - covers the USB part
+ * see flexcop.c for copyright information
  */
-
 #define FC_LOG_PREFIX "flexcop_usb"
 #include "flexcop-usb.h"
 #include "flexcop-common.h"
@@ -18,42 +15,47 @@
 /* debug */
 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
 #define dprintk(level,args...) \
-	    do { if ((debug & level)) { printk(args); } } while (0)
-#define debug_dump(b,l,method) {\
+	do { if ((debug & level)) printk(args); } while (0)
+
+#define debug_dump(b, l, method) do {\
 	int i; \
-	for (i = 0; i < l; i++) method("%02x ", b[i]); \
-	method("\n");\
-}
+	for (i = 0; i < l; i++) \
+		method("%02x ", b[i]); \
+	method("\n"); \
+} while (0)
 
 #define DEBSTATUS ""
 #else
-#define dprintk(level,args...)
-#define debug_dump(b,l,method)
+#define dprintk(level, args...)
+#define debug_dump(b, l, method)
 #define DEBSTATUS " (debugging is not enabled)"
 #endif
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,"
+		"ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
 #undef DEBSTATUS
 
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_ts(args...)   dprintk(0x02,args)
-#define deb_ctrl(args...) dprintk(0x04,args)
-#define deb_i2c(args...)  dprintk(0x08,args)
-#define deb_v8(args...)   dprintk(0x10,args)
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_ts(args...) dprintk(0x02, args)
+#define deb_ctrl(args...) dprintk(0x04, args)
+#define deb_i2c(args...) dprintk(0x08, args)
+#define deb_v8(args...) dprintk(0x10, args)
 
 /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
  * in the IBI address, to make the V8 code simpler.
- * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used)
+ * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used)
  *                  in general: 0000 0HHH 000L LL00
  * IBI ADDRESS FORMAT:                    RHHH BLLL
  *
  * where R is the read(1)/write(0) bit, B is the busy bit
  * and HHH and LLL are the two sets of three bits from the PCI address.
  */
-#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
-#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
+#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \
+	(((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
+#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \
+	(((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
 
 /*
  * DKT 020228
@@ -69,12 +71,13 @@
 	struct flexcop_usb *fc_usb = fc->bus_specific;
 	u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
 	u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
-	u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read ? 0x80 : 0);
+	u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
+		(read ? 0x80 : 0);
 
 	int len = usb_control_msg(fc_usb->udev,
 			read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
 			request,
-			request_type,  /* 0xc0 read or 0x40 write*/
+			request_type, /* 0xc0 read or 0x40 write */
 			wAddress,
 			0,
 			val,
@@ -82,55 +85,49 @@
 			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
 
 	if (len != sizeof(u32)) {
-		err("error while %s dword from %d (%d).",read ? "reading" : "writing",
-			wAddress,wRegOffsPCI);
+		err("error while %s dword from %d (%d).", read ? "reading" :
+				"writing", wAddress, wRegOffsPCI);
 		return -EIO;
 	}
 	return 0;
 }
-
 /*
  * DKT 010817 - add support for V8 memory read/write and flash update
  */
 static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
 		flexcop_usb_request_t req, u8 page, u16 wAddress,
-		u8 *pbBuffer,u32 buflen)
+		u8 *pbBuffer, u32 buflen)
 {
-//	u8 dwRequestType;
 	u8 request_type = USB_TYPE_VENDOR;
 	u16 wIndex;
-	int nWaitTime,pipe,len;
-
+	int nWaitTime, pipe, len;
 	wIndex = page << 8;
 
 	switch (req) {
-		case B2C2_USB_READ_V8_MEM:
-			nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
-			request_type |= USB_DIR_IN;
-//			dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
-			pipe = B2C2_USB_CTRL_PIPE_IN;
+	case B2C2_USB_READ_V8_MEM:
+		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
+		request_type |= USB_DIR_IN;
+		pipe = B2C2_USB_CTRL_PIPE_IN;
 		break;
-		case B2C2_USB_WRITE_V8_MEM:
-			wIndex |= pbBuffer[0];
-			request_type |= USB_DIR_OUT;
-			nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
-//			dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
-			pipe = B2C2_USB_CTRL_PIPE_OUT;
+	case B2C2_USB_WRITE_V8_MEM:
+		wIndex |= pbBuffer[0];
+		request_type |= USB_DIR_OUT;
+		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
+		pipe = B2C2_USB_CTRL_PIPE_OUT;
 		break;
-		case B2C2_USB_FLASH_BLOCK:
-			request_type |= USB_DIR_OUT;
-			nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
-//			dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
-			pipe = B2C2_USB_CTRL_PIPE_OUT;
+	case B2C2_USB_FLASH_BLOCK:
+		request_type |= USB_DIR_OUT;
+		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
+		pipe = B2C2_USB_CTRL_PIPE_OUT;
 		break;
-		default:
-			deb_info("unsupported request for v8_mem_req %x.\n",req);
+	default:
+		deb_info("unsupported request for v8_mem_req %x.\n", req);
 		return -EINVAL;
 	}
-	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req,
-			wAddress,wIndex,buflen);
+	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
+			wAddress, wIndex, buflen);
 
-	len = usb_control_msg(fc_usb->udev,pipe,
+	len = usb_control_msg(fc_usb->udev, pipe,
 			req,
 			request_type,
 			wAddress,
@@ -139,39 +136,53 @@
 			buflen,
 			nWaitTime * HZ);
 
-	debug_dump(pbBuffer,len,deb_v8);
-
+	debug_dump(pbBuffer, len, deb_v8);
 	return len == buflen ? 0 : -EIO;
 }
 
 #define bytes_left_to_read_on_page(paddr,buflen) \
-			((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
-			? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
+	((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
+	 ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
 
-static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req,
-		flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len)
+static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,
+		flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start,
+		u32 addr, int extended, u8 *buf, u32 len)
 {
 	int i,ret = 0;
 	u16 wMax;
 	u32 pagechunk = 0;
 
 	switch(req) {
-		case B2C2_USB_READ_V8_MEM:  wMax = USB_MEM_READ_MAX; break;
-		case B2C2_USB_WRITE_V8_MEM:	wMax = USB_MEM_WRITE_MAX; break;
-		case B2C2_USB_FLASH_BLOCK:  wMax = USB_FLASH_MAX; break;
-		default:
-			return -EINVAL;
+	case B2C2_USB_READ_V8_MEM:
+		wMax = USB_MEM_READ_MAX;
+		break;
+	case B2C2_USB_WRITE_V8_MEM:
+		wMax = USB_MEM_WRITE_MAX;
+		break;
+	case B2C2_USB_FLASH_BLOCK:
+		wMax = USB_FLASH_MAX;
+		break;
+	default:
+		return -EINVAL;
 		break;
 	}
 	for (i = 0; i < len;) {
-		pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len);
-		deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended));
-		if ((ret = flexcop_usb_v8_memory_req(fc_usb,req,
-				page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */
-				(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended),
-				&buf[i],pagechunk)) < 0)
-			return ret;
+		pagechunk =
+			wMax < bytes_left_to_read_on_page(addr, len) ?
+				wMax :
+				bytes_left_to_read_on_page(addr, len);
+		deb_info("%x\n",
+			(addr & V8_MEMORY_PAGE_MASK) |
+				(V8_MEMORY_EXTENDED*extended));
 
+		ret = flexcop_usb_v8_memory_req(fc_usb, req,
+			page_start + (addr / V8_MEMORY_PAGE_SIZE),
+			(addr & V8_MEMORY_PAGE_MASK) |
+				(V8_MEMORY_EXTENDED*extended),
+			&buf[i], pagechunk);
+
+		if (ret < 0)
+			return ret;
 		addr += pagechunk;
 		len -= pagechunk;
 	}
@@ -180,8 +191,9 @@
 
 static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
 {
-	return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM,
-			V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6);
+	return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM,
+		V8_MEMORY_PAGE_FLASH, 0x1f010, 1,
+		fc->dvb_adapter.proposed_mac, 6);
 }
 
 #if 0
@@ -191,11 +203,8 @@
 {
 	u16 wValue;
 	u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
-//	u8 dwRequestType = (u8) RTYPE_GENERIC,
 	int nWaitTime = 2,
-		pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
-		len;
-
+	    pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
 	wValue = (func << 8) | extra;
 
 	len = usb_control_msg(fc_usb->udev,pipe,
@@ -218,36 +227,35 @@
 	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
 	u16 wValue, wIndex;
 	int nWaitTime,pipe,len;
-//	u8 dwRequestType;
 	u8 request_type = USB_TYPE_VENDOR;
 
 	switch (func) {
-		case USB_FUNC_I2C_WRITE:
-		case USB_FUNC_I2C_MULTIWRITE:
-		case USB_FUNC_I2C_REPEATWRITE:
+	case USB_FUNC_I2C_WRITE:
+	case USB_FUNC_I2C_MULTIWRITE:
+	case USB_FUNC_I2C_REPEATWRITE:
 		/* DKT 020208 - add this to support special case of DiSEqC */
-		case USB_FUNC_I2C_CHECKWRITE:
-			pipe = B2C2_USB_CTRL_PIPE_OUT;
-			nWaitTime = 2;
-//			dwRequestType = (u8) RTYPE_GENERIC;
-			request_type |= USB_DIR_OUT;
+	case USB_FUNC_I2C_CHECKWRITE:
+		pipe = B2C2_USB_CTRL_PIPE_OUT;
+		nWaitTime = 2;
+		request_type |= USB_DIR_OUT;
 		break;
-		case USB_FUNC_I2C_READ:
-		case USB_FUNC_I2C_REPEATREAD:
-			pipe = B2C2_USB_CTRL_PIPE_IN;
-			nWaitTime = 2;
-//			dwRequestType = (u8) RTYPE_GENERIC;
-			request_type |= USB_DIR_IN;
+	case USB_FUNC_I2C_READ:
+	case USB_FUNC_I2C_REPEATREAD:
+		pipe = B2C2_USB_CTRL_PIPE_IN;
+		nWaitTime = 2;
+		request_type |= USB_DIR_IN;
 		break;
-		default:
-			deb_info("unsupported function for i2c_req %x\n",func);
-			return -EINVAL;
+	default:
+		deb_info("unsupported function for i2c_req %x\n", func);
+		return -EINVAL;
 	}
 	wValue = (func << 8) | (i2c->port << 4);
 	wIndex = (chipaddr << 8 ) | addr;
 
-	deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
-		wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8);
+	deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",
+			func, request_type, req,
+			wValue & 0xff, wValue >> 8,
+			wIndex & 0xff, wIndex >> 8);
 
 	len = usb_control_msg(fc_usb->udev,pipe,
 			req,
@@ -257,44 +265,49 @@
 			buf,
 			buflen,
 			nWaitTime * HZ);
-
 	return len == buflen ? 0 : -EREMOTEIO;
 }
 
-/* actual bus specific access functions, make sure prototype are/will be equal to pci */
-static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg)
+/* actual bus specific access functions,
+   make sure prototype are/will be equal to pci */
+static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc,
+	flexcop_ibi_register reg)
 {
 	flexcop_ibi_value val;
 	val.raw = 0;
-	flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1);
+	flexcop_usb_readwrite_dw(fc, reg, &val.raw, 1);
 	return val;
 }
 
-static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val)
+static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc,
+		flexcop_ibi_register reg, flexcop_ibi_value val)
 {
-	return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
+	return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0);
 }
 
 static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
-	flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+		flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
 {
 	if (op == FC_READ)
 		return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
-			USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
+				USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
 	else
 		return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
-			USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
+				USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
 }
 
-static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
+static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb,
+	u8 *buffer, int buffer_length)
 {
 	u8 *b;
 	int l;
 
-	deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length);
+	deb_ts("tmp_buffer_length=%d, buffer_length=%d\n",
+		fc_usb->tmp_buffer_length, buffer_length);
 
 	if (fc_usb->tmp_buffer_length > 0) {
-		memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length);
+		memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer,
+				buffer_length);
 		fc_usb->tmp_buffer_length += buffer_length;
 		b = fc_usb->tmp_buffer;
 		l = fc_usb->tmp_buffer_length;
@@ -304,23 +317,26 @@
 	}
 
 	while (l >= 190) {
-		if (*b == 0xff)
+		if (*b == 0xff) {
 			switch (*(b+1) & 0x03) {
-				case 0x01: /* media packet */
-					if ( *(b+2) == 0x47 )
-						flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1);
-					else
-						deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) );
-
-					b += 190;
-					l -= 190;
+			case 0x01: /* media packet */
+				if (*(b+2) == 0x47)
+					flexcop_pass_dmx_packets(
+							fc_usb->fc_dev, b+2, 1);
+				else
+					deb_ts(
+					"not ts packet %02x %02x %02x %02x \n",
+						*(b+2), *(b+3),
+						*(b+4), *(b+5));
+				b += 190;
+				l -= 190;
 				break;
-				default:
-					deb_ts("wrong packet type\n");
-					l = 0;
+			default:
+				deb_ts("wrong packet type\n");
+				l = 0;
 				break;
 			}
-		else {
+		} else {
 			deb_ts("wrong header\n");
 			l = 0;
 		}
@@ -337,23 +353,26 @@
 	int i;
 
 	if (urb->actual_length > 0)
-		deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length);
+		deb_ts("urb completed, bufsize: %d actlen; %d\n",
+			urb->transfer_buffer_length, urb->actual_length);
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		if (urb->iso_frame_desc[i].status < 0) {
-			err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status);
+			err("iso frame descriptor %d has an error: %d\n", i,
+				urb->iso_frame_desc[i].status);
 		} else
 			if (urb->iso_frame_desc[i].actual_length > 0) {
-				deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length);
+				deb_ts("passed %d bytes to the demux\n",
+					urb->iso_frame_desc[i].actual_length);
 
 				flexcop_usb_process_frame(fc_usb,
-					urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+					urb->transfer_buffer +
+						urb->iso_frame_desc[i].offset,
 					urb->iso_frame_desc[i].actual_length);
-		}
+			}
 		urb->iso_frame_desc[i].status = 0;
 		urb->iso_frame_desc[i].actual_length = 0;
 	}
-
 	usb_submit_urb(urb,GFP_ATOMIC);
 }
 
@@ -374,35 +393,47 @@
 		}
 
 	if (fc_usb->iso_buffer != NULL)
-		pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr);
+		pci_free_consistent(NULL,
+			fc_usb->buffer_size, fc_usb->iso_buffer,
+			fc_usb->dma_addr);
 }
 
 static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
 {
-	u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
-	int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
+	u16 frame_size = le16_to_cpu(
+		fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
+	int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO *
+		frame_size, i, j, ret;
 	int buffer_offset = 0;
 
-	deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
-			B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
+	deb_ts("creating %d iso-urbs with %d frames "
+			"each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB,
+			B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize);
 
-	fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr);
+	fc_usb->iso_buffer = pci_alloc_consistent(NULL,
+			bufsize, &fc_usb->dma_addr);
 	if (fc_usb->iso_buffer == NULL)
 		return -ENOMEM;
+
 	memset(fc_usb->iso_buffer, 0, bufsize);
 	fc_usb->buffer_size = bufsize;
 
 	/* creating iso urbs */
-	for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
-		if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
+	for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
+		fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,
+			GFP_ATOMIC);
+		if (fc_usb->iso_urb[i] == NULL) {
 			ret = -ENOMEM;
 			goto urb_error;
 		}
+	}
+
 	/* initialising and submitting iso urbs */
 	for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
 		int frame_offset = 0;
 		struct urb *urb = fc_usb->iso_urb[i];
-		deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset);
+		deb_ts("initializing and submitting urb no. %d "
+			"(buf_offset: %d).\n", i, buffer_offset);
 
 		urb->dev = fc_usb->udev;
 		urb->context = fc_usb;
@@ -416,26 +447,26 @@
 
 		buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
 		for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
-			deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset);
+			deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",
+					i, j, frame_offset);
 			urb->iso_frame_desc[j].offset = frame_offset;
 			urb->iso_frame_desc[j].length = frame_size;
 			frame_offset += frame_size;
 		}
 
 		if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) {
-			err("submitting urb %d failed with %d.",i,ret);
+			err("submitting urb %d failed with %d.", i, ret);
 			goto urb_error;
 		}
 		deb_ts("submitted urb no. %d.\n",i);
 	}
 
-/* SRAM */
-
-	flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET |
-			FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB);
-	flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
-	flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
-
+	/* SRAM */
+	flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA |
+			FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI,
+			FC_SRAM_DEST_TARGET_WAN_USB);
+	flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS);
+	flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1);
 	return 0;
 
 urb_error:
@@ -448,20 +479,20 @@
 	/* use the alternate setting with the larges buffer */
 	usb_set_interface(fc_usb->udev,0,1);
 	switch (fc_usb->udev->speed) {
-		case USB_SPEED_LOW:
-			err("cannot handle USB speed because it is to sLOW.");
-			return -ENODEV;
-			break;
-		case USB_SPEED_FULL:
-			info("running at FULL speed.");
-			break;
-		case USB_SPEED_HIGH:
-			info("running at HIGH speed.");
-			break;
-		case USB_SPEED_UNKNOWN: /* fall through */
-		default:
-			err("cannot handle USB speed because it is unkown.");
-			return -ENODEV;
+	case USB_SPEED_LOW:
+		err("cannot handle USB speed because it is too slow.");
+		return -ENODEV;
+		break;
+	case USB_SPEED_FULL:
+		info("running at FULL speed.");
+		break;
+	case USB_SPEED_HIGH:
+		info("running at HIGH speed.");
+		break;
+	case USB_SPEED_UNKNOWN: /* fall through */
+	default:
+		err("cannot handle USB speed because it is unknown.");
+		return -ENODEV;
 	}
 	usb_set_intfdata(fc_usb->uintf, fc_usb);
 	return 0;
@@ -485,7 +516,7 @@
 		return -ENOMEM;
 	}
 
-/* general flexcop init */
+	/* general flexcop init */
 	fc_usb = fc->bus_specific;
 	fc_usb->fc_dev = fc;
 
@@ -502,21 +533,21 @@
 	fc->dev = &udev->dev;
 	fc->owner = THIS_MODULE;
 
-/* bus specific part */
+	/* bus specific part */
 	fc_usb->udev = udev;
 	fc_usb->uintf = intf;
 	if ((ret = flexcop_usb_init(fc_usb)) != 0)
 		goto err_kfree;
 
-/* init flexcop */
+	/* init flexcop */
 	if ((ret = flexcop_device_initialize(fc)) != 0)
 		goto err_usb_exit;
 
-/* xfer init */
+	/* xfer init */
 	if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
 		goto err_fc_exit;
 
-	info("%s successfully initialized and connected.",DRIVER_NAME);
+	info("%s successfully initialized and connected.", DRIVER_NAME);
 	return 0;
 
 err_fc_exit:
@@ -535,12 +566,12 @@
 	flexcop_device_exit(fc_usb->fc_dev);
 	flexcop_usb_exit(fc_usb);
 	flexcop_device_kfree(fc_usb->fc_dev);
-	info("%s successfully deinitialized and disconnected.",DRIVER_NAME);
+	info("%s successfully deinitialized and disconnected.", DRIVER_NAME);
 }
 
 static struct usb_device_id flexcop_usb_table [] = {
-	    { USB_DEVICE(0x0af7, 0x0101) },
-	    { }
+	{ USB_DEVICE(0x0af7, 0x0101) },
+	{ }
 };
 MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
 
@@ -557,10 +588,9 @@
 {
 	int result;
 	if ((result = usb_register(&flexcop_usb_driver))) {
-		err("usb_register failed. (%d)",result);
+		err("usb_register failed. (%d)", result);
 		return result;
 	}
-
 	return 0;
 }
 
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h
index 630e647..92529a9 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.h
+++ b/drivers/media/dvb/b2c2/flexcop-usb.h
@@ -1,15 +1,20 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-usb.h - header file for the USB part
+ * see flexcop.c for copyright information
+ */
 #ifndef __FLEXCOP_USB_H_INCLUDED__
 #define __FLEXCOP_USB_H_INCLUDED__
 
 #include <linux/usb.h>
 
 /* transfer parameters */
-#define B2C2_USB_FRAMES_PER_ISO		4
-#define B2C2_USB_NUM_ISO_URB		4
+#define B2C2_USB_FRAMES_PER_ISO 4
+#define B2C2_USB_NUM_ISO_URB 4
 
-#define B2C2_USB_CTRL_PIPE_IN		usb_rcvctrlpipe(fc_usb->udev,0)
-#define B2C2_USB_CTRL_PIPE_OUT		usb_sndctrlpipe(fc_usb->udev,0)
-#define B2C2_USB_DATA_PIPE			usb_rcvisocpipe(fc_usb->udev,0x81)
+#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev, 0)
+#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev, 0)
+#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev, 0x81)
 
 struct flexcop_usb {
 	struct usb_device *udev;
@@ -18,8 +23,8 @@
 	u8 *iso_buffer;
 	int buffer_size;
 	dma_addr_t dma_addr;
-	struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
 
+	struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
 	struct flexcop_device *fc_dev;
 
 	u8 tmp_buffer[1023+190];
@@ -30,14 +35,6 @@
 /* request types TODO What is its use?*/
 typedef enum {
 
-/* something is wrong with this part
-	RTYPE_READ_DW         = (1 << 6),
-	RTYPE_WRITE_DW_1      = (3 << 6),
-	RTYPE_READ_V8_MEMORY  = (6 << 6),
-	RTYPE_WRITE_V8_MEMORY = (7 << 6),
-	RTYPE_WRITE_V8_FLASH  = (8 << 6),
-	RTYPE_GENERIC         = (9 << 6),
-*/
 } flexcop_usb_request_type_t;
 #endif
 
@@ -47,7 +44,6 @@
 	B2C2_USB_READ_V8_MEM  = 0x05,
 	B2C2_USB_READ_REG     = 0x08,
 	B2C2_USB_WRITE_REG    = 0x0A,
-/*	B2C2_USB_WRITEREGLO   = 0x0A, */
 	B2C2_USB_WRITEREGHI   = 0x0B,
 	B2C2_USB_FLASH_BLOCK  = 0x10,
 	B2C2_USB_I2C_REQUEST  = 0x11,
@@ -62,15 +58,13 @@
 	USB_FUNC_I2C_REPEATWRITE = 0x04,
 	USB_FUNC_GET_DESCRIPTOR  = 0x05,
 	USB_FUNC_I2C_REPEATREAD  = 0x06,
-/* DKT 020208 - add this to support special case of DiSEqC */
+	/* DKT 020208 - add this to support special case of DiSEqC */
 	USB_FUNC_I2C_CHECKWRITE  = 0x07,
 	USB_FUNC_I2C_CHECKRESULT = 0x08,
 } flexcop_usb_i2c_function_t;
 
-/*
- * function definition for UTILITY request 0x12
- * DKT 020304 - new utility function
- */
+/* function definition for UTILITY request 0x12
+ * DKT 020304 - new utility function */
 typedef enum {
 	UTILITY_SET_FILTER          = 0x01,
 	UTILITY_DATA_ENABLE         = 0x02,
@@ -84,7 +78,7 @@
 	UTILITY_DATA_RESET          = 0x0A,
 	UTILITY_GET_DATA_STATUS     = 0x10,
 	UTILITY_GET_V8_REG          = 0x11,
-/* DKT 020326 - add function for v1.14 */
+	/* DKT 020326 - add function for v1.14 */
 	UTILITY_SRAM_WRITE          = 0x12,
 	UTILITY_SRAM_READ           = 0x13,
 	UTILITY_SRAM_TESTFILL       = 0x14,
@@ -92,13 +86,13 @@
 	UTILITY_SRAM_TESTVERIFY     = 0x16,
 } flexcop_usb_utility_function_t;
 
-#define B2C2_WAIT_FOR_OPERATION_RW  1*HZ       /* 1 s */
-#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ       /* 3 s */
-#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ       /* 1 s */
+#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ)
+#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ)
+#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ)
 
-#define B2C2_WAIT_FOR_OPERATION_V8READ   3*HZ  /* 3 s */
-#define B2C2_WAIT_FOR_OPERATION_V8WRITE  3*HZ  /* 3 s */
-#define B2C2_WAIT_FOR_OPERATION_V8FLASH  3*HZ  /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ)
+#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ)
+#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ)
 
 typedef enum {
 	V8_MEMORY_PAGE_DVB_CI = 0x20,
@@ -107,13 +101,11 @@
 	V8_MEMORY_PAGE_FLASH  = 0x80
 } flexcop_usb_mem_page_t;
 
-#define V8_MEMORY_EXTENDED      (1 << 15)
-
-#define USB_MEM_READ_MAX                32
-#define USB_MEM_WRITE_MAX               1
-#define USB_FLASH_MAX                   8
-
-#define V8_MEMORY_PAGE_SIZE     0x8000      // 32K
-#define V8_MEMORY_PAGE_MASK     0x7FFF
+#define V8_MEMORY_EXTENDED (1 << 15)
+#define USB_MEM_READ_MAX   32
+#define USB_MEM_WRITE_MAX   1
+#define USB_FLASH_MAX       8
+#define V8_MEMORY_PAGE_SIZE 0x8000 /* 32K */
+#define V8_MEMORY_PAGE_MASK 0x7FFF
 
 #endif
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 9106895..2df1b02 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -1,22 +1,20 @@
 /*
- * flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de>
- *
- * based on the skystar2-driver
- * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop.c - main module part
+ * Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de>
+ * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
  *
  * Acknowledgements:
- *     John Jurrius from BBTI, Inc. for extensive support with
- *         code examples and data books
- *
- *     Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
+ *   John Jurrius from BBTI, Inc. for extensive support
+ *                    with code examples and data books
+ *   Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
  *
  * Contributions to the skystar2-driver have been done by
- *     Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
- *     Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
- *     Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering)
- *
+ *   Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
+ *   Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
+ *   Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu)
+ *   Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac
+ *               filtering)
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -46,7 +44,10 @@
 
 int b2c2_flexcop_debug;
 module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug,
+		"set debug level (1=info,2=tuner,4=i2c,8=ts,"
+		"16=sram,32=reg (|-able))."
+		DEBSTATUS);
 #undef DEBSTATUS
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -57,37 +58,36 @@
 static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct flexcop_device *fc = dvbdmxfeed->demux->priv;
-	return flexcop_pid_feed_control(fc,dvbdmxfeed,1);
+	return flexcop_pid_feed_control(fc, dvbdmxfeed, 1);
 }
 
 static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct flexcop_device *fc = dvbdmxfeed->demux->priv;
-	return flexcop_pid_feed_control(fc,dvbdmxfeed,0);
+	return flexcop_pid_feed_control(fc, dvbdmxfeed, 0);
 }
 
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
 	int ret = dvb_register_adapter(&fc->dvb_adapter,
-				       "FlexCop Digital TV device", fc->owner,
-				       fc->dev, adapter_nr);
+			"FlexCop Digital TV device", fc->owner,
+			fc->dev, adapter_nr);
 	if (ret < 0) {
 		err("error registering DVB adapter");
 		return ret;
 	}
 	fc->dvb_adapter.priv = fc;
 
-	fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+	fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING
+			| DMX_MEMORY_BASED_FILTERING);
 	fc->demux.priv = fc;
-
 	fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED;
-
 	fc->demux.start_feed = flexcop_dvb_start_feed;
 	fc->demux.stop_feed = flexcop_dvb_stop_feed;
 	fc->demux.write_to_decoder = NULL;
 
 	if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
-		err("dvb_dmx failed: error %d",ret);
+		err("dvb_dmx failed: error %d", ret);
 		goto err_dmx;
 	}
 
@@ -97,23 +97,23 @@
 	fc->dmxdev.demux = &fc->demux.dmx;
 	fc->dmxdev.capabilities = 0;
 	if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
-		err("dvb_dmxdev_init failed: error %d",ret);
+		err("dvb_dmxdev_init failed: error %d", ret);
 		goto err_dmx_dev;
 	}
 
 	if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
-		err("adding hw_frontend to dmx failed: error %d",ret);
+		err("adding hw_frontend to dmx failed: error %d", ret);
 		goto err_dmx_add_hw_frontend;
 	}
 
 	fc->mem_frontend.source = DMX_MEMORY_FE;
 	if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) {
-		err("adding mem_frontend to dmx failed: error %d",ret);
+		err("adding mem_frontend to dmx failed: error %d", ret);
 		goto err_dmx_add_mem_frontend;
 	}
 
 	if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
-		err("connect frontend failed: error %d",ret);
+		err("connect frontend failed: error %d", ret);
 		goto err_connect_frontend;
 	}
 
@@ -123,9 +123,9 @@
 	return 0;
 
 err_connect_frontend:
-	fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
+	fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend);
 err_dmx_add_mem_frontend:
-	fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+	fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend);
 err_dmx_add_hw_frontend:
 	dvb_dmxdev_release(&fc->dmxdev);
 err_dmx_dev:
@@ -141,12 +141,13 @@
 		dvb_net_release(&fc->dvbnet);
 
 		fc->demux.dmx.close(&fc->demux.dmx);
-		fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
-		fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+		fc->demux.dmx.remove_frontend(&fc->demux.dmx,
+			&fc->mem_frontend);
+		fc->demux.dmx.remove_frontend(&fc->demux.dmx,
+			&fc->hw_frontend);
 		dvb_dmxdev_release(&fc->dmxdev);
 		dvb_dmx_release(&fc->demux);
 		dvb_unregister_adapter(&fc->dvb_adapter);
-
 		deb_info("deinitialized dvb stuff\n");
 	}
 	fc->init_state &= ~FC_STATE_DVB_INIT;
@@ -168,9 +169,9 @@
 
 static void flexcop_reset(struct flexcop_device *fc)
 {
-	flexcop_ibi_value v210,v204;
+	flexcop_ibi_value v210, v204;
 
-/* reset the flexcop itself */
+	/* reset the flexcop itself */
 	fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
 
 	v210.raw = 0;
@@ -183,13 +184,11 @@
 	v210.sw_reset_210.reset_block_600 = 1;
 	v210.sw_reset_210.reset_block_700 = 1;
 	v210.sw_reset_210.Block_reset_enable = 0xb2;
-
 	v210.sw_reset_210.Special_controls = 0xc259;
-
 	fc->write_ibi_reg(fc,sw_reset_210,v210);
 	msleep(1);
 
-/* reset the periphical devices */
+	/* reset the periphical devices */
 
 	v204 = fc->read_ibi_reg(fc,misc_204);
 	v204.misc_204.Per_reset_sig = 0;
@@ -201,25 +200,24 @@
 
 void flexcop_reset_block_300(struct flexcop_device *fc)
 {
-	flexcop_ibi_value v208_save = fc->read_ibi_reg(fc,ctrl_208),
-					  v210 = fc->read_ibi_reg(fc,sw_reset_210);
+	flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208),
+			  v210 = fc->read_ibi_reg(fc, sw_reset_210);
 
-	deb_rdump("208: %08x, 210: %08x\n",v208_save.raw,v210.raw);
-
+	deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw);
 	fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
 
 	v210.sw_reset_210.reset_block_300 = 1;
 	v210.sw_reset_210.Block_reset_enable = 0xb2;
 
 	fc->write_ibi_reg(fc,sw_reset_210,v210);
-	udelay(1000);
 	fc->write_ibi_reg(fc,ctrl_208,v208_save);
 }
 
 struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
 {
 	void *bus;
-	struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), GFP_KERNEL);
+	struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device),
+				GFP_KERNEL);
 	if (!fc) {
 		err("no memory");
 		return NULL;
@@ -254,7 +252,6 @@
 	flexcop_determine_revision(fc);
 	flexcop_sram_init(fc);
 	flexcop_hw_filter_init(fc);
-
 	flexcop_smc_ctrl(fc, 0);
 
 	if ((ret = flexcop_dvb_init(fc)))
@@ -279,7 +276,6 @@
 		goto error;
 
 	flexcop_device_name(fc,"initialization of","complete");
-
 	return 0;
 
 error:
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h
index 0cebe1d..897b10c 100644
--- a/drivers/media/dvb/b2c2/flexcop.h
+++ b/drivers/media/dvb/b2c2/flexcop.h
@@ -1,9 +1,7 @@
 /*
- * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
- * flexcop.h - private header file for all flexcop-chip-source files.
- *
- * see flexcop.c for copyright information.
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop.h - private header file for all flexcop-chip-source files
+ * see flexcop.c for copyright information
  */
 #ifndef __FLEXCOP_H__
 #define __FLEXCOP_H___
@@ -21,11 +19,11 @@
 #define dprintk(level,args...)
 #endif
 
-#define deb_info(args...)  dprintk(0x01,args)
-#define deb_tuner(args...) dprintk(0x02,args)
-#define deb_i2c(args...)   dprintk(0x04,args)
-#define deb_ts(args...)    dprintk(0x08,args)
-#define deb_sram(args...)  dprintk(0x10,args)
-#define deb_rdump(args...)  dprintk(0x20,args)
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_tuner(args...) dprintk(0x02, args)
+#define deb_i2c(args...) dprintk(0x04, args)
+#define deb_ts(args...) dprintk(0x08, args)
+#define deb_sram(args...) dprintk(0x10, args)
+#define deb_rdump(args...) dprintk(0x20, args)
 
 #endif
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
index ed9a675..8f64bdb 100644
--- a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
+++ b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
@@ -1,10 +1,7 @@
-/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  * register descriptions
- *
- * see flexcop.c for copyright information.
+ * see flexcop.c for copyright information
  */
-
 /* This file is automatically generated, do not edit things here. */
 #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
 #define __FLEXCOP_IBI_VALUE_INCLUDED__
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
index 49f2315..c75830d 100644
--- a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
+++ b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
@@ -1,10 +1,7 @@
-/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- *
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
  * register descriptions
- *
- * see flexcop.c for copyright information.
+ * see flexcop.c for copyright information
  */
-
 /* This file is automatically generated, do not edit things here. */
 #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
 #define __FLEXCOP_IBI_VALUE_INCLUDED__
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 27edb0e..8668e63 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -8,7 +8,7 @@
 	select DVB_OR51211 if !DVB_FE_CUSTOMISE
 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Support for PCI cards based on the Bt8xx PCI bridge. Examples are
 	  the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 0258451..4601b05 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -552,16 +552,19 @@
 	return result;
 }
 
-static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg)
+static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg)
 {
-	struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
-	struct dst_state* state = (struct dst_state*) dvbdev->priv;
+	struct dvb_device *dvbdev;
+	struct dst_state *state;
 	struct ca_slot_info *p_ca_slot_info;
 	struct ca_caps *p_ca_caps;
 	struct ca_msg *p_ca_message;
 	void __user *arg = (void __user *)ioctl_arg;
 	int result = 0;
 
+	lock_kernel();
+	dvbdev = (struct dvb_device *)file->private_data;
+	state = (struct dst_state *)dvbdev->priv;
 	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
 	p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
 	p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
@@ -647,6 +650,7 @@
 	kfree (p_ca_slot_info);
 	kfree (p_ca_caps);
 
+	unlock_kernel();
 	return result;
 }
 
@@ -682,9 +686,9 @@
 	return 0;
 }
 
-static struct file_operations dst_ca_fops = {
+static const struct file_operations dst_ca_fops = {
 	.owner = THIS_MODULE,
-	.ioctl = dst_ca_ioctl,
+	.unlocked_ioctl = dst_ca_ioctl,
 	.open = dst_ca_open,
 	.release = dst_ca_release,
 	.read = dst_ca_read,
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 48762a2..b1857c1 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -814,7 +814,7 @@
 
 	mutex_init(&card->lock);
 	card->bttv_nr = sub->core->nr;
-	strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
+	strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));
 	card->i2c_adapter = &sub->core->i2c_adap;
 
 	switch(sub->core->type) {
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
index 43f4d44..de3eeb0 100644
--- a/drivers/media/dvb/dm1105/Kconfig
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -8,6 +8,7 @@
 	select DVB_STB6000 if !DVB_FE_CUSTOMISE
 	select DVB_CX24116 if !DVB_FE_CUSTOMISE
 	select DVB_SI21XX if !DVB_FE_CUSTOMISE
+	select VIDEO_IR
 	help
 	  Support for cards based on the SDMC DM1105 PCI chip like
 	  DvbWorld 2002
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index f48f73a..5b20cf5 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -156,46 +156,12 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static u16 ir_codes_dm1105_nec[128] = {
-	[0x0a] = KEY_Q,		/*power*/
-	[0x0c] = KEY_M,		/*mute*/
-	[0x11] = KEY_1,
-	[0x12] = KEY_2,
-	[0x13] = KEY_3,
-	[0x14] = KEY_4,
-	[0x15] = KEY_5,
-	[0x16] = KEY_6,
-	[0x17] = KEY_7,
-	[0x18] = KEY_8,
-	[0x19] = KEY_9,
-	[0x10] = KEY_0,
-	[0x1c] = KEY_PAGEUP,	/*ch+*/
-	[0x0f] = KEY_PAGEDOWN,	/*ch-*/
-	[0x1a] = KEY_O,		/*vol+*/
-	[0x0e] = KEY_Z,		/*vol-*/
-	[0x04] = KEY_R,		/*rec*/
-	[0x09] = KEY_D,		/*fav*/
-	[0x08] = KEY_BACKSPACE,	/*rewind*/
-	[0x07] = KEY_A,		/*fast*/
-	[0x0b] = KEY_P,		/*pause*/
-	[0x02] = KEY_ESC,	/*cancel*/
-	[0x03] = KEY_G,		/*tab*/
-	[0x00] = KEY_UP,	/*up*/
-	[0x1f] = KEY_ENTER,	/*ok*/
-	[0x01] = KEY_DOWN,	/*down*/
-	[0x05] = KEY_C,		/*cap*/
-	[0x06] = KEY_S,		/*stop*/
-	[0x40] = KEY_F,		/*full*/
-	[0x1e] = KEY_W,		/*tvmode*/
-	[0x1b] = KEY_B,		/*recall*/
-};
-
 /* infrared remote control */
 struct infrared {
-	u16	key_map[128];
 	struct input_dev	*input_dev;
+	struct ir_input_state	ir;
 	char			input_phys[32];
-	struct tasklet_struct	ir_tasklet;
+	struct work_struct	work;
 	u32			ir_command;
 };
 
@@ -220,10 +186,14 @@
 	/* i2c */
 	struct i2c_adapter i2c_adap;
 
+	/* irq */
+	struct work_struct work;
+
 	/* dma */
 	dma_addr_t dma_addr;
 	unsigned char *ts_buf;
 	u32 wrp;
+	u32 nextwrp;
 	u32 buffer_size;
 	unsigned int	PacketErrorCount;
 	unsigned int dmarst;
@@ -233,8 +203,6 @@
 
 #define dm_io_mem(reg)	((unsigned long)(&dm1105dvb->io_mem[reg]))
 
-static struct dm1105dvb *dm1105dvb_local;
-
 static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
 			    struct i2c_msg *msgs, int num)
 {
@@ -407,38 +375,61 @@
 	return 0;
 }
 
-/* ir tasklet */
-static void dm1105_emit_key(unsigned long parm)
+/* ir work handler */
+static void dm1105_emit_key(struct work_struct *work)
 {
-	struct infrared *ir = (struct infrared *) parm;
+	struct infrared *ir = container_of(work, struct infrared, work);
 	u32 ircom = ir->ir_command;
 	u8 data;
-	u16 keycode;
+
+	if (ir_debug)
+		printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
 
 	data = (ircom >> 8) & 0x7f;
 
-	input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
-	input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
-	keycode = ir->key_map[data];
+	ir_input_keydown(ir->input_dev, &ir->ir, data, data);
+	ir_input_nokey(ir->input_dev, &ir->ir);
+}
 
-	if (!keycode)
-		return;
+/* work handler */
+static void dm1105_dmx_buffer(struct work_struct *work)
+{
+	struct dm1105dvb *dm1105dvb =
+				container_of(work, struct dm1105dvb, work);
+	unsigned int nbpackets;
+	u32 oldwrp = dm1105dvb->wrp;
+	u32 nextwrp = dm1105dvb->nextwrp;
 
-	input_event(ir->input_dev, EV_KEY, keycode, 1);
-	input_sync(ir->input_dev);
-	input_event(ir->input_dev, EV_KEY, keycode, 0);
-	input_sync(ir->input_dev);
+	if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
+			(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
+			(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+		dm1105dvb->PacketErrorCount++;
+		/* bad packet found */
+		if ((dm1105dvb->PacketErrorCount >= 2) &&
+				(dm1105dvb->dmarst == 0)) {
+			outb(1, dm_io_mem(DM1105_RST));
+			dm1105dvb->wrp = 0;
+			dm1105dvb->PacketErrorCount = 0;
+			dm1105dvb->dmarst = 0;
+			return;
+		}
+	}
 
+	if (nextwrp < oldwrp) {
+		memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
+						dm1105dvb->ts_buf, nextwrp);
+		nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
+	} else
+		nbpackets = (nextwrp - oldwrp) / 188;
+
+	dm1105dvb->wrp = nextwrp;
+	dvb_dmx_swfilter_packets(&dm1105dvb->demux,
+					&dm1105dvb->ts_buf[oldwrp], nbpackets);
 }
 
 static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
 {
 	struct dm1105dvb *dm1105dvb = dev_id;
-	unsigned int piece;
-	unsigned int nbpackets;
-	u32 command;
-	u32 nextwrp;
-	u32 oldwrp;
 
 	/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
 	unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
@@ -447,71 +438,25 @@
 	switch (intsts) {
 	case INTSTS_TSIRQ:
 	case (INTSTS_TSIRQ | INTSTS_IR):
-		nextwrp = inl(dm_io_mem(DM1105_WRP)) -
-			inl(dm_io_mem(DM1105_STADR)) ;
-		oldwrp = dm1105dvb->wrp;
-		spin_lock(&dm1105dvb->lock);
-		if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
-				(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
-				(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
-			dm1105dvb->PacketErrorCount++;
-			/* bad packet found */
-			if ((dm1105dvb->PacketErrorCount >= 2) &&
-					(dm1105dvb->dmarst == 0)) {
-				outb(1, dm_io_mem(DM1105_RST));
-				dm1105dvb->wrp = 0;
-				dm1105dvb->PacketErrorCount = 0;
-				dm1105dvb->dmarst = 0;
-				spin_unlock(&dm1105dvb->lock);
-				return IRQ_HANDLED;
-			}
-		}
-		if (nextwrp < oldwrp) {
-			piece = dm1105dvb->buffer_size - oldwrp;
-			memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
-			nbpackets = (piece + nextwrp)/188;
-		} else	{
-			nbpackets = (nextwrp - oldwrp)/188;
-		}
-		dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
-		dm1105dvb->wrp = nextwrp;
-		spin_unlock(&dm1105dvb->lock);
+		dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
+					inl(dm_io_mem(DM1105_STADR));
+		schedule_work(&dm1105dvb->work);
 		break;
 	case INTSTS_IR:
-		command = inl(dm_io_mem(DM1105_IRCODE));
-		if (ir_debug)
-			printk("dm1105: received byte 0x%04x\n", command);
-
-		dm1105dvb->ir.ir_command = command;
-		tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
+		dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
+		schedule_work(&dm1105dvb->ir.work);
 		break;
 	}
+
 	return IRQ_HANDLED;
-
-
-}
-
-/* register with input layer */
-static void input_register_keys(struct infrared *ir)
-{
-	int i;
-
-	memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
-
-	for (i = 0; i < ARRAY_SIZE(ir->key_map); i++)
-			set_bit(ir->key_map[i], ir->input_dev->keybit);
-
-	ir->input_dev->keycode = ir->key_map;
-	ir->input_dev->keycodesize = sizeof(ir->key_map[0]);
-	ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
 }
 
 int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
 {
 	struct input_dev *input_dev;
-	int err;
-
-	dm1105dvb_local = dm1105;
+	IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec;
+	int ir_type = IR_TYPE_OTHER;
+	int err = -ENOMEM;
 
 	input_dev = input_allocate_device();
 	if (!input_dev)
@@ -521,12 +466,11 @@
 	snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
 		"pci-%s/ir0", pci_name(dm1105->pdev));
 
-	input_dev->evbit[0] = BIT(EV_KEY);
+	ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes);
 	input_dev->name = "DVB on-card IR receiver";
-
 	input_dev->phys = dm1105->ir.input_phys;
 	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 2;
+	input_dev->id.version = 1;
 	if (dm1105->pdev->subsystem_vendor) {
 		input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
 		input_dev->id.product = dm1105->pdev->subsystem_device;
@@ -534,25 +478,22 @@
 		input_dev->id.vendor = dm1105->pdev->vendor;
 		input_dev->id.product = dm1105->pdev->device;
 	}
+
 	input_dev->dev.parent = &dm1105->pdev->dev;
-	/* initial keymap */
-	memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map);
-	input_register_keys(&dm1105->ir);
+
+	INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
+
 	err = input_register_device(input_dev);
 	if (err) {
 		input_free_device(input_dev);
 		return err;
 	}
 
-	tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
-
 	return 0;
 }
 
-
 void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
 {
-	tasklet_kill(&dm1105->ir.ir_tasklet);
 	input_unregister_device(dm1105->ir.input_dev);
 
 }
@@ -710,7 +651,7 @@
 
 	dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
 	if (!dm1105dvb)
-		goto out;
+		return -ENOMEM;
 
 	dm1105dvb->pdev = pdev;
 	dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
@@ -740,13 +681,9 @@
 	spin_lock_init(&dm1105dvb->lock);
 	pci_set_drvdata(pdev, dm1105dvb);
 
-	ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
-	if (ret < 0)
-		goto err_pci_iounmap;
-
 	ret = dm1105dvb_hw_init(dm1105dvb);
 	if (ret < 0)
-		goto err_free_irq;
+		goto err_pci_iounmap;
 
 	/* i2c */
 	i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
@@ -813,8 +750,15 @@
 
 	dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
 	dm1105_ir_init(dm1105dvb);
-out:
-	return ret;
+
+	INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
+
+	ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
+						DRIVER_NAME, dm1105dvb);
+	if (ret < 0)
+		goto err_free_irq;
+
+	return 0;
 
 err_disconnect_frontend:
 	dmx->disconnect_frontend(dmx);
@@ -843,7 +787,7 @@
 err_kfree:
 	pci_set_drvdata(pdev, NULL);
 	kfree(dm1105dvb);
-	goto out;
+	return ret;
 }
 
 static void __devexit dm1105_remove(struct pci_dev *pdev)
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 069d847..c35fbb8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1024,7 +1024,7 @@
 	return ret;
 }
 
-static struct file_operations dvb_demux_fops = {
+static const struct file_operations dvb_demux_fops = {
 	.owner = THIS_MODULE,
 	.read = dvb_demux_read,
 	.ioctl = dvb_demux_ioctl,
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 7e3aeaa..cb22da5 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1607,7 +1607,7 @@
 EXPORT_SYMBOL(dvb_ca_en50221_init);
 
 
-static struct file_operations dvb_ca_fops = {
+static const struct file_operations dvb_ca_fops = {
 	.owner = THIS_MODULE,
 	.read = dvb_ca_en50221_io_read,
 	.write = dvb_ca_en50221_io_write,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8dcb3fb..ebc7815 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1875,7 +1875,7 @@
 	return ret;
 }
 
-static struct file_operations dvb_frontend_fops = {
+static const struct file_operations dvb_frontend_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= dvb_generic_ioctl,
 	.poll		= dvb_frontend_poll,
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index f6ba846..8280f8d 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1459,7 +1459,7 @@
 }
 
 
-static struct file_operations dvb_net_fops = {
+static const struct file_operations dvb_net_fops = {
 	.owner = THIS_MODULE,
 	.ioctl = dvb_net_ioctl,
 	.open =	dvb_generic_open,
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 6a32680..a454ee8 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -228,8 +228,8 @@
 	dvbdev->fops = dvbdevfops;
 	init_waitqueue_head (&dvbdev->wait_queue);
 
-	memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
-	dvbdev->fops->owner = adap->module;
+	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
+	dvbdevfops->owner = adap->module;
 
 	list_add_tail (&dvbdev->list_head, &adap->device_list);
 
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index dca49cf..7992730 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -71,7 +71,7 @@
 
 struct dvb_device {
 	struct list_head list_head;
-	struct file_operations *fops;
+	const struct file_operations *fops;
 	struct dvb_adapter *adapter;
 	int type;
 	int minor;
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 49f7b20..6103caa 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -25,7 +25,7 @@
 	depends on DVB_USB
 	select DVB_DIB3000MC
 	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
 
@@ -34,7 +34,7 @@
 	depends on DVB_USB
 	select DVB_PLL if !DVB_FE_CUSTOMISE
 	select DVB_DIB3000MB
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
 	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -55,7 +55,7 @@
 	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
 	depends on DVB_USB
 	select DVB_DIB3000MC
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Support for USB2.0 DVB-T receivers based on reference designs made by
 	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -69,15 +69,17 @@
 config DVB_USB_DIB0700
 	tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
 	depends on DVB_USB
-	select DVB_DIB7000P
-	select DVB_DIB7000M
-	select DVB_DIB3000MC
+	select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+	select DVB_DIB7000M if !DVB_FE_CUSTOMISE
+	select DVB_DIB3000MC if !DVB_FE_CUSTOMISE
 	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-	select DVB_TUNER_DIB0070
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
+	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+	select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
 	  USB bridge is also present in devices having the DiB7700 DVB-T-USB
@@ -95,7 +97,8 @@
 	depends on DVB_USB
 	select DVB_PLL if !DVB_FE_CUSTOMISE
 	select DVB_DIB3000MC
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
+	select DVB_MT352 if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
@@ -108,10 +111,11 @@
 	select DVB_MT352 if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+	select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE
 	select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
 	  Currently, only DVB and ATSC modes are supported, analog mode
@@ -125,8 +129,8 @@
 	depends on DVB_USB
 	select DVB_MT352 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
 	  Currently, only devices with a product id of
@@ -137,7 +141,7 @@
 	tristate "Genesys Logic GL861 USB2.0 support"
 	depends on DVB_USB
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
 	  receiver with USB ID 0db0:5581.
@@ -146,7 +150,7 @@
 	tristate "Alcor Micro AU6610 USB2.0 support"
 	depends on DVB_USB
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
 
@@ -199,7 +203,7 @@
 	depends on DVB_USB
 	select DVB_DIB3000MC
 	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
 
@@ -235,8 +239,8 @@
 config DVB_USB_AF9005
 	tristate "Afatech AF9005 DVB-T USB1.1 support"
 	depends on DVB_USB && EXPERIMENTAL
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
 	  and the TerraTec Cinergy T USB XE (Rev.1)
@@ -284,7 +288,7 @@
 	tristate "AME DTV-5100 USB2.0 DVB-T support"
 	depends on DVB_USB
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
 
@@ -293,9 +297,18 @@
 	depends on DVB_USB && EXPERIMENTAL
 	select DVB_AF9013
 	select DVB_PLL              if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2060   if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_QT1010   if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MT2060   if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_QT1010   if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
 	help
 	  Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
+
+config DVB_USB_CE6230
+	tristate "Intel CE6230 DVB-T USB2.0 support"
+	depends on DVB_USB && EXPERIMENTAL
+	select DVB_ZL10353
+	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
+	help
+	  Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 3122b7c..f92734e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -76,6 +76,8 @@
 dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
 obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
 
+dvb-usb-ce6230-objs = ce6230.o
+obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 6a97a40..f0ba8b0 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -27,9 +27,7 @@
 #include "qt1010.h"
 #include "tda18271.h"
 #include "mxl5005s.h"
-#if 0
-#include "mc44s80x.h"
-#endif
+#include "mc44s803.h"
 
 static int dvb_usb_af9015_debug;
 module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
@@ -37,9 +35,6 @@
 static int dvb_usb_af9015_remote;
 module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
 MODULE_PARM_DESC(remote, "select remote");
-static int dvb_usb_af9015_dual_mode;
-module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);
-MODULE_PARM_DESC(dual_mode, "enable dual mode");
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static DEFINE_MUTEX(af9015_usb_mutex);
@@ -283,6 +278,21 @@
 			req.data = &msg[i+1].buf[0];
 			ret = af9015_ctrl_msg(d, &req);
 			i += 2;
+		} else if (msg[i].flags & I2C_M_RD) {
+			ret = -EINVAL;
+			if (msg[i].addr ==
+				af9015_af9013_config[0].demod_address)
+				goto error;
+			else
+				req.cmd = READ_I2C;
+			req.i2c_addr = msg[i].addr;
+			req.addr = addr;
+			req.mbox = mbox;
+			req.addr_len = addr_len;
+			req.data_len = msg[i].len;
+			req.data = &msg[i].buf[0];
+			ret = af9015_ctrl_msg(d, &req);
+			i += 1;
 		} else {
 			if (msg[i].addr ==
 				af9015_af9013_config[0].demod_address)
@@ -748,6 +758,16 @@
 				af9015_config.ir_table_size =
 				  ARRAY_SIZE(af9015_ir_table_digittrade);
 				break;
+			case AF9015_REMOTE_AVERMEDIA_KS:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_avermedia;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_avermedia);
+				af9015_config.ir_table =
+				  af9015_ir_table_avermedia_ks;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_avermedia_ks);
+				break;
 			}
 		} else {
 			switch (le16_to_cpu(udev->descriptor.idVendor)) {
@@ -836,9 +856,6 @@
 		goto error;
 	af9015_config.dual_mode = val;
 	deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
-	/* disable dual mode by default because it is buggy */
-	if (!dvb_usb_af9015_dual_mode)
-		af9015_config.dual_mode = 0;
 
 	/* Set adapter0 buffer size according to USB port speed, adapter1 buffer
 	   size can be static because it is enabled only USB2.0 */
@@ -935,7 +952,6 @@
 		switch (val) {
 		case AF9013_TUNER_ENV77H11D5:
 		case AF9013_TUNER_MT2060:
-		case AF9013_TUNER_MC44S803:
 		case AF9013_TUNER_QT1010:
 		case AF9013_TUNER_UNKNOWN:
 		case AF9013_TUNER_MT2060_2:
@@ -948,6 +964,10 @@
 		case AF9013_TUNER_MXL5005R:
 			af9015_af9013_config[i].rf_spec_inv = 0;
 			break;
+		case AF9013_TUNER_MC44S803:
+			af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
+			af9015_af9013_config[i].rf_spec_inv = 1;
+			break;
 		default:
 			warn("tuner id:%d not supported, please report!", val);
 			return -ENODEV;
@@ -1135,6 +1155,11 @@
 	.AgcMasterByte   = 0x00,
 };
 
+static struct mc44s803_config af9015_mc44s803_config = {
+	.i2c_address = 0xc0,
+	.dig_out = 1,
+};
+
 static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	struct af9015_state *state = adap->dev->priv;
@@ -1179,15 +1204,8 @@
 			DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_MC44S803:
-#if 0
-		ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap)
-			== NULL ? -ENODEV : 0;
-#else
-		ret = -ENODEV;
-		info("Freescale MC44S803 tuner found but no driver for that" \
-			"tuner. Look at the Linuxtv.org for tuner driver" \
-			"status.");
-#endif
+		ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
+			&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
 		break;
 	case AF9013_TUNER_UNKNOWN:
 	default:
@@ -1218,6 +1236,7 @@
 	{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
 /* 15 */{USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGI_VOX_MINI_III)},
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U)},
+	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_2)},
 	{0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1417,7 +1436,8 @@
 			{
 				.name = "KWorld USB DVB-T TV Stick II " \
 					"(VS-DVB-T 395U)",
-				.cold_ids = {&af9015_usb_table[16], NULL},
+				.cold_ids = {&af9015_usb_table[16],
+					     &af9015_usb_table[17], NULL},
 				.warm_ids = {NULL},
 			},
 		}
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index 21c7782..00e2571 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -124,6 +124,7 @@
 	AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
 	AF9015_REMOTE_MYGICTV_U718,
 	AF9015_REMOTE_DIGITTRADE_DVB_T,
+	AF9015_REMOTE_AVERMEDIA_KS,
 };
 
 /* Leadtek WinFast DTV Dongle Gold */
@@ -597,6 +598,36 @@
 	0x03, 0xfc, 0x03, 0xfc, 0x0e, 0x05, 0x00,
 };
 
+static u8 af9015_ir_table_avermedia_ks[] = {
+	0x05, 0xfa, 0x01, 0xfe, 0x12, 0x05, 0x00,
+	0x05, 0xfa, 0x02, 0xfd, 0x0e, 0x05, 0x00,
+	0x05, 0xfa, 0x03, 0xfc, 0x0d, 0x05, 0x00,
+	0x05, 0xfa, 0x04, 0xfb, 0x2e, 0x05, 0x00,
+	0x05, 0xfa, 0x05, 0xfa, 0x2d, 0x05, 0x00,
+	0x05, 0xfa, 0x06, 0xf9, 0x10, 0x05, 0x00,
+	0x05, 0xfa, 0x07, 0xf8, 0x0f, 0x05, 0x00,
+	0x05, 0xfa, 0x08, 0xf7, 0x3d, 0x05, 0x00,
+	0x05, 0xfa, 0x09, 0xf6, 0x1e, 0x05, 0x00,
+	0x05, 0xfa, 0x0a, 0xf5, 0x1f, 0x05, 0x00,
+	0x05, 0xfa, 0x0b, 0xf4, 0x20, 0x05, 0x00,
+	0x05, 0xfa, 0x0c, 0xf3, 0x21, 0x05, 0x00,
+	0x05, 0xfa, 0x0d, 0xf2, 0x22, 0x05, 0x00,
+	0x05, 0xfa, 0x0e, 0xf1, 0x23, 0x05, 0x00,
+	0x05, 0xfa, 0x0f, 0xf0, 0x24, 0x05, 0x00,
+	0x05, 0xfa, 0x10, 0xef, 0x25, 0x05, 0x00,
+	0x05, 0xfa, 0x11, 0xee, 0x26, 0x05, 0x00,
+	0x05, 0xfa, 0x12, 0xed, 0x27, 0x05, 0x00,
+	0x05, 0xfa, 0x13, 0xec, 0x04, 0x05, 0x00,
+	0x05, 0xfa, 0x15, 0xea, 0x0a, 0x05, 0x00,
+	0x05, 0xfa, 0x16, 0xe9, 0x11, 0x05, 0x00,
+	0x05, 0xfa, 0x17, 0xe8, 0x15, 0x05, 0x00,
+	0x05, 0xfa, 0x18, 0xe7, 0x16, 0x05, 0x00,
+	0x05, 0xfa, 0x1c, 0xe3, 0x05, 0x05, 0x00,
+	0x05, 0xfa, 0x1d, 0xe2, 0x09, 0x05, 0x00,
+	0x05, 0xfa, 0x4d, 0xb2, 0x3f, 0x05, 0x00,
+	0x05, 0xfa, 0x56, 0xa9, 0x3e, 0x05, 0x00
+};
+
 /* Digittrade DVB-T USB Stick */
 static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = {
 	{ 0x01, 0x0f, KEY_LAST },	/* RETURN */
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c
new file mode 100644
index 0000000..5862820
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/ce6230.c
@@ -0,0 +1,328 @@
+/*
+ * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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 "ce6230.h"
+#include "zl10353.h"
+#include "mxl5005s.h"
+
+/* debug */
+static int dvb_usb_ce6230_debug;
+module_param_named(debug, dvb_usb_ce6230_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct zl10353_config ce6230_zl10353_config;
+
+static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
+{
+	int ret;
+	unsigned int pipe;
+	u8 request;
+	u8 requesttype;
+	u16 value;
+	u16 index;
+	u8 buf[req->data_len];
+
+	request = req->cmd;
+	value = req->value;
+	index = req->index;
+
+	switch (req->cmd) {
+	case I2C_READ:
+	case DEMOD_READ:
+	case REG_READ:
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
+		break;
+	case I2C_WRITE:
+	case DEMOD_WRITE:
+	case REG_WRITE:
+		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
+		break;
+	default:
+		err("unknown command:%02x", req->cmd);
+		ret = -EPERM;
+		goto error;
+	}
+
+	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
+		/* write */
+		memcpy(buf, req->data, req->data_len);
+		pipe = usb_sndctrlpipe(udev, 0);
+	} else {
+		/* read */
+		pipe = usb_rcvctrlpipe(udev, 0);
+	}
+
+	msleep(1); /* avoid I2C errors */
+
+	ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
+				buf, sizeof(buf), CE6230_USB_TIMEOUT);
+
+	ce6230_debug_dump(request, requesttype, value, index, buf,
+		req->data_len, deb_xfer);
+
+	if (ret < 0)
+		deb_info("%s: usb_control_msg failed:%d\n", __func__, ret);
+	else
+		ret = 0;
+
+	/* read request, copy returned data to return buf */
+	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
+		memcpy(req->data, buf, req->data_len);
+
+error:
+	return ret;
+}
+
+static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
+{
+	return ce6230_rw_udev(d->udev, req);
+}
+
+/* I2C */
+static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+			   int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i = 0;
+	struct req_t req;
+	int ret = 0;
+	memset(&req, 0, sizeof(&req));
+
+	if (num > 2)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	while (i < num) {
+		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+			if (msg[i].addr ==
+				ce6230_zl10353_config.demod_address) {
+				req.cmd = DEMOD_READ;
+				req.value = msg[i].addr >> 1;
+				req.index = msg[i].buf[0];
+				req.data_len = msg[i+1].len;
+				req.data = &msg[i+1].buf[0];
+				ret = ce6230_ctrl_msg(d, &req);
+			} else {
+				err("i2c read not implemented");
+				ret = -EPERM;
+			}
+			i += 2;
+		} else {
+			if (msg[i].addr ==
+				ce6230_zl10353_config.demod_address) {
+				req.cmd = DEMOD_WRITE;
+				req.value = msg[i].addr >> 1;
+				req.index = msg[i].buf[0];
+				req.data_len = msg[i].len-1;
+				req.data = &msg[i].buf[1];
+				ret = ce6230_ctrl_msg(d, &req);
+			} else {
+				req.cmd = I2C_WRITE;
+				req.value = 0x2000 + (msg[i].addr >> 1);
+				req.index = 0x0000;
+				req.data_len = msg[i].len;
+				req.data = &msg[i].buf[0];
+				ret = ce6230_ctrl_msg(d, &req);
+			}
+			i += 1;
+		}
+		if (ret)
+			break;
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return ret ? ret : i;
+}
+
+static u32 ce6230_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm ce6230_i2c_algo = {
+	.master_xfer   = ce6230_i2c_xfer,
+	.functionality = ce6230_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static struct zl10353_config ce6230_zl10353_config = {
+	.demod_address = 0x1e,
+	.adc_clock = 450000,
+	.if2 = 45700,
+	.no_tuner = 1,
+	.parallel_ts = 1,
+	.clock_ctl_1 = 0x34,
+	.pll_0 = 0x0e,
+};
+
+static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	deb_info("%s:\n", __func__);
+	adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+		&adap->dev->i2c_adap);
+	if (adap->fe == NULL)
+		return -ENODEV;
+	return 0;
+}
+
+static struct mxl5005s_config ce6230_mxl5003s_config = {
+	.i2c_address     = 0xc6,
+	.if_freq         = IF_FREQ_4570000HZ,
+	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+	.agc_mode        = MXL_SINGLE_AGC,
+	.tracking_filter = MXL_TF_DEFAULT,
+	.rssi_enable     = MXL_RSSI_ENABLE,
+	.cap_select      = MXL_CAP_SEL_ENABLE,
+	.div_out         = MXL_DIV_OUT_4,
+	.clock_out       = MXL_CLOCK_OUT_DISABLE,
+	.output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+	.top		 = MXL5005S_TOP_25P2,
+	.mod_mode        = MXL_DIGITAL_MODE,
+	.if_mode         = MXL_ZERO_IF,
+	.AgcMasterByte   = 0x00,
+};
+
+static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	int ret;
+	deb_info("%s:\n", __func__);
+	ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
+			&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
+	return ret;
+}
+
+static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	int ret;
+	deb_info("%s: onoff:%d\n", __func__, onoff);
+
+	/* InterfaceNumber 1 / AlternateSetting 0     idle
+	   InterfaceNumber 1 / AlternateSetting 1     streaming */
+	ret = usb_set_interface(d->udev, 1, onoff);
+	if (ret)
+		err("usb_set_interface failed with error:%d", ret);
+
+	return ret;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties ce6230_properties;
+
+static int ce6230_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	int ret = 0;
+	struct dvb_usb_device *d = NULL;
+
+	deb_info("%s: interface:%d\n", __func__,
+		intf->cur_altsetting->desc.bInterfaceNumber);
+
+	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+		ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE,
+			&d, adapter_nr);
+		if (ret)
+			err("init failed with error:%d\n", ret);
+	}
+
+	return ret;
+}
+
+static struct usb_device_id ce6230_table[] = {
+	{ USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) },
+	{ } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ce6230_table);
+
+static struct dvb_usb_device_properties ce6230_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.no_reconnect = 1,
+
+	.size_of_priv = 0,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.frontend_attach  = ce6230_zl10353_frontend_attach,
+			.tuner_attach     = ce6230_mxl5003s_tuner_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 6,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 512,
+					}
+				}
+			},
+		}
+	},
+
+	.power_ctrl = ce6230_power_ctrl,
+
+	.i2c_algo = &ce6230_i2c_algo,
+
+	.num_device_descs = 1,
+	.devices = {
+		{
+			.name = "Intel CE9500 reference design",
+			.cold_ids = {NULL},
+			.warm_ids = {&ce6230_table[0], NULL},
+		},
+	}
+};
+
+static struct usb_driver ce6230_driver = {
+	.name       = "dvb_usb_ce6230",
+	.probe      = ce6230_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table   = ce6230_table,
+};
+
+/* module stuff */
+static int __init ce6230_module_init(void)
+{
+	int ret;
+	deb_info("%s:\n", __func__);
+	ret = usb_register(&ce6230_driver);
+	if (ret)
+		err("usb_register failed with error:%d", ret);
+
+	return ret;
+}
+
+static void __exit ce6230_module_exit(void)
+{
+	deb_info("%s:\n", __func__);
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&ce6230_driver);
+}
+
+module_init(ce6230_module_init);
+module_exit(ce6230_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ce6230.h b/drivers/media/dvb/dvb-usb/ce6230.h
new file mode 100644
index 0000000..97c4248
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/ce6230.h
@@ -0,0 +1,69 @@
+/*
+ * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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.
+ *
+ */
+
+#ifndef _DVB_USB_CE6230_H_
+#define _DVB_USB_CE6230_H_
+
+#define DVB_USB_LOG_PREFIX "ce6230"
+#include "dvb-usb.h"
+
+#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args)
+#define deb_rc(args...)   dprintk(dvb_usb_ce6230_debug, 0x02, args)
+#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args)
+#define deb_reg(args...)  dprintk(dvb_usb_ce6230_debug, 0x08, args)
+#define deb_i2c(args...)  dprintk(dvb_usb_ce6230_debug, 0x10, args)
+#define deb_fw(args...)   dprintk(dvb_usb_ce6230_debug, 0x20, args)
+
+#define ce6230_debug_dump(r, t, v, i, b, l, func) { \
+	int loop_; \
+	func("%02x %02x %02x %02x %02x %02x %02x %02x", \
+		t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
+	if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
+		func(" >>> "); \
+	else \
+		func(" <<< "); \
+	for (loop_ = 0; loop_ < l; loop_++) \
+		func("%02x ", b[loop_]); \
+	func("\n");\
+}
+
+#define CE6230_USB_TIMEOUT 1000
+
+struct req_t {
+	u8  cmd;       /* [1] */
+	u16 value;     /* [2|3] */
+	u16 index;     /* [4|5] */
+	u16 data_len;  /* [6|7] */
+	u8  *data;
+};
+
+enum ce6230_cmd {
+	CONFIG_READ          = 0xd0, /* rd 0 (unclear) */
+	UNKNOWN_WRITE        = 0xc7, /* wr 7 (unclear) */
+	I2C_READ             = 0xd9, /* rd 9 (unclear) */
+	I2C_WRITE            = 0xca, /* wr a */
+	DEMOD_READ           = 0xdb, /* rd b */
+	DEMOD_WRITE          = 0xcc, /* wr c */
+	REG_READ             = 0xde, /* rd e */
+	REG_WRITE            = 0xcf, /* wr f */
+};
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 200b215..db7f7f7 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -158,6 +158,10 @@
 				err("i2c read error (status = %d)\n", result);
 				break;
 			}
+
+			deb_data("<<< ");
+			debug_dump(msg[i].buf, msg[i].len, deb_data);
+
 		} else {
 			/* Write request */
 			buf[0] = REQUEST_NEW_I2C_WRITE;
@@ -169,6 +173,9 @@
 			/* The Actual i2c payload */
 			memcpy(&buf[4], msg[i].buf, msg[i].len);
 
+			deb_data(">>> ");
+			debug_dump(buf, msg[i].len + 4, deb_data);
+
 			result = usb_control_msg(d->udev,
 						 usb_sndctrlpipe(d->udev, 0),
 						 REQUEST_NEW_I2C_WRITE,
@@ -211,7 +218,8 @@
 
 			/* special thing in the current firmware: when length is zero the read-failed */
 			if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
-				deb_info("I2C read failed on address %x\n", msg[i].addr);
+				deb_info("I2C read failed on address 0x%02x\n",
+					 msg[i].addr);
 				break;
 			}
 
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 635d30a..8ddbadf 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -17,6 +17,8 @@
 #include "xc5000.h"
 #include "s5h1411.h"
 #include "dib0070.h"
+#include "lgdt3305.h"
+#include "mxl5007t.h"
 
 static int force_lna_activation;
 module_param(force_lna_activation, int, 0644);
@@ -262,7 +264,12 @@
 		msleep(10);
 		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 		msleep(10);
-		dib7000p_i2c_enumeration(&adap->dev->i2c_adap,1,18,stk7700d_dib7000p_mt2266_config);
+		if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+					     stk7700d_dib7000p_mt2266_config)
+		    != 0) {
+			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+			return -ENODEV;
+		}
 	}
 
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
@@ -284,7 +291,12 @@
 		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
 		msleep(10);
 		dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-		dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config);
+		if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+					     stk7700d_dib7000p_mt2266_config)
+		    != 0) {
+			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+			return -ENODEV;
+		}
 	}
 
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
@@ -421,8 +433,12 @@
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 	msleep(10);
 
-	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-		&stk7700ph_dib7700_xc3028_config);
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+				     &stk7700ph_dib7700_xc3028_config) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		    __func__);
+		return -ENODEV;
+	}
 
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&stk7700ph_dib7700_xc3028_config);
@@ -1187,8 +1203,12 @@
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-		&dib7070p_dib7000p_config);
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+				     &dib7070p_dib7000p_config) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		    __func__);
+		return -ENODEV;
+	}
 
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
 		&dib7070p_dib7000p_config);
@@ -1244,7 +1264,12 @@
 	msleep(10);
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
-	dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config);
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+				     stk7070pd_dib7000p_config) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
+		    __func__);
+		return -ENODEV;
+	}
 
 	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
 	return adap->fe == NULL ? -ENODEV : 0;
@@ -1347,6 +1372,72 @@
 		== NULL ? -ENODEV : 0;
 }
 
+static struct lgdt3305_config hcw_lgdt3305_config = {
+	.i2c_addr           = 0x0e,
+	.mpeg_mode          = LGDT3305_MPEG_PARALLEL,
+	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_LOW,
+	.deny_i2c_rptr      = 0,
+	.spectral_inversion = 1,
+	.qam_if_khz         = 6000,
+	.vsb_if_khz         = 6000,
+	.usref_8vsb         = 0x0500,
+};
+
+static struct mxl5007t_config hcw_mxl5007t_config = {
+	.xtal_freq_hz = MxL_XTAL_25_MHZ,
+	.if_freq_hz = MxL_IF_6_MHZ,
+	.invert_if = 1,
+};
+
+/* TIGER-ATSC map:
+   GPIO0  - LNA_CTR  (H: LNA power enabled, L: LNA power disabled)
+   GPIO1  - ANT_SEL  (H: VPA, L: MCX)
+   GPIO4  - SCL2
+   GPIO6  - EN_TUNER
+   GPIO7  - SDA2
+   GPIO10 - DEM_RST
+
+   MXL is behind LG's i2c repeater.  LG is on SCL2/SDA2 gpios on the DIB
+ */
+static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_state *st = adap->dev->priv;
+
+	/* Make use of the new i2c functions from FW 1.20 */
+	st->fw_use_new_i2c_api = 1;
+
+	st->disable_streaming_master_mode = 1;
+
+	/* fe power enable */
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+	msleep(30);
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(30);
+
+	/* demod reset */
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(30);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+	msleep(30);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(30);
+
+	adap->fe = dvb_attach(lgdt3305_attach,
+			      &hcw_lgdt3305_config,
+			      &adap->dev->i2c_adap);
+
+	return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	return dvb_attach(mxl5007t_attach, adap->fe,
+			  &adap->dev->i2c_adap, 0x60,
+			  &hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
+}
+
+
 /* DVB-USB and USB stuff follows */
 struct usb_device_id dib0700_usb_id_table[] = {
 /* 0 */	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
@@ -1396,6 +1487,12 @@
 	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_EXPRESS) },
 	{ USB_DEVICE(USB_VID_TERRATEC,
 			USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) },
+	{ USB_DEVICE(USB_VID_SONY,	USB_PID_SONY_PLAYTV) },
+/* 45 */{ USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_PD378S) },
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) },
+	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) },
+	{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_MC770) },
+	{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1595,7 +1692,7 @@
 			},
 		},
 
-		.num_device_descs = 9,
+		.num_device_descs = 11,
 		.devices = {
 			{   "DiBcom STK7070P reference design",
 				{ &dib0700_usb_id_table[15], NULL },
@@ -1633,6 +1730,14 @@
 				{ &dib0700_usb_id_table[33], NULL },
 				{ NULL },
 			},
+			{   "Elgato EyeTV DTT",
+				{ &dib0700_usb_id_table[49], NULL },
+				{ NULL },
+			},
+			{   "Yuan PD378S",
+				{ &dib0700_usb_id_table[45], NULL },
+				{ NULL },
+			},
 		},
 
 		.rc_interval      = DEFAULT_RC_INTERVAL,
@@ -1661,7 +1766,7 @@
 			}
 		},
 
-		.num_device_descs = 5,
+		.num_device_descs = 6,
 		.devices = {
 			{   "DiBcom STK7070PD reference design",
 				{ &dib0700_usb_id_table[17], NULL },
@@ -1682,8 +1787,16 @@
 			{  "Terratec Cinergy DT USB XS Diversity",
 				{ &dib0700_usb_id_table[43], NULL },
 				{ NULL },
+			},
+			{  "Sony PlayTV",
+				{ &dib0700_usb_id_table[44], NULL },
+				{ NULL },
 			}
-		}
+		},
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = dib0700_rc_keys,
+		.rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+		.rc_query         = dib0700_rc_query
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 1,
@@ -1699,7 +1812,7 @@
 			},
 		},
 
-		.num_device_descs = 5,
+		.num_device_descs = 7,
 		.devices = {
 			{   "Terratec Cinergy HT USB XE",
 				{ &dib0700_usb_id_table[27], NULL },
@@ -1725,6 +1838,10 @@
 				{ &dib0700_usb_id_table[39], NULL },
 				{ NULL },
 			},
+			{   "YUAN High-Tech MC770",
+				{ &dib0700_usb_id_table[48], NULL },
+				{ NULL },
+			},
 		},
 		.rc_interval      = DEFAULT_RC_INTERVAL,
 		.rc_key_map       = dib0700_rc_keys,
@@ -1759,6 +1876,31 @@
 		.rc_key_map       = dib0700_rc_keys,
 		.rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
 		.rc_query         = dib0700_rc_query
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.frontend_attach  = lgdt3305_frontend_attach,
+				.tuner_attach     = mxl5007t_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv = sizeof(struct
+						dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 2,
+		.devices = {
+			{   "Hauppauge ATSC MiniCard (B200)",
+				{ &dib0700_usb_id_table[46], NULL },
+				{ NULL },
+			},
+			{   "Hauppauge ATSC MiniCard (B210)",
+				{ &dib0700_usb_id_table[47], NULL },
+				{ NULL },
+			},
+		},
 	},
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 0db0c06..dc7ea21 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -27,12 +27,14 @@
 #define USB_VID_DIBCOM				0x10b8
 #define USB_VID_DPOSH				0x1498
 #define USB_VID_DVICO				0x0fe9
+#define USB_VID_ELGATO				0x0fd9
 #define USB_VID_EMPIA				0xeb1a
 #define USB_VID_GENPIX				0x09c0
 #define USB_VID_GRANDTEC			0x5032
 #define USB_VID_HANFTEK				0x15f4
 #define USB_VID_HAUPPAUGE			0x2040
 #define USB_VID_HYPER_PALTEK			0x1025
+#define USB_VID_INTEL				0x8086
 #define USB_VID_KWORLD				0xeb2a
 #define USB_VID_KWORLD_2			0x1b80
 #define USB_VID_KYE				0x0458
@@ -48,6 +50,7 @@
 #define USB_VID_TERRATEC			0x0ccd
 #define USB_VID_TELESTAR			0x10b9
 #define USB_VID_VISIONPLUS			0x13d3
+#define USB_VID_SONY				0x1415
 #define USB_VID_TWINHAN				0x1822
 #define USB_VID_ULTIMA_ELECTRONIC		0x05d8
 #define USB_VID_UNIWILL				0x1584
@@ -95,8 +98,10 @@
 #define USB_PID_UNIWILL_STK7700P			0x6003
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
+#define USB_PID_INTEL_CE9500				0x9500
 #define USB_PID_KWORLD_399U				0xe399
 #define USB_PID_KWORLD_395U				0xe396
+#define USB_PID_KWORLD_395U_2				0xe39b
 #define USB_PID_KWORLD_PC160_2T				0xc160
 #define USB_PID_KWORLD_VSTREAM_COLD			0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df
@@ -149,6 +154,8 @@
 #define USB_PID_HAUPPAUGE_MYTV_T			0x7080
 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK			0x9580
 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009		0x5200
+#define USB_PID_HAUPPAUGE_TIGER_ATSC			0xb200
+#define USB_PID_HAUPPAUGE_TIGER_ATSC_B210		0xb210
 #define USB_PID_AVERMEDIA_EXPRESS			0xb568
 #define USB_PID_AVERMEDIA_VOLAR				0xa807
 #define USB_PID_AVERMEDIA_VOLAR_2			0xb808
@@ -232,9 +239,13 @@
 #define USB_PID_ASUS_U3100				0x173f
 #define USB_PID_YUAN_EC372S				0x1edc
 #define USB_PID_YUAN_STK7700PH				0x1f08
+#define USB_PID_YUAN_PD378S				0x2edc
+#define USB_PID_YUAN_MC770				0x0871
 #define USB_PID_DW2102					0x2102
 #define USB_PID_XTENSIONS_XD_380			0x0381
 #define USB_PID_TELESTAR_STARSTICK_2			0x8000
 #define USB_PID_MSI_DIGI_VOX_MINI_III                   0x8807
+#define USB_PID_SONY_PLAYTV				0x0003
+#define USB_PID_ELGATO_EYETV_DTT			0x0021
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index b1de0f7..2d5352e 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -223,7 +223,7 @@
 	int generic_bulk_ctrl_endpoint;
 
 	int num_device_descs;
-	struct dvb_usb_device_description devices[9];
+	struct dvb_usb_device_description devices[11];
 };
 
 /**
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 32526f1..12f7730 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -151,7 +151,7 @@
 		subunit_type = data[1] >> 3;
 		subunit_id = data[1] & 7;
 		op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
-		printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
+		printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n",
 		       prefix, subunit_type, subunit_id, length,
 		       debug_fcp_ctype(data[0]),
 		       debug_fcp_opcode(op, data, length));
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 0026956..a206cee 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -1,17 +1,21 @@
-menu "Customise DVB Frontends"
-	depends on DVB_CORE
-
 config DVB_FE_CUSTOMISE
 	bool "Customise the frontend modules to build"
+	depends on DVB_CORE
 	default N
 	help
-	  This allows the user to deselect frontend drivers unnecessary
-	  for their hardware from the build. Use this option with care
-	  as deselecting frontends which are in fact necessary will result
-	  in DVB devices which cannot be tuned due to lack of driver support.
+	  This allows the user to select/deselect frontend drivers for their
+	  hardware from the build.
+
+	  Use this option with care as deselecting frontends which are in fact
+	  necessary will result in DVB devices which cannot be tuned due to lack
+	  of driver support.
 
 	  If unsure say N.
 
+if DVB_FE_CUSTOMISE
+
+menu "Customise DVB Frontends"
+
 comment "Multistandard (satellite) frontends"
 	depends on DVB_CORE
 
@@ -55,6 +59,13 @@
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_ZL10036
+	tristate "Zarlink ZL10036 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
 config DVB_S5H1420
 	tristate "Samsung S5H1420 based"
 	depends on DVB_CORE && I2C
@@ -83,6 +94,20 @@
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_STV6110
+	tristate "ST STV6110 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	  help
+	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_STV0900
+	tristate "ST STV0900 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S/S2 demodulator. Say Y when you want to support this frontend.
+
 config DVB_TDA8083
 	tristate "Philips TDA8083 based"
 	depends on DVB_CORE && I2C
@@ -288,6 +313,13 @@
 	help
 	  A DVB-T tuner module. Say Y when you want to support this frontend.
 
+config DVB_AF9013
+	tristate "Afatech AF9013 demodulator"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
 	depends on DVB_CORE
 
@@ -387,6 +419,14 @@
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+config DVB_LGDT3305
+	tristate "LG Electronics LGDT3305 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
 config DVB_S5H1409
 	tristate "Samsung S5H1409 based"
 	depends on DVB_CORE && I2C
@@ -397,7 +437,7 @@
 
 config DVB_AU8522
 	tristate "Auvitek AU8522 based"
-	depends on DVB_CORE && I2C
+	depends on DVB_CORE && I2C && VIDEO_V4L2
 	default m if DVB_FE_CUSTOMISE
 	help
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -446,11 +486,11 @@
 	depends on DVB_CORE
 
 config DVB_LNBP21
-	tristate "LNBP21 SEC controller"
+	tristate "LNBP21/LNBH24 SEC controllers"
 	depends on DVB_CORE && I2C
 	default m if DVB_FE_CUSTOMISE
 	help
-	  An SEC control chip.
+	  An SEC control chips.
 
 config DVB_ISL6405
 	tristate "ISL6405 SEC controller"
@@ -478,11 +518,6 @@
 config DVB_DUMMY_FE
 	tristate "Dummy frontend driver"
 	default n
-
-config DVB_AF9013
-	tristate "Afatech AF9013 demodulator"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
 endmenu
+
+endif
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index af7bdf0..65a336a 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -7,6 +7,8 @@
 
 s921-objs := s921_module.o s921_core.o
 stb0899-objs = stb0899_drv.o stb0899_algo.o
+stv0900-objs = stv0900_core.o stv0900_sw.o
+au8522-objs = au8522_dig.o au8522_decoder.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -28,6 +30,7 @@
 obj-$(CONFIG_DVB_SP887X) += sp887x.o
 obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
 obj-$(CONFIG_DVB_MT352) += mt352.o
+obj-$(CONFIG_DVB_ZL10036) += zl10036.o
 obj-$(CONFIG_DVB_ZL10353) += zl10353.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
 obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
@@ -41,6 +44,7 @@
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
+obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
 obj-$(CONFIG_DVB_ISL6405) += isl6405.o
@@ -64,4 +68,6 @@
 obj-$(CONFIG_DVB_STV0288) += stv0288.o
 obj-$(CONFIG_DVB_STB6000) += stb6000.o
 obj-$(CONFIG_DVB_S921) += s921.o
+obj-$(CONFIG_DVB_STV6110) += stv6110.o
+obj-$(CONFIG_DVB_STV0900) += stv0900.o
 
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
index 7b94f55..565dcf3 100644
--- a/drivers/media/dvb/frontends/au8522.h
+++ b/drivers/media/dvb/frontends/au8522.h
@@ -74,6 +74,22 @@
 }
 #endif /* CONFIG_DVB_AU8522 */
 
+/* Other modes may need to be added later */
+enum au8522_video_input {
+	AU8522_COMPOSITE_CH1 = 1,
+	AU8522_COMPOSITE_CH2,
+	AU8522_COMPOSITE_CH3,
+	AU8522_COMPOSITE_CH4,
+	AU8522_COMPOSITE_CH4_SIF,
+	AU8522_SVIDEO_CH13,
+	AU8522_SVIDEO_CH24,
+};
+
+enum au8522_audio_input {
+	AU8522_AUDIO_NONE,
+	AU8522_AUDIO_SIF,
+};
+
 #endif /* __AU8522_H__ */
 
 /*
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
new file mode 100644
index 0000000..d63e152
--- /dev/null
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -0,0 +1,835 @@
+/*
+ * Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
+ *
+ * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
+ * Copyright (C) 2005-2008 Auvitek International, 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Developer notes:
+ *
+ * VBI support is not yet working
+ * Saturation and hue setting are not yet working
+ * Enough is implemented here for CVBS and S-Video inputs, but the actual
+ *  analog demodulator code isn't implemented (not needed for xc5000 since it
+ *  has its own demodulator and outputs CVBS)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
+#include <media/v4l2-device.h>
+#include "au8522.h"
+#include "au8522_priv.h"
+
+MODULE_AUTHOR("Devin Heitmueller");
+MODULE_LICENSE("GPL");
+
+static int au8522_analog_debug;
+
+
+module_param_named(analog_debug, au8522_analog_debug, int, 0644);
+
+MODULE_PARM_DESC(analog_debug,
+		 "Analog debugging messages [0=Off (default) 1=On]");
+
+struct au8522_register_config {
+	u16 reg_name;
+	u8 reg_val[8];
+};
+
+
+/* Video Decoder Filter Coefficients
+   The values are as follows from left to right
+   0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
+*/
+struct au8522_register_config filter_coef[] = {
+	{AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
+	{AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
+	{AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
+	{AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
+	{AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
+	{AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
+	{AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
+	{AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
+	{AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
+	{AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
+	{AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
+	{AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
+	{AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
+	{AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
+	{AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
+	{AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
+	{AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
+	{AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
+	{AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
+	{AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
+	{AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
+	{AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
+
+};
+#define NUM_FILTER_COEF (sizeof(filter_coef)\
+			 / sizeof(struct au8522_register_config))
+
+
+/* Registers 0x060b through 0x0652 are the LP Filter coefficients
+   The values are as follows from left to right
+   0="SIF" 1="ATVRF/ATVRF13"
+   Note: the "ATVRF/ATVRF13" mode has never been tested
+*/
+struct au8522_register_config lpfilter_coef[] = {
+	{0x060b, {0x21, 0x0b} },
+	{0x060c, {0xad, 0xad} },
+	{0x060d, {0x70, 0xf0} },
+	{0x060e, {0xea, 0xe9} },
+	{0x060f, {0xdd, 0xdd} },
+	{0x0610, {0x08, 0x64} },
+	{0x0611, {0x60, 0x60} },
+	{0x0612, {0xf8, 0xb2} },
+	{0x0613, {0x01, 0x02} },
+	{0x0614, {0xe4, 0xb4} },
+	{0x0615, {0x19, 0x02} },
+	{0x0616, {0xae, 0x2e} },
+	{0x0617, {0xee, 0xc5} },
+	{0x0618, {0x56, 0x56} },
+	{0x0619, {0x30, 0x58} },
+	{0x061a, {0xf9, 0xf8} },
+	{0x061b, {0x24, 0x64} },
+	{0x061c, {0x07, 0x07} },
+	{0x061d, {0x30, 0x30} },
+	{0x061e, {0xa9, 0xed} },
+	{0x061f, {0x09, 0x0b} },
+	{0x0620, {0x42, 0xc2} },
+	{0x0621, {0x1d, 0x2a} },
+	{0x0622, {0xd6, 0x56} },
+	{0x0623, {0x95, 0x8b} },
+	{0x0624, {0x2b, 0x2b} },
+	{0x0625, {0x30, 0x24} },
+	{0x0626, {0x3e, 0x3e} },
+	{0x0627, {0x62, 0xe2} },
+	{0x0628, {0xe9, 0xf5} },
+	{0x0629, {0x99, 0x19} },
+	{0x062a, {0xd4, 0x11} },
+	{0x062b, {0x03, 0x04} },
+	{0x062c, {0xb5, 0x85} },
+	{0x062d, {0x1e, 0x20} },
+	{0x062e, {0x2a, 0xea} },
+	{0x062f, {0xd7, 0xd2} },
+	{0x0630, {0x15, 0x15} },
+	{0x0631, {0xa3, 0xa9} },
+	{0x0632, {0x1f, 0x1f} },
+	{0x0633, {0xf9, 0xd1} },
+	{0x0634, {0xc0, 0xc3} },
+	{0x0635, {0x4d, 0x8d} },
+	{0x0636, {0x21, 0x31} },
+	{0x0637, {0x83, 0x83} },
+	{0x0638, {0x08, 0x8c} },
+	{0x0639, {0x19, 0x19} },
+	{0x063a, {0x45, 0xa5} },
+	{0x063b, {0xef, 0xec} },
+	{0x063c, {0x8a, 0x8a} },
+	{0x063d, {0xf4, 0xf6} },
+	{0x063e, {0x8f, 0x8f} },
+	{0x063f, {0x44, 0x0c} },
+	{0x0640, {0xef, 0xf0} },
+	{0x0641, {0x66, 0x66} },
+	{0x0642, {0xcc, 0xd2} },
+	{0x0643, {0x41, 0x41} },
+	{0x0644, {0x63, 0x93} },
+	{0x0645, {0x8e, 0x8e} },
+	{0x0646, {0xa2, 0x42} },
+	{0x0647, {0x7b, 0x7b} },
+	{0x0648, {0x04, 0x04} },
+	{0x0649, {0x00, 0x00} },
+	{0x064a, {0x40, 0x40} },
+	{0x064b, {0x8c, 0x98} },
+	{0x064c, {0x00, 0x00} },
+	{0x064d, {0x63, 0xc3} },
+	{0x064e, {0x04, 0x04} },
+	{0x064f, {0x20, 0x20} },
+	{0x0650, {0x00, 0x00} },
+	{0x0651, {0x40, 0x40} },
+	{0x0652, {0x01, 0x01} },
+};
+#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
+			   / sizeof(struct au8522_register_config))
+
+static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct au8522_state, sd);
+}
+
+static void setup_vbi(struct au8522_state *state, int aud_input)
+{
+	int i;
+
+	/* These are set to zero regardless of what mode we're in */
+	au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,
+			0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
+			0x00);
+	au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
+			0x00);
+
+	/* Setup the VBI registers */
+	for (i = 0x30; i < 0x60; i++)
+		au8522_writereg(state, i, 0x40);
+
+	/* For some reason, every register is 0x40 except register 0x44
+	   (confirmed via the HVR-950q USB capture) */
+	au8522_writereg(state, 0x44, 0x60);
+
+	/* Enable VBI (we always do this regardless of whether the user is
+	   viewing closed caption info) */
+	au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
+			AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
+
+}
+
+static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
+{
+	int i;
+	int filter_coef_type;
+
+	/* Provide reasonable defaults for picture tuning values */
+	au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
+	au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
+	state->brightness = 0xed - 128;
+	au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
+	state->contrast = 0x79;
+	au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
+	au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
+	au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
+
+	/* Other decoder registers */
+	au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
+
+	if (input_mode == 0x23) {
+		/* S-Video input mapping */
+		au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
+	} else {
+		/* All other modes (CVBS/ATVRF etc.) */
+		au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
+	}
+
+	au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
+			AU8522_TVDEC_PGA_REG012H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
+			AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
+	au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
+			AU8522_TVDED_DBG_MODE_REG060H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+			AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
+	au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+			AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
+	au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
+			AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
+			AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
+			AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
+			AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
+			AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
+			AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
+			AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
+			AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
+			AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
+			AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
+			AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
+			AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
+			AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
+			AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
+	au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
+	au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
+			AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
+	au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
+	au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
+			AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
+			AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
+			AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
+			AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
+			AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
+	au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
+			AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
+	au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
+			AU8522_TOREGAAGC_REG0E5H_CVBS);
+	au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
+
+	setup_vbi(state, 0);
+
+	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
+	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+		/* Despite what the table says, for the HVR-950q we still need
+		   to be in CVBS mode for the S-Video input (reason uknown). */
+		/* filter_coef_type = 3; */
+		filter_coef_type = 5;
+	} else {
+		filter_coef_type = 5;
+	}
+
+	/* Load the Video Decoder Filter Coefficients */
+	for (i = 0; i < NUM_FILTER_COEF; i++) {
+		au8522_writereg(state, filter_coef[i].reg_name,
+				filter_coef[i].reg_val[filter_coef_type]);
+	}
+
+	/* It's not clear what these registers are for, but they are always
+	   set to the same value regardless of what mode we're in */
+	au8522_writereg(state, AU8522_REG42EH, 0x87);
+	au8522_writereg(state, AU8522_REG42FH, 0xa2);
+	au8522_writereg(state, AU8522_REG430H, 0xbf);
+	au8522_writereg(state, AU8522_REG431H, 0xcb);
+	au8522_writereg(state, AU8522_REG432H, 0xa1);
+	au8522_writereg(state, AU8522_REG433H, 0x41);
+	au8522_writereg(state, AU8522_REG434H, 0x88);
+	au8522_writereg(state, AU8522_REG435H, 0xc2);
+	au8522_writereg(state, AU8522_REG436H, 0x3c);
+}
+
+static void au8522_setup_cvbs_mode(struct au8522_state *state)
+{
+	/* here we're going to try the pre-programmed route */
+	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
+
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
+
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+			AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+
+	setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
+{
+	/* here we're going to try the pre-programmed route */
+	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
+
+	/* It's not clear why they turn off the PGA before enabling the clamp
+	   control, but the Windows trace does it so we will too... */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+	/* Enable clamping control */
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
+
+	/* Turn on the PGA */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
+
+	/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+			AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+
+	setup_decoder_defaults(state,
+			       AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+static void au8522_setup_svideo_mode(struct au8522_state *state)
+{
+	au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
+			AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
+
+	/* Set input to Y on Channe1, C on Channel 3 */
+	au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
+			AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+
+	/* Disable clamping control (required for S-video) */
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
+
+	setup_decoder_defaults(state,
+			       AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void disable_audio_input(struct au8522_state *state)
+{
+	/* This can probably be optimized */
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
+	au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
+	au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
+
+	au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+	au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
+	au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
+
+	au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
+	msleep(5);
+	au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
+	au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
+	au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+}
+
+/* 0=disable, 1=SIF */
+static void set_audio_input(struct au8522_state *state, int aud_input)
+{
+	int i;
+
+	/* Note that this function needs to be used in conjunction with setting
+	   the input routing via register 0x81 */
+
+	if (aud_input == AU8522_AUDIO_NONE) {
+		disable_audio_input(state);
+		return;
+	}
+
+	if (aud_input != AU8522_AUDIO_SIF) {
+		/* The caller asked for a mode we don't currently support */
+		printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
+		       aud_input);
+		return;
+	}
+
+	/* Load the Audio Decoder Filter Coefficients */
+	for (i = 0; i < NUM_LPFILTER_COEF; i++) {
+		au8522_writereg(state, lpfilter_coef[i].reg_name,
+				lpfilter_coef[i].reg_val[0]);
+	}
+
+	/* Setup audio */
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
+	au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
+	au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
+	msleep(150);
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
+	msleep(1);
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
+	msleep(50);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
+	msleep(80);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
+	au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
+	au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
+	au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
+	msleep(70);
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
+	au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
+	au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct au8522_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		state->brightness = ctrl->value;
+		au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
+				ctrl->value - 128);
+		break;
+	case V4L2_CID_CONTRAST:
+		state->contrast = ctrl->value;
+		au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
+				ctrl->value);
+		break;
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_MUTE:
+		/* Not yet implemented */
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct au8522_state *state = to_state(sd);
+
+	/* Note that we are using values cached in the state structure instead
+	   of reading the registers due to issues with i2c reads not working
+	   properly/consistently yet on the HVR-950q */
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = state->brightness;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctrl->value = state->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_MUTE:
+		/* Not yet supported */
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	switch (fmt->type) {
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	switch (fmt->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		/* Not yet implemented */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int au8522_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct au8522_state *state = to_state(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	reg->val = au8522_readreg(state, reg->reg & 0xffff);
+	return 0;
+}
+
+static int au8522_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct au8522_state *state = to_state(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	au8522_writereg(state, reg->reg, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct au8522_state *state = to_state(sd);
+
+	if (enable) {
+		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+				0x01);
+		msleep(1);
+		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+				AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+	} else {
+		/* This does not completely power down the device
+		   (it only reduces it from around 140ma to 80ma) */
+		au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+				1 << 5);
+	}
+	return 0;
+}
+
+static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	case V4L2_CID_CONTRAST:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1,
+					    AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+		/* Not yet implemented */
+	default:
+		break;
+	}
+
+	qc->type = 0;
+	return -EINVAL;
+}
+
+static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct au8522_state *state = to_state(sd);
+
+	au8522_writereg(state, 0xa4, 1 << 5);
+
+	return 0;
+}
+
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+				  const struct v4l2_routing *route)
+{
+	struct au8522_state *state = to_state(sd);
+
+	au8522_reset(sd, 0);
+
+	/* Jam open the i2c gate to the tuner.  We do this here to handle the
+	   case where the user went into digital mode (causing the gate to be
+	   closed), and then came back to analog mode */
+	au8522_writereg(state, 0x106, 1);
+
+	if (route->input == AU8522_COMPOSITE_CH1) {
+		au8522_setup_cvbs_mode(state);
+	} else if (route->input == AU8522_SVIDEO_CH13) {
+		au8522_setup_svideo_mode(state);
+	} else if (route->input == AU8522_COMPOSITE_CH4_SIF) {
+		au8522_setup_cvbs_tuner_mode(state);
+	} else {
+		printk(KERN_ERR "au8522 mode not currently supported\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int au8522_s_audio_routing(struct v4l2_subdev *sd,
+				  const struct v4l2_routing *route)
+{
+	struct au8522_state *state = to_state(sd);
+	set_audio_input(state, route->input);
+	return 0;
+}
+
+static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	int val = 0;
+	struct au8522_state *state = to_state(sd);
+	u8 lock_status;
+
+	/* Interrogate the decoder to see if we are getting a real signal */
+	lock_status = au8522_readreg(state, 0x00);
+	if (lock_status == 0xa2)
+		vt->signal = 0x01;
+	else
+		vt->signal = 0x00;
+
+	vt->capability |=
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+		V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+	val = V4L2_TUNER_SUB_MONO;
+	vt->rxsubchans = val;
+	vt->audmode = V4L2_TUNER_MODE_STEREO;
+	return 0;
+}
+
+static int au8522_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *chip)
+{
+	struct au8522_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
+}
+
+static int au8522_log_status(struct v4l2_subdev *sd)
+{
+	/* FIXME: Add some status info here */
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops au8522_core_ops = {
+	.log_status = au8522_log_status,
+	.g_chip_ident = au8522_g_chip_ident,
+	.g_ctrl = au8522_g_ctrl,
+	.s_ctrl = au8522_s_ctrl,
+	.queryctrl = au8522_queryctrl,
+	.reset = au8522_reset,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = au8522_g_register,
+	.s_register = au8522_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
+	.g_tuner = au8522_g_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
+	.s_routing = au8522_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops au8522_video_ops = {
+	.s_routing = au8522_s_video_routing,
+	.g_fmt = au8522_g_fmt,
+	.s_fmt = au8522_s_fmt,
+	.s_stream = au8522_s_stream,
+};
+
+static const struct v4l2_subdev_ops au8522_ops = {
+	.core = &au8522_core_ops,
+	.tuner = &au8522_tuner_ops,
+	.audio = &au8522_audio_ops,
+	.video = &au8522_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int au8522_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct au8522_state *state;
+	struct v4l2_subdev *sd;
+	int instance;
+	struct au8522_config *demod_config;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		return -EIO;
+	}
+
+	/* allocate memory for the internal state */
+	instance = au8522_get_state(&state, client->adapter, client->addr);
+	switch (instance) {
+	case 0:
+		printk(KERN_ERR "au8522_decoder allocation failed\n");
+		return -EIO;
+	case 1:
+		/* new demod instance */
+		printk(KERN_INFO "au8522_decoder creating new instance...\n");
+		break;
+	default:
+		/* existing demod instance */
+		printk(KERN_INFO "au8522_decoder attach existing instance.\n");
+		break;
+	}
+
+	demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
+	demod_config->demod_address = 0x8e >> 1;
+
+	state->config = demod_config;
+	state->i2c = client->adapter;
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &au8522_ops);
+
+	state->c = client;
+	state->vid_input = AU8522_COMPOSITE_CH1;
+	state->aud_input = AU8522_AUDIO_NONE;
+	state->id = 8522;
+	state->rev = 0;
+
+	/* Jam open the i2c gate to the tuner */
+	au8522_writereg(state, 0x106, 1);
+
+	return 0;
+}
+
+static int au8522_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	v4l2_device_unregister_subdev(sd);
+	au8522_release_state(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id au8522_id[] = {
+	{"au8522", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, au8522_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "au8522",
+	.probe = au8522_probe,
+	.remove = au8522_remove,
+	.id_table = au8522_id,
+};
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522_dig.c
similarity index 91%
rename from drivers/media/dvb/frontends/au8522.c
rename to drivers/media/dvb/frontends/au8522_dig.c
index eabf9a6..3573125 100644
--- a/drivers/media/dvb/frontends/au8522.c
+++ b/drivers/media/dvb/frontends/au8522_dig.c
@@ -27,35 +27,25 @@
 #include <linux/delay.h>
 #include "dvb_frontend.h"
 #include "au8522.h"
-
-struct au8522_state {
-
-	struct i2c_adapter *i2c;
-
-	/* configuration settings */
-	const struct au8522_config *config;
-
-	struct dvb_frontend frontend;
-
-	u32 current_frequency;
-	fe_modulation_t current_modulation;
-
-	u32 fe_status;
-	unsigned int led_state;
-};
+#include "au8522_priv.h"
 
 static int debug;
 
-#define dprintk(arg...) do {		\
-	if (debug) 			\
-		 printk(arg); 		\
+/* Despite the name "hybrid_tuner", the framework works just as well for
+   hybrid demodulators as well... */
+static LIST_HEAD(hybrid_tuner_instance_list);
+static DEFINE_MUTEX(au8522_list_mutex);
+
+#define dprintk(arg...)\
+	do { if (debug)\
+		printk(arg);\
 	} while (0)
 
 /* 16 bit registers, 8 bit values */
-static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
 {
 	int ret;
-	u8 buf [] = { reg >> 8, reg & 0xff, data };
+	u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
 
 	struct i2c_msg msg = { .addr = state->config->demod_address,
 			       .flags = 0, .buf = buf, .len = 3 };
@@ -69,13 +59,13 @@
 	return (ret != 1) ? -1 : 0;
 }
 
-static u8 au8522_readreg(struct au8522_state *state, u16 reg)
+u8 au8522_readreg(struct au8522_state *state, u16 reg)
 {
 	int ret;
-	u8 b0 [] = { reg >> 8, reg & 0xff };
-	u8 b1 [] = { 0 };
+	u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
+	u8 b1[] = { 0 };
 
-	struct i2c_msg msg [] = {
+	struct i2c_msg msg[] = {
 		{ .addr = state->config->demod_address, .flags = 0,
 		  .buf = b0, .len = 2 },
 		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
@@ -528,7 +518,7 @@
 
 /* Reset the demod hardware and reset all of the configuration registers
    to a default state. */
-static int au8522_init(struct dvb_frontend *fe)
+int au8522_init(struct dvb_frontend *fe)
 {
 	struct au8522_state *state = fe->demodulator_priv;
 	dprintk("%s()\n", __func__);
@@ -624,7 +614,7 @@
 	return 0;
 }
 
-static int au8522_sleep(struct dvb_frontend *fe)
+int au8522_sleep(struct dvb_frontend *fe)
 {
 	struct au8522_state *state = fe->demodulator_priv;
 	dprintk("%s()\n", __func__);
@@ -632,6 +622,9 @@
 	/* turn off led */
 	au8522_led_ctrl(state, 0);
 
+	/* Power down the chip */
+	au8522_writereg(state, 0xa4, 1 << 5);
+
 	state->current_frequency = 0;
 
 	return 0;
@@ -798,23 +791,58 @@
 	return 0;
 }
 
+static struct dvb_frontend_ops au8522_ops;
+
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+		     u8 client_address)
+{
+	int ret;
+
+	mutex_lock(&au8522_list_mutex);
+	ret = hybrid_tuner_request_state(struct au8522_state, (*state),
+					 hybrid_tuner_instance_list,
+					 i2c, client_address, "au8522");
+	mutex_unlock(&au8522_list_mutex);
+
+	return ret;
+}
+
+void au8522_release_state(struct au8522_state *state)
+{
+	mutex_lock(&au8522_list_mutex);
+	if (state != NULL)
+		hybrid_tuner_release_state(state);
+	mutex_unlock(&au8522_list_mutex);
+}
+
+
 static void au8522_release(struct dvb_frontend *fe)
 {
 	struct au8522_state *state = fe->demodulator_priv;
-	kfree(state);
+	au8522_release_state(state);
 }
 
-static struct dvb_frontend_ops au8522_ops;
-
 struct dvb_frontend *au8522_attach(const struct au8522_config *config,
 				   struct i2c_adapter *i2c)
 {
 	struct au8522_state *state = NULL;
+	int instance;
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
+	instance = au8522_get_state(&state, i2c, config->demod_address);
+	switch (instance) {
+	case 0:
+		dprintk("%s state allocation failed\n", __func__);
+		break;
+	case 1:
+		/* new demod instance */
+		dprintk("%s using new instance\n", __func__);
+		break;
+	default:
+		/* existing demod instance */
+		dprintk("%s using existing instance\n", __func__);
+		break;
+	}
 
 	/* setup the state */
 	state->config = config;
@@ -836,7 +864,7 @@
 	return &state->frontend;
 
 error:
-	kfree(state);
+	au8522_release_state(state);
 	return NULL;
 }
 EXPORT_SYMBOL(au8522_attach);
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
new file mode 100644
index 0000000..f328f2b
--- /dev/null
+++ b/drivers/media/dvb/frontends/au8522_priv.h
@@ -0,0 +1,412 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
+    Copyright (C) 2008 Devin Heitmueller <dheitmueller@linuxtv.org>
+    Copyright (C) 2005-2008 Auvitek International, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "au8522.h"
+#include "tuner-i2c.h"
+
+struct au8522_state {
+	struct i2c_client *c;
+	struct i2c_adapter *i2c;
+
+	/* Used for sharing of the state between analog and digital mode */
+	struct tuner_i2c_props i2c_props;
+	struct list_head hybrid_tuner_instance_list;
+
+	/* configuration settings */
+	const struct au8522_config *config;
+
+	struct dvb_frontend frontend;
+
+	u32 current_frequency;
+	fe_modulation_t current_modulation;
+
+	u32 fe_status;
+	unsigned int led_state;
+
+	/* Analog settings */
+	struct v4l2_subdev sd;
+	v4l2_std_id std;
+	int vid_input;
+	int aud_input;
+	u32 id;
+	u32 rev;
+	u8 brightness;
+	u8 contrast;
+};
+
+/* These are routines shared by both the VSB/QAM demodulator and the analog
+   decoder */
+int au8522_writereg(struct au8522_state *state, u16 reg, u8 data);
+u8 au8522_readreg(struct au8522_state *state, u16 reg);
+int au8522_init(struct dvb_frontend *fe);
+int au8522_sleep(struct dvb_frontend *fe);
+
+int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
+		     u8 client_address);
+void au8522_release_state(struct au8522_state *state);
+
+/* REGISTERS */
+#define AU8522_INPUT_CONTROL_REG081H			0x081
+#define AU8522_PGA_CONTROL_REG082H			0x082
+#define AU8522_CLAMPING_CONTROL_REG083H			0x083
+
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H		0x0A3
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H		0x0A4
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H		0x0A5
+#define AU8522_AGC_CONTROL_RANGE_REG0A6H		0x0A6
+#define AU8522_SYSTEM_GAIN_CONTROL_REG0A7H		0x0A7
+#define AU8522_TUNER_AGC_RF_STOP_REG0A8H  		0x0A8
+#define AU8522_TUNER_AGC_RF_START_REG0A9H		0x0A9
+#define AU8522_TUNER_RF_AGC_DEFAULT_REG0AAH		0x0AA
+#define AU8522_TUNER_AGC_IF_STOP_REG0ABH		0x0AB
+#define AU8522_TUNER_AGC_IF_START_REG0ACH		0x0AC
+#define AU8522_TUNER_AGC_IF_DEFAULT_REG0ADH		0x0AD
+#define AU8522_TUNER_AGC_STEP_REG0AEH			0x0AE
+#define AU8522_TUNER_GAIN_STEP_REG0AFH			0x0AF
+
+/* Receiver registers */
+#define AU8522_FRMREGTHRD1_REG0B0H			0x0B0
+#define AU8522_FRMREGAGC1H_REG0B1H 			0x0B1
+#define AU8522_FRMREGSHIFT1_REG0B2H 			0x0B2
+#define AU8522_TOREGAGC1_REG0B3H 			0x0B3
+#define AU8522_TOREGASHIFT1_REG0B4H 			0x0B4
+#define AU8522_FRMREGBBH_REG0B5H			0x0B5
+#define AU8522_FRMREGBBM_REG0B6H 			0x0B6
+#define AU8522_FRMREGBBL_REG0B7H     			0x0B7
+/* 0xB8 TO 0xD7 are the filter coefficients */
+#define AU8522_FRMREGTHRD2_REG0D8H 			0x0D8
+#define AU8522_FRMREGAGC2H_REG0D9H 			0x0D9
+#define AU8522_TOREGAGC2_REG0DAH 			0x0DA
+#define AU8522_TOREGSHIFT2_REG0DBH 			0x0DB
+#define AU8522_FRMREGPILOTH_REG0DCH			0x0DC
+#define AU8522_FRMREGPILOTM_REG0DDH			0x0DD
+#define AU8522_FRMREGPILOTL_REG0DEH			0x0DE
+#define AU8522_TOREGFREQ_REG0DFH			0x0DF
+
+#define AU8522_RX_PGA_RFOUT_REG0EBH			0x0EB
+#define AU8522_RX_PGA_IFOUT_REG0ECH			0x0EC
+#define AU8522_RX_PGA_PGAOUT_REG0EDH			0x0ED
+
+#define AU8522_CHIP_MODE_REG0FEH			0x0FE
+
+/* I2C bus control registers */
+#define AU8522_I2C_CONTROL_REG0_REG090H    		0x090
+#define AU8522_I2C_CONTROL_REG1_REG091H    		0x091
+#define AU8522_I2C_STATUS_REG092H          		0x092
+#define AU8522_I2C_WR_DATA0_REG093H			0x093
+#define AU8522_I2C_WR_DATA1_REG094H			0x094
+#define AU8522_I2C_WR_DATA2_REG095H			0x095
+#define AU8522_I2C_WR_DATA3_REG096H			0x096
+#define AU8522_I2C_WR_DATA4_REG097H			0x097
+#define AU8522_I2C_WR_DATA5_REG098H			0x098
+#define AU8522_I2C_WR_DATA6_REG099H			0x099
+#define AU8522_I2C_WR_DATA7_REG09AH			0x09A
+#define AU8522_I2C_RD_DATA0_REG09BH			0x09B
+#define AU8522_I2C_RD_DATA1_REG09CH			0x09C
+#define AU8522_I2C_RD_DATA2_REG09DH			0x09D
+#define AU8522_I2C_RD_DATA3_REG09EH			0x09E
+#define AU8522_I2C_RD_DATA4_REG09FH			0x09F
+#define AU8522_I2C_RD_DATA5_REG0A0H			0x0A0
+#define AU8522_I2C_RD_DATA6_REG0A1H			0x0A1
+#define AU8522_I2C_RD_DATA7_REG0A2H			0x0A2
+
+#define AU8522_ENA_USB_REG101H				0x101
+
+#define AU8522_I2S_CTRL_0_REG110H  			0x110
+#define AU8522_I2S_CTRL_1_REG111H 			0x111
+#define AU8522_I2S_CTRL_2_REG112H 			0x112
+
+#define AU8522_FRMREGFFECONTROL_REG121H    		0x121
+#define AU8522_FRMREGDFECONTROL_REG122H    		0x122
+
+#define AU8522_CARRFREQOFFSET0_REG201H 			0x201
+#define AU8522_CARRFREQOFFSET1_REG202H			0x202
+
+#define AU8522_DECIMATION_GAIN_REG21AH			0x21A
+#define AU8522_FRMREGIFSLP_REG21BH 			0x21B
+#define AU8522_FRMREGTHRDL2_REG21CH 			0x21C
+#define AU8522_FRMREGSTEP3DB_REG21DH 			0x21D
+#define AU8522_DAGC_GAIN_ADJUSTMENT_REG21EH		0x21E
+#define AU8522_FRMREGPLLMODE_REG21FH 			0x21F
+#define AU8522_FRMREGCSTHRD_REG220H 			0x220
+#define AU8522_FRMREGCRLOCKDMAX_REG221H 		0x221
+#define AU8522_FRMREGCRPERIODMASK_REG222H 		0x222
+#define AU8522_FRMREGCRLOCK0THH_REG223H 		0x223
+#define AU8522_FRMREGCRLOCK1THH_REG224H 		0x224
+#define AU8522_FRMREGCRLOCK0THL_REG225H 		0x225
+#define AU8522_FRMREGCRLOCK1THL_REG226H 		0x226
+#define AU_FRMREGPLLACQPHASESCL_REG227H			0x227
+#define AU8522_FRMREGFREQFBCTRL_REG228H 		0x228
+
+/* Analog TV Decoder */
+#define AU8522_TVDEC_STATUS_REG000H			0x000
+#define AU8522_TVDEC_INT_STATUS_REG001H			0x001
+#define AU8522_TVDEC_MACROVISION_STATUS_REG002H 	0x002
+#define AU8522_TVDEC_SHARPNESSREG009H			0x009
+#define AU8522_TVDEC_BRIGHTNESS_REG00AH			0x00A
+#define AU8522_TVDEC_CONTRAST_REG00BH			0x00B
+#define AU8522_TVDEC_SATURATION_CB_REG00CH		0x00C
+#define AU8522_TVDEC_SATURATION_CR_REG00DH		0x00D
+#define AU8522_TVDEC_HUE_H_REG00EH			0x00E
+#define AU8522_TVDEC_HUE_L_REG00FH                   	0x00F
+#define AU8522_TVDEC_INT_MASK_REG010H			0x010
+#define AU8522_VIDEO_MODE_REG011H			0x011
+#define AU8522_TVDEC_PGA_REG012H			0x012
+#define AU8522_TVDEC_COMB_MODE_REG015H			0x015
+#define AU8522_REG016H                            	0x016
+#define AU8522_TVDED_DBG_MODE_REG060H			0x060
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H		0x061
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H		0x062
+#define AU8522_TVDEC_VCR_DET_LLIM_REG063H		0x063
+#define AU8522_TVDEC_VCR_DET_HLIM_REG064H		0x064
+#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H		0x065
+#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H		0x066
+#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H		0x067
+#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H		0x068
+#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H   		0x069
+#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH		0x06A
+#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH   		0x06B
+#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH  		0x06C
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH 		0x06D
+#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH       	0x06E
+#define AU8522_TVDEC_UV_SEP_THR_REG06FH  		0x06F
+#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H		0x070
+#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H		0x073
+#define AU8522_TVDEC_DCAGC_CTRL_REG077H			0x077
+#define AU8522_TVDEC_PIC_START_ADJ_REG078H		0x078
+#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H		0x079
+#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH	0x07A
+#define AU8522_TVDEC_INTRP_CTRL_REG07BH			0x07B
+#define AU8522_TVDEC_PLL_STATUS_REG07EH			0x07E
+#define AU8522_TVDEC_FSC_FREQ_REG07FH			0x07F
+
+#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H		0x0E4
+#define AU8522_TOREGAAGC_REG0E5H			0x0E5
+
+#define AU8522_TVDEC_CHROMA_AGC_REG401H		0x401
+#define AU8522_TVDEC_CHROMA_SFT_REG402H		0x402
+#define AU8522_FILTER_COEF_R410     		0x410
+#define AU8522_FILTER_COEF_R411     		0x411
+#define AU8522_FILTER_COEF_R412     		0x412
+#define AU8522_FILTER_COEF_R413     		0x413
+#define AU8522_FILTER_COEF_R414     		0x414
+#define AU8522_FILTER_COEF_R415     		0x415
+#define AU8522_FILTER_COEF_R416     		0x416
+#define AU8522_FILTER_COEF_R417     		0x417
+#define AU8522_FILTER_COEF_R418     		0x418
+#define AU8522_FILTER_COEF_R419     		0x419
+#define AU8522_FILTER_COEF_R41A     		0x41A
+#define AU8522_FILTER_COEF_R41B     		0x41B
+#define AU8522_FILTER_COEF_R41C     		0x41C
+#define AU8522_FILTER_COEF_R41D     		0x41D
+#define AU8522_FILTER_COEF_R41E     		0x41E
+#define AU8522_FILTER_COEF_R41F     		0x41F
+#define AU8522_FILTER_COEF_R420     		0x420
+#define AU8522_FILTER_COEF_R421     		0x421
+#define AU8522_FILTER_COEF_R422     		0x422
+#define AU8522_FILTER_COEF_R423     		0x423
+#define AU8522_FILTER_COEF_R424     		0x424
+#define AU8522_FILTER_COEF_R425     		0x425
+#define AU8522_FILTER_COEF_R426     		0x426
+#define AU8522_FILTER_COEF_R427     		0x427
+#define AU8522_FILTER_COEF_R428     		0x428
+#define AU8522_FILTER_COEF_R429     		0x429
+#define AU8522_FILTER_COEF_R42A     		0x42A
+#define AU8522_FILTER_COEF_R42B     		0x42B
+#define AU8522_FILTER_COEF_R42C     		0x42C
+#define AU8522_FILTER_COEF_R42D     		0x42D
+
+/* VBI Control Registers */
+#define AU8522_TVDEC_VBI_RX_FIFO_CONTAIN_REG004H  	0x004
+#define AU8522_TVDEC_VBI_TX_FIFO_CONTAIN_REG005H  	0x005
+#define AU8522_TVDEC_VBI_RX_FIFO_READ_REG006H      	0x006
+#define AU8522_TVDEC_VBI_FIFO_STATUS_REG007H       	0x007
+#define AU8522_TVDEC_VBI_CTRL_H_REG017H			0x017
+#define AU8522_TVDEC_VBI_CTRL_L_REG018H			0x018
+#define AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H	0x019
+#define AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH		0x01A
+#define AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH		0x01B
+#define AU8522_TVDEC_VBI_USER_THRESH1_REG01CH		0x01C
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH	0x01E
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH   	0x01F
+#define AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H   	0x020
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H 	0x021
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H  	0x022
+#define AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H	0x023
+
+#define AU8522_REG071H					0x071
+#define AU8522_REG072H					0x072
+#define AU8522_REG074H					0x074
+#define AU8522_REG075H					0x075
+
+/* Digital Demodulator Registers */
+#define AU8522_FRAME_COUNT0_REG084H			0x084
+#define AU8522_RS_STATUS_G0_REG085H			0x085
+#define AU8522_RS_STATUS_B0_REG086H			0x086
+#define AU8522_RS_STATUS_E_REG087H			0x087
+#define AU8522_DEMODULATION_STATUS_REG088H		0x088
+#define AU8522_TOREGTRESTATUS_REG0E6H			0x0E6
+#define AU8522_TSPORT_CONTROL_REG10BH			0x10B
+#define AU8522_TSTHES_REG10CH				0x10C
+#define AU8522_FRMREGDFEKEEP_REG301H			0x301
+#define AU8522_DFE_AVERAGE_REG302H			0x302
+#define AU8522_FRMREGEQLERRWIN_REG303H			0x303
+#define AU8522_FRMREGFFEKEEP_REG304H			0x304
+#define AU8522_FRMREGDFECONTROL1_REG305H		0x305
+#define AU8522_FRMREGEQLERRLOW_REG306H			0x306
+
+#define AU8522_REG42EH				0x42E
+#define AU8522_REG42FH				0x42F
+#define AU8522_REG430H				0x430
+#define AU8522_REG431H				0x431
+#define AU8522_REG432H				0x432
+#define AU8522_REG433H				0x433
+#define AU8522_REG434H				0x434
+#define AU8522_REG435H				0x435
+#define AU8522_REG436H				0x436
+
+/* GPIO Registers */
+#define AU8522_GPIO_CONTROL_REG0E0H			0x0E0
+#define AU8522_GPIO_STATUS_REG0E1H			0x0E1
+#define AU8522_GPIO_DATA_REG0E2H			0x0E2
+
+/* Audio Control Registers */
+#define AU8522_AUDIOAGC_REG0EEH 			0x0EE
+#define AU8522_AUDIO_STATUS_REG0F0H 			0x0F0
+#define AU8522_AUDIO_MODE_REG0F1H 			0x0F1
+#define AU8522_AUDIO_VOLUME_L_REG0F2H 			0x0F2
+#define AU8522_AUDIO_VOLUME_R_REG0F3H 			0x0F3
+#define AU8522_AUDIO_VOLUME_REG0F4H 			0x0F4
+#define AU8522_FRMREGAUPHASE_REG0F7H 			0x0F7
+#define AU8522_REG0F9H					0x0F9
+
+#define AU8522_AUDIOAGC2_REG605H 			0x605
+#define AU8522_AUDIOFREQ_REG606H 			0x606
+
+
+/**************************************************************/
+
+#define AU8522_INPUT_CONTROL_REG081H_ATSC               	0xC4
+#define AU8522_INPUT_CONTROL_REG081H_ATVRF			0xC4
+#define AU8522_INPUT_CONTROL_REG081H_ATVRF13			0xC4
+#define AU8522_INPUT_CONTROL_REG081H_J83B64             	0xC4
+#define AU8522_INPUT_CONTROL_REG081H_J83B256            	0xC4
+#define AU8522_INPUT_CONTROL_REG081H_CVBS               	0x20
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH1			0xA2
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH2			0xA0
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH3			0x69
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4			0x68
+#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF        	0x28
+/* CH1 AS Y,CH3 AS C */
+#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13        	0x23
+/* CH2 AS Y,CH4 AS C */
+#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24        	0x20
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATSC        	0x0C
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B64      	0x09
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B256    		0x09
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS        	0x12
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF       	0x1A
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF13		0x1A
+#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO		0x02
+
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CLEAR		0x00
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO		0x9C
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS     	0x9D
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATSC		0xE8
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B256 		0xCA
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B64  		0xCA
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF   		0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF13		0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_PAL		0xDD
+#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_FM		0xDD
+
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATSC		0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B256 		0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B64  		0x80
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_ATSC	0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B256	0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B64	0x40
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_CLEAR	0x00
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF		0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF13		0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_SVIDEO  		0x04
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_CVBS		0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PWM     		0x03
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_IIS      	0x09
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PAL		0x01
+#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_FM		0x01
+
+/* STILL NEED TO BE REFACTORED @@@@@@@@@@@@@@ */
+#define AU8522_TVDEC_CONTRAST_REG00BH_CVBS			0x79
+#define AU8522_TVDEC_SATURATION_CB_REG00CH_CVBS			0x80
+#define AU8522_TVDEC_SATURATION_CR_REG00DH_CVBS			0x80
+#define AU8522_TVDEC_HUE_H_REG00EH_CVBS				0x00
+#define AU8522_TVDEC_HUE_L_REG00FH_CVBS				0x00
+#define AU8522_TVDEC_PGA_REG012H_CVBS				0x0F
+#define AU8522_TVDEC_COMB_MODE_REG015H_CVBS			0x00
+#define AU8522_REG016H_CVBS					0x00
+#define AU8522_TVDED_DBG_MODE_REG060H_CVBS			0x00
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS			0x0B
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13		0x03
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13		0x00
+#define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS			0x19
+#define AU8522_REG0F9H_AUDIO					0x20
+#define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS			0xA7
+#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS		0x0A
+#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS		0x32
+#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS		0x19
+#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS		0x23
+#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS		0x41
+#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS		0x0A
+#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS		0x32
+#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS		0x34
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS		0x05
+#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS		0x6E
+#define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS			0x0F
+#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS		0x80
+#define AU8522_REG071H_CVBS					0x18
+#define AU8522_REG072H_CVBS					0x30
+#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS		0xF0
+#define AU8522_REG074H_CVBS					0x80
+#define AU8522_REG075H_CVBS					0xF0
+#define AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS			0xFB
+#define AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS			0x04
+#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS		0x00
+#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS		0x00
+#define AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS			0xEE
+#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS			0xFE
+#define AU8522_TOREGAAGC_REG0E5H_CVBS				0x00
+#define AU8522_TVDEC_VBI6A_REG035H_CVBS				0x40
+
+/* Enables Closed captioning */
+#define AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON			0x21
diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb/frontends/cx24113.c
index f6e7b03..e4fd533 100644
--- a/drivers/media/dvb/frontends/cx24113.c
+++ b/drivers/media/dvb/frontends/cx24113.c
@@ -559,7 +559,7 @@
 		kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
 	int rc;
 	if (state == NULL) {
-		err("Unable to kmalloc\n");
+		err("Unable to kzalloc\n");
 		goto error;
 	}
 
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index 28ad609..9b9f572 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -15,6 +15,9 @@
 	September, 9th 2008
 	    Fixed locking on high symbol rates (>30000).
 	    Implement MPEG initialization parameter.
+	January, 17th 2009
+	    Fill set_voltage with actually control voltage code.
+	    Correct set tone to not affect voltage.
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -146,7 +149,7 @@
 	CMD_GETAGC      = 0x19,
 	CMD_LNBCONFIG   = 0x20,
 	CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */
-	CMD_SET_TONEPRE = 0x22,
+	CMD_LNBDCLEVEL  = 0x22,
 	CMD_SET_TONE    = 0x23,
 	CMD_UPDFWVERS   = 0x35,
 	CMD_TUNERSLEEP  = 0x36,
@@ -667,16 +670,6 @@
 	return 0;
 }
 
-static int cx24116_set_voltage(struct dvb_frontend *fe,
-	fe_sec_voltage_t voltage)
-{
-	/* The isl6421 module will override this function in the fops. */
-	dprintk("%s() This should never appear if the isl6421 module "
-		"is loaded correctly\n", __func__);
-
-	return -EOPNOTSUPP;
-}
-
 static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
@@ -837,6 +830,34 @@
 	return -ETIMEDOUT; /* -EBUSY ? */
 }
 
+static int cx24116_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t voltage)
+{
+	struct cx24116_cmd cmd;
+	int ret;
+
+	dprintk("%s: %s\n", __func__,
+		voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+		voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+	/* Wait for LNB ready */
+	ret = cx24116_wait_for_lnb(fe);
+	if (ret != 0)
+		return ret;
+
+	/* Wait for voltage/min repeat delay */
+	msleep(100);
+
+	cmd.args[0x00] = CMD_LNBDCLEVEL;
+	cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
+	cmd.len = 0x02;
+
+	/* Min delay time before DiSEqC send */
+	msleep(15);
+
+	return cx24116_cmd_execute(fe, &cmd);
+}
+
 static int cx24116_set_tone(struct dvb_frontend *fe,
 	fe_sec_tone_mode_t tone)
 {
@@ -857,14 +878,6 @@
 	/* Min delay time after DiSEqC send */
 	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
 
-	/* This is always done before the tone is set */
-	cmd.args[0x00] = CMD_SET_TONEPRE;
-	cmd.args[0x01] = 0x00;
-	cmd.len = 0x02;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
 	/* Now we set the tone */
 	cmd.args[0x00] = CMD_SET_TONE;
 	cmd.args[0x01] = 0x00;
@@ -1099,13 +1112,10 @@
 	dprintk("%s\n", __func__);
 
 	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
 	if (state == NULL)
 		goto error1;
 
-	/* setup the state */
-	memset(state, 0, sizeof(struct cx24116_state));
-
 	state->config = config;
 	state->i2c = i2c;
 
@@ -1154,7 +1164,12 @@
 	if (ret != 0)
 		return ret;
 
-	return cx24116_diseqc_init(fe);
+	ret = cx24116_diseqc_init(fe);
+	if (ret != 0)
+		return ret;
+
+	/* HVR-4000 needs this */
+	return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
 }
 
 /*
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 1a8c36f..0592f04 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -1069,13 +1069,13 @@
 struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 				    struct i2c_adapter *i2c)
 {
+	/* allocate memory for the internal state */
 	struct cx24123_state *state =
 		kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
 
 	dprintk("\n");
-	/* allocate memory for the internal state */
 	if (state == NULL) {
-		err("Unable to kmalloc\n");
+		err("Unable to kzalloc\n");
 		goto error;
 	}
 
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index 21f2c51..9670f5d 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -58,6 +58,4 @@
 }
 #endif
 
-extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
-
 #endif
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
index 4142ed7..d75ffad 100644
--- a/drivers/media/dvb/frontends/dib3000mc.h
+++ b/drivers/media/dvb/frontends/dib3000mc.h
@@ -39,20 +39,44 @@
 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
-#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE))
-extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg);
+#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
+				      defined(MODULE))
+extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
+					     u8 i2c_addr,
+					     struct dib3000mc_config *cfg);
+extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c,
+				     int no_of_demods, u8 default_addr,
+				     struct dib3000mc_config cfg[]);
+extern
+struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
+						   int gating);
 #else
-static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+static inline
+struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+				      struct dib3000mc_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline
+int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c,
+			      int no_of_demods, u8 default_addr,
+			      struct dib3000mc_config cfg[])
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline
+struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
+						   int gating)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MC
 
-extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]);
-
-extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
-
 extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
 extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
 
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h
index 597e9cc..113819c 100644
--- a/drivers/media/dvb/frontends/dib7000m.h
+++ b/drivers/media/dvb/frontends/dib7000m.h
@@ -38,8 +38,32 @@
 
 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
 
-extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg);
-extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
+				     defined(MODULE))
+extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
+					    u8 i2c_addr,
+					    struct dib7000m_config *cfg);
+extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *,
+						   enum dibx000_i2c_interface,
+						   int);
+#else
+static inline
+struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
+				     u8 i2c_addr, struct dib7000m_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline
+struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *demod,
+					    enum dibx000_i2c_interface intf,
+					    int gating)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
 
 /* TODO
 extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index aab8112..02a4c82 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -37,7 +37,8 @@
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
 
-#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE))
+#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
+				     defined(MODULE))
 extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
 					    u8 i2c_addr,
 					    struct dib7000p_config *cfg);
@@ -49,10 +50,11 @@
 				    struct dib7000p_config cfg[]);
 extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
 extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
+extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
 #else
-static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
-						   u8 i2c_addr,
-						   struct dib7000p_config *cfg)
+static inline
+struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
+				     struct dib7000p_config *cfg)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
@@ -60,36 +62,39 @@
 
 static inline
 struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
-					    enum dibx000_i2c_interface i, int x)
+					    enum dibx000_i2c_interface i,
+					    int x)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
 
-static inline
-int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
-				    int no_of_demods, u8 default_addr,
-				    struct dib7000p_config cfg[])
+static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+					   int no_of_demods, u8 default_addr,
+					   struct dib7000p_config cfg[])
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-static inline
-int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static inline int dib7000p_set_gpio(struct dvb_frontend *fe,
+				    u8 num, u8 dir, u8 val)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-static inline
-int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 #endif
 
-extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-
 #endif
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.h b/drivers/media/dvb/frontends/dvb_dummy_fe.h
index 8210f19..1fcb987 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.h
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.h
@@ -25,8 +25,27 @@
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
+#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \
+defined(MODULE))
 extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);
+#else
+static inline struct dvb_frontend *dvb_dummy_fe_ofdm_attach(void)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_DUMMY_FE */
 
 #endif // DVB_DUMMY_FE_H
diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
index 8cdc54e..08ca851 100644
--- a/drivers/media/dvb/frontends/itd1000_priv.h
+++ b/drivers/media/dvb/frontends/itd1000_priv.h
@@ -31,7 +31,7 @@
 	/* ugly workaround for flexcop's incapable i2c-controller
 	 * FIXME, if possible
 	 */
-	u8 shadow[255];
+	u8 shadow[256];
 };
 
 enum itd1000_register {
diff --git a/drivers/media/dvb/frontends/lgdt3304.c b/drivers/media/dvb/frontends/lgdt3304.c
index 3bb0c43..eb72a98 100644
--- a/drivers/media/dvb/frontends/lgdt3304.c
+++ b/drivers/media/dvb/frontends/lgdt3304.c
@@ -363,7 +363,6 @@
 
 	struct lgdt3304_state *state;
 	state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
-	memset(state, 0x0, sizeof(struct lgdt3304_state));
 	state->addr = config->i2c_address;
 	state->i2c = i2c;
 
diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
new file mode 100644
index 0000000..d92d055
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgdt3305.c
@@ -0,0 +1,1087 @@
+/*
+ *    Support for LGDT3305 - VSB/QAM
+ *
+ *    Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.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.
+ *
+ */
+
+#include <linux/dvb/frontend.h>
+#include "dvb_math.h"
+#include "lgdt3305.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
+
+#define DBG_INFO 1
+#define DBG_REG  2
+
+#define lg_printk(kern, fmt, arg...)					\
+	printk(kern "%s: " fmt, __func__, ##arg)
+
+#define lg_info(fmt, arg...)	printk(KERN_INFO "lgdt3305: " fmt, ##arg)
+#define lg_warn(fmt, arg...)	lg_printk(KERN_WARNING,       fmt, ##arg)
+#define lg_err(fmt, arg...)	lg_printk(KERN_ERR,           fmt, ##arg)
+#define lg_dbg(fmt, arg...) if (debug & DBG_INFO)			\
+				lg_printk(KERN_DEBUG,         fmt, ##arg)
+#define lg_reg(fmt, arg...) if (debug & DBG_REG)			\
+				lg_printk(KERN_DEBUG,         fmt, ##arg)
+
+#define lg_fail(ret)							\
+({									\
+	int __ret;							\
+	__ret = (ret < 0);						\
+	if (__ret)							\
+		lg_err("error %d on line %d\n",	ret, __LINE__);		\
+	__ret;								\
+})
+
+struct lgdt3305_state {
+	struct i2c_adapter *i2c_adap;
+	const struct lgdt3305_config *cfg;
+
+	struct dvb_frontend frontend;
+
+	fe_modulation_t current_modulation;
+	u32 current_frequency;
+	u32 snr;
+};
+
+/* ------------------------------------------------------------------------ */
+
+#define LGDT3305_GEN_CTRL_1                   0x0000
+#define LGDT3305_GEN_CTRL_2                   0x0001
+#define LGDT3305_GEN_CTRL_3                   0x0002
+#define LGDT3305_GEN_STATUS                   0x0003
+#define LGDT3305_GEN_CONTROL                  0x0007
+#define LGDT3305_GEN_CTRL_4                   0x000a
+#define LGDT3305_DGTL_AGC_REF_1               0x0012
+#define LGDT3305_DGTL_AGC_REF_2               0x0013
+#define LGDT3305_CR_CTR_FREQ_1                0x0106
+#define LGDT3305_CR_CTR_FREQ_2                0x0107
+#define LGDT3305_CR_CTR_FREQ_3                0x0108
+#define LGDT3305_CR_CTR_FREQ_4                0x0109
+#define LGDT3305_CR_MSE_1                     0x011b
+#define LGDT3305_CR_MSE_2                     0x011c
+#define LGDT3305_CR_LOCK_STATUS               0x011d
+#define LGDT3305_CR_CTRL_7                    0x0126
+#define LGDT3305_AGC_POWER_REF_1              0x0300
+#define LGDT3305_AGC_POWER_REF_2              0x0301
+#define LGDT3305_AGC_DELAY_PT_1               0x0302
+#define LGDT3305_AGC_DELAY_PT_2               0x0303
+#define LGDT3305_RFAGC_LOOP_FLTR_BW_1         0x0306
+#define LGDT3305_RFAGC_LOOP_FLTR_BW_2         0x0307
+#define LGDT3305_IFBW_1                       0x0308
+#define LGDT3305_IFBW_2                       0x0309
+#define LGDT3305_AGC_CTRL_1                   0x030c
+#define LGDT3305_AGC_CTRL_4                   0x0314
+#define LGDT3305_EQ_MSE_1                     0x0413
+#define LGDT3305_EQ_MSE_2                     0x0414
+#define LGDT3305_EQ_MSE_3                     0x0415
+#define LGDT3305_PT_MSE_1                     0x0417
+#define LGDT3305_PT_MSE_2                     0x0418
+#define LGDT3305_PT_MSE_3                     0x0419
+#define LGDT3305_FEC_BLOCK_CTRL               0x0504
+#define LGDT3305_FEC_LOCK_STATUS              0x050a
+#define LGDT3305_FEC_PKT_ERR_1                0x050c
+#define LGDT3305_FEC_PKT_ERR_2                0x050d
+#define LGDT3305_TP_CTRL_1                    0x050e
+#define LGDT3305_BERT_PERIOD                  0x0801
+#define LGDT3305_BERT_ERROR_COUNT_1           0x080a
+#define LGDT3305_BERT_ERROR_COUNT_2           0x080b
+#define LGDT3305_BERT_ERROR_COUNT_3           0x080c
+#define LGDT3305_BERT_ERROR_COUNT_4           0x080d
+
+static int lgdt3305_write_reg(struct lgdt3305_state *state, u16 reg, u8 val)
+{
+	int ret;
+	u8 buf[] = { reg >> 8, reg & 0xff, val };
+	struct i2c_msg msg = {
+		.addr = state->cfg->i2c_addr, .flags = 0,
+		.buf = buf, .len = 3,
+	};
+
+	lg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
+
+	ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+	if (ret != 1) {
+		lg_err("error (addr %02x %02x <- %02x, err = %i)\n",
+		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int lgdt3305_read_reg(struct lgdt3305_state *state, u16 reg, u8 *val)
+{
+	int ret;
+	u8 reg_buf[] = { reg >> 8, reg & 0xff };
+	struct i2c_msg msg[] = {
+		{ .addr = state->cfg->i2c_addr,
+		  .flags = 0, .buf = reg_buf, .len = 2 },
+		{ .addr = state->cfg->i2c_addr,
+		  .flags = I2C_M_RD, .buf = val, .len = 1 },
+	};
+
+	lg_reg("reg: 0x%04x\n", reg);
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	if (ret != 2) {
+		lg_err("error (addr %02x reg %04x error (ret == %i)\n",
+		       state->cfg->i2c_addr, reg, ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+	return 0;
+}
+
+#define read_reg(state, reg)						\
+({									\
+	u8 __val;							\
+	int ret = lgdt3305_read_reg(state, reg, &__val);		\
+	if (lg_fail(ret))						\
+		__val = 0;						\
+	__val;								\
+})
+
+static int lgdt3305_set_reg_bit(struct lgdt3305_state *state,
+				u16 reg, int bit, int onoff)
+{
+	u8 val;
+	int ret;
+
+	lg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
+
+	ret = lgdt3305_read_reg(state, reg, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= ~(1 << bit);
+	val |= (onoff & 1) << bit;
+
+	ret = lgdt3305_write_reg(state, reg, val);
+fail:
+	return ret;
+}
+
+struct lgdt3305_reg {
+	u16 reg;
+	u8 val;
+};
+
+static int lgdt3305_write_regs(struct lgdt3305_state *state,
+			       struct lgdt3305_reg *regs, int len)
+{
+	int i, ret;
+
+	lg_reg("writing %d registers...\n", len);
+
+	for (i = 0; i < len - 1; i++) {
+		ret = lgdt3305_write_reg(state, regs[i].reg, regs[i].val);
+		if (lg_fail(ret))
+			return ret;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_soft_reset(struct lgdt3305_state *state)
+{
+	int ret;
+
+	lg_dbg("\n");
+
+	ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	msleep(20);
+	ret = lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_3, 0, 1);
+fail:
+	return ret;
+}
+
+static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
+				     enum lgdt3305_mpeg_mode mode)
+{
+	lg_dbg("(%d)\n", mode);
+	return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
+}
+
+static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
+				       enum lgdt3305_tp_clock_edge edge,
+				       enum lgdt3305_tp_valid_polarity valid)
+{
+	u8 val;
+	int ret;
+
+	lg_dbg("edge = %d, valid = %d\n", edge, valid);
+
+	ret = lgdt3305_read_reg(state, LGDT3305_TP_CTRL_1, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= ~0x09;
+
+	if (edge)
+		val |= 0x08;
+	if (valid)
+		val |= 0x01;
+
+	ret = lgdt3305_write_reg(state, LGDT3305_TP_CTRL_1, val);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_soft_reset(state);
+fail:
+	return ret;
+}
+
+static int lgdt3305_set_modulation(struct lgdt3305_state *state,
+				   struct dvb_frontend_parameters *param)
+{
+	u8 opermode;
+	int ret;
+
+	lg_dbg("\n");
+
+	ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_1, &opermode);
+	if (lg_fail(ret))
+		goto fail;
+
+	opermode &= ~0x03;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		opermode |= 0x03;
+		break;
+	case QAM_64:
+		opermode |= 0x00;
+		break;
+	case QAM_256:
+		opermode |= 0x01;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret = lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_1, opermode);
+fail:
+	return ret;
+}
+
+static int lgdt3305_set_filter_extension(struct lgdt3305_state *state,
+					 struct dvb_frontend_parameters *param)
+{
+	int val;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		val = 0;
+		break;
+	case QAM_64:
+	case QAM_256:
+		val = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	lg_dbg("val = %d\n", val);
+
+	return lgdt3305_set_reg_bit(state, 0x043f, 2, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_passband_digital_agc(struct lgdt3305_state *state,
+					 struct dvb_frontend_parameters *param)
+{
+	u16 agc_ref;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		agc_ref = 0x32c4;
+		break;
+	case QAM_64:
+		agc_ref = 0x2a00;
+		break;
+	case QAM_256:
+		agc_ref = 0x2a80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	lg_dbg("agc ref: 0x%04x\n", agc_ref);
+
+	lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_1, agc_ref >> 8);
+	lgdt3305_write_reg(state, LGDT3305_DGTL_AGC_REF_2, agc_ref & 0xff);
+
+	return 0;
+}
+
+static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
+			       struct dvb_frontend_parameters *param)
+{
+	u16 ifbw, rfbw, agcdelay;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		agcdelay = 0x04c0;
+		rfbw     = 0x8000;
+		ifbw     = 0x8000;
+		break;
+	case QAM_64:
+	case QAM_256:
+		agcdelay = 0x046b;
+		rfbw     = 0x8889;
+		ifbw     = 0x8888;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (state->cfg->rf_agc_loop) {
+		lg_dbg("agcdelay: 0x%04x, rfbw: 0x%04x\n", agcdelay, rfbw);
+
+		/* rf agc loop filter bandwidth */
+		lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_1,
+				   agcdelay >> 8);
+		lgdt3305_write_reg(state, LGDT3305_AGC_DELAY_PT_2,
+				   agcdelay & 0xff);
+
+		lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_1,
+				   rfbw >> 8);
+		lgdt3305_write_reg(state, LGDT3305_RFAGC_LOOP_FLTR_BW_2,
+				   rfbw & 0xff);
+	} else {
+		lg_dbg("ifbw: 0x%04x\n", ifbw);
+
+		/* if agc loop filter bandwidth */
+		lgdt3305_write_reg(state, LGDT3305_IFBW_1, ifbw >> 8);
+		lgdt3305_write_reg(state, LGDT3305_IFBW_2, ifbw & 0xff);
+	}
+
+	return 0;
+}
+
+static int lgdt3305_agc_setup(struct lgdt3305_state *state,
+			      struct dvb_frontend_parameters *param)
+{
+	int lockdten, acqen;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		lockdten = 0;
+		acqen = 0;
+		break;
+	case QAM_64:
+	case QAM_256:
+		lockdten = 1;
+		acqen = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
+
+	/* control agc function */
+	lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
+	lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
+
+	return lgdt3305_rfagc_loop(state, param);
+}
+
+static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
+				      struct dvb_frontend_parameters *param)
+{
+	u16 usref = 0;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		if (state->cfg->usref_8vsb)
+			usref = state->cfg->usref_8vsb;
+		break;
+	case QAM_64:
+		if (state->cfg->usref_qam64)
+			usref = state->cfg->usref_qam64;
+		break;
+	case QAM_256:
+		if (state->cfg->usref_qam256)
+			usref = state->cfg->usref_qam256;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (usref) {
+		lg_dbg("set manual mode: 0x%04x\n", usref);
+
+		lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 3, 1);
+
+		lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_1,
+				   0xff & (usref >> 8));
+		lgdt3305_write_reg(state, LGDT3305_AGC_POWER_REF_2,
+				   0xff & (usref >> 0));
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_spectral_inversion(struct lgdt3305_state *state,
+				       struct dvb_frontend_parameters *param,
+				       int inversion)
+{
+	int ret;
+
+	lg_dbg("(%d)\n", inversion);
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		ret = lgdt3305_write_reg(state, LGDT3305_CR_CTRL_7,
+					 inversion ? 0xf9 : 0x79);
+		break;
+	case QAM_64:
+	case QAM_256:
+		ret = lgdt3305_write_reg(state, LGDT3305_FEC_BLOCK_CTRL,
+					 inversion ? 0xfd : 0xff);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int lgdt3305_set_if(struct lgdt3305_state *state,
+			   struct dvb_frontend_parameters *param)
+{
+	u16 if_freq_khz;
+	u8 nco1, nco2, nco3, nco4;
+	u64 nco;
+
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		if_freq_khz = state->cfg->vsb_if_khz;
+		break;
+	case QAM_64:
+	case QAM_256:
+		if_freq_khz = state->cfg->qam_if_khz;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	nco = if_freq_khz / 10;
+
+#define LGDT3305_64BIT_DIVISION_ENABLED 0
+	/* FIXME: 64bit division disabled to avoid linking error:
+	 * WARNING: "__udivdi3" [lgdt3305.ko] undefined!
+	 */
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+#if LGDT3305_64BIT_DIVISION_ENABLED
+		nco <<= 24;
+		nco /= 625;
+#else
+		nco *= ((1 << 24) / 625);
+#endif
+		break;
+	case QAM_64:
+	case QAM_256:
+#if LGDT3305_64BIT_DIVISION_ENABLED
+		nco <<= 28;
+		nco /= 625;
+#else
+		nco *= ((1 << 28) / 625);
+#endif
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	nco1 = (nco >> 24) & 0x3f;
+	nco1 |= 0x40;
+	nco2 = (nco >> 16) & 0xff;
+	nco3 = (nco >> 8) & 0xff;
+	nco4 = nco & 0xff;
+
+	lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, nco1);
+	lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, nco2);
+	lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, nco3);
+	lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, nco4);
+
+	lg_dbg("%d KHz -> [%02x%02x%02x%02x]\n",
+	       if_freq_khz, nco1, nco2, nco3, nco4);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+
+	if (state->cfg->deny_i2c_rptr)
+		return 0;
+
+	lg_dbg("(%d)\n", enable);
+
+	return lgdt3305_set_reg_bit(state, LGDT3305_GEN_CTRL_2, 5,
+				    enable ? 0 : 1);
+}
+
+static int lgdt3305_sleep(struct dvb_frontend *fe)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	u8 gen_ctrl_3, gen_ctrl_4;
+
+	lg_dbg("\n");
+
+	gen_ctrl_3 = read_reg(state, LGDT3305_GEN_CTRL_3);
+	gen_ctrl_4 = read_reg(state, LGDT3305_GEN_CTRL_4);
+
+	/* hold in software reset while sleeping */
+	gen_ctrl_3 &= ~0x01;
+	/* tristate the IF-AGC pin */
+	gen_ctrl_3 |=  0x02;
+	/* tristate the RF-AGC pin */
+	gen_ctrl_3 |=  0x04;
+
+	/* disable vsb/qam module */
+	gen_ctrl_4 &= ~0x01;
+	/* disable adc module */
+	gen_ctrl_4 &= ~0x02;
+
+	lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_3, gen_ctrl_3);
+	lgdt3305_write_reg(state, LGDT3305_GEN_CTRL_4, gen_ctrl_4);
+
+	return 0;
+}
+
+static int lgdt3305_init(struct dvb_frontend *fe)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	int ret;
+
+	static struct lgdt3305_reg lgdt3305_init_data[] = {
+		{ .reg = LGDT3305_GEN_CTRL_1,
+		  .val = 0x03, },
+		{ .reg = LGDT3305_GEN_CTRL_2,
+		  .val = 0xb0, },
+		{ .reg = LGDT3305_GEN_CTRL_3,
+		  .val = 0x01, },
+		{ .reg = LGDT3305_GEN_CONTROL,
+		  .val = 0x6f, },
+		{ .reg = LGDT3305_GEN_CTRL_4,
+		  .val = 0x03, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_1,
+		  .val = 0x32, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_2,
+		  .val = 0xc4, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_1,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_2,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_3,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_4,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTRL_7,
+		  .val = 0x79, },
+		{ .reg = LGDT3305_AGC_POWER_REF_1,
+		  .val = 0x32, },
+		{ .reg = LGDT3305_AGC_POWER_REF_2,
+		  .val = 0xc4, },
+		{ .reg = LGDT3305_AGC_DELAY_PT_1,
+		  .val = 0x0d, },
+		{ .reg = LGDT3305_AGC_DELAY_PT_2,
+		  .val = 0x30, },
+		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1,
+		  .val = 0x80, },
+		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_IFBW_1,
+		  .val = 0x80, },
+		{ .reg = LGDT3305_IFBW_2,
+		  .val = 0x00, },
+		{ .reg = LGDT3305_AGC_CTRL_1,
+		  .val = 0x30, },
+		{ .reg = LGDT3305_AGC_CTRL_4,
+		  .val = 0x61, },
+		{ .reg = LGDT3305_FEC_BLOCK_CTRL,
+		  .val = 0xff, },
+		{ .reg = LGDT3305_TP_CTRL_1,
+		  .val = 0x1b, },
+	};
+
+	lg_dbg("\n");
+
+	ret = lgdt3305_write_regs(state, lgdt3305_init_data,
+				  ARRAY_SIZE(lgdt3305_init_data));
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_soft_reset(state);
+fail:
+	return ret;
+}
+
+static int lgdt3305_set_parameters(struct dvb_frontend *fe,
+				   struct dvb_frontend_parameters *param)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (lg_fail(ret))
+			goto fail;
+		state->current_frequency = param->frequency;
+	}
+
+	ret = lgdt3305_set_modulation(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_passband_digital_agc(state, param);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_set_agc_power_ref(state, param);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_agc_setup(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* low if */
+	ret = lgdt3305_write_reg(state, LGDT3305_GEN_CONTROL, 0x2f);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_set_reg_bit(state, LGDT3305_CR_CTR_FREQ_1, 6, 1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_set_if(state, param);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_spectral_inversion(state, param,
+					  state->cfg->spectral_inversion
+					  ? 1 : 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_set_filter_extension(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->current_modulation = param->u.vsb.modulation;
+
+	ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
+	ret = lgdt3305_mpeg_mode_polarity(state,
+					  state->cfg->tpclk_edge,
+					  state->cfg->tpvalid_polarity);
+fail:
+	return ret;
+}
+
+static int lgdt3305_get_frontend(struct dvb_frontend *fe,
+				 struct dvb_frontend_parameters *param)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+
+	lg_dbg("\n");
+
+	param->u.vsb.modulation = state->current_modulation;
+	param->frequency = state->current_frequency;
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_read_cr_lock_status(struct lgdt3305_state *state,
+					int *locked)
+{
+	u8 val;
+	int ret;
+	char *cr_lock_state = "";
+
+	*locked = 0;
+
+	ret = lgdt3305_read_reg(state, LGDT3305_CR_LOCK_STATUS, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	switch (state->current_modulation) {
+	case QAM_256:
+	case QAM_64:
+		if (val & (1 << 1))
+			*locked = 1;
+
+		switch (val & 0x07) {
+		case 0:
+			cr_lock_state = "QAM UNLOCK";
+			break;
+		case 4:
+			cr_lock_state = "QAM 1stLock";
+			break;
+		case 6:
+			cr_lock_state = "QAM 2ndLock";
+			break;
+		case 7:
+			cr_lock_state = "QAM FinalLock";
+			break;
+		default:
+			cr_lock_state = "CLOCKQAM-INVALID!";
+			break;
+		}
+		break;
+	case VSB_8:
+		if (val & (1 << 7)) {
+			*locked = 1;
+			cr_lock_state = "CLOCKVSB";
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	lg_dbg("(%d) %s\n", *locked, cr_lock_state);
+fail:
+	return ret;
+}
+
+static int lgdt3305_read_fec_lock_status(struct lgdt3305_state *state,
+					 int *locked)
+{
+	u8 val;
+	int ret, mpeg_lock, fec_lock, viterbi_lock;
+
+	*locked = 0;
+
+	switch (state->current_modulation) {
+	case QAM_256:
+	case QAM_64:
+		ret = lgdt3305_read_reg(state,
+					LGDT3305_FEC_LOCK_STATUS, &val);
+		if (lg_fail(ret))
+			goto fail;
+
+		mpeg_lock    = (val & (1 << 0)) ? 1 : 0;
+		fec_lock     = (val & (1 << 2)) ? 1 : 0;
+		viterbi_lock = (val & (1 << 3)) ? 1 : 0;
+
+		*locked = mpeg_lock && fec_lock && viterbi_lock;
+
+		lg_dbg("(%d) %s%s%s\n", *locked,
+		       mpeg_lock    ? "mpeg lock  "  : "",
+		       fec_lock     ? "fec lock  "   : "",
+		       viterbi_lock ? "viterbi lock" : "");
+		break;
+	case VSB_8:
+	default:
+		ret = -EINVAL;
+	}
+fail:
+	return ret;
+}
+
+static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	u8 val;
+	int ret, signal, inlock, nofecerr, snrgood,
+		cr_lock, fec_lock, sync_lock;
+
+	*status = 0;
+
+	ret = lgdt3305_read_reg(state, LGDT3305_GEN_STATUS, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	signal    = (val & (1 << 4)) ? 1 : 0;
+	inlock    = (val & (1 << 3)) ? 0 : 1;
+	sync_lock = (val & (1 << 2)) ? 1 : 0;
+	nofecerr  = (val & (1 << 1)) ? 1 : 0;
+	snrgood   = (val & (1 << 0)) ? 1 : 0;
+
+	lg_dbg("%s%s%s%s%s\n",
+	       signal    ? "SIGNALEXIST " : "",
+	       inlock    ? "INLOCK "      : "",
+	       sync_lock ? "SYNCLOCK "    : "",
+	       nofecerr  ? "NOFECERR "    : "",
+	       snrgood   ? "SNRGOOD "     : "");
+
+	ret = lgdt3305_read_cr_lock_status(state, &cr_lock);
+	if (lg_fail(ret))
+		goto fail;
+
+	if (signal)
+		*status |= FE_HAS_SIGNAL;
+	if (cr_lock)
+		*status |= FE_HAS_CARRIER;
+	if (nofecerr)
+		*status |= FE_HAS_VITERBI;
+	if (sync_lock)
+		*status |= FE_HAS_SYNC;
+
+	switch (state->current_modulation) {
+	case QAM_256:
+	case QAM_64:
+		ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
+		if (lg_fail(ret))
+			goto fail;
+
+		if (fec_lock)
+			*status |= FE_HAS_LOCK;
+		break;
+	case VSB_8:
+		if (inlock)
+			*status |= FE_HAS_LOCK;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* borrowed from lgdt330x.c */
+static u32 calculate_snr(u32 mse, u32 c)
+{
+	if (mse == 0) /* no signal */
+		return 0;
+
+	mse = intlog10(mse);
+	if (mse > c) {
+		/* Negative SNR, which is possible, but realisticly the
+		demod will lose lock before the signal gets this bad.  The
+		API only allows for unsigned values, so just return 0 */
+		return 0;
+	}
+	return 10*(c - mse);
+}
+
+static int lgdt3305_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	u32 noise;	/* noise value */
+	u32 c;		/* per-modulation SNR calculation constant */
+
+	switch (state->current_modulation) {
+	case VSB_8:
+#ifdef USE_PTMSE
+		/* Use Phase Tracker Mean-Square Error Register */
+		/* SNR for ranges from -13.11 to +44.08 */
+		noise =	((read_reg(state, LGDT3305_PT_MSE_1) & 0x07) << 16) |
+			(read_reg(state, LGDT3305_PT_MSE_2) << 8) |
+			(read_reg(state, LGDT3305_PT_MSE_3) & 0xff);
+		c = 73957994; /* log10(25*32^2)*2^24 */
+#else
+		/* Use Equalizer Mean-Square Error Register */
+		/* SNR for ranges from -16.12 to +44.08 */
+		noise =	((read_reg(state, LGDT3305_EQ_MSE_1) & 0x0f) << 16) |
+			(read_reg(state, LGDT3305_EQ_MSE_2) << 8) |
+			(read_reg(state, LGDT3305_EQ_MSE_3) & 0xff);
+		c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+		break;
+	case QAM_64:
+	case QAM_256:
+		noise = (read_reg(state, LGDT3305_CR_MSE_1) << 8) |
+			(read_reg(state, LGDT3305_CR_MSE_2) & 0xff);
+
+		c = (state->current_modulation == QAM_64) ?
+			97939837 : 98026066;
+		/* log10(688128)*2^24 and log10(696320)*2^24 */
+		break;
+	default:
+		return -EINVAL;
+	}
+	state->snr = calculate_snr(noise, c);
+	/* report SNR in dB * 10 */
+	*snr = (state->snr / ((1 << 24) / 10));
+	lg_dbg("noise = 0x%08x, snr = %d.%02d dB\n", noise,
+	       state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+
+	return 0;
+}
+
+static int lgdt3305_read_signal_strength(struct dvb_frontend *fe,
+					 u16 *strength)
+{
+	/* borrowed from lgdt330x.c
+	 *
+	 * Calculate strength from SNR up to 35dB
+	 * Even though the SNR can go higher than 35dB,
+	 * there is some comfort factor in having a range of
+	 * strong signals that can show at 100%
+	 */
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	u16 snr;
+	int ret;
+
+	*strength = 0;
+
+	ret = fe->ops.read_snr(fe, &snr);
+	if (lg_fail(ret))
+		goto fail;
+	/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
+	/* scale the range 0 - 35*2^24 into 0 - 65535 */
+	if (state->snr >= 8960 * 0x10000)
+		*strength = 0xffff;
+	else
+		*strength = state->snr / 8960;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3305_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int lgdt3305_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+
+	*ucblocks =
+		(read_reg(state, LGDT3305_FEC_PKT_ERR_1) << 8) |
+		(read_reg(state, LGDT3305_FEC_PKT_ERR_2) & 0xff);
+
+	return 0;
+}
+
+static int lgdt3305_get_tune_settings(struct dvb_frontend *fe,
+				      struct dvb_frontend_tune_settings
+					*fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 500;
+	lg_dbg("\n");
+	return 0;
+}
+
+static void lgdt3305_release(struct dvb_frontend *fe)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	lg_dbg("\n");
+	kfree(state);
+}
+
+static struct dvb_frontend_ops lgdt3305_ops;
+
+struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
+				     struct i2c_adapter *i2c_adap)
+{
+	struct lgdt3305_state *state = NULL;
+	int ret;
+	u8 val;
+
+	lg_dbg("(%d-%04x)\n",
+	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
+	       config ? config->i2c_addr : 0);
+
+	state = kzalloc(sizeof(struct lgdt3305_state), GFP_KERNEL);
+	if (state == NULL)
+		goto fail;
+
+	state->cfg = config;
+	state->i2c_adap = i2c_adap;
+
+	memcpy(&state->frontend.ops, &lgdt3305_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* verify that we're talking to a lg dt3305 */
+	ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
+	if ((lg_fail(ret)) | (val == 0))
+		goto fail;
+	ret = lgdt3305_write_reg(state, 0x0808, 0x80);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_read_reg(state, 0x0808, &val);
+	if ((lg_fail(ret)) | (val != 0x80))
+		goto fail;
+	ret = lgdt3305_write_reg(state, 0x0808, 0x00);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->current_frequency = -1;
+	state->current_modulation = -1;
+
+	return &state->frontend;
+fail:
+	lg_warn("unable to detect LGDT3305 hardware\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(lgdt3305_attach);
+
+static struct dvb_frontend_ops lgdt3305_ops = {
+	.info = {
+		.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
+		.type               = FE_ATSC,
+		.frequency_min      = 54000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.i2c_gate_ctrl        = lgdt3305_i2c_gate_ctrl,
+	.init                 = lgdt3305_init,
+	.sleep                = lgdt3305_sleep,
+	.set_frontend         = lgdt3305_set_parameters,
+	.get_frontend         = lgdt3305_get_frontend,
+	.get_tune_settings    = lgdt3305_get_tune_settings,
+	.read_status          = lgdt3305_read_status,
+	.read_ber             = lgdt3305_read_ber,
+	.read_signal_strength = lgdt3305_read_signal_strength,
+	.read_snr             = lgdt3305_read_snr,
+	.read_ucblocks        = lgdt3305_read_ucblocks,
+	.release              = lgdt3305_release,
+};
+
+MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h
new file mode 100644
index 0000000..4fa6e52
--- /dev/null
+++ b/drivers/media/dvb/frontends/lgdt3305.h
@@ -0,0 +1,85 @@
+/*
+ *    Support for LGDT3305 - VSB/QAM
+ *
+ *    Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.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.
+ *
+ */
+
+#ifndef _LGDT3305_H_
+#define _LGDT3305_H_
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+
+enum lgdt3305_mpeg_mode {
+	LGDT3305_MPEG_PARALLEL = 0,
+	LGDT3305_MPEG_SERIAL = 1,
+};
+
+enum lgdt3305_tp_clock_edge {
+	LGDT3305_TPCLK_RISING_EDGE = 0,
+	LGDT3305_TPCLK_FALLING_EDGE = 1,
+};
+
+enum lgdt3305_tp_valid_polarity {
+	LGDT3305_TP_VALID_LOW = 0,
+	LGDT3305_TP_VALID_HIGH = 1,
+};
+
+struct lgdt3305_config {
+	u8 i2c_addr;
+
+	/* user defined IF frequency in KHz */
+	u16 qam_if_khz;
+	u16 vsb_if_khz;
+
+	/* AGC Power reference - defaults are used if left unset */
+	u16 usref_8vsb;   /* default: 0x32c4 */
+	u16 usref_qam64;  /* default: 0x5400 */
+	u16 usref_qam256; /* default: 0x2a80 */
+
+	/* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
+	int deny_i2c_rptr:1;
+
+	/* spectral inversion - 0:disabled 1:enabled */
+	int spectral_inversion:1;
+
+	/* use RF AGC loop - 0:disabled 1:enabled */
+	int rf_agc_loop:1;
+
+	enum lgdt3305_mpeg_mode mpeg_mode;
+	enum lgdt3305_tp_clock_edge tpclk_edge;
+	enum lgdt3305_tp_valid_polarity tpvalid_polarity;
+};
+
+#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
+				     defined(MODULE))
+extern
+struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
+				     struct i2c_adapter *i2c_adap);
+#else
+static inline
+struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
+				     struct i2c_adapter *i2c_adap)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LGDT3305 */
+
+#endif /* _LGDT3305_H_ */
diff --git a/drivers/media/dvb/frontends/lnbh24.h b/drivers/media/dvb/frontends/lnbh24.h
new file mode 100644
index 0000000..c059b16
--- /dev/null
+++ b/drivers/media/dvb/frontends/lnbh24.h
@@ -0,0 +1,55 @@
+/*
+ * lnbh24.h - driver for lnb supply and control ic lnbh24
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 _LNBH24_H
+#define _LNBH24_H
+
+/* system register bits */
+#define LNBH24_OLF	0x01
+#define LNBH24_OTF	0x02
+#define LNBH24_EN	0x04
+#define LNBH24_VSEL	0x08
+#define LNBH24_LLC	0x10
+#define LNBH24_TEN	0x20
+#define LNBH24_TTX	0x40
+#define LNBH24_PCL	0x80
+
+#include <linux/dvb/frontend.h>
+
+#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
+							&& defined(MODULE))
+/* override_set and override_clear control which
+   system register bits (above) to always set & clear */
+extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear, u8 i2c_addr);
+#else
+static inline struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear, u8 i2c_addr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
index 76f935d..1dcc56f 100644
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -1,7 +1,8 @@
 /*
- * lnbp21.h - driver for lnb supply and control ic lnbp21
+ * lnbp21.c - driver for lnb supply and control ic lnbp21
  *
  * Copyright (C) 2006 Oliver Endriss
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -33,18 +34,21 @@
 
 #include "dvb_frontend.h"
 #include "lnbp21.h"
+#include "lnbh24.h"
 
 struct lnbp21 {
 	u8			config;
 	u8			override_or;
 	u8			override_and;
 	struct i2c_adapter	*i2c;
+	u8			i2c_addr;
 };
 
-static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int lnbp21_set_voltage(struct dvb_frontend *fe,
+					fe_sec_voltage_t voltage)
 {
 	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
 				.buf = &lnbp21->config,
 				.len = sizeof(lnbp21->config) };
 
@@ -72,7 +76,7 @@
 static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 {
 	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
 				.buf = &lnbp21->config,
 				.len = sizeof(lnbp21->config) };
 
@@ -97,15 +101,18 @@
 	fe->sec_priv = NULL;
 }
 
-struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear, u8 i2c_addr, u8 config)
 {
 	struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
 	if (!lnbp21)
 		return NULL;
 
 	/* default configuration */
-	lnbp21->config = LNBP21_ISEL;
+	lnbp21->config = config;
 	lnbp21->i2c = i2c;
+	lnbp21->i2c_addr = i2c_addr;
 	fe->sec_priv = lnbp21;
 
 	/* bits which should be forced to '1' */
@@ -126,11 +133,29 @@
 	/* override frontend ops */
 	fe->ops.set_voltage = lnbp21_set_voltage;
 	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+	printk(KERN_INFO "LNBx2x attached on addr=%x", lnbp21->i2c_addr);
 
 	return fe;
 }
+
+struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear, u8 i2c_addr)
+{
+	return lnbx2x_attach(fe, i2c, override_set, override_clear,
+							i2c_addr, LNBH24_TTX);
+}
+EXPORT_SYMBOL(lnbh24_attach);
+
+struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear)
+{
+	return lnbx2x_attach(fe, i2c, override_set, override_clear,
+							0x08, LNBP21_ISEL);
+}
 EXPORT_SYMBOL(lnbp21_attach);
 
-MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
-MODULE_AUTHOR("Oliver Endriss");
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24");
+MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
index 8fe094b..fcdf1c6 100644
--- a/drivers/media/dvb/frontends/lnbp21.h
+++ b/drivers/media/dvb/frontends/lnbp21.h
@@ -28,26 +28,48 @@
 #define _LNBP21_H
 
 /* system register bits */
+/* [RO] 0=OK; 1=over current limit flag */
 #define LNBP21_OLF	0x01
+/* [RO] 0=OK; 1=over temperature flag (150 C) */
 #define LNBP21_OTF	0x02
+/* [RW] 0=disable LNB power, enable loopthrough
+	1=enable LNB power, disable loopthrough */
 #define LNBP21_EN	0x04
+/* [RW] 0=low voltage (13/14V, vert pol)
+	1=high voltage (18/19V,horiz pol) */
 #define LNBP21_VSEL	0x08
+/* [RW] increase LNB voltage by 1V:
+	0=13/18V; 1=14/19V */
 #define LNBP21_LLC	0x10
+/* [RW] 0=tone controlled by DSQIN pin
+	1=tone enable, disable DSQIN */
 #define LNBP21_TEN	0x20
+/* [RW] current limit select:
+	0:Iout=500-650mA Isc=300mA
+	1:Iout=400-550mA Isc=200mA */
 #define LNBP21_ISEL	0x40
+/* [RW] short-circuit protect:
+	0=pulsed (dynamic) curr limiting
+	1=static curr limiting */
 #define LNBP21_PCL	0x80
 
 #include <linux/dvb/frontend.h>
 
-#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) && defined(MODULE))
-/* override_set and override_clear control which system register bits (above) to always set & clear */
-extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
+							&& defined(MODULE))
+/* override_set and override_clear control which
+ system register bits (above) to always set & clear */
+extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear);
 #else
-static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
+				struct i2c_adapter *i2c, u8 override_set,
+				u8 override_clear)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
-#endif // CONFIG_DVB_LNBP21
+#endif
 
-#endif // _LNBP21_H
+#endif
diff --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c
index 892af8c..3f5a0e1 100644
--- a/drivers/media/dvb/frontends/s921_module.c
+++ b/drivers/media/dvb/frontends/s921_module.c
@@ -169,7 +169,6 @@
 
 	struct s921_state *state;
 	state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
-	memset(state, 0x0, sizeof(struct s921_state));
 
 	state->addr = config->i2c_address;
 	state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/stb6100_cfg.h b/drivers/media/dvb/frontends/stb6100_cfg.h
index d313340..6314d18 100644
--- a/drivers/media/dvb/frontends/stb6100_cfg.h
+++ b/drivers/media/dvb/frontends/stb6100_cfg.h
@@ -36,7 +36,6 @@
 			return err;
 		}
 		*frequency = t_state.frequency;
-		printk("%s: Frequency=%d\n", __func__, t_state.frequency);
 	}
 	return 0;
 }
@@ -59,7 +58,6 @@
 			return err;
 		}
 	}
-	printk("%s: Frequency=%d\n", __func__, t_state.frequency);
 	return 0;
 }
 
@@ -81,7 +79,6 @@
 		}
 		*bandwidth = t_state.bandwidth;
 	}
-	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
 	return 0;
 }
 
@@ -103,6 +100,5 @@
 			return err;
 		}
 	}
-	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
 	return 0;
 }
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h
new file mode 100644
index 0000000..8a1332c
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900.h
@@ -0,0 +1,62 @@
+/*
+ * stv0900.h
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 STV0900_H
+#define STV0900_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0900_config {
+	u8 demod_address;
+	u32 xtal;
+	u8 clkmode;/* 0 for CLKI,  2 for XTALI */
+
+	u8 diseqc_mode;
+
+	u8 path1_mode;
+	u8 path2_mode;
+
+	u8 tun1_maddress;/* 0, 1, 2, 3 for 0xc0, 0xc2, 0xc4, 0xc6 */
+	u8 tun2_maddress;
+	u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
+	u8 tun2_adc;
+};
+
+#if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \
+							&& defined(MODULE))
+extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
+					struct i2c_adapter *i2c, int demod);
+#else
+static inline struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
+					struct i2c_adapter *i2c, int demod)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
+
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
new file mode 100644
index 0000000..8499bcf
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -0,0 +1,1949 @@
+/*
+ * stv0900_core.c
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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/string.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+
+#include "stv0900.h"
+#include "stv0900_reg.h"
+#include "stv0900_priv.h"
+#include "stv0900_init.h"
+
+static int stvdebug = 1;
+module_param_named(debug, stvdebug, int, 0644);
+
+/* internal params node */
+struct stv0900_inode {
+	/* pointer for internal params, one for each pair of demods */
+	struct stv0900_internal		*internal;
+	struct stv0900_inode		*next_inode;
+};
+
+/* first internal params */
+static struct stv0900_inode *stv0900_first_inode;
+
+/* find chip by i2c adapter and i2c address */
+static struct stv0900_inode *find_inode(struct i2c_adapter *i2c_adap,
+							u8 i2c_addr)
+{
+	struct stv0900_inode *temp_chip = stv0900_first_inode;
+
+	if (temp_chip != NULL) {
+		/*
+		 Search of the last stv0900 chip or
+		 find it by i2c adapter and i2c address */
+		while ((temp_chip != NULL) &&
+			((temp_chip->internal->i2c_adap != i2c_adap) ||
+			(temp_chip->internal->i2c_addr != i2c_addr)))
+
+			temp_chip = temp_chip->next_inode;
+
+	}
+
+	return temp_chip;
+}
+
+/* deallocating chip */
+static void remove_inode(struct stv0900_internal *internal)
+{
+	struct stv0900_inode *prev_node = stv0900_first_inode;
+	struct stv0900_inode *del_node = find_inode(internal->i2c_adap,
+						internal->i2c_addr);
+
+	if (del_node != NULL) {
+		if (del_node == stv0900_first_inode) {
+			stv0900_first_inode = del_node->next_inode;
+		} else {
+			while (prev_node->next_inode != del_node)
+				prev_node = prev_node->next_inode;
+
+			if (del_node->next_inode == NULL)
+				prev_node->next_inode = NULL;
+			else
+				prev_node->next_inode =
+					prev_node->next_inode->next_inode;
+		}
+
+		kfree(del_node);
+	}
+}
+
+/* allocating new chip */
+static struct stv0900_inode *append_internal(struct stv0900_internal *internal)
+{
+	struct stv0900_inode *new_node = stv0900_first_inode;
+
+	if (new_node == NULL) {
+		new_node = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL);
+		stv0900_first_inode = new_node;
+	} else {
+		while (new_node->next_inode != NULL)
+			new_node = new_node->next_inode;
+
+		new_node->next_inode = kmalloc(sizeof(struct stv0900_inode), GFP_KERNEL);
+		if (new_node->next_inode != NULL)
+			new_node = new_node->next_inode;
+		else
+			new_node = NULL;
+	}
+
+	if (new_node != NULL) {
+		new_node->internal = internal;
+		new_node->next_inode = NULL;
+	}
+
+	return new_node;
+}
+
+s32 ge2comp(s32 a, s32 width)
+{
+	if (width == 32)
+		return a;
+	else
+		return (a >= (1 << (width - 1))) ? (a - (1 << width)) : a;
+}
+
+void stv0900_write_reg(struct stv0900_internal *i_params, u16 reg_addr,
+								u8 reg_data)
+{
+	u8 data[3];
+	int ret;
+	struct i2c_msg i2cmsg = {
+		.addr  = i_params->i2c_addr,
+		.flags = 0,
+		.len   = 3,
+		.buf   = data,
+	};
+
+	data[0] = MSB(reg_addr);
+	data[1] = LSB(reg_addr);
+	data[2] = reg_data;
+
+	ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
+	if (ret != 1)
+		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+}
+
+u8 stv0900_read_reg(struct stv0900_internal *i_params, u16 reg_addr)
+{
+	u8 data[2];
+	int ret;
+	struct i2c_msg i2cmsg = {
+		.addr  = i_params->i2c_addr,
+		.flags = 0,
+		.len   = 2,
+		.buf   = data,
+	};
+
+	data[0] = MSB(reg_addr);
+	data[1] = LSB(reg_addr);
+
+	ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
+	if (ret != 1)
+		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+
+	i2cmsg.flags = I2C_M_RD;
+	i2cmsg.len = 1;
+	ret = i2c_transfer(i_params->i2c_adap, &i2cmsg, 1);
+	if (ret != 1)
+		dprintk(KERN_ERR "%s: i2c error %d\n", __func__, ret);
+
+	return data[0];
+}
+
+void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
+{
+	u8 position = 0, i = 0;
+
+	(*mask) = label & 0xff;
+
+	while ((position == 0) && (i < 8)) {
+		position = ((*mask) >> i) & 0x01;
+		i++;
+	}
+
+	(*pos) = (i - 1);
+}
+
+void stv0900_write_bits(struct stv0900_internal *i_params, u32 label, u8 val)
+{
+	u8 reg, mask, pos;
+
+	reg = stv0900_read_reg(i_params, (label >> 16) & 0xffff);
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	reg = (reg & (~mask)) | val;
+	stv0900_write_reg(i_params, (label >> 16) & 0xffff, reg);
+
+}
+
+u8 stv0900_get_bits(struct stv0900_internal *i_params, u32 label)
+{
+	u8 val = 0xff;
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = stv0900_read_reg(i_params, label >> 16);
+	val = (val & mask) >> pos;
+
+	return val;
+}
+
+enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *i_params)
+{
+	s32 i;
+	enum fe_stv0900_error error;
+
+	if (i_params != NULL) {
+		i_params->chip_id = stv0900_read_reg(i_params, R0900_MID);
+		if (i_params->errs == STV0900_NO_ERROR) {
+			/*Startup sequence*/
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5c);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5c);
+			stv0900_write_reg(i_params, R0900_P1_TNRCFG, 0x6c);
+			stv0900_write_reg(i_params, R0900_P2_TNRCFG, 0x6f);
+			stv0900_write_reg(i_params, R0900_P1_I2CRPT, 0x24);
+			stv0900_write_reg(i_params, R0900_P2_I2CRPT, 0x24);
+			stv0900_write_reg(i_params, R0900_NCOARSE, 0x13);
+			msleep(3);
+			stv0900_write_reg(i_params, R0900_I2CCFG, 0x08);
+
+			switch (i_params->clkmode) {
+			case 0:
+			case 2:
+				stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20
+						| i_params->clkmode);
+				break;
+			default:
+				/* preserve SELOSCI bit */
+				i = 0x02 & stv0900_read_reg(i_params, R0900_SYNTCTRL);
+				stv0900_write_reg(i_params, R0900_SYNTCTRL, 0x20 | i);
+				break;
+			}
+
+			msleep(3);
+			for (i = 0; i < 182; i++)
+				stv0900_write_reg(i_params, STV0900_InitVal[i][0], STV0900_InitVal[i][1]);
+
+			if (stv0900_read_reg(i_params, R0900_MID) >= 0x20) {
+				stv0900_write_reg(i_params, R0900_TSGENERAL, 0x0c);
+				for (i = 0; i < 32; i++)
+					stv0900_write_reg(i_params, STV0900_Cut20_AddOnVal[i][0], STV0900_Cut20_AddOnVal[i][1]);
+			}
+
+			stv0900_write_reg(i_params, R0900_P1_FSPYCFG, 0x6c);
+			stv0900_write_reg(i_params, R0900_P2_FSPYCFG, 0x6c);
+			stv0900_write_reg(i_params, R0900_TSTRES0, 0x80);
+			stv0900_write_reg(i_params, R0900_TSTRES0, 0x00);
+		}
+		error = i_params->errs;
+	} else
+		error = STV0900_INVALID_HANDLE;
+
+	return error;
+
+}
+
+u32 stv0900_get_mclk_freq(struct stv0900_internal *i_params, u32 ext_clk)
+{
+	u32 mclk = 90000000, div = 0, ad_div = 0;
+
+	div = stv0900_get_bits(i_params, F0900_M_DIV);
+	ad_div = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6);
+
+	mclk = (div + 1) * ext_clk / ad_div;
+
+	dprintk(KERN_INFO "%s: Calculated Mclk = %d\n", __func__, mclk);
+
+	return mclk;
+}
+
+enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *i_params, u32 mclk)
+{
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+	u32 m_div, clk_sel;
+
+	dprintk(KERN_INFO "%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+			i_params->quartz);
+
+	if (i_params == NULL)
+		error = STV0900_INVALID_HANDLE;
+	else {
+		if (i_params->errs)
+			error = STV0900_I2C_ERROR;
+		else {
+			clk_sel = ((stv0900_get_bits(i_params, F0900_SELX1RATIO) == 1) ? 4 : 6);
+			m_div = ((clk_sel * mclk) / i_params->quartz) - 1;
+			stv0900_write_bits(i_params, F0900_M_DIV, m_div);
+			i_params->mclk = stv0900_get_mclk_freq(i_params,
+							i_params->quartz);
+
+			/*Set the DiseqC frequency to 22KHz */
+			/*
+				Formula:
+				DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg)
+				DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg)
+			*/
+			m_div = i_params->mclk / 704000;
+			stv0900_write_reg(i_params, R0900_P1_F22TX, m_div);
+			stv0900_write_reg(i_params, R0900_P1_F22RX, m_div);
+
+			stv0900_write_reg(i_params, R0900_P2_F22TX, m_div);
+			stv0900_write_reg(i_params, R0900_P2_F22RX, m_div);
+
+			if ((i_params->errs))
+				error = STV0900_I2C_ERROR;
+		}
+	}
+
+	return error;
+}
+
+u32 stv0900_get_err_count(struct stv0900_internal *i_params, int cntr,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 lsb, msb, hsb, err_val;
+	s32 err1field_hsb, err1field_msb, err1field_lsb;
+	s32 err2field_hsb, err2field_msb, err2field_lsb;
+
+	dmd_reg(err1field_hsb, F0900_P1_ERR_CNT12, F0900_P2_ERR_CNT12);
+	dmd_reg(err1field_msb, F0900_P1_ERR_CNT11, F0900_P2_ERR_CNT11);
+	dmd_reg(err1field_lsb, F0900_P1_ERR_CNT10, F0900_P2_ERR_CNT10);
+
+	dmd_reg(err2field_hsb, F0900_P1_ERR_CNT22, F0900_P2_ERR_CNT22);
+	dmd_reg(err2field_msb, F0900_P1_ERR_CNT21, F0900_P2_ERR_CNT21);
+	dmd_reg(err2field_lsb, F0900_P1_ERR_CNT20, F0900_P2_ERR_CNT20);
+
+	switch (cntr) {
+	case 0:
+	default:
+		hsb = stv0900_get_bits(i_params, err1field_hsb);
+		msb = stv0900_get_bits(i_params, err1field_msb);
+		lsb = stv0900_get_bits(i_params, err1field_lsb);
+		break;
+	case 1:
+		hsb = stv0900_get_bits(i_params, err2field_hsb);
+		msb = stv0900_get_bits(i_params, err2field_msb);
+		lsb = stv0900_get_bits(i_params, err2field_lsb);
+		break;
+	}
+
+	err_val = (hsb << 16) + (msb << 8) + (lsb);
+
+	return err_val;
+}
+
+static int stv0900_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	u32 fi2c;
+
+	dmd_reg(fi2c, F0900_P1_I2CT_ON, F0900_P2_I2CT_ON);
+	if (enable)
+		stv0900_write_bits(i_params, fi2c, 1);
+
+	return 0;
+}
+
+static void stv0900_set_ts_parallel_serial(struct stv0900_internal *i_params,
+					enum fe_stv0900_clock_type path1_ts,
+					enum fe_stv0900_clock_type path2_ts)
+{
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if (i_params->chip_id >= 0x20) {
+		switch (path1_ts) {
+		case STV0900_PARALLEL_PUNCT_CLOCK:
+		case STV0900_DVBCI_CLOCK:
+			switch (path2_ts) {
+			case STV0900_SERIAL_PUNCT_CLOCK:
+			case STV0900_SERIAL_CONT_CLOCK:
+			default:
+				stv0900_write_reg(i_params, R0900_TSGENERAL,
+							0x00);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(i_params, R0900_TSGENERAL,
+							0x06);
+				stv0900_write_bits(i_params,
+						F0900_P1_TSFIFO_MANSPEED, 3);
+				stv0900_write_bits(i_params,
+						F0900_P2_TSFIFO_MANSPEED, 0);
+				stv0900_write_reg(i_params,
+						R0900_P1_TSSPEED, 0x14);
+				stv0900_write_reg(i_params,
+						R0900_P2_TSSPEED, 0x28);
+				break;
+			}
+			break;
+		case STV0900_SERIAL_PUNCT_CLOCK:
+		case STV0900_SERIAL_CONT_CLOCK:
+		default:
+			switch (path2_ts) {
+			case STV0900_SERIAL_PUNCT_CLOCK:
+			case STV0900_SERIAL_CONT_CLOCK:
+			default:
+				stv0900_write_reg(i_params,
+						R0900_TSGENERAL, 0x0C);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(i_params,
+						R0900_TSGENERAL, 0x0A);
+				dprintk(KERN_INFO "%s: 0x0a\n", __func__);
+				break;
+			}
+			break;
+		}
+	} else {
+		switch (path1_ts) {
+		case STV0900_PARALLEL_PUNCT_CLOCK:
+		case STV0900_DVBCI_CLOCK:
+			switch (path2_ts) {
+			case STV0900_SERIAL_PUNCT_CLOCK:
+			case STV0900_SERIAL_CONT_CLOCK:
+			default:
+				stv0900_write_reg(i_params, R0900_TSGENERAL1X,
+							0x10);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(i_params, R0900_TSGENERAL1X,
+							0x16);
+				stv0900_write_bits(i_params,
+						F0900_P1_TSFIFO_MANSPEED, 3);
+				stv0900_write_bits(i_params,
+						F0900_P2_TSFIFO_MANSPEED, 0);
+				stv0900_write_reg(i_params, R0900_P1_TSSPEED,
+							0x14);
+				stv0900_write_reg(i_params, R0900_P2_TSSPEED,
+							0x28);
+				break;
+			}
+
+			break;
+		case STV0900_SERIAL_PUNCT_CLOCK:
+		case STV0900_SERIAL_CONT_CLOCK:
+		default:
+			switch (path2_ts) {
+			case STV0900_SERIAL_PUNCT_CLOCK:
+			case STV0900_SERIAL_CONT_CLOCK:
+			default:
+				stv0900_write_reg(i_params, R0900_TSGENERAL1X,
+							0x14);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(i_params, R0900_TSGENERAL1X,
+							0x12);
+				dprintk(KERN_INFO "%s: 0x12\n", __func__);
+				break;
+			}
+
+			break;
+		}
+	}
+
+	switch (path1_ts) {
+	case STV0900_PARALLEL_PUNCT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_DVBCI_CLOCK:
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01);
+		break;
+	case STV0900_SERIAL_PUNCT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_SERIAL_CONT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(i_params, F0900_P1_TSFIFO_DVBCI, 0x01);
+		break;
+	default:
+		break;
+	}
+
+	switch (path2_ts) {
+	case STV0900_PARALLEL_PUNCT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_DVBCI_CLOCK:
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01);
+		break;
+	case STV0900_SERIAL_PUNCT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_SERIAL_CONT_CLOCK:
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(i_params, F0900_P2_TSFIFO_DVBCI, 0x01);
+		break;
+	default:
+		break;
+	}
+
+	stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1);
+	stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 0);
+	stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1);
+	stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 0);
+}
+
+void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency,
+							u32 bandwidth)
+{
+	struct dvb_frontend_ops *frontend_ops = NULL;
+	struct dvb_tuner_ops *tuner_ops = NULL;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+
+	if (tuner_ops->set_frequency) {
+		if ((tuner_ops->set_frequency(fe, frequency)) < 0)
+			dprintk("%s: Invalid parameter\n", __func__);
+		else
+			dprintk("%s: Frequency=%d\n", __func__, frequency);
+
+	}
+
+	if (tuner_ops->set_bandwidth) {
+		if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0)
+			dprintk("%s: Invalid parameter\n", __func__);
+		else
+			dprintk("%s: Bandwidth=%d\n", __func__, bandwidth);
+
+	}
+}
+
+void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct dvb_frontend_ops *frontend_ops = NULL;
+	struct dvb_tuner_ops *tuner_ops = NULL;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+
+	if (tuner_ops->set_bandwidth) {
+		if ((tuner_ops->set_bandwidth(fe, bandwidth)) < 0)
+			dprintk("%s: Invalid parameter\n", __func__);
+		else
+			dprintk("%s: Bandwidth=%d\n", __func__, bandwidth);
+
+	}
+}
+
+static s32 stv0900_get_rf_level(struct stv0900_internal *i_params,
+				const struct stv0900_table *lookup,
+				enum fe_stv0900_demod_num demod)
+{
+	s32 agc_gain = 0,
+		imin,
+		imax,
+		i,
+		rf_lvl = 0;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if ((lookup != NULL) && lookup->size) {
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE1),
+						stv0900_get_bits(i_params, F0900_P1_AGCIQ_VALUE0));
+			break;
+		case STV0900_DEMOD_2:
+			agc_gain = MAKEWORD(stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE1),
+						stv0900_get_bits(i_params, F0900_P2_AGCIQ_VALUE0));
+			break;
+		}
+
+		imin = 0;
+		imax = lookup->size - 1;
+		if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[imax].regval)) {
+			while ((imax - imin) > 1) {
+				i = (imax + imin) >> 1;
+
+				if (INRANGE(lookup->table[imin].regval, agc_gain, lookup->table[i].regval))
+					imax = i;
+				else
+					imin = i;
+			}
+
+			rf_lvl = (((s32)agc_gain - lookup->table[imin].regval)
+					* (lookup->table[imax].realval - lookup->table[imin].realval)
+					/ (lookup->table[imax].regval - lookup->table[imin].regval))
+					+ lookup->table[imin].realval;
+		} else if (agc_gain > lookup->table[0].regval)
+			rf_lvl = 5;
+		else if (agc_gain < lookup->table[lookup->size-1].regval)
+			rf_lvl = -100;
+
+	}
+
+	dprintk(KERN_INFO "%s: RFLevel = %d\n", __func__, rf_lvl);
+
+	return rf_lvl;
+}
+
+static int stv0900_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *internal = state->internal;
+	s32 rflevel = stv0900_get_rf_level(internal, &stv0900_rf,
+								state->demod);
+
+	*strength = (rflevel + 100) * (16383 / 105);
+
+	return 0;
+}
+
+
+static s32 stv0900_carr_get_quality(struct dvb_frontend *fe,
+					const struct stv0900_table *lookup)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32 c_n = -100,
+		regval, imin, imax,
+		i,
+		lock_flag_field,
+		noise_field1,
+		noise_field0;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(lock_flag_field, F0900_P1_LOCK_DEFINITIF,
+					F0900_P2_LOCK_DEFINITIF);
+	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+		dmd_reg(noise_field1, F0900_P1_NOSPLHT_NORMED1,
+					F0900_P2_NOSPLHT_NORMED1);
+		dmd_reg(noise_field0, F0900_P1_NOSPLHT_NORMED0,
+					F0900_P2_NOSPLHT_NORMED0);
+	} else {
+		dmd_reg(noise_field1, F0900_P1_NOSDATAT_NORMED1,
+					F0900_P2_NOSDATAT_NORMED1);
+		dmd_reg(noise_field0, F0900_P1_NOSDATAT_NORMED0,
+					F0900_P2_NOSDATAT_NORMED0);
+	}
+
+	if (stv0900_get_bits(i_params, lock_flag_field)) {
+		if ((lookup != NULL) && lookup->size) {
+			regval = 0;
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				regval += MAKEWORD(stv0900_get_bits(i_params,
+								noise_field1),
+						stv0900_get_bits(i_params,
+								noise_field0));
+				msleep(1);
+			}
+
+			regval /= 16;
+			imin = 0;
+			imax = lookup->size - 1;
+			if (INRANGE(lookup->table[imin].regval,
+					regval,
+					lookup->table[imax].regval)) {
+				while ((imax - imin) > 1) {
+					i = (imax + imin) >> 1;
+					if (INRANGE(lookup->table[imin].regval,
+						    regval,
+						    lookup->table[i].regval))
+						imax = i;
+					else
+						imin = i;
+				}
+
+				c_n = ((regval - lookup->table[imin].regval)
+						* (lookup->table[imax].realval
+						- lookup->table[imin].realval)
+						/ (lookup->table[imax].regval
+						- lookup->table[imin].regval))
+						+ lookup->table[imin].realval;
+			} else if (regval < lookup->table[imin].regval)
+				c_n = 1000;
+		}
+	}
+
+	return c_n;
+}
+
+static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	*snr = stv0900_carr_get_quality(fe,
+			(const struct stv0900_table *)&stv0900_s2_cn);
+	*snr += 30;
+	*snr *= (16383 / 1030);
+
+	return 0;
+}
+
+static u32 stv0900_get_ber(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+	u32 ber = 10000000, i;
+	s32 dmd_state_reg;
+	s32 demod_state;
+	s32 vstatus_reg;
+	s32 prvit_field;
+	s32 pdel_status_reg;
+	s32 pdel_lock_field;
+
+	dmd_reg(dmd_state_reg, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE);
+	dmd_reg(vstatus_reg, R0900_P1_VSTATUSVIT, R0900_P2_VSTATUSVIT);
+	dmd_reg(prvit_field, F0900_P1_PRFVIT, F0900_P2_PRFVIT);
+	dmd_reg(pdel_status_reg, R0900_P1_PDELSTATUS1, R0900_P2_PDELSTATUS1);
+	dmd_reg(pdel_lock_field, F0900_P1_PKTDELIN_LOCK,
+				F0900_P2_PKTDELIN_LOCK);
+
+	demod_state = stv0900_get_bits(i_params, dmd_state_reg);
+
+	switch (demod_state) {
+	case STV0900_SEARCH:
+	case STV0900_PLH_DETECTED:
+	default:
+		ber = 10000000;
+		break;
+	case STV0900_DVBS_FOUND:
+		ber = 0;
+		for (i = 0; i < 5; i++) {
+			msleep(5);
+			ber += stv0900_get_err_count(i_params, 0, demod);
+		}
+
+		ber /= 5;
+		if (stv0900_get_bits(i_params, prvit_field)) {
+			ber *= 9766;
+			ber = ber >> 13;
+		}
+
+		break;
+	case STV0900_DVBS2_FOUND:
+		ber = 0;
+		for (i = 0; i < 5; i++) {
+			msleep(5);
+			ber += stv0900_get_err_count(i_params, 0, demod);
+		}
+
+		ber /= 5;
+		if (stv0900_get_bits(i_params, pdel_lock_field)) {
+			ber *= 9766;
+			ber = ber >> 13;
+		}
+
+		break;
+	}
+
+	return ber;
+}
+
+static int stv0900_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *internal = state->internal;
+
+	*ber = stv0900_get_ber(internal, state->demod);
+
+	return 0;
+}
+
+int stv0900_get_demod_lock(struct stv0900_internal *i_params,
+			enum fe_stv0900_demod_num demod, s32 time_out)
+{
+	s32 timer = 0,
+		lock = 0,
+		header_field,
+		lock_field;
+
+	enum fe_stv0900_search_state	dmd_state;
+
+	dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE);
+	dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF);
+	while ((timer < time_out) && (lock == 0)) {
+		dmd_state = stv0900_get_bits(i_params, header_field);
+		dprintk("Demod State = %d\n", dmd_state);
+		switch (dmd_state) {
+		case STV0900_SEARCH:
+		case STV0900_PLH_DETECTED:
+		default:
+			lock = 0;
+			break;
+		case STV0900_DVBS2_FOUND:
+		case STV0900_DVBS_FOUND:
+			lock = stv0900_get_bits(i_params, lock_field);
+			break;
+		}
+
+		if (lock == 0)
+			msleep(10);
+
+		timer += 10;
+	}
+
+	if (lock)
+		dprintk("DEMOD LOCK OK\n");
+	else
+		dprintk("DEMOD LOCK FAIL\n");
+
+	return lock;
+}
+
+void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+	s32 regflist,
+	i;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(regflist, R0900_P1_MODCODLST0, R0900_P2_MODCODLST0);
+
+	for (i = 0; i < 16; i++)
+		stv0900_write_reg(i_params, regflist + i, 0xff);
+}
+
+void stv0900_activate_s2_modcode(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+	u32 matype,
+	mod_code,
+	fmod,
+	reg_index,
+	field_index;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if (i_params->chip_id <= 0x11) {
+		msleep(5);
+
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			mod_code = stv0900_read_reg(i_params,
+							R0900_P1_PLHMODCOD);
+			matype = mod_code & 0x3;
+			mod_code = (mod_code & 0x7f) >> 2;
+
+			reg_index = R0900_P1_MODCODLSTF - mod_code / 2;
+			field_index = mod_code % 2;
+			break;
+		case STV0900_DEMOD_2:
+			mod_code = stv0900_read_reg(i_params,
+							R0900_P2_PLHMODCOD);
+			matype = mod_code & 0x3;
+			mod_code = (mod_code & 0x7f) >> 2;
+
+			reg_index = R0900_P2_MODCODLSTF - mod_code / 2;
+			field_index = mod_code % 2;
+			break;
+		}
+
+
+		switch (matype) {
+		case 0:
+		default:
+			fmod = 14;
+			break;
+		case 1:
+			fmod = 13;
+			break;
+		case 2:
+			fmod = 11;
+			break;
+		case 3:
+			fmod = 7;
+			break;
+		}
+
+		if ((INRANGE(STV0900_QPSK_12, mod_code, STV0900_8PSK_910))
+							&& (matype <= 1)) {
+			if (field_index == 0)
+				stv0900_write_reg(i_params, reg_index,
+							0xf0 | fmod);
+			else
+				stv0900_write_reg(i_params, reg_index,
+							(fmod << 4) | 0xf);
+		}
+	} else if (i_params->chip_id >= 0x12) {
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			for (reg_index = 0; reg_index < 7; reg_index++)
+				stv0900_write_reg(i_params, R0900_P1_MODCODLST0 + reg_index, 0xff);
+
+			stv0900_write_reg(i_params, R0900_P1_MODCODLSTE, 0xff);
+			stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0xcf);
+			for (reg_index = 0; reg_index < 8; reg_index++)
+				stv0900_write_reg(i_params, R0900_P1_MODCODLST7 + reg_index, 0xcc);
+
+			break;
+		case STV0900_DEMOD_2:
+			for (reg_index = 0; reg_index < 7; reg_index++)
+				stv0900_write_reg(i_params, R0900_P2_MODCODLST0 + reg_index, 0xff);
+
+			stv0900_write_reg(i_params, R0900_P2_MODCODLSTE, 0xff);
+			stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0xcf);
+			for (reg_index = 0; reg_index < 8; reg_index++)
+				stv0900_write_reg(i_params, R0900_P2_MODCODLST7 + reg_index, 0xcc);
+
+			break;
+		}
+
+	}
+}
+
+void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 reg_index;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_reg(i_params, R0900_P1_MODCODLST0, 0xff);
+		stv0900_write_reg(i_params, R0900_P1_MODCODLST1, 0xf0);
+		stv0900_write_reg(i_params, R0900_P1_MODCODLSTF, 0x0f);
+		for (reg_index = 0; reg_index < 13; reg_index++)
+			stv0900_write_reg(i_params,
+					R0900_P1_MODCODLST2 + reg_index, 0);
+
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_reg(i_params, R0900_P2_MODCODLST0, 0xff);
+		stv0900_write_reg(i_params, R0900_P2_MODCODLST1, 0xf0);
+		stv0900_write_reg(i_params, R0900_P2_MODCODLSTF, 0x0f);
+		for (reg_index = 0; reg_index < 13; reg_index++)
+			stv0900_write_reg(i_params,
+					R0900_P2_MODCODLST2 + reg_index, 0);
+
+		break;
+	}
+}
+
+static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static int stb0900_set_property(struct dvb_frontend *fe,
+				struct dtv_property *tvp)
+{
+	dprintk(KERN_INFO "%s(..)\n", __func__);
+
+	return 0;
+}
+
+static int stb0900_get_property(struct dvb_frontend *fe,
+				struct dtv_property *tvp)
+{
+	dprintk(KERN_INFO "%s(..)\n", __func__);
+
+	return 0;
+}
+
+void stv0900_start_search(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1f);
+
+		if (i_params->chip_id == 0x10)
+			stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xaa);
+
+		if (i_params->chip_id < 0x20)
+			stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55);
+
+		if (i_params->dmd1_symbol_rate <= 5000000) {
+			stv0900_write_reg(i_params, R0900_P1_CARCFG, 0x44);
+			stv0900_write_reg(i_params, R0900_P1_CFRUP1, 0x0f);
+			stv0900_write_reg(i_params, R0900_P1_CFRUP0, 0xff);
+			stv0900_write_reg(i_params, R0900_P1_CFRLOW1, 0xf0);
+			stv0900_write_reg(i_params, R0900_P1_CFRLOW0, 0x00);
+			stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68);
+		} else {
+			stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xc4);
+			stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44);
+		}
+
+		stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0);
+		stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0);
+
+		if (i_params->chip_id >= 0x20) {
+			stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41);
+			stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41);
+
+			if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) {
+				stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82);
+				stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0);
+			}
+		}
+
+		stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xe0);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xc0);
+		stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0);
+		stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0);
+		stv0900_write_bits(i_params, F0900_P1_S1S2_SEQUENTIAL, 0);
+		stv0900_write_reg(i_params, R0900_P1_RTC, 0x88);
+		if (i_params->chip_id >= 0x20) {
+			if (i_params->dmd1_symbol_rate < 2000000) {
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x39);
+				stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x40);
+			}
+
+			if (i_params->dmd1_symbol_rate < 10000000) {
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4c);
+				stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20);
+			} else {
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x4b);
+				stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x20);
+			}
+
+		} else {
+			if (i_params->dmd1_symbol_rate < 10000000)
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xef);
+			else
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed);
+		}
+
+		switch (i_params->dmd1_srch_algo) {
+		case STV0900_WARM_START:
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+			break;
+		case STV0900_COLD_START:
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1f);
+		if (i_params->chip_id == 0x10)
+			stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xaa);
+
+		if (i_params->chip_id < 0x20)
+			stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55);
+
+		if (i_params->dmd2_symbol_rate <= 5000000) {
+			stv0900_write_reg(i_params, R0900_P2_CARCFG, 0x44);
+			stv0900_write_reg(i_params, R0900_P2_CFRUP1, 0x0f);
+			stv0900_write_reg(i_params, R0900_P2_CFRUP0, 0xff);
+			stv0900_write_reg(i_params, R0900_P2_CFRLOW1, 0xf0);
+			stv0900_write_reg(i_params, R0900_P2_CFRLOW0, 0x00);
+			stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68);
+		} else {
+			stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xc4);
+			stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44);
+		}
+
+		stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0);
+		stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0);
+
+		if (i_params->chip_id >= 0x20) {
+			stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41);
+			stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41);
+			if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) {
+				stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82);
+				stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0);
+			}
+		}
+
+		stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xe0);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xc0);
+		stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0);
+		stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0);
+		stv0900_write_bits(i_params, F0900_P2_S1S2_SEQUENTIAL, 0);
+		stv0900_write_reg(i_params, R0900_P2_RTC, 0x88);
+		if (i_params->chip_id >= 0x20) {
+			if (i_params->dmd2_symbol_rate < 2000000) {
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x39);
+				stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x40);
+			}
+
+			if (i_params->dmd2_symbol_rate < 10000000) {
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4c);
+				stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20);
+			} else {
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x4b);
+				stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x20);
+			}
+
+		} else {
+			if (i_params->dmd2_symbol_rate < 10000000)
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xef);
+			else
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed);
+		}
+
+		switch (i_params->dmd2_srch_algo) {
+		case STV0900_WARM_START:
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+			break;
+		case STV0900_COLD_START:
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15);
+			break;
+		default:
+			break;
+		}
+
+		break;
+	}
+}
+
+u8 stv0900_get_optim_carr_loop(s32 srate, enum fe_stv0900_modcode modcode,
+							s32 pilot, u8 chip_id)
+{
+	u8 aclc_value = 0x29;
+	s32	i;
+	const struct stv0900_car_loop_optim *car_loop_s2;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if (chip_id <= 0x12)
+		car_loop_s2 = FE_STV0900_S2CarLoop;
+	else if (chip_id == 0x20)
+		car_loop_s2 = FE_STV0900_S2CarLoopCut20;
+	else
+		car_loop_s2 = FE_STV0900_S2CarLoop;
+
+	if (modcode < STV0900_QPSK_12) {
+		i = 0;
+		while ((i < 3) && (modcode != FE_STV0900_S2LowQPCarLoopCut20[i].modcode))
+			i++;
+
+		if (i >= 3)
+			i = 2;
+	} else {
+		i = 0;
+		while ((i < 14) && (modcode != car_loop_s2[i].modcode))
+			i++;
+
+		if (i >= 14) {
+			i = 0;
+			while ((i < 11) && (modcode != FE_STV0900_S2APSKCarLoopCut20[i].modcode))
+				i++;
+
+			if (i >= 11)
+				i = 10;
+		}
+	}
+
+	if (modcode <= STV0900_QPSK_25) {
+		if (pilot) {
+			if (srate <= 3000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_2;
+			else if (srate <= 7000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_5;
+			else if (srate <= 15000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_10;
+			else if (srate <= 25000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_20;
+			else
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_on_30;
+		} else {
+			if (srate <= 3000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_2;
+			else if (srate <= 7000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_5;
+			else if (srate <= 15000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_10;
+			else if (srate <= 25000000)
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_20;
+			else
+				aclc_value = FE_STV0900_S2LowQPCarLoopCut20[i].car_loop_pilots_off_30;
+		}
+
+	} else if (modcode <= STV0900_8PSK_910) {
+		if (pilot) {
+			if (srate <= 3000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_on_2;
+			else if (srate <= 7000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_on_5;
+			else if (srate <= 15000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_on_10;
+			else if (srate <= 25000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_on_20;
+			else
+				aclc_value = car_loop_s2[i].car_loop_pilots_on_30;
+		} else {
+			if (srate <= 3000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_off_2;
+			else if (srate <= 7000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_off_5;
+			else if (srate <= 15000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_off_10;
+			else if (srate <= 25000000)
+				aclc_value = car_loop_s2[i].car_loop_pilots_off_20;
+			else
+				aclc_value = car_loop_s2[i].car_loop_pilots_off_30;
+		}
+
+	} else {
+		if (srate <= 3000000)
+			aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_2;
+		else if (srate <= 7000000)
+			aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_5;
+		else if (srate <= 15000000)
+			aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_10;
+		else if (srate <= 25000000)
+			aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_20;
+		else
+			aclc_value = FE_STV0900_S2APSKCarLoopCut20[i].car_loop_pilots_on_30;
+	}
+
+	return aclc_value;
+}
+
+u8 stv0900_get_optim_short_carr_loop(s32 srate, enum fe_stv0900_modulation modulation, u8 chip_id)
+{
+	s32 mod_index = 0;
+
+	u8 aclc_value = 0x0b;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	switch (modulation) {
+	case STV0900_QPSK:
+	default:
+		mod_index = 0;
+		break;
+	case STV0900_8PSK:
+		mod_index = 1;
+		break;
+	case STV0900_16APSK:
+		mod_index = 2;
+		break;
+	case STV0900_32APSK:
+		mod_index = 3;
+		break;
+	}
+
+	switch (chip_id) {
+	case 0x20:
+		if (srate <= 3000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_2;
+		else if (srate <= 7000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_5;
+		else if (srate <= 15000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_10;
+		else if (srate <= 25000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_20;
+		else
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut20_30;
+
+		break;
+	case 0x12:
+	default:
+		if (srate <= 3000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_2;
+		else if (srate <= 7000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_5;
+		else if (srate <= 15000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_10;
+		else if (srate <= 25000000)
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_20;
+		else
+			aclc_value = FE_STV0900_S2ShortCarLoop[mod_index].car_loop_cut12_30;
+
+		break;
+	}
+
+	return aclc_value;
+}
+
+static enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_mode LDPC_Mode,
+					enum fe_stv0900_demod_num demod)
+{
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	switch (LDPC_Mode) {
+	case STV0900_DUAL:
+	default:
+		if ((i_params->demod_mode != STV0900_DUAL)
+			|| (stv0900_get_bits(i_params, F0900_DDEMOD) != 1)) {
+			stv0900_write_reg(i_params, R0900_GENCFG, 0x1d);
+
+			i_params->demod_mode = STV0900_DUAL;
+
+			stv0900_write_bits(i_params, F0900_FRESFEC, 1);
+			stv0900_write_bits(i_params, F0900_FRESFEC, 0);
+		}
+
+		break;
+	case STV0900_SINGLE:
+		if (demod == STV0900_DEMOD_2)
+			stv0900_write_reg(i_params, R0900_GENCFG, 0x06);
+		else
+			stv0900_write_reg(i_params, R0900_GENCFG, 0x04);
+
+		i_params->demod_mode = STV0900_SINGLE;
+
+		stv0900_write_bits(i_params, F0900_FRESFEC, 1);
+		stv0900_write_bits(i_params, F0900_FRESFEC, 0);
+		stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1);
+		stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0);
+		stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1);
+		stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0);
+		break;
+	}
+
+	return error;
+}
+
+static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
+					struct stv0900_init_params *p_init)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+	enum fe_stv0900_error demodError = STV0900_NO_ERROR;
+	int selosci;
+
+	struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
+						state->config->demod_address);
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if (temp_int != NULL) {
+		state->internal = temp_int->internal;
+		(state->internal->dmds_used)++;
+		dprintk(KERN_INFO "%s: Find Internal Structure!\n", __func__);
+		return STV0900_NO_ERROR;
+	} else {
+		state->internal = kmalloc(sizeof(struct stv0900_internal), GFP_KERNEL);
+		temp_int = append_internal(state->internal);
+		state->internal->dmds_used = 1;
+		state->internal->i2c_adap = state->i2c_adap;
+		state->internal->i2c_addr = state->config->demod_address;
+		state->internal->clkmode = state->config->clkmode;
+		state->internal->errs = STV0900_NO_ERROR;
+		dprintk(KERN_INFO "%s: Create New Internal Structure!\n", __func__);
+	}
+
+	if (state->internal != NULL) {
+		demodError = stv0900_initialize(state->internal);
+		if (demodError == STV0900_NO_ERROR) {
+				error = STV0900_NO_ERROR;
+		} else {
+			if (demodError == STV0900_INVALID_HANDLE)
+				error = STV0900_INVALID_HANDLE;
+			else
+				error = STV0900_I2C_ERROR;
+		}
+
+		if (state->internal != NULL) {
+			if (error == STV0900_NO_ERROR) {
+				state->internal->demod_mode = p_init->demod_mode;
+
+				stv0900_st_dvbs2_single(state->internal, state->internal->demod_mode, STV0900_DEMOD_1);
+
+				state->internal->chip_id = stv0900_read_reg(state->internal, R0900_MID);
+				state->internal->rolloff = p_init->rolloff;
+				state->internal->quartz = p_init->dmd_ref_clk;
+
+				stv0900_write_bits(state->internal, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
+				stv0900_write_bits(state->internal, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
+
+				stv0900_set_ts_parallel_serial(state->internal, p_init->path1_ts_clock, p_init->path2_ts_clock);
+				stv0900_write_bits(state->internal, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
+				switch (p_init->tuner1_adc) {
+				case 1:
+					stv0900_write_reg(state->internal, R0900_TSTTNR1, 0x26);
+					break;
+				default:
+					break;
+				}
+
+				stv0900_write_bits(state->internal, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress);
+				switch (p_init->tuner2_adc) {
+				case 1:
+					stv0900_write_reg(state->internal, R0900_TSTTNR3, 0x26);
+					break;
+				default:
+					break;
+				}
+
+				stv0900_write_bits(state->internal, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inversion);
+				stv0900_write_bits(state->internal, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inversion);
+				stv0900_set_mclk(state->internal, 135000000);
+				msleep(3);
+
+				switch (state->internal->clkmode) {
+				case 0:
+				case 2:
+					stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | state->internal->clkmode);
+					break;
+				default:
+					selosci = 0x02 & stv0900_read_reg(state->internal, R0900_SYNTCTRL);
+					stv0900_write_reg(state->internal, R0900_SYNTCTRL, 0x20 | selosci);
+					break;
+				}
+				msleep(3);
+
+				state->internal->mclk = stv0900_get_mclk_freq(state->internal, state->internal->quartz);
+				if (state->internal->errs)
+					error = STV0900_I2C_ERROR;
+			}
+		} else {
+			error = STV0900_INVALID_HANDLE;
+		}
+	}
+
+	return error;
+}
+
+static int stv0900_status(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	enum fe_stv0900_search_state demod_state;
+	s32 mode_field, delin_field, lock_field, fifo_field, lockedvit_field;
+	int locked = FALSE;
+
+	dmd_reg(mode_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE);
+	dmd_reg(lock_field, F0900_P1_LOCK_DEFINITIF, F0900_P2_LOCK_DEFINITIF);
+	dmd_reg(delin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK);
+	dmd_reg(fifo_field, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK);
+	dmd_reg(lockedvit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT);
+
+	demod_state = stv0900_get_bits(i_params, mode_field);
+	switch (demod_state) {
+	case STV0900_SEARCH:
+	case STV0900_PLH_DETECTED:
+	default:
+		locked = FALSE;
+		break;
+	case STV0900_DVBS2_FOUND:
+		locked = stv0900_get_bits(i_params, lock_field) &&
+				stv0900_get_bits(i_params, delin_field) &&
+				stv0900_get_bits(i_params, fifo_field);
+		break;
+	case STV0900_DVBS_FOUND:
+		locked = stv0900_get_bits(i_params, lock_field) &&
+				stv0900_get_bits(i_params, lockedvit_field) &&
+				stv0900_get_bits(i_params, fifo_field);
+		break;
+	}
+
+	return locked;
+}
+
+static enum dvbfe_search stv0900_search(struct dvb_frontend *fe,
+					struct dvb_frontend_parameters *params)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	struct stv0900_search_params p_search;
+	struct stv0900_signal_info p_result;
+
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+
+	dprintk(KERN_INFO "%s: ", __func__);
+
+	p_result.locked = FALSE;
+	p_search.path = state->demod;
+	p_search.frequency = c->frequency;
+	p_search.symbol_rate = c->symbol_rate;
+	p_search.search_range = 10000000;
+	p_search.fec = STV0900_FEC_UNKNOWN;
+	p_search.standard = STV0900_AUTO_SEARCH;
+	p_search.iq_inversion = STV0900_IQ_AUTO;
+	p_search.search_algo = STV0900_BLIND_SEARCH;
+
+	if ((INRANGE(100000, p_search.symbol_rate, 70000000)) &&
+			(INRANGE(100000, p_search.search_range, 50000000))) {
+		switch (p_search.path) {
+		case STV0900_DEMOD_1:
+		default:
+			i_params->dmd1_srch_standard = p_search.standard;
+			i_params->dmd1_symbol_rate = p_search.symbol_rate;
+			i_params->dmd1_srch_range = p_search.search_range;
+			i_params->tuner1_freq = p_search.frequency;
+			i_params->dmd1_srch_algo = p_search.search_algo;
+			i_params->dmd1_srch_iq_inv = p_search.iq_inversion;
+			i_params->dmd1_fec = p_search.fec;
+			break;
+
+		case STV0900_DEMOD_2:
+			i_params->dmd2_srch_stndrd = p_search.standard;
+			i_params->dmd2_symbol_rate = p_search.symbol_rate;
+			i_params->dmd2_srch_range = p_search.search_range;
+			i_params->tuner2_freq = p_search.frequency;
+			i_params->dmd2_srch_algo = p_search.search_algo;
+			i_params->dmd2_srch_iq_inv = p_search.iq_inversion;
+			i_params->dmd2_fec = p_search.fec;
+			break;
+		}
+
+		if ((stv0900_algo(fe) == STV0900_RANGEOK) &&
+					(i_params->errs == STV0900_NO_ERROR)) {
+			switch (p_search.path) {
+			case STV0900_DEMOD_1:
+			default:
+				p_result.locked = i_params->dmd1_rslts.locked;
+				p_result.standard = i_params->dmd1_rslts.standard;
+				p_result.frequency = i_params->dmd1_rslts.frequency;
+				p_result.symbol_rate = i_params->dmd1_rslts.symbol_rate;
+				p_result.fec = i_params->dmd1_rslts.fec;
+				p_result.modcode = i_params->dmd1_rslts.modcode;
+				p_result.pilot = i_params->dmd1_rslts.pilot;
+				p_result.frame_length = i_params->dmd1_rslts.frame_length;
+				p_result.spectrum = i_params->dmd1_rslts.spectrum;
+				p_result.rolloff = i_params->dmd1_rslts.rolloff;
+				p_result.modulation = i_params->dmd1_rslts.modulation;
+				break;
+			case STV0900_DEMOD_2:
+				p_result.locked = i_params->dmd2_rslts.locked;
+				p_result.standard = i_params->dmd2_rslts.standard;
+				p_result.frequency = i_params->dmd2_rslts.frequency;
+				p_result.symbol_rate = i_params->dmd2_rslts.symbol_rate;
+				p_result.fec = i_params->dmd2_rslts.fec;
+				p_result.modcode = i_params->dmd2_rslts.modcode;
+				p_result.pilot = i_params->dmd2_rslts.pilot;
+				p_result.frame_length = i_params->dmd2_rslts.frame_length;
+				p_result.spectrum = i_params->dmd2_rslts.spectrum;
+				p_result.rolloff = i_params->dmd2_rslts.rolloff;
+				p_result.modulation = i_params->dmd2_rslts.modulation;
+				break;
+			}
+
+		} else {
+			p_result.locked = FALSE;
+			switch (p_search.path) {
+			case STV0900_DEMOD_1:
+				switch (i_params->dmd1_err) {
+				case STV0900_I2C_ERROR:
+					error = STV0900_I2C_ERROR;
+					break;
+				case STV0900_NO_ERROR:
+				default:
+					error = STV0900_SEARCH_FAILED;
+					break;
+				}
+				break;
+			case STV0900_DEMOD_2:
+				switch (i_params->dmd2_err) {
+				case STV0900_I2C_ERROR:
+					error = STV0900_I2C_ERROR;
+					break;
+				case STV0900_NO_ERROR:
+				default:
+					error = STV0900_SEARCH_FAILED;
+					break;
+				}
+				break;
+			}
+		}
+
+	} else
+		error = STV0900_BAD_PARAMETER;
+
+	if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) {
+		dprintk(KERN_INFO "Search Success\n");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		dprintk(KERN_INFO "Search Fail\n");
+		return DVBFE_ALGO_SEARCH_FAILED;
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int stv0900_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk("%s: ", __func__);
+
+	if ((stv0900_status(state->internal, state->demod)) == TRUE) {
+		dprintk("DEMOD LOCK OK\n");
+		*status = FE_HAS_CARRIER
+			| FE_HAS_VITERBI
+			| FE_HAS_SYNC
+			| FE_HAS_LOCK;
+	} else
+		dprintk("DEMOD LOCK FAIL\n");
+
+	return 0;
+}
+
+static int stv0900_track(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p)
+{
+	return 0;
+}
+
+static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts)
+{
+
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	s32 rst_field;
+
+	dmd_reg(rst_field, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE);
+
+	if (stop_ts == TRUE)
+		stv0900_write_bits(i_params, rst_field, 1);
+	else
+		stv0900_write_bits(i_params, rst_field, 0);
+
+	return 0;
+}
+
+static int stv0900_diseqc_init(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	s32 mode_field, reset_field;
+
+	dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE);
+	dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET);
+
+	stv0900_write_bits(i_params, mode_field, state->config->diseqc_mode);
+	stv0900_write_bits(i_params, reset_field, 1);
+	stv0900_write_bits(i_params, reset_field, 0);
+
+	return 0;
+}
+
+static int stv0900_init(struct dvb_frontend *fe)
+{
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	stv0900_stop_ts(fe, 1);
+	stv0900_diseqc_init(fe);
+
+	return 0;
+}
+
+static int stv0900_diseqc_send(struct stv0900_internal *i_params , u8 *Data,
+				u32 NbData, enum fe_stv0900_demod_num demod)
+{
+	s32 i = 0;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 1);
+		while (i < NbData) {
+			while (stv0900_get_bits(i_params, F0900_P1_FIFO_FULL))
+				;/* checkpatch complains */
+			stv0900_write_reg(i_params, R0900_P1_DISTXDATA, Data[i]);
+			i++;
+		}
+
+		stv0900_write_bits(i_params, F0900_P1_DIS_PRECHARGE, 0);
+		i = 0;
+		while ((stv0900_get_bits(i_params, F0900_P1_TX_IDLE) != 1) && (i < 10)) {
+			msleep(10);
+			i++;
+		}
+
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 1);
+
+		while (i < NbData) {
+			while (stv0900_get_bits(i_params, F0900_P2_FIFO_FULL))
+				;/* checkpatch complains */
+			stv0900_write_reg(i_params, R0900_P2_DISTXDATA, Data[i]);
+			i++;
+		}
+
+		stv0900_write_bits(i_params, F0900_P2_DIS_PRECHARGE, 0);
+		i = 0;
+		while ((stv0900_get_bits(i_params, F0900_P2_TX_IDLE) != 1) && (i < 10)) {
+			msleep(10);
+			i++;
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+static int stv0900_send_master_cmd(struct dvb_frontend *fe,
+					struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	return stv0900_diseqc_send(state->internal,
+				cmd->msg,
+				cmd->msg_len,
+				state->demod);
+}
+
+static int stv0900_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	s32 mode_field;
+	u32 diseqc_fifo;
+
+	dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE);
+	dmd_reg(diseqc_fifo, R0900_P1_DISTXDATA, R0900_P2_DISTXDATA);
+
+	switch (burst) {
+	case SEC_MINI_A:
+		stv0900_write_bits(i_params, mode_field, 3);/* Unmodulated */
+		stv0900_write_reg(i_params, diseqc_fifo, 0x00);
+		break;
+	case SEC_MINI_B:
+		stv0900_write_bits(i_params, mode_field, 2);/* Modulated */
+		stv0900_write_reg(i_params, diseqc_fifo, 0xff);
+		break;
+	}
+
+	return 0;
+}
+
+static int stv0900_recv_slave_reply(struct dvb_frontend *fe,
+				struct dvb_diseqc_slave_reply *reply)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	s32 i = 0;
+
+	switch (state->demod) {
+	case STV0900_DEMOD_1:
+	default:
+		reply->msg_len = 0;
+
+		while ((stv0900_get_bits(i_params, F0900_P1_RX_END) != 1) && (i < 10)) {
+			msleep(10);
+			i++;
+		}
+
+		if (stv0900_get_bits(i_params, F0900_P1_RX_END)) {
+			reply->msg_len = stv0900_get_bits(i_params, F0900_P1_FIFO_BYTENBR);
+
+			for (i = 0; i < reply->msg_len; i++)
+				reply->msg[i] = stv0900_read_reg(i_params, R0900_P1_DISRXDATA);
+		}
+		break;
+	case STV0900_DEMOD_2:
+		reply->msg_len = 0;
+
+		while ((stv0900_get_bits(i_params, F0900_P2_RX_END) != 1) && (i < 10)) {
+			msleep(10);
+			i++;
+		}
+
+		if (stv0900_get_bits(i_params, F0900_P2_RX_END)) {
+			reply->msg_len = stv0900_get_bits(i_params, F0900_P2_FIFO_BYTENBR);
+
+			for (i = 0; i < reply->msg_len; i++)
+				reply->msg[i] = stv0900_read_reg(i_params, R0900_P2_DISRXDATA);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	s32 mode_field, reset_field;
+
+	dprintk(KERN_INFO "%s: %s\n", __func__, ((tone == 0) ? "Off" : "On"));
+
+	dmd_reg(mode_field, F0900_P1_DISTX_MODE, F0900_P2_DISTX_MODE);
+	dmd_reg(reset_field, F0900_P1_DISEQC_RESET, F0900_P2_DISEQC_RESET);
+
+	if (tone) {
+		/*Set the DiseqC mode to 22Khz continues tone*/
+		stv0900_write_bits(i_params, mode_field, 0);
+		stv0900_write_bits(i_params, reset_field, 1);
+		/*release DiseqC reset to enable the 22KHz tone*/
+		stv0900_write_bits(i_params, reset_field, 0);
+	} else {
+		stv0900_write_bits(i_params, mode_field, 0);
+		/*maintain the DiseqC reset to disable the 22KHz tone*/
+		stv0900_write_bits(i_params, reset_field, 1);
+	}
+
+	return 0;
+}
+
+static void stv0900_release(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if ((--(state->internal->dmds_used)) <= 0) {
+
+		dprintk(KERN_INFO "%s: Actually removing\n", __func__);
+
+		remove_inode(state->internal);
+		kfree(state->internal);
+	}
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0900_ops = {
+
+	.info = {
+		.name			= "STV0900 frontend",
+		.type			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 125,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,
+		.caps			= FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+					  FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
+					  FE_CAN_FEC_7_8 | FE_CAN_QPSK    |
+					  FE_CAN_2G_MODULATION |
+					  FE_CAN_FEC_AUTO
+	},
+	.release			= stv0900_release,
+	.init				= stv0900_init,
+	.get_frontend_algo		= stv0900_frontend_algo,
+	.i2c_gate_ctrl			= stv0900_i2c_gate_ctrl,
+	.diseqc_send_master_cmd		= stv0900_send_master_cmd,
+	.diseqc_send_burst		= stv0900_send_burst,
+	.diseqc_recv_slave_reply	= stv0900_recv_slave_reply,
+	.set_tone			= stv0900_set_tone,
+	.set_property			= stb0900_set_property,
+	.get_property			= stb0900_get_property,
+	.search				= stv0900_search,
+	.track				= stv0900_track,
+	.read_status			= stv0900_read_status,
+	.read_ber			= stv0900_read_ber,
+	.read_signal_strength		= stv0900_read_signal_strength,
+	.read_snr			= stv0900_read_snr,
+};
+
+struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
+					struct i2c_adapter *i2c,
+					int demod)
+{
+	struct stv0900_state *state = NULL;
+	struct stv0900_init_params init_params;
+	enum fe_stv0900_error err_stv0900;
+
+	state = kzalloc(sizeof(struct stv0900_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->demod		= demod;
+	state->config		= config;
+	state->i2c_adap		= i2c;
+
+	memcpy(&state->frontend.ops, &stv0900_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	switch (demod) {
+	case 0:
+	case 1:
+		init_params.dmd_ref_clk  	= config->xtal;
+		init_params.demod_mode		= STV0900_DUAL;
+		init_params.rolloff		= STV0900_35;
+		init_params.path1_ts_clock	= config->path1_mode;
+		init_params.tun1_maddress	= config->tun1_maddress;
+		init_params.tun1_iq_inversion	= STV0900_IQ_NORMAL;
+		init_params.tuner1_adc		= config->tun1_adc;
+		init_params.path2_ts_clock	= config->path2_mode;
+		init_params.tun2_maddress	= config->tun2_maddress;
+		init_params.tuner2_adc		= config->tun2_adc;
+		init_params.tun2_iq_inversion	= STV0900_IQ_SWAPPED;
+
+		err_stv0900 = stv0900_init_internal(&state->frontend,
+							&init_params);
+
+		if (err_stv0900)
+			goto error;
+
+		break;
+	default:
+		goto error;
+		break;
+	}
+
+	dprintk("%s: Attaching STV0900 demodulator(%d) \n", __func__, demod);
+	return &state->frontend;
+
+error:
+	dprintk("%s: Failed to attach STV0900 demodulator(%d) \n",
+		__func__, demod);
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv0900_attach);
+
+MODULE_PARM_DESC(debug, "Set debug");
+
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_DESCRIPTION("ST STV0900 frontend");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv0900_init.h b/drivers/media/dvb/frontends/stv0900_init.h
new file mode 100644
index 0000000..ff388b4
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900_init.h
@@ -0,0 +1,441 @@
+/*
+ * stv0900_init.h
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 STV0900_INIT_H
+#define STV0900_INIT_H
+
+#include "stv0900_priv.h"
+
+/* DVBS2 C/N Look-Up table */
+static const struct stv0900_table stv0900_s2_cn = {
+	55,
+	{
+		{ -30,	13348 }, /*C/N=-3dB*/
+		{ -20,	12640 }, /*C/N=-2dB*/
+		{ -10,	11883 }, /*C/N=-1dB*/
+		{ 0,	11101 }, /*C/N=-0dB*/
+		{ 5,	10718 }, /*C/N=0.5dB*/
+		{ 10,	10339 }, /*C/N=1.0dB*/
+		{ 15,	9947 }, /*C/N=1.5dB*/
+		{ 20,	9552 }, /*C/N=2.0dB*/
+		{ 25,	9183 }, /*C/N=2.5dB*/
+		{ 30,	8799 }, /*C/N=3.0dB*/
+		{ 35,	8422 }, /*C/N=3.5dB*/
+		{ 40,	8062 }, /*C/N=4.0dB*/
+		{ 45,	7707 }, /*C/N=4.5dB*/
+		{ 50,	7353 }, /*C/N=5.0dB*/
+		{ 55,	7025 }, /*C/N=5.5dB*/
+		{ 60,	6684 }, /*C/N=6.0dB*/
+		{ 65,	6331 }, /*C/N=6.5dB*/
+		{ 70,	6036 }, /*C/N=7.0dB*/
+		{ 75,	5727 }, /*C/N=7.5dB*/
+		{ 80,	5437 }, /*C/N=8.0dB*/
+		{ 85,	5164 }, /*C/N=8.5dB*/
+		{ 90,	4902 }, /*C/N=9.0dB*/
+		{ 95,	4653 }, /*C/N=9.5dB*/
+		{ 100,	4408 }, /*C/N=10.0dB*/
+		{ 105,	4187 }, /*C/N=10.5dB*/
+		{ 110,	3961 }, /*C/N=11.0dB*/
+		{ 115,	3751 }, /*C/N=11.5dB*/
+		{ 120,	3558 }, /*C/N=12.0dB*/
+		{ 125,	3368 }, /*C/N=12.5dB*/
+		{ 130,	3191 }, /*C/N=13.0dB*/
+		{ 135,	3017 }, /*C/N=13.5dB*/
+		{ 140,	2862 }, /*C/N=14.0dB*/
+		{ 145,	2710 }, /*C/N=14.5dB*/
+		{ 150,	2565 }, /*C/N=15.0dB*/
+		{ 160,	2300 }, /*C/N=16.0dB*/
+		{ 170,	2058 }, /*C/N=17.0dB*/
+		{ 180,	1849 }, /*C/N=18.0dB*/
+		{ 190,	1663 }, /*C/N=19.0dB*/
+		{ 200,	1495 }, /*C/N=20.0dB*/
+		{ 210,	1349 }, /*C/N=21.0dB*/
+		{ 220,	1222 }, /*C/N=22.0dB*/
+		{ 230,	1110 }, /*C/N=23.0dB*/
+		{ 240,	1011 }, /*C/N=24.0dB*/
+		{ 250,	925 }, /*C/N=25.0dB*/
+		{ 260,	853 }, /*C/N=26.0dB*/
+		{ 270,	789 }, /*C/N=27.0dB*/
+		{ 280,	734 }, /*C/N=28.0dB*/
+		{ 290,	690 }, /*C/N=29.0dB*/
+		{ 300,	650 }, /*C/N=30.0dB*/
+		{ 310,	619 }, /*C/N=31.0dB*/
+		{ 320,	593 }, /*C/N=32.0dB*/
+		{ 330,	571 }, /*C/N=33.0dB*/
+		{ 400,	498 }, /*C/N=40.0dB*/
+		{ 450,	484 }, /*C/N=45.0dB*/
+		{ 500,	481 }  /*C/N=50.0dB*/
+	}
+};
+
+/* RF level C/N Look-Up table */
+static const struct stv0900_table stv0900_rf = {
+	14,
+	{
+		{ -5, 0xCAA1 }, /*-5dBm*/
+		{ -10, 0xC229 }, /*-10dBm*/
+		{ -15, 0xBB08 }, /*-15dBm*/
+		{ -20, 0xB4BC }, /*-20dBm*/
+		{ -25, 0xAD5A }, /*-25dBm*/
+		{ -30, 0xA298 }, /*-30dBm*/
+		{ -35, 0x98A8 }, /*-35dBm*/
+		{ -40, 0x8389 }, /*-40dBm*/
+		{ -45, 0x59BE }, /*-45dBm*/
+		{ -50, 0x3A14 }, /*-50dBm*/
+		{ -55, 0x2D11 }, /*-55dBm*/
+		{ -60, 0x210D }, /*-60dBm*/
+		{ -65, 0xA14F }, /*-65dBm*/
+		{ -70, 0x7AA }	/*-70dBm*/
+	}
+};
+
+struct stv0900_car_loop_optim {
+	enum fe_stv0900_modcode modcode;
+	u8 car_loop_pilots_on_2;
+	u8 car_loop_pilots_off_2;
+	u8 car_loop_pilots_on_5;
+	u8 car_loop_pilots_off_5;
+	u8 car_loop_pilots_on_10;
+	u8 car_loop_pilots_off_10;
+	u8 car_loop_pilots_on_20;
+	u8 car_loop_pilots_off_20;
+	u8 car_loop_pilots_on_30;
+	u8 car_loop_pilots_off_30;
+
+};
+
+struct stv0900_short_frames_car_loop_optim {
+	enum fe_stv0900_modulation modulation;
+	u8 car_loop_cut12_2;    /* Cut 1.2,   SR<=3msps     */
+	u8 car_loop_cut20_2;    /* Cut 2.0,   SR<3msps      */
+	u8 car_loop_cut12_5;    /* Cut 1.2,   3<SR<=7msps   */
+	u8 car_loop_cut20_5;    /* Cut 2.0,   3<SR<=7msps   */
+	u8 car_loop_cut12_10;   /* Cut 1.2,   7<SR<=15msps  */
+	u8 car_loop_cut20_10;   /* Cut 2.0,   7<SR<=15msps  */
+	u8 car_loop_cut12_20;   /* Cut 1.2,   10<SR<=25msps */
+	u8 car_loop_cut20_20;   /* Cut 2.0,   10<SR<=25msps */
+	u8 car_loop_cut12_30;   /* Cut 1.2,   25<SR<=45msps */
+	u8 car_loop_cut20_30;   /* Cut 2.0,   10<SR<=45msps */
+
+};
+
+/* Cut 1.x Tracking carrier loop carrier QPSK 1/2 to 8PSK 9/10 long Frame */
+static const struct stv0900_car_loop_optim	FE_STV0900_S2CarLoop[14] = {
+	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon 	10MPoff	20MPon 	20MPoff	30MPon 	30MPoff */
+	{ STV0900_QPSK_12,	0x1C,	0x0D,	0x1B,	0x2C,	0x3A,	0x1C,	0x2A,	0x3B,	0x2A,	0x1B },
+	{ STV0900_QPSK_35,	0x2C,	0x0D,	0x2B,	0x2C,	0x3A,	0x0C,	0x3A,	0x2B,	0x2A,	0x0B },
+	{ STV0900_QPSK_23,	0x2C,	0x0D,	0x2B,	0x2C,	0x0B,	0x0C,	0x3A,	0x1B,	0x2A,	0x3A },
+	{ STV0900_QPSK_34,	0x3C,	0x0D,	0x3B,	0x1C,	0x0B,	0x3B,	0x3A,	0x0B,	0x2A,	0x3A },
+	{ STV0900_QPSK_45,	0x3C,	0x0D,	0x3B,	0x1C,	0x0B,	0x3B,	0x3A,	0x0B,	0x2A,	0x3A },
+	{ STV0900_QPSK_56,	0x0D,	0x0D,	0x3B,	0x1C,	0x0B,	0x3B,	0x3A,	0x0B,	0x2A,	0x3A },
+	{ STV0900_QPSK_89,	0x0D,	0x0D,	0x3B,	0x1C,	0x1B,	0x3B,	0x3A,	0x0B,	0x2A,	0x3A },
+	{ STV0900_QPSK_910,	0x1D,	0x0D,	0x3B,	0x1C,	0x1B,	0x3B,	0x3A,	0x0B,	0x2A,	0x3A },
+	{ STV0900_8PSK_35,	0x29,	0x3B,	0x09,	0x2B,	0x38,	0x0B,	0x18,	0x1A,	0x08,	0x0A },
+	{ STV0900_8PSK_23,	0x0A,	0x3B,	0x29,	0x2B,	0x19,	0x0B,	0x38,	0x1A,	0x18,	0x0A },
+	{ STV0900_8PSK_34,	0x3A,	0x3B,	0x2A,	0x2B,	0x39,	0x0B,	0x19,	0x1A,	0x38,	0x0A },
+	{ STV0900_8PSK_56,	0x1B,	0x3B,	0x0B,	0x2B,	0x1A,	0x0B,	0x39,	0x1A,	0x19,	0x0A },
+	{ STV0900_8PSK_89,	0x3B,	0x3B,	0x0B,	0x2B,	0x2A,	0x0B,	0x39,	0x1A,	0x29,	0x39 },
+	{ STV0900_8PSK_910,	0x3B,	0x3B, 	0x0B,	0x2B, 	0x2A,	0x0B,	0x39,	0x1A,	0x29,	0x39 }
+};
+
+
+/* Cut 2.0 Tracking carrier loop carrier QPSK 1/2 to 8PSK 9/10 long Frame */
+static const struct stv0900_car_loop_optim	FE_STV0900_S2CarLoopCut20[14]	= {
+	/* Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon 	10MPoff	20MPon 	20MPoff	30MPon 	30MPoff */
+	{ STV0900_QPSK_12,	0x1F,	0x3F,	0x1E,	0x3F,	0x3D,	0x1F,	0x3D,	0x3E,	0x3D,	0x1E },
+	{ STV0900_QPSK_35,	0x2F,	0x3F,	0x2E,	0x2F,	0x3D,	0x0F,	0x0E,	0x2E,	0x3D,	0x0E },
+	{ STV0900_QPSK_23,	0x2F,	0x3F,	0x2E,	0x2F,	0x0E,	0x0F,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_QPSK_34,	0x3F,	0x3F,	0x3E,	0x1F,	0x0E,	0x3E,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_QPSK_45,	0x3F,	0x3F,	0x3E,	0x1F,	0x0E,	0x3E,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_QPSK_56,	0x3F,	0x3F,	0x3E,	0x1F,	0x0E,	0x3E,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_QPSK_89,	0x3F,	0x3F,	0x3E,	0x1F,	0x1E,	0x3E,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_QPSK_910,	0x3F,	0x3F,	0x3E,	0x1F,	0x1E,	0x3E,	0x0E,	0x1E,	0x3D,	0x3D },
+	{ STV0900_8PSK_35,	0x3c,	0x0c,	0x1c,	0x3b,	0x0c,	0x3b,	0x2b,	0x2b,	0x1b,	0x2b },
+	{ STV0900_8PSK_23,	0x1d,	0x0c,	0x3c,	0x0c,	0x2c,	0x3b,	0x0c,	0x2b,	0x2b,	0x2b },
+	{ STV0900_8PSK_34,	0x0e,	0x1c,	0x3d,	0x0c,	0x0d,	0x3b,	0x2c,	0x3b,	0x0c,	0x2b },
+	{ STV0900_8PSK_56,	0x2e,	0x3e,	0x1e,	0x2e,	0x2d,	0x1e,	0x3c,	0x2d,	0x2c,	0x1d },
+	{ STV0900_8PSK_89,	0x3e,	0x3e,	0x1e,	0x2e,	0x3d,	0x1e,	0x0d,	0x2d,	0x3c,	0x1d },
+	{ STV0900_8PSK_910,	0x3e,	0x3e, 	0x1e,	0x2e, 	0x3d,	0x1e,	0x1d,	0x2d,	0x0d,	0x1d }
+};
+
+
+
+/* Cut 2.0 Tracking carrier loop carrier 16APSK 2/3 to 32APSK 9/10 long Frame */
+static const struct stv0900_car_loop_optim FE_STV0900_S2APSKCarLoopCut20[11] = {
+	/* Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon 	10MPoff	20MPon 	20MPoff	30MPon 	30MPoff */
+	{ STV0900_16APSK_23,	0x0C,	0x0C,	0x0C,	0x0C,	0x1D,	0x0C,	0x3C,	0x0C,	0x2C,	0x0C },
+	{ STV0900_16APSK_34,	0x0C,	0x0C,	0x0C,	0x0C,	0x0E,	0x0C,	0x2D,	0x0C,	0x1D,	0x0C },
+	{ STV0900_16APSK_45,	0x0C,	0x0C,	0x0C,	0x0C,	0x1E,	0x0C,	0x3D,	0x0C,	0x2D,	0x0C },
+	{ STV0900_16APSK_56,	0x0C,	0x0C,	0x0C,	0x0C,	0x1E,	0x0C,	0x3D,	0x0C,	0x2D,	0x0C },
+	{ STV0900_16APSK_89,	0x0C,	0x0C,	0x0C,	0x0C,	0x2E,	0x0C,	0x0E,	0x0C,	0x3D,	0x0C },
+	{ STV0900_16APSK_910,	0x0C,	0x0C,	0x0C,	0x0C,	0x2E,	0x0C,	0x0E,	0x0C,	0x3D,	0x0C },
+	{ STV0900_32APSK_34,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C },
+	{ STV0900_32APSK_45,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C },
+	{ STV0900_32APSK_56,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C },
+	{ STV0900_32APSK_89,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C },
+	{ STV0900_32APSK_910,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C,	0x0C }
+};
+
+
+/* Cut 2.0 Tracking carrier loop carrier QPSK 1/4 to QPSK 2/5 long Frame */
+static const struct stv0900_car_loop_optim FE_STV0900_S2LowQPCarLoopCut20[3] = {
+	/* Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon 	10MPoff	20MPon 	20MPoff	30MPon 	30MPoff */
+	{ STV0900_QPSK_14,	0x0F,	0x3F,	0x0E,	0x3F,	0x2D,	0x2F,	0x2D,	0x1F,	0x3D,	0x3E },
+	{ STV0900_QPSK_13,	0x0F,	0x3F,	0x0E,	0x3F,	0x2D,	0x2F,	0x3D,	0x0F,	0x3D,	0x2E },
+	{ STV0900_QPSK_25,	0x1F,	0x3F,	0x1E,	0x3F,	0x3D,	0x1F,	0x3D,	0x3E,	0x3D,	0x2E }
+};
+
+
+/* Cut 2.0 Tracking carrier loop carrier  short Frame, cut 1.2 and 2.0 */
+static const struct stv0900_short_frames_car_loop_optim FE_STV0900_S2ShortCarLoop[4]	= {
+	/*Mod	2M_cut1.2 2M_cut2.0 5M_cut1.2 5M_cut2.0 10M_cut1.2 10M_cut2.0 20M_cut1.2 20M_cut2.0 30M_cut1.2 30M_cut2.0 */
+	{ STV0900_QPSK,		0x3C,	0x2F,	0x2B,	0x2E,	0x0B,	0x0E,	0x3A,	0x0E,	0x2A,	0x3D },
+	{ STV0900_8PSK,		0x0B,	0x3E,	0x2A,	0x0E,	0x0A,	0x2D,	0x19,	0x0D,	0x09,	0x3C },
+	{ STV0900_16APSK,	0x1B,	0x1E,	0x1B,	0x1E,	0x1B,	0x1E,	0x3A,	0x3D,	0x2A,	0x2D },
+	{ STV0900_32APSK,	0x1B,	0x1E,	0x1B,	0x1E,	0x1B,	0x1E,	0x3A,	0x3D,	0x2A,	0x2D }
+};
+
+static const u16 STV0900_InitVal[182][2] = {
+	{ R0900_OUTCFG		, 0x00	},
+	{ R0900_MODECFG		, 0xff	},
+	{ R0900_AGCRF1CFG	, 0x11	},
+	{ R0900_AGCRF2CFG	, 0x13	},
+	{ R0900_TSGENERAL1X	, 0x14	},
+	{ R0900_TSTTNR2		, 0x21	},
+	{ R0900_TSTTNR4		, 0x21	},
+	{ R0900_P2_DISTXCTL	, 0x22	},
+	{ R0900_P2_F22TX	, 0xc0	},
+	{ R0900_P2_F22RX	, 0xc0	},
+	{ R0900_P2_DISRXCTL	, 0x00	},
+	{ R0900_P2_TNRSTEPS	, 0x87	},
+	{ R0900_P2_TNRGAIN	, 0x09	},
+	{ R0900_P2_DMDCFGMD	, 0xF9	},
+	{ R0900_P2_DEMOD	, 0x08	},
+	{ R0900_P2_DMDCFG3	, 0xc4	},
+	{ R0900_P2_CARFREQ	, 0xed	},
+	{ R0900_P2_TNRCFG2	, 0x02	},
+	{ R0900_P2_TNRCFG3	, 0x02	},
+	{ R0900_P2_LDT		, 0xd0	},
+	{ R0900_P2_LDT2		, 0xb8	},
+	{ R0900_P2_TMGCFG	, 0xd2	},
+	{ R0900_P2_TMGTHRISE	, 0x20	},
+	{ R0900_P2_TMGTHFALL	, 0x00	},
+	{ R0900_P2_FECSPY	, 0x88	},
+	{ R0900_P2_FSPYDATA	, 0x3a	},
+	{ R0900_P2_FBERCPT4	, 0x00	},
+	{ R0900_P2_FSPYBER	, 0x10	},
+	{ R0900_P2_ERRCTRL1	, 0x35	},
+	{ R0900_P2_ERRCTRL2	, 0xc1	},
+	{ R0900_P2_CFRICFG	, 0xf8	},
+	{ R0900_P2_NOSCFG	, 0x1c	},
+	{ R0900_P2_DMDT0M	, 0x20	},
+	{ R0900_P2_CORRELMANT	, 0x70	},
+	{ R0900_P2_CORRELABS	, 0x88	},
+	{ R0900_P2_AGC2O	, 0x5b	},
+	{ R0900_P2_AGC2REF	, 0x38	},
+	{ R0900_P2_CARCFG	, 0xe4	},
+	{ R0900_P2_ACLC		, 0x1A	},
+	{ R0900_P2_BCLC		, 0x09	},
+	{ R0900_P2_CARHDR	, 0x08	},
+	{ R0900_P2_KREFTMG	, 0xc1	},
+	{ R0900_P2_SFRUPRATIO	, 0xf0	},
+	{ R0900_P2_SFRLOWRATIO	, 0x70	},
+	{ R0900_P2_SFRSTEP	, 0x58	},
+	{ R0900_P2_TMGCFG2	, 0x01	},
+	{ R0900_P2_CAR2CFG	, 0x26	},
+	{ R0900_P2_BCLC2S2Q	, 0x86	},
+	{ R0900_P2_BCLC2S28	, 0x86	},
+	{ R0900_P2_SMAPCOEF7	, 0x77	},
+	{ R0900_P2_SMAPCOEF6	, 0x85	},
+	{ R0900_P2_SMAPCOEF5	, 0x77	},
+	{ R0900_P2_TSCFGL	, 0x20	},
+	{ R0900_P2_DMDCFG2	, 0x3b	},
+	{ R0900_P2_MODCODLST0	, 0xff	},
+	{ R0900_P2_MODCODLST1	, 0xff	},
+	{ R0900_P2_MODCODLST2	, 0xff	},
+	{ R0900_P2_MODCODLST3	, 0xff	},
+	{ R0900_P2_MODCODLST4	, 0xff	},
+	{ R0900_P2_MODCODLST5	, 0xff	},
+	{ R0900_P2_MODCODLST6	, 0xff	},
+	{ R0900_P2_MODCODLST7	, 0xcc	},
+	{ R0900_P2_MODCODLST8	, 0xcc	},
+	{ R0900_P2_MODCODLST9	, 0xcc	},
+	{ R0900_P2_MODCODLSTA	, 0xcc	},
+	{ R0900_P2_MODCODLSTB	, 0xcc	},
+	{ R0900_P2_MODCODLSTC	, 0xcc	},
+	{ R0900_P2_MODCODLSTD	, 0xcc	},
+	{ R0900_P2_MODCODLSTE	, 0xcc	},
+	{ R0900_P2_MODCODLSTF	, 0xcf	},
+	{ R0900_P1_DISTXCTL	, 0x22	},
+	{ R0900_P1_F22TX	, 0xc0	},
+	{ R0900_P1_F22RX	, 0xc0	},
+	{ R0900_P1_DISRXCTL	, 0x00	},
+	{ R0900_P1_TNRSTEPS	, 0x87	},
+	{ R0900_P1_TNRGAIN	, 0x09	},
+	{ R0900_P1_DMDCFGMD	, 0xf9	},
+	{ R0900_P1_DEMOD	, 0x08	},
+	{ R0900_P1_DMDCFG3	, 0xc4	},
+	{ R0900_P1_DMDT0M	, 0x20	},
+	{ R0900_P1_CARFREQ	, 0xed	},
+	{ R0900_P1_TNRCFG2	, 0x82	},
+	{ R0900_P1_TNRCFG3	, 0x02	},
+	{ R0900_P1_LDT		, 0xd0	},
+	{ R0900_P1_LDT2		, 0xb8	},
+	{ R0900_P1_TMGCFG	, 0xd2	},
+	{ R0900_P1_TMGTHRISE	, 0x20	},
+	{ R0900_P1_TMGTHFALL	, 0x00	},
+	{ R0900_P1_SFRUPRATIO	, 0xf0	},
+	{ R0900_P1_SFRLOWRATIO	, 0x70	},
+	{ R0900_P1_TSCFGL	, 0x20	},
+	{ R0900_P1_FECSPY	, 0x88	},
+	{ R0900_P1_FSPYDATA	, 0x3a	},
+	{ R0900_P1_FBERCPT4	, 0x00	},
+	{ R0900_P1_FSPYBER	, 0x10	},
+	{ R0900_P1_ERRCTRL1	, 0x35	},
+	{ R0900_P1_ERRCTRL2	, 0xc1	},
+	{ R0900_P1_CFRICFG	, 0xf8	},
+	{ R0900_P1_NOSCFG	, 0x1c	},
+	{ R0900_P1_CORRELMANT	, 0x70	},
+	{ R0900_P1_CORRELABS	, 0x88	},
+	{ R0900_P1_AGC2O	, 0x5b	},
+	{ R0900_P1_AGC2REF	, 0x38	},
+	{ R0900_P1_CARCFG	, 0xe4	},
+	{ R0900_P1_ACLC		, 0x1A	},
+	{ R0900_P1_BCLC		, 0x09	},
+	{ R0900_P1_CARHDR	, 0x08	},
+	{ R0900_P1_KREFTMG	, 0xc1	},
+	{ R0900_P1_SFRSTEP	, 0x58	},
+	{ R0900_P1_TMGCFG2	, 0x01	},
+	{ R0900_P1_CAR2CFG	, 0x26	},
+	{ R0900_P1_BCLC2S2Q	, 0x86	},
+	{ R0900_P1_BCLC2S28	, 0x86	},
+	{ R0900_P1_SMAPCOEF7	, 0x77	},
+	{ R0900_P1_SMAPCOEF6	, 0x85	},
+	{ R0900_P1_SMAPCOEF5	, 0x77	},
+	{ R0900_P1_DMDCFG2	, 0x3b	},
+	{ R0900_P1_MODCODLST0	, 0xff	},
+	{ R0900_P1_MODCODLST1	, 0xff	},
+	{ R0900_P1_MODCODLST2	, 0xff	},
+	{ R0900_P1_MODCODLST3	, 0xff	},
+	{ R0900_P1_MODCODLST4	, 0xff	},
+	{ R0900_P1_MODCODLST5	, 0xff	},
+	{ R0900_P1_MODCODLST6	, 0xff	},
+	{ R0900_P1_MODCODLST7	, 0xcc	},
+	{ R0900_P1_MODCODLST8	, 0xcc	},
+	{ R0900_P1_MODCODLST9	, 0xcc	},
+	{ R0900_P1_MODCODLSTA	, 0xcc	},
+	{ R0900_P1_MODCODLSTB	, 0xcc	},
+	{ R0900_P1_MODCODLSTC	, 0xcc	},
+	{ R0900_P1_MODCODLSTD	, 0xcc	},
+	{ R0900_P1_MODCODLSTE	, 0xcc	},
+	{ R0900_P1_MODCODLSTF	, 0xcf	},
+	{ R0900_GENCFG		, 0x1d	},
+	{ R0900_NBITER_NF4	, 0x37	},
+	{ R0900_NBITER_NF5	, 0x29	},
+	{ R0900_NBITER_NF6	, 0x37	},
+	{ R0900_NBITER_NF7	, 0x33	},
+	{ R0900_NBITER_NF8	, 0x31	},
+	{ R0900_NBITER_NF9	, 0x2f	},
+	{ R0900_NBITER_NF10	, 0x39	},
+	{ R0900_NBITER_NF11	, 0x3a	},
+	{ R0900_NBITER_NF12	, 0x29	},
+	{ R0900_NBITER_NF13	, 0x37	},
+	{ R0900_NBITER_NF14	, 0x33	},
+	{ R0900_NBITER_NF15	, 0x2f	},
+	{ R0900_NBITER_NF16	, 0x39	},
+	{ R0900_NBITER_NF17	, 0x3a	},
+	{ R0900_NBITERNOERR	, 0x04	},
+	{ R0900_GAINLLR_NF4	, 0x0C	},
+	{ R0900_GAINLLR_NF5	, 0x0F	},
+	{ R0900_GAINLLR_NF6	, 0x11	},
+	{ R0900_GAINLLR_NF7	, 0x14	},
+	{ R0900_GAINLLR_NF8	, 0x17	},
+	{ R0900_GAINLLR_NF9	, 0x19	},
+	{ R0900_GAINLLR_NF10	, 0x20	},
+	{ R0900_GAINLLR_NF11	, 0x21	},
+	{ R0900_GAINLLR_NF12	, 0x0D	},
+	{ R0900_GAINLLR_NF13	, 0x0F	},
+	{ R0900_GAINLLR_NF14	, 0x13	},
+	{ R0900_GAINLLR_NF15	, 0x1A	},
+	{ R0900_GAINLLR_NF16	, 0x1F	},
+	{ R0900_GAINLLR_NF17	, 0x21	},
+	{ R0900_RCCFGH		, 0x20	},
+	{ R0900_P1_FECM		, 0x01	}, /*disable DSS modes*/
+	{ R0900_P2_FECM		, 0x01	}, /*disable DSS modes*/
+	{ R0900_P1_PRVIT	, 0x2F	}, /*disable puncture rate 6/7*/
+	{ R0900_P2_PRVIT	, 0x2F	}, /*disable puncture rate 6/7*/
+	{ R0900_STROUT1CFG	, 0x4c	},
+	{ R0900_STROUT2CFG	, 0x4c	},
+	{ R0900_CLKOUT1CFG	, 0x50	},
+	{ R0900_CLKOUT2CFG	, 0x50	},
+	{ R0900_DPN1CFG		, 0x4a	},
+	{ R0900_DPN2CFG		, 0x4a	},
+	{ R0900_DATA71CFG	, 0x52	},
+	{ R0900_DATA72CFG	, 0x52	},
+	{ R0900_P1_TSCFGM	, 0xc0	},
+	{ R0900_P2_TSCFGM	, 0xc0	},
+	{ R0900_P1_TSCFGH	, 0xe0	}, /* DVB-CI timings */
+	{ R0900_P2_TSCFGH	, 0xe0	}, /* DVB-CI timings */
+	{ R0900_P1_TSSPEED	, 0x40	},
+	{ R0900_P2_TSSPEED	, 0x40	},
+};
+
+static const u16 STV0900_Cut20_AddOnVal[32][2] = {
+	{ R0900_P2_DMDCFG3	, 0xe8	},
+	{ R0900_P2_DMDCFG4	, 0x10	},
+	{ R0900_P2_CARFREQ	, 0x38	},
+	{ R0900_P2_CARHDR	, 0x20	},
+	{ R0900_P2_KREFTMG	, 0x5a	},
+	{ R0900_P2_SMAPCOEF7	, 0x06	},
+	{ R0900_P2_SMAPCOEF6	, 0x00	},
+	{ R0900_P2_SMAPCOEF5	, 0x04	},
+	{ R0900_P2_NOSCFG	, 0x0c	},
+	{ R0900_P1_DMDCFG3	, 0xe8	},
+	{ R0900_P1_DMDCFG4	, 0x10	},
+	{ R0900_P1_CARFREQ	, 0x38	},
+	{ R0900_P1_CARHDR	, 0x20	},
+	{ R0900_P1_KREFTMG	, 0x5a	},
+	{ R0900_P1_SMAPCOEF7	, 0x06	},
+	{ R0900_P1_SMAPCOEF6	, 0x00	},
+	{ R0900_P1_SMAPCOEF5	, 0x04	},
+	{ R0900_P1_NOSCFG	, 0x0c	},
+	{ R0900_GAINLLR_NF4	, 0x21	},
+	{ R0900_GAINLLR_NF5	, 0x21	},
+	{ R0900_GAINLLR_NF6	, 0x20	},
+	{ R0900_GAINLLR_NF7	, 0x1F	},
+	{ R0900_GAINLLR_NF8	, 0x1E	},
+	{ R0900_GAINLLR_NF9	, 0x1E	},
+	{ R0900_GAINLLR_NF10	, 0x1D	},
+	{ R0900_GAINLLR_NF11	, 0x1B	},
+	{ R0900_GAINLLR_NF12	, 0x20	},
+	{ R0900_GAINLLR_NF13	, 0x20	},
+	{ R0900_GAINLLR_NF14	, 0x20	},
+	{ R0900_GAINLLR_NF15	, 0x20	},
+	{ R0900_GAINLLR_NF16	, 0x20	},
+	{ R0900_GAINLLR_NF17	, 0x21	}
+
+};
+
+#endif
diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h
new file mode 100644
index 0000000..762d5af
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900_priv.h
@@ -0,0 +1,430 @@
+/*
+ * stv0900_priv.h
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 STV0900_PRIV_H
+#define STV0900_PRIV_H
+
+#include <linux/i2c.h>
+
+#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
+#define INRANGE(X, Y, Z) ((((X) <= (Y)) && ((Y) <= (Z))) \
+		|| (((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0)
+
+#ifndef MAKEWORD
+#define MAKEWORD(X, Y) (((X) << 8) + (Y))
+#endif
+
+#define LSB(X) (((X) & 0xFF))
+#define MSB(Y) (((Y) >> 8) & 0xFF)
+
+#ifndef TRUE
+#define TRUE (1 == 1)
+#endif
+#ifndef FALSE
+#define FALSE (!TRUE)
+#endif
+
+#define	dmd_reg(a, b, c) \
+	do { \
+		a = 0; \
+		switch (demod) { \
+		case STV0900_DEMOD_1: \
+		default: \
+			a = b; \
+			break; \
+		case STV0900_DEMOD_2: \
+			a = c; \
+			break; \
+		} \
+	} while (0)
+
+#define dmd_choose(a, b)	(demod = STV0900_DEMOD_2 ? b : a))
+
+static int stvdebug;
+
+#define dprintk(args...) \
+	do { \
+		if (stvdebug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+#define STV0900_MAXLOOKUPSIZE 500
+#define STV0900_BLIND_SEARCH_AGC2_TH 700
+
+/* One point of the lookup table */
+struct stv000_lookpoint {
+	s32 realval;/* real value */
+	s32 regval;/* binary value */
+};
+
+/* Lookup table definition */
+struct stv0900_table{
+	s32 size;/* Size of the lookup table */
+	struct stv000_lookpoint table[STV0900_MAXLOOKUPSIZE];/* Lookup table */
+};
+
+enum fe_stv0900_error {
+	STV0900_NO_ERROR = 0,
+	STV0900_INVALID_HANDLE,
+	STV0900_BAD_PARAMETER,
+	STV0900_I2C_ERROR,
+	STV0900_SEARCH_FAILED,
+};
+
+enum fe_stv0900_clock_type {
+	STV0900_USE_REGISTERS_DEFAULT,
+	STV0900_SERIAL_PUNCT_CLOCK,/*Serial punctured clock */
+	STV0900_SERIAL_CONT_CLOCK,/*Serial continues clock */
+	STV0900_PARALLEL_PUNCT_CLOCK,/*Parallel punctured clock */
+	STV0900_DVBCI_CLOCK/*Parallel continues clock : DVBCI */
+};
+
+enum fe_stv0900_search_state {
+	STV0900_SEARCH = 0,
+	STV0900_PLH_DETECTED,
+	STV0900_DVBS2_FOUND,
+	STV0900_DVBS_FOUND
+
+};
+
+enum fe_stv0900_ldpc_state {
+	STV0900_PATH1_OFF_PATH2_OFF = 0,
+	STV0900_PATH1_ON_PATH2_OFF = 1,
+	STV0900_PATH1_OFF_PATH2_ON = 2,
+	STV0900_PATH1_ON_PATH2_ON = 3
+};
+
+enum fe_stv0900_signal_type {
+	STV0900_NOAGC1 = 0,
+	STV0900_AGC1OK,
+	STV0900_NOTIMING,
+	STV0900_ANALOGCARRIER,
+	STV0900_TIMINGOK,
+	STV0900_NOAGC2,
+	STV0900_AGC2OK,
+	STV0900_NOCARRIER,
+	STV0900_CARRIEROK,
+	STV0900_NODATA,
+	STV0900_DATAOK,
+	STV0900_OUTOFRANGE,
+	STV0900_RANGEOK
+};
+
+enum fe_stv0900_demod_num {
+	STV0900_DEMOD_1,
+	STV0900_DEMOD_2
+};
+
+enum fe_stv0900_tracking_standard {
+	STV0900_DVBS1_STANDARD,/* Found Standard*/
+	STV0900_DVBS2_STANDARD,
+	STV0900_DSS_STANDARD,
+	STV0900_TURBOCODE_STANDARD,
+	STV0900_UNKNOWN_STANDARD
+};
+
+enum fe_stv0900_search_standard {
+	STV0900_AUTO_SEARCH,
+	STV0900_SEARCH_DVBS1,/* Search Standard*/
+	STV0900_SEARCH_DVBS2,
+	STV0900_SEARCH_DSS,
+	STV0900_SEARCH_TURBOCODE
+};
+
+enum fe_stv0900_search_algo {
+	STV0900_BLIND_SEARCH,/* offset freq and SR are Unknown */
+	STV0900_COLD_START,/* only the SR is known */
+	STV0900_WARM_START/* offset freq and SR are known */
+};
+
+enum fe_stv0900_modulation {
+	STV0900_QPSK,
+	STV0900_8PSK,
+	STV0900_16APSK,
+	STV0900_32APSK,
+	STV0900_UNKNOWN
+};
+
+enum fe_stv0900_modcode {
+	STV0900_DUMMY_PLF,
+	STV0900_QPSK_14,
+	STV0900_QPSK_13,
+	STV0900_QPSK_25,
+	STV0900_QPSK_12,
+	STV0900_QPSK_35,
+	STV0900_QPSK_23,
+	STV0900_QPSK_34,
+	STV0900_QPSK_45,
+	STV0900_QPSK_56,
+	STV0900_QPSK_89,
+	STV0900_QPSK_910,
+	STV0900_8PSK_35,
+	STV0900_8PSK_23,
+	STV0900_8PSK_34,
+	STV0900_8PSK_56,
+	STV0900_8PSK_89,
+	STV0900_8PSK_910,
+	STV0900_16APSK_23,
+	STV0900_16APSK_34,
+	STV0900_16APSK_45,
+	STV0900_16APSK_56,
+	STV0900_16APSK_89,
+	STV0900_16APSK_910,
+	STV0900_32APSK_34,
+	STV0900_32APSK_45,
+	STV0900_32APSK_56,
+	STV0900_32APSK_89,
+	STV0900_32APSK_910,
+	STV0900_MODCODE_UNKNOWN
+};
+
+enum fe_stv0900_fec {/*DVBS1, DSS and turbo code puncture rate*/
+	STV0900_FEC_1_2 = 0,
+	STV0900_FEC_2_3,
+	STV0900_FEC_3_4,
+	STV0900_FEC_4_5,/*for turbo code only*/
+	STV0900_FEC_5_6,
+	STV0900_FEC_6_7,/*for DSS only */
+	STV0900_FEC_7_8,
+	STV0900_FEC_8_9,/*for turbo code only*/
+	STV0900_FEC_UNKNOWN
+};
+
+enum fe_stv0900_frame_length {
+	STV0900_LONG_FRAME,
+	STV0900_SHORT_FRAME
+};
+
+enum fe_stv0900_pilot {
+	STV0900_PILOTS_OFF,
+	STV0900_PILOTS_ON
+};
+
+enum fe_stv0900_rolloff {
+	STV0900_35,
+	STV0900_25,
+	STV0900_20
+};
+
+enum fe_stv0900_search_iq {
+	STV0900_IQ_AUTO,
+	STV0900_IQ_AUTO_NORMAL_FIRST,
+	STV0900_IQ_FORCE_NORMAL,
+	STV0900_IQ_FORCE_SWAPPED
+};
+
+enum stv0900_iq_inversion {
+	STV0900_IQ_NORMAL,
+	STV0900_IQ_SWAPPED
+};
+
+enum fe_stv0900_diseqc_mode {
+	STV0900_22KHZ_Continues = 0,
+	STV0900_DISEQC_2_3_PWM = 2,
+	STV0900_DISEQC_3_3_PWM = 3,
+	STV0900_DISEQC_2_3_ENVELOP = 4,
+	STV0900_DISEQC_3_3_ENVELOP = 5
+};
+
+enum fe_stv0900_demod_mode {
+	STV0900_SINGLE = 0,
+	STV0900_DUAL
+};
+
+struct stv0900_init_params{
+	u32	dmd_ref_clk;/* Refrence,Input clock for the demod in Hz */
+
+	/* Demodulator Type (single demod or dual demod) */
+	enum fe_stv0900_demod_mode	demod_mode;
+	enum fe_stv0900_rolloff		rolloff;
+	enum fe_stv0900_clock_type	path1_ts_clock;
+
+	u8	tun1_maddress;
+	int	tuner1_adc;
+
+	/* IQ from the tuner1 to the demod */
+	enum stv0900_iq_inversion	tun1_iq_inversion;
+	enum fe_stv0900_clock_type	path2_ts_clock;
+
+	u8	tun2_maddress;
+	int	tuner2_adc;
+
+	/* IQ from the tuner2 to the demod */
+	enum stv0900_iq_inversion	tun2_iq_inversion;
+};
+
+struct stv0900_search_params {
+	enum fe_stv0900_demod_num	path;/* Path Used demod1 or 2 */
+
+	u32	frequency;/* Transponder frequency (in KHz) */
+	u32	symbol_rate;/* Transponder symbol rate  (in bds)*/
+	u32	search_range;/* Range of the search (in Hz) */
+
+	enum fe_stv0900_search_standard	standard;
+	enum fe_stv0900_modulation	modulation;
+	enum fe_stv0900_fec		fec;
+	enum fe_stv0900_modcode		modcode;
+	enum fe_stv0900_search_iq	iq_inversion;
+	enum fe_stv0900_search_algo	search_algo;
+
+};
+
+struct stv0900_signal_info {
+	int	locked;/* Transponder locked */
+	u32	frequency;/* Transponder frequency (in KHz) */
+	u32	symbol_rate;/* Transponder symbol rate  (in Mbds) */
+
+	enum fe_stv0900_tracking_standard	standard;
+	enum fe_stv0900_fec			fec;
+	enum fe_stv0900_modcode			modcode;
+	enum fe_stv0900_modulation		modulation;
+	enum fe_stv0900_pilot			pilot;
+	enum fe_stv0900_frame_length		frame_length;
+	enum stv0900_iq_inversion		spectrum;
+	enum fe_stv0900_rolloff			rolloff;
+
+	s32 Power;/* Power of the RF signal (dBm) */
+	s32 C_N;/* Carrier to noise ratio (dB x10)*/
+	u32 BER;/* Bit error rate (x10^7) */
+
+};
+
+struct stv0900_internal{
+	s32	quartz;
+	s32	mclk;
+	/* manual RollOff for DVBS1/DSS only */
+	enum fe_stv0900_rolloff		rolloff;
+	/* Demodulator use for single demod or for dual demod) */
+	enum fe_stv0900_demod_mode	demod_mode;
+
+	/*Demod 1*/
+	s32	tuner1_freq;
+	s32	tuner1_bw;
+	s32	dmd1_symbol_rate;
+	s32	dmd1_srch_range;
+
+	/* algorithm for search Blind, Cold or Warm*/
+	enum fe_stv0900_search_algo	dmd1_srch_algo;
+	/* search standard: Auto, DVBS1/DSS only or DVBS2 only*/
+	enum fe_stv0900_search_standard	dmd1_srch_standard;
+	/* inversion search : auto, auto norma first, normal or inverted */
+	enum fe_stv0900_search_iq	dmd1_srch_iq_inv;
+	enum fe_stv0900_modcode		dmd1_modcode;
+	enum fe_stv0900_modulation	dmd1_modulation;
+	enum fe_stv0900_fec		dmd1_fec;
+
+	struct stv0900_signal_info	dmd1_rslts;
+	enum fe_stv0900_signal_type	dmd1_state;
+
+	enum fe_stv0900_error		dmd1_err;
+
+	/*Demod 2*/
+	s32	tuner2_freq;
+	s32	tuner2_bw;
+	s32	dmd2_symbol_rate;
+	s32	dmd2_srch_range;
+
+	enum fe_stv0900_search_algo	dmd2_srch_algo;
+	enum fe_stv0900_search_standard	dmd2_srch_stndrd;
+	/* inversion search : auto, auto normal first, normal or inverted */
+	enum fe_stv0900_search_iq	dmd2_srch_iq_inv;
+	enum fe_stv0900_modcode		dmd2_modcode;
+	enum fe_stv0900_modulation	dmd2_modulation;
+	enum fe_stv0900_fec		dmd2_fec;
+
+	/* results of the search*/
+	struct stv0900_signal_info	dmd2_rslts;
+	/* current state of the search algorithm */
+	enum fe_stv0900_signal_type	dmd2_state;
+
+	enum fe_stv0900_error		dmd2_err;
+
+	struct i2c_adapter	*i2c_adap;
+	u8			i2c_addr;
+	u8			clkmode;/* 0 for CLKI, 2 for XTALI */
+	u8			chip_id;
+	enum fe_stv0900_error	errs;
+	int dmds_used;
+};
+
+/* state for each demod */
+struct stv0900_state {
+	/* pointer for internal params, one for each pair of demods */
+	struct stv0900_internal		*internal;
+	struct i2c_adapter		*i2c_adap;
+	const struct stv0900_config	*config;
+	struct dvb_frontend		frontend;
+	int demod;
+};
+
+extern s32 ge2comp(s32 a, s32 width);
+
+extern void stv0900_write_reg(struct stv0900_internal *i_params,
+				u16 reg_addr, u8 reg_data);
+
+extern u8 stv0900_read_reg(struct stv0900_internal *i_params,
+				u16 reg_addr);
+
+extern void stv0900_write_bits(struct stv0900_internal *i_params,
+				u32 label, u8 val);
+
+extern u8 stv0900_get_bits(struct stv0900_internal *i_params,
+				u32 label);
+
+extern int stv0900_get_demod_lock(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod, s32 time_out);
+extern int stv0900_check_signal_presence(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe);
+
+extern void stv0900_set_tuner(struct dvb_frontend *fe, u32 frequency,
+				u32 bandwidth);
+extern void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth);
+
+extern void stv0900_start_search(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern u8 stv0900_get_optim_carr_loop(s32 srate,
+				enum fe_stv0900_modcode modcode,
+				s32 pilot, u8 chip_id);
+
+extern u8 stv0900_get_optim_short_carr_loop(s32 srate,
+				enum fe_stv0900_modulation modulation,
+				u8 chip_id);
+
+extern void stv0900_stop_all_s2_modcod(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern void stv0900_activate_s2_modcode(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern void stv0900_activate_s2_modcode_single(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe,
+				enum fe_stv0900_demod_num demod);
+
+#endif
diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h
new file mode 100644
index 0000000..264f9cf
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900_reg.h
@@ -0,0 +1,3787 @@
+/*
+ * stv0900_reg.h
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 STV0900_REG_H
+#define STV0900_REG_H
+
+/*MID*/
+#define R0900_MID  0xf100
+#define F0900_MCHIP_IDENT  0xf10000f0
+#define F0900_MRELEASE  0xf100000f
+
+/*DACR1*/
+#define R0900_DACR1  0xf113
+#define F0900_DAC_MODE  0xf11300e0
+#define F0900_DAC_VALUE1  0xf113000f
+
+/*DACR2*/
+#define R0900_DACR2  0xf114
+#define F0900_DAC_VALUE0  0xf11400ff
+
+/*OUTCFG*/
+#define R0900_OUTCFG  0xf11c
+#define F0900_INV_DATA6  0xf11c0080
+#define F0900_OUTSERRS1_HZ  0xf11c0040
+#define F0900_OUTSERRS2_HZ  0xf11c0020
+#define F0900_OUTSERRS3_HZ  0xf11c0010
+#define F0900_OUTPARRS3_HZ  0xf11c0008
+#define F0900_OUTHZ3_CONTROL  0xf11c0007
+
+/*MODECFG*/
+#define R0900_MODECFG  0xf11d
+#define F0900_FECSPY_SEL_2  0xf11d0020
+#define F0900_HWARE_SEL_2  0xf11d0010
+#define F0900_PKTDEL_SEL_2  0xf11d0008
+#define F0900_DISEQC_SEL_2  0xf11d0004
+#define F0900_VIT_SEL_2  0xf11d0002
+#define F0900_DEMOD_SEL_2  0xf11d0001
+
+/*IRQSTATUS3*/
+#define R0900_IRQSTATUS3  0xf120
+#define F0900_SPLL_LOCK  0xf1200020
+#define F0900_SSTREAM_LCK_3  0xf1200010
+#define F0900_SSTREAM_LCK_2  0xf1200008
+#define F0900_SSTREAM_LCK_1  0xf1200004
+#define F0900_SDVBS1_PRF_2  0xf1200002
+#define F0900_SDVBS1_PRF_1  0xf1200001
+
+/*IRQSTATUS2*/
+#define R0900_IRQSTATUS2  0xf121
+#define F0900_SSPY_ENDSIM_3  0xf1210080
+#define F0900_SSPY_ENDSIM_2  0xf1210040
+#define F0900_SSPY_ENDSIM_1  0xf1210020
+#define F0900_SPKTDEL_ERROR_2  0xf1210010
+#define F0900_SPKTDEL_LOCKB_2  0xf1210008
+#define F0900_SPKTDEL_LOCK_2  0xf1210004
+#define F0900_SPKTDEL_ERROR_1  0xf1210002
+#define F0900_SPKTDEL_LOCKB_1  0xf1210001
+
+/*IRQSTATUS1*/
+#define R0900_IRQSTATUS1  0xf122
+#define F0900_SPKTDEL_LOCK_1  0xf1220080
+#define F0900_SEXTPINB2  0xf1220040
+#define F0900_SEXTPIN2  0xf1220020
+#define F0900_SEXTPINB1  0xf1220010
+#define F0900_SEXTPIN1  0xf1220008
+#define F0900_SDEMOD_LOCKB_2  0xf1220004
+#define F0900_SDEMOD_LOCK_2  0xf1220002
+#define F0900_SDEMOD_IRQ_2  0xf1220001
+
+/*IRQSTATUS0*/
+#define R0900_IRQSTATUS0  0xf123
+#define F0900_SDEMOD_LOCKB_1  0xf1230080
+#define F0900_SDEMOD_LOCK_1  0xf1230040
+#define F0900_SDEMOD_IRQ_1  0xf1230020
+#define F0900_SBCH_ERRFLAG  0xf1230010
+#define F0900_SDISEQC2RX_IRQ  0xf1230008
+#define F0900_SDISEQC2TX_IRQ  0xf1230004
+#define F0900_SDISEQC1RX_IRQ  0xf1230002
+#define F0900_SDISEQC1TX_IRQ  0xf1230001
+
+/*IRQMASK3*/
+#define R0900_IRQMASK3  0xf124
+#define F0900_MPLL_LOCK  0xf1240020
+#define F0900_MSTREAM_LCK_3  0xf1240010
+#define F0900_MSTREAM_LCK_2  0xf1240008
+#define F0900_MSTREAM_LCK_1  0xf1240004
+#define F0900_MDVBS1_PRF_2  0xf1240002
+#define F0900_MDVBS1_PRF_1  0xf1240001
+
+/*IRQMASK2*/
+#define R0900_IRQMASK2  0xf125
+#define F0900_MSPY_ENDSIM_3  0xf1250080
+#define F0900_MSPY_ENDSIM_2  0xf1250040
+#define F0900_MSPY_ENDSIM_1  0xf1250020
+#define F0900_MPKTDEL_ERROR_2  0xf1250010
+#define F0900_MPKTDEL_LOCKB_2  0xf1250008
+#define F0900_MPKTDEL_LOCK_2  0xf1250004
+#define F0900_MPKTDEL_ERROR_1  0xf1250002
+#define F0900_MPKTDEL_LOCKB_1  0xf1250001
+
+/*IRQMASK1*/
+#define R0900_IRQMASK1  0xf126
+#define F0900_MPKTDEL_LOCK_1  0xf1260080
+#define F0900_MEXTPINB2  0xf1260040
+#define F0900_MEXTPIN2  0xf1260020
+#define F0900_MEXTPINB1  0xf1260010
+#define F0900_MEXTPIN1  0xf1260008
+#define F0900_MDEMOD_LOCKB_2  0xf1260004
+#define F0900_MDEMOD_LOCK_2  0xf1260002
+#define F0900_MDEMOD_IRQ_2  0xf1260001
+
+/*IRQMASK0*/
+#define R0900_IRQMASK0  0xf127
+#define F0900_MDEMOD_LOCKB_1  0xf1270080
+#define F0900_MDEMOD_LOCK_1  0xf1270040
+#define F0900_MDEMOD_IRQ_1  0xf1270020
+#define F0900_MBCH_ERRFLAG  0xf1270010
+#define F0900_MDISEQC2RX_IRQ  0xf1270008
+#define F0900_MDISEQC2TX_IRQ  0xf1270004
+#define F0900_MDISEQC1RX_IRQ  0xf1270002
+#define F0900_MDISEQC1TX_IRQ  0xf1270001
+
+/*I2CCFG*/
+#define R0900_I2CCFG  0xf129
+#define F0900_I2C2_FASTMODE  0xf1290080
+#define F0900_STATUS_WR2  0xf1290040
+#define F0900_I2C2ADDR_INC  0xf1290030
+#define F0900_I2C_FASTMODE  0xf1290008
+#define F0900_STATUS_WR  0xf1290004
+#define F0900_I2CADDR_INC  0xf1290003
+
+/*P1_I2CRPT*/
+#define R0900_P1_I2CRPT  0xf12a
+#define F0900_P1_I2CT_ON  0xf12a0080
+#define F0900_P1_ENARPT_LEVEL  0xf12a0070
+#define F0900_P1_SCLT_DELAY  0xf12a0008
+#define F0900_P1_STOP_ENABLE  0xf12a0004
+#define F0900_P1_STOP_SDAT2SDA  0xf12a0002
+
+/*P2_I2CRPT*/
+#define R0900_P2_I2CRPT  0xf12b
+#define F0900_P2_I2CT_ON  0xf12b0080
+#define F0900_P2_ENARPT_LEVEL  0xf12b0070
+#define F0900_P2_SCLT_DELAY  0xf12b0008
+#define F0900_P2_STOP_ENABLE  0xf12b0004
+#define F0900_P2_STOP_SDAT2SDA  0xf12b0002
+
+/*CLKI2CFG*/
+#define R0900_CLKI2CFG  0xf140
+#define F0900_CLKI2_OPD  0xf1400080
+#define F0900_CLKI2_CONFIG  0xf140007e
+#define F0900_CLKI2_XOR  0xf1400001
+
+/*GPIO1CFG*/
+#define R0900_GPIO1CFG  0xf141
+#define F0900_GPIO1_OPD  0xf1410080
+#define F0900_GPIO1_CONFIG  0xf141007e
+#define F0900_GPIO1_XOR  0xf1410001
+
+/*GPIO2CFG*/
+#define R0900_GPIO2CFG  0xf142
+#define F0900_GPIO2_OPD  0xf1420080
+#define F0900_GPIO2_CONFIG  0xf142007e
+#define F0900_GPIO2_XOR  0xf1420001
+
+/*GPIO3CFG*/
+#define R0900_GPIO3CFG  0xf143
+#define F0900_GPIO3_OPD  0xf1430080
+#define F0900_GPIO3_CONFIG  0xf143007e
+#define F0900_GPIO3_XOR  0xf1430001
+
+/*GPIO4CFG*/
+#define R0900_GPIO4CFG  0xf144
+#define F0900_GPIO4_OPD  0xf1440080
+#define F0900_GPIO4_CONFIG  0xf144007e
+#define F0900_GPIO4_XOR  0xf1440001
+
+/*GPIO5CFG*/
+#define R0900_GPIO5CFG  0xf145
+#define F0900_GPIO5_OPD  0xf1450080
+#define F0900_GPIO5_CONFIG  0xf145007e
+#define F0900_GPIO5_XOR  0xf1450001
+
+/*GPIO6CFG*/
+#define R0900_GPIO6CFG  0xf146
+#define F0900_GPIO6_OPD  0xf1460080
+#define F0900_GPIO6_CONFIG  0xf146007e
+#define F0900_GPIO6_XOR  0xf1460001
+
+/*GPIO7CFG*/
+#define R0900_GPIO7CFG  0xf147
+#define F0900_GPIO7_OPD  0xf1470080
+#define F0900_GPIO7_CONFIG  0xf147007e
+#define F0900_GPIO7_XOR  0xf1470001
+
+/*GPIO8CFG*/
+#define R0900_GPIO8CFG  0xf148
+#define F0900_GPIO8_OPD  0xf1480080
+#define F0900_GPIO8_CONFIG  0xf148007e
+#define F0900_GPIO8_XOR  0xf1480001
+
+/*GPIO9CFG*/
+#define R0900_GPIO9CFG  0xf149
+#define F0900_GPIO9_OPD  0xf1490080
+#define F0900_GPIO9_CONFIG  0xf149007e
+#define F0900_GPIO9_XOR  0xf1490001
+
+/*GPIO10CFG*/
+#define R0900_GPIO10CFG  0xf14a
+#define F0900_GPIO10_OPD  0xf14a0080
+#define F0900_GPIO10_CONFIG  0xf14a007e
+#define F0900_GPIO10_XOR  0xf14a0001
+
+/*GPIO11CFG*/
+#define R0900_GPIO11CFG  0xf14b
+#define F0900_GPIO11_OPD  0xf14b0080
+#define F0900_GPIO11_CONFIG  0xf14b007e
+#define F0900_GPIO11_XOR  0xf14b0001
+
+/*GPIO12CFG*/
+#define R0900_GPIO12CFG  0xf14c
+#define F0900_GPIO12_OPD  0xf14c0080
+#define F0900_GPIO12_CONFIG  0xf14c007e
+#define F0900_GPIO12_XOR  0xf14c0001
+
+/*GPIO13CFG*/
+#define R0900_GPIO13CFG  0xf14d
+#define F0900_GPIO13_OPD  0xf14d0080
+#define F0900_GPIO13_CONFIG  0xf14d007e
+#define F0900_GPIO13_XOR  0xf14d0001
+
+/*CS0CFG*/
+#define R0900_CS0CFG  0xf14e
+#define F0900_CS0_OPD  0xf14e0080
+#define F0900_CS0_CONFIG  0xf14e007e
+#define F0900_CS0_XOR  0xf14e0001
+
+/*CS1CFG*/
+#define R0900_CS1CFG  0xf14f
+#define F0900_CS1_OPD  0xf14f0080
+#define F0900_CS1_CONFIG  0xf14f007e
+#define F0900_CS1_XOR  0xf14f0001
+
+/*STDBYCFG*/
+#define R0900_STDBYCFG  0xf150
+#define F0900_STDBY_OPD  0xf1500080
+#define F0900_STDBY_CONFIG  0xf150007e
+#define F0900_STBDY_XOR  0xf1500001
+
+/*DIRCLKCFG*/
+#define R0900_DIRCLKCFG  0xf151
+#define F0900_DIRCLK_OPD  0xf1510080
+#define F0900_DIRCLK_CONFIG  0xf151007e
+#define F0900_DIRCLK_XOR  0xf1510001
+
+/*AGCRF1CFG*/
+#define R0900_AGCRF1CFG  0xf152
+#define F0900_AGCRF1_OPD  0xf1520080
+#define F0900_AGCRF1_CONFIG  0xf152007e
+#define F0900_AGCRF1_XOR  0xf1520001
+
+/*SDAT1CFG*/
+#define R0900_SDAT1CFG  0xf153
+#define F0900_SDAT1_OPD  0xf1530080
+#define F0900_SDAT1_CONFIG  0xf153007e
+#define F0900_SDAT1_XOR  0xf1530001
+
+/*SCLT1CFG*/
+#define R0900_SCLT1CFG  0xf154
+#define F0900_SCLT1_OPD  0xf1540080
+#define F0900_SCLT1_CONFIG  0xf154007e
+#define F0900_SCLT1_XOR  0xf1540001
+
+/*DISEQCO1CFG*/
+#define R0900_DISEQCO1CFG  0xf155
+#define F0900_DISEQCO1_OPD  0xf1550080
+#define F0900_DISEQCO1_CONFIG  0xf155007e
+#define F0900_DISEQC1_XOR  0xf1550001
+
+/*AGCRF2CFG*/
+#define R0900_AGCRF2CFG  0xf156
+#define F0900_AGCRF2_OPD  0xf1560080
+#define F0900_AGCRF2_CONFIG  0xf156007e
+#define F0900_AGCRF2_XOR  0xf1560001
+
+/*SDAT2CFG*/
+#define R0900_SDAT2CFG  0xf157
+#define F0900_SDAT2_OPD  0xf1570080
+#define F0900_SDAT2_CONFIG  0xf157007e
+#define F0900_SDAT2_XOR  0xf1570001
+
+/*SCLT2CFG*/
+#define R0900_SCLT2CFG  0xf158
+#define F0900_SCLT2_OPD  0xf1580080
+#define F0900_SCLT2_CONFIG  0xf158007e
+#define F0900_SCLT2_XOR  0xf1580001
+
+/*DISEQCO2CFG*/
+#define R0900_DISEQCO2CFG  0xf159
+#define F0900_DISEQCO2_OPD  0xf1590080
+#define F0900_DISEQCO2_CONFIG  0xf159007e
+#define F0900_DISEQC2_XOR  0xf1590001
+
+/*CLKOUT27CFG*/
+#define R0900_CLKOUT27CFG  0xf15a
+#define F0900_CLKOUT27_OPD  0xf15a0080
+#define F0900_CLKOUT27_CONFIG  0xf15a007e
+#define F0900_CLKOUT27_XOR  0xf15a0001
+
+/*ERROR1CFG*/
+#define R0900_ERROR1CFG  0xf15b
+#define F0900_ERROR1_OPD  0xf15b0080
+#define F0900_ERROR1_CONFIG  0xf15b007e
+#define F0900_ERROR1_XOR  0xf15b0001
+
+/*DPN1CFG*/
+#define R0900_DPN1CFG  0xf15c
+#define F0900_DPN1_OPD  0xf15c0080
+#define F0900_DPN1_CONFIG  0xf15c007e
+#define F0900_DPN1_XOR  0xf15c0001
+
+/*STROUT1CFG*/
+#define R0900_STROUT1CFG  0xf15d
+#define F0900_STROUT1_OPD  0xf15d0080
+#define F0900_STROUT1_CONFIG  0xf15d007e
+#define F0900_STROUT1_XOR  0xf15d0001
+
+/*CLKOUT1CFG*/
+#define R0900_CLKOUT1CFG  0xf15e
+#define F0900_CLKOUT1_OPD  0xf15e0080
+#define F0900_CLKOUT1_CONFIG  0xf15e007e
+#define F0900_CLKOUT1_XOR  0xf15e0001
+
+/*DATA71CFG*/
+#define R0900_DATA71CFG  0xf15f
+#define F0900_DATA71_OPD  0xf15f0080
+#define F0900_DATA71_CONFIG  0xf15f007e
+#define F0900_DATA71_XOR  0xf15f0001
+
+/*ERROR2CFG*/
+#define R0900_ERROR2CFG  0xf160
+#define F0900_ERROR2_OPD  0xf1600080
+#define F0900_ERROR2_CONFIG  0xf160007e
+#define F0900_ERROR2_XOR  0xf1600001
+
+/*DPN2CFG*/
+#define R0900_DPN2CFG  0xf161
+#define F0900_DPN2_OPD  0xf1610080
+#define F0900_DPN2_CONFIG  0xf161007e
+#define F0900_DPN2_XOR  0xf1610001
+
+/*STROUT2CFG*/
+#define R0900_STROUT2CFG  0xf162
+#define F0900_STROUT2_OPD  0xf1620080
+#define F0900_STROUT2_CONFIG  0xf162007e
+#define F0900_STROUT2_XOR  0xf1620001
+
+/*CLKOUT2CFG*/
+#define R0900_CLKOUT2CFG  0xf163
+#define F0900_CLKOUT2_OPD  0xf1630080
+#define F0900_CLKOUT2_CONFIG  0xf163007e
+#define F0900_CLKOUT2_XOR  0xf1630001
+
+/*DATA72CFG*/
+#define R0900_DATA72CFG  0xf164
+#define F0900_DATA72_OPD  0xf1640080
+#define F0900_DATA72_CONFIG  0xf164007e
+#define F0900_DATA72_XOR  0xf1640001
+
+/*ERROR3CFG*/
+#define R0900_ERROR3CFG  0xf165
+#define F0900_ERROR3_OPD  0xf1650080
+#define F0900_ERROR3_CONFIG  0xf165007e
+#define F0900_ERROR3_XOR  0xf1650001
+
+/*DPN3CFG*/
+#define R0900_DPN3CFG  0xf166
+#define F0900_DPN3_OPD  0xf1660080
+#define F0900_DPN3_CONFIG  0xf166007e
+#define F0900_DPN3_XOR  0xf1660001
+
+/*STROUT3CFG*/
+#define R0900_STROUT3CFG  0xf167
+#define F0900_STROUT3_OPD  0xf1670080
+#define F0900_STROUT3_CONFIG  0xf167007e
+#define F0900_STROUT3_XOR  0xf1670001
+
+/*CLKOUT3CFG*/
+#define R0900_CLKOUT3CFG  0xf168
+#define F0900_CLKOUT3_OPD  0xf1680080
+#define F0900_CLKOUT3_CONFIG  0xf168007e
+#define F0900_CLKOUT3_XOR  0xf1680001
+
+/*DATA73CFG*/
+#define R0900_DATA73CFG  0xf169
+#define F0900_DATA73_OPD  0xf1690080
+#define F0900_DATA73_CONFIG  0xf169007e
+#define F0900_DATA73_XOR  0xf1690001
+
+/*FSKTFC2*/
+#define R0900_FSKTFC2  0xf170
+#define F0900_FSKT_KMOD  0xf17000fc
+#define F0900_FSKT_CAR2  0xf1700003
+
+/*FSKTFC1*/
+#define R0900_FSKTFC1  0xf171
+#define F0900_FSKT_CAR1  0xf17100ff
+
+/*FSKTFC0*/
+#define R0900_FSKTFC0  0xf172
+#define F0900_FSKT_CAR0  0xf17200ff
+
+/*FSKTDELTAF1*/
+#define R0900_FSKTDELTAF1  0xf173
+#define F0900_FSKT_DELTAF1  0xf173000f
+
+/*FSKTDELTAF0*/
+#define R0900_FSKTDELTAF0  0xf174
+#define F0900_FSKT_DELTAF0  0xf17400ff
+
+/*FSKTCTRL*/
+#define R0900_FSKTCTRL  0xf175
+#define F0900_FSKT_EN_SGN  0xf1750040
+#define F0900_FSKT_MOD_SGN  0xf1750020
+#define F0900_FSKT_MOD_EN  0xf175001c
+#define F0900_FSKT_DACMODE  0xf1750003
+
+/*FSKRFC2*/
+#define R0900_FSKRFC2  0xf176
+#define F0900_FSKR_DETSGN  0xf1760040
+#define F0900_FSKR_OUTSGN  0xf1760020
+#define F0900_FSKR_KAGC  0xf176001c
+#define F0900_FSKR_CAR2  0xf1760003
+
+/*FSKRFC1*/
+#define R0900_FSKRFC1  0xf177
+#define F0900_FSKR_CAR1  0xf17700ff
+
+/*FSKRFC0*/
+#define R0900_FSKRFC0  0xf178
+#define F0900_FSKR_CAR0  0xf17800ff
+
+/*FSKRK1*/
+#define R0900_FSKRK1  0xf179
+#define F0900_FSKR_K1_EXP  0xf17900e0
+#define F0900_FSKR_K1_MANT  0xf179001f
+
+/*FSKRK2*/
+#define R0900_FSKRK2  0xf17a
+#define F0900_FSKR_K2_EXP  0xf17a00e0
+#define F0900_FSKR_K2_MANT  0xf17a001f
+
+/*FSKRAGCR*/
+#define R0900_FSKRAGCR  0xf17b
+#define F0900_FSKR_OUTCTL  0xf17b00c0
+#define F0900_FSKR_AGC_REF  0xf17b003f
+
+/*FSKRAGC*/
+#define R0900_FSKRAGC  0xf17c
+#define F0900_FSKR_AGC_ACCU  0xf17c00ff
+
+/*FSKRALPHA*/
+#define R0900_FSKRALPHA  0xf17d
+#define F0900_FSKR_ALPHA_EXP  0xf17d001c
+#define F0900_FSKR_ALPHA_M  0xf17d0003
+
+/*FSKRPLTH1*/
+#define R0900_FSKRPLTH1  0xf17e
+#define F0900_FSKR_BETA  0xf17e00f0
+#define F0900_FSKR_PLL_TRESH1  0xf17e000f
+
+/*FSKRPLTH0*/
+#define R0900_FSKRPLTH0  0xf17f
+#define F0900_FSKR_PLL_TRESH0  0xf17f00ff
+
+/*FSKRDF1*/
+#define R0900_FSKRDF1  0xf180
+#define F0900_FSKR_OUT  0xf1800080
+#define F0900_FSKR_DELTAF1  0xf180001f
+
+/*FSKRDF0*/
+#define R0900_FSKRDF0  0xf181
+#define F0900_FSKR_DELTAF0  0xf18100ff
+
+/*FSKRSTEPP*/
+#define R0900_FSKRSTEPP  0xf182
+#define F0900_FSKR_STEP_PLUS  0xf18200ff
+
+/*FSKRSTEPM*/
+#define R0900_FSKRSTEPM  0xf183
+#define F0900_FSKR_STEP_MINUS  0xf18300ff
+
+/*FSKRDET1*/
+#define R0900_FSKRDET1  0xf184
+#define F0900_FSKR_DETECT  0xf1840080
+#define F0900_FSKR_CARDET_ACCU1  0xf184000f
+
+/*FSKRDET0*/
+#define R0900_FSKRDET0  0xf185
+#define F0900_FSKR_CARDET_ACCU0  0xf18500ff
+
+/*FSKRDTH1*/
+#define R0900_FSKRDTH1  0xf186
+#define F0900_FSKR_CARLOSS_THRESH1  0xf18600f0
+#define F0900_FSKR_CARDET_THRESH1  0xf186000f
+
+/*FSKRDTH0*/
+#define R0900_FSKRDTH0  0xf187
+#define F0900_FSKR_CARDET_THRESH0  0xf18700ff
+
+/*FSKRLOSS*/
+#define R0900_FSKRLOSS  0xf188
+#define F0900_FSKR_CARLOSS_THRESH0  0xf18800ff
+
+/*P2_DISTXCTL*/
+#define R0900_P2_DISTXCTL  0xf190
+#define F0900_P2_TIM_OFF  0xf1900080
+#define F0900_P2_DISEQC_RESET  0xf1900040
+#define F0900_P2_TIM_CMD  0xf1900030
+#define F0900_P2_DIS_PRECHARGE  0xf1900008
+#define F0900_P2_DISTX_MODE  0xf1900007
+
+/*P2_DISRXCTL*/
+#define R0900_P2_DISRXCTL  0xf191
+#define F0900_P2_RECEIVER_ON  0xf1910080
+#define F0900_P2_IGNO_SHORT22K  0xf1910040
+#define F0900_P2_ONECHIP_TRX  0xf1910020
+#define F0900_P2_EXT_ENVELOP  0xf1910010
+#define F0900_P2_PIN_SELECT  0xf191000c
+#define F0900_P2_IRQ_RXEND  0xf1910002
+#define F0900_P2_IRQ_4NBYTES  0xf1910001
+
+/*P2_DISRX_ST0*/
+#define R0900_P2_DISRX_ST0  0xf194
+#define F0900_P2_RX_END  0xf1940080
+#define F0900_P2_RX_ACTIVE  0xf1940040
+#define F0900_P2_SHORT_22KHZ  0xf1940020
+#define F0900_P2_CONT_TONE  0xf1940010
+#define F0900_P2_FIFO_4BREADY  0xf1940008
+#define F0900_P2_FIFO_EMPTY  0xf1940004
+#define F0900_P2_ABORT_DISRX  0xf1940001
+
+/*P2_DISRX_ST1*/
+#define R0900_P2_DISRX_ST1  0xf195
+#define F0900_P2_RX_FAIL  0xf1950080
+#define F0900_P2_FIFO_PARITYFAIL  0xf1950040
+#define F0900_P2_RX_NONBYTE  0xf1950020
+#define F0900_P2_FIFO_OVERFLOW  0xf1950010
+#define F0900_P2_FIFO_BYTENBR  0xf195000f
+
+/*P2_DISRXDATA*/
+#define R0900_P2_DISRXDATA  0xf196
+#define F0900_P2_DISRX_DATA  0xf19600ff
+
+/*P2_DISTXDATA*/
+#define R0900_P2_DISTXDATA  0xf197
+#define F0900_P2_DISEQC_FIFO  0xf19700ff
+
+/*P2_DISTXSTATUS*/
+#define R0900_P2_DISTXSTATUS  0xf198
+#define F0900_P2_TX_FAIL  0xf1980080
+#define F0900_P2_FIFO_FULL  0xf1980040
+#define F0900_P2_TX_IDLE  0xf1980020
+#define F0900_P2_GAP_BURST  0xf1980010
+#define F0900_P2_TXFIFO_BYTES  0xf198000f
+
+/*P2_F22TX*/
+#define R0900_P2_F22TX  0xf199
+#define F0900_P2_F22_REG  0xf19900ff
+
+/*P2_F22RX*/
+#define R0900_P2_F22RX  0xf19a
+#define F0900_P2_F22RX_REG  0xf19a00ff
+
+/*P2_ACRPRESC*/
+#define R0900_P2_ACRPRESC  0xf19c
+#define F0900_P2_ACR_CODFRDY  0xf19c0008
+#define F0900_P2_ACR_PRESC  0xf19c0007
+
+/*P2_ACRDIV*/
+#define R0900_P2_ACRDIV  0xf19d
+#define F0900_P2_ACR_DIV  0xf19d00ff
+
+/*P1_DISTXCTL*/
+#define R0900_P1_DISTXCTL  0xf1a0
+#define F0900_P1_TIM_OFF  0xf1a00080
+#define F0900_P1_DISEQC_RESET  0xf1a00040
+#define F0900_P1_TIM_CMD  0xf1a00030
+#define F0900_P1_DIS_PRECHARGE  0xf1a00008
+#define F0900_P1_DISTX_MODE  0xf1a00007
+
+/*P1_DISRXCTL*/
+#define R0900_P1_DISRXCTL  0xf1a1
+#define F0900_P1_RECEIVER_ON  0xf1a10080
+#define F0900_P1_IGNO_SHORT22K  0xf1a10040
+#define F0900_P1_ONECHIP_TRX  0xf1a10020
+#define F0900_P1_EXT_ENVELOP  0xf1a10010
+#define F0900_P1_PIN_SELECT  0xf1a1000c
+#define F0900_P1_IRQ_RXEND  0xf1a10002
+#define F0900_P1_IRQ_4NBYTES  0xf1a10001
+
+/*P1_DISRX_ST0*/
+#define R0900_P1_DISRX_ST0  0xf1a4
+#define F0900_P1_RX_END  0xf1a40080
+#define F0900_P1_RX_ACTIVE  0xf1a40040
+#define F0900_P1_SHORT_22KHZ  0xf1a40020
+#define F0900_P1_CONT_TONE  0xf1a40010
+#define F0900_P1_FIFO_4BREADY  0xf1a40008
+#define F0900_P1_FIFO_EMPTY  0xf1a40004
+#define F0900_P1_ABORT_DISRX  0xf1a40001
+
+/*P1_DISRX_ST1*/
+#define R0900_P1_DISRX_ST1  0xf1a5
+#define F0900_P1_RX_FAIL  0xf1a50080
+#define F0900_P1_FIFO_PARITYFAIL  0xf1a50040
+#define F0900_P1_RX_NONBYTE  0xf1a50020
+#define F0900_P1_FIFO_OVERFLOW  0xf1a50010
+#define F0900_P1_FIFO_BYTENBR  0xf1a5000f
+
+/*P1_DISRXDATA*/
+#define R0900_P1_DISRXDATA  0xf1a6
+#define F0900_P1_DISRX_DATA  0xf1a600ff
+
+/*P1_DISTXDATA*/
+#define R0900_P1_DISTXDATA  0xf1a7
+#define F0900_P1_DISEQC_FIFO  0xf1a700ff
+
+/*P1_DISTXSTATUS*/
+#define R0900_P1_DISTXSTATUS  0xf1a8
+#define F0900_P1_TX_FAIL  0xf1a80080
+#define F0900_P1_FIFO_FULL  0xf1a80040
+#define F0900_P1_TX_IDLE  0xf1a80020
+#define F0900_P1_GAP_BURST  0xf1a80010
+#define F0900_P1_TXFIFO_BYTES  0xf1a8000f
+
+/*P1_F22TX*/
+#define R0900_P1_F22TX  0xf1a9
+#define F0900_P1_F22_REG  0xf1a900ff
+
+/*P1_F22RX*/
+#define R0900_P1_F22RX  0xf1aa
+#define F0900_P1_F22RX_REG  0xf1aa00ff
+
+/*P1_ACRPRESC*/
+#define R0900_P1_ACRPRESC  0xf1ac
+#define F0900_P1_ACR_CODFRDY  0xf1ac0008
+#define F0900_P1_ACR_PRESC  0xf1ac0007
+
+/*P1_ACRDIV*/
+#define R0900_P1_ACRDIV  0xf1ad
+#define F0900_P1_ACR_DIV  0xf1ad00ff
+
+/*NCOARSE*/
+#define R0900_NCOARSE  0xf1b3
+#define F0900_M_DIV  0xf1b300ff
+
+/*SYNTCTRL*/
+#define R0900_SYNTCTRL  0xf1b6
+#define F0900_STANDBY  0xf1b60080
+#define F0900_BYPASSPLLCORE  0xf1b60040
+#define F0900_SELX1RATIO  0xf1b60020
+#define F0900_I2C_TUD  0xf1b60010
+#define F0900_STOP_PLL  0xf1b60008
+#define F0900_BYPASSPLLFSK  0xf1b60004
+#define F0900_SELOSCI  0xf1b60002
+#define F0900_BYPASSPLLADC  0xf1b60001
+
+/*FILTCTRL*/
+#define R0900_FILTCTRL  0xf1b7
+#define F0900_INV_CLK135  0xf1b70080
+#define F0900_PERM_BYPDIS  0xf1b70040
+#define F0900_SEL_FSKCKDIV  0xf1b70004
+#define F0900_INV_CLKFSK  0xf1b70002
+#define F0900_BYPASS_APPLI  0xf1b70001
+
+/*PLLSTAT*/
+#define R0900_PLLSTAT  0xf1b8
+#define F0900_ACM_SEL  0xf1b80080
+#define F0900_DTV_SEL  0xf1b80040
+#define F0900_PLLLOCK  0xf1b80001
+
+/*STOPCLK1*/
+#define R0900_STOPCLK1  0xf1c2
+#define F0900_STOP_CLKPKDT2  0xf1c20040
+#define F0900_STOP_CLKPKDT1  0xf1c20020
+#define F0900_STOP_CLKFEC  0xf1c20010
+#define F0900_STOP_CLKADCI2  0xf1c20008
+#define F0900_INV_CLKADCI2  0xf1c20004
+#define F0900_STOP_CLKADCI1  0xf1c20002
+#define F0900_INV_CLKADCI1  0xf1c20001
+
+/*STOPCLK2*/
+#define R0900_STOPCLK2  0xf1c3
+#define F0900_STOP_CLKSAMP2  0xf1c30010
+#define F0900_STOP_CLKSAMP1  0xf1c30008
+#define F0900_STOP_CLKVIT2  0xf1c30004
+#define F0900_STOP_CLKVIT1  0xf1c30002
+#define F0900_STOP_CLKTS  0xf1c30001
+
+/*TSTTNR0*/
+#define R0900_TSTTNR0  0xf1df
+#define F0900_SEL_FSK  0xf1df0080
+#define F0900_FSK_PON  0xf1df0004
+#define F0900_FSK_OPENLOOP  0xf1df0002
+
+/*TSTTNR1*/
+#define R0900_TSTTNR1  0xf1e0
+#define F0900_BYPASS_ADC1  0xf1e00080
+#define F0900_INVADC1_CKOUT  0xf1e00040
+#define F0900_SELIQSRC1  0xf1e00030
+#define F0900_ADC1_PON  0xf1e00002
+#define F0900_ADC1_INMODE  0xf1e00001
+
+/*TSTTNR2*/
+#define R0900_TSTTNR2  0xf1e1
+#define F0900_DISEQC1_PON  0xf1e10020
+#define F0900_DISEQC1_TEST  0xf1e1001f
+
+/*TSTTNR3*/
+#define R0900_TSTTNR3  0xf1e2
+#define F0900_BYPASS_ADC2  0xf1e20080
+#define F0900_INVADC2_CKOUT  0xf1e20040
+#define F0900_SELIQSRC2  0xf1e20030
+#define F0900_ADC2_PON  0xf1e20002
+#define F0900_ADC2_INMODE  0xf1e20001
+
+/*TSTTNR4*/
+#define R0900_TSTTNR4  0xf1e3
+#define F0900_DISEQC2_PON  0xf1e30020
+#define F0900_DISEQC2_TEST  0xf1e3001f
+
+/*P2_IQCONST*/
+#define R0900_P2_IQCONST  0xf200
+#define F0900_P2_CONSTEL_SELECT  0xf2000060
+#define F0900_P2_IQSYMB_SEL  0xf200001f
+
+/*P2_NOSCFG*/
+#define R0900_P2_NOSCFG  0xf201
+#define F0900_P2_DUMMYPL_NOSDATA  0xf2010020
+#define F0900_P2_NOSPLH_BETA  0xf2010018
+#define F0900_P2_NOSDATA_BETA  0xf2010007
+
+/*P2_ISYMB*/
+#define R0900_P2_ISYMB  0xf202
+#define F0900_P2_I_SYMBOL  0xf20201ff
+
+/*P2_QSYMB*/
+#define R0900_P2_QSYMB  0xf203
+#define F0900_P2_Q_SYMBOL  0xf20301ff
+
+/*P2_AGC1CFG*/
+#define R0900_P2_AGC1CFG  0xf204
+#define F0900_P2_DC_FROZEN  0xf2040080
+#define F0900_P2_DC_CORRECT  0xf2040040
+#define F0900_P2_AMM_FROZEN  0xf2040020
+#define F0900_P2_AMM_CORRECT  0xf2040010
+#define F0900_P2_QUAD_FROZEN  0xf2040008
+#define F0900_P2_QUAD_CORRECT  0xf2040004
+#define F0900_P2_DCCOMP_SLOW  0xf2040002
+#define F0900_P2_IQMISM_SLOW  0xf2040001
+
+/*P2_AGC1CN*/
+#define R0900_P2_AGC1CN  0xf206
+#define F0900_P2_AGC1_LOCKED  0xf2060080
+#define F0900_P2_AGC1_OVERFLOW  0xf2060040
+#define F0900_P2_AGC1_NOSLOWLK  0xf2060020
+#define F0900_P2_AGC1_MINPOWER  0xf2060010
+#define F0900_P2_AGCOUT_FAST  0xf2060008
+#define F0900_P2_AGCIQ_BETA  0xf2060007
+
+/*P2_AGC1REF*/
+#define R0900_P2_AGC1REF  0xf207
+#define F0900_P2_AGCIQ_REF  0xf20700ff
+
+/*P2_IDCCOMP*/
+#define R0900_P2_IDCCOMP  0xf208
+#define F0900_P2_IAVERAGE_ADJ  0xf20801ff
+
+/*P2_QDCCOMP*/
+#define R0900_P2_QDCCOMP  0xf209
+#define F0900_P2_QAVERAGE_ADJ  0xf20901ff
+
+/*P2_POWERI*/
+#define R0900_P2_POWERI  0xf20a
+#define F0900_P2_POWER_I  0xf20a00ff
+
+/*P2_POWERQ*/
+#define R0900_P2_POWERQ  0xf20b
+#define F0900_P2_POWER_Q  0xf20b00ff
+
+/*P2_AGC1AMM*/
+#define R0900_P2_AGC1AMM  0xf20c
+#define F0900_P2_AMM_VALUE  0xf20c00ff
+
+/*P2_AGC1QUAD*/
+#define R0900_P2_AGC1QUAD  0xf20d
+#define F0900_P2_QUAD_VALUE  0xf20d01ff
+
+/*P2_AGCIQIN1*/
+#define R0900_P2_AGCIQIN1  0xf20e
+#define F0900_P2_AGCIQ_VALUE1  0xf20e00ff
+
+/*P2_AGCIQIN0*/
+#define R0900_P2_AGCIQIN0  0xf20f
+#define F0900_P2_AGCIQ_VALUE0  0xf20f00ff
+
+/*P2_DEMOD*/
+#define R0900_P2_DEMOD  0xf210
+#define F0900_P2_DEMOD_STOP  0xf2100040
+#define F0900_P2_SPECINV_CONTROL  0xf2100030
+#define F0900_P2_FORCE_ENASAMP  0xf2100008
+#define F0900_P2_MANUAL_ROLLOFF  0xf2100004
+#define F0900_P2_ROLLOFF_CONTROL  0xf2100003
+
+/*P2_DMDMODCOD*/
+#define R0900_P2_DMDMODCOD  0xf211
+#define F0900_P2_MANUAL_MODCOD  0xf2110080
+#define F0900_P2_DEMOD_MODCOD  0xf211007c
+#define F0900_P2_DEMOD_TYPE  0xf2110003
+
+/*P2_DSTATUS*/
+#define R0900_P2_DSTATUS  0xf212
+#define F0900_P2_CAR_LOCK  0xf2120080
+#define F0900_P2_TMGLOCK_QUALITY  0xf2120060
+#define F0900_P2_SDVBS1_ENABLE  0xf2120010
+#define F0900_P2_LOCK_DEFINITIF  0xf2120008
+#define F0900_P2_TIMING_IS_LOCKED  0xf2120004
+#define F0900_P2_COARSE_TMGLOCK  0xf2120002
+#define F0900_P2_COARSE_CARLOCK  0xf2120001
+
+/*P2_DSTATUS2*/
+#define R0900_P2_DSTATUS2  0xf213
+#define F0900_P2_DEMOD_DELOCK  0xf2130080
+#define F0900_P2_DEMOD_TIMEOUT  0xf2130040
+#define F0900_P2_MODCODRQ_SYNCTAG  0xf2130020
+#define F0900_P2_POLYPH_SATEVENT  0xf2130010
+#define F0900_P2_AGC1_NOSIGNALACK  0xf2130008
+#define F0900_P2_AGC2_OVERFLOW  0xf2130004
+#define F0900_P2_CFR_OVERFLOW  0xf2130002
+#define F0900_P2_GAMMA_OVERUNDER  0xf2130001
+
+/*P2_DMDCFGMD*/
+#define R0900_P2_DMDCFGMD  0xf214
+#define F0900_P2_DVBS2_ENABLE  0xf2140080
+#define F0900_P2_DVBS1_ENABLE  0xf2140040
+#define F0900_P2_CFR_AUTOSCAN  0xf2140020
+#define F0900_P2_SCAN_ENABLE  0xf2140010
+#define F0900_P2_TUN_AUTOSCAN  0xf2140008
+#define F0900_P2_NOFORCE_RELOCK  0xf2140004
+#define F0900_P2_TUN_RNG  0xf2140003
+
+/*P2_DMDCFG2*/
+#define R0900_P2_DMDCFG2  0xf215
+#define F0900_P2_AGC1_WAITLOCK  0xf2150080
+#define F0900_P2_S1S2_SEQUENTIAL  0xf2150040
+#define F0900_P2_OVERFLOW_TIMEOUT  0xf2150020
+#define F0900_P2_SCANFAIL_TIMEOUT  0xf2150010
+#define F0900_P2_DMDTOUT_BACK  0xf2150008
+#define F0900_P2_CARLOCK_S1ENABLE  0xf2150004
+#define F0900_P2_COARSE_LK3MODE  0xf2150002
+#define F0900_P2_COARSE_LK2MODE  0xf2150001
+
+/*P2_DMDISTATE*/
+#define R0900_P2_DMDISTATE  0xf216
+#define F0900_P2_I2C_NORESETDMODE  0xf2160080
+#define F0900_P2_FORCE_ETAPED  0xf2160040
+#define F0900_P2_SDMDRST_DIRCLK  0xf2160020
+#define F0900_P2_I2C_DEMOD_MODE  0xf216001f
+
+/*P2_DMDT0M*/
+#define R0900_P2_DMDT0M  0xf217
+#define F0900_P2_DMDT0_MIN  0xf21700ff
+
+/*P2_DMDSTATE*/
+#define R0900_P2_DMDSTATE  0xf21b
+#define F0900_P2_DEMOD_LOCKED  0xf21b0080
+#define F0900_P2_HEADER_MODE  0xf21b0060
+#define F0900_P2_DEMOD_MODE  0xf21b001f
+
+/*P2_DMDFLYW*/
+#define R0900_P2_DMDFLYW  0xf21c
+#define F0900_P2_I2C_IRQVAL  0xf21c00f0
+#define F0900_P2_FLYWHEEL_CPT  0xf21c000f
+
+/*P2_DSTATUS3*/
+#define R0900_P2_DSTATUS3  0xf21d
+#define F0900_P2_CFR_ZIGZAG  0xf21d0080
+#define F0900_P2_DEMOD_CFGMODE  0xf21d0060
+#define F0900_P2_GAMMA_LOWBAUDRATE  0xf21d0010
+#define F0900_P2_RELOCK_MODE  0xf21d0008
+#define F0900_P2_DEMOD_FAIL  0xf21d0004
+#define F0900_P2_ETAPE1A_DVBXMEM  0xf21d0003
+
+/*P2_DMDCFG3*/
+#define R0900_P2_DMDCFG3  0xf21e
+#define F0900_P2_DVBS1_TMGWAIT  0xf21e0080
+#define F0900_P2_NO_BWCENTERING  0xf21e0040
+#define F0900_P2_INV_SEQSRCH  0xf21e0020
+#define F0900_P2_DIS_SFRUPLOW_TRK  0xf21e0010
+#define F0900_P2_NOSTOP_FIFOFULL  0xf21e0008
+#define F0900_P2_LOCKTIME_MODE  0xf21e0007
+
+/*P2_DMDCFG4*/
+#define R0900_P2_DMDCFG4  0xf21f
+#define F0900_P2_TUNER_NRELAUNCH  0xf21f0008
+#define F0900_P2_DIS_CLKENABLE  0xf21f0004
+#define F0900_P2_DIS_HDRDIVLOCK  0xf21f0002
+#define F0900_P2_NO_TNRWBINIT  0xf21f0001
+
+/*P2_CORRELMANT*/
+#define R0900_P2_CORRELMANT  0xf220
+#define F0900_P2_CORREL_MANT  0xf22000ff
+
+/*P2_CORRELABS*/
+#define R0900_P2_CORRELABS  0xf221
+#define F0900_P2_CORREL_ABS  0xf22100ff
+
+/*P2_CORRELEXP*/
+#define R0900_P2_CORRELEXP  0xf222
+#define F0900_P2_CORREL_ABSEXP  0xf22200f0
+#define F0900_P2_CORREL_EXP  0xf222000f
+
+/*P2_PLHMODCOD*/
+#define R0900_P2_PLHMODCOD  0xf224
+#define F0900_P2_SPECINV_DEMOD  0xf2240080
+#define F0900_P2_PLH_MODCOD  0xf224007c
+#define F0900_P2_PLH_TYPE  0xf2240003
+
+/*P2_AGCK32*/
+#define R0900_P2_AGCK32  0xf22b
+#define F0900_P2_R3ADJOFF_32APSK  0xf22b0080
+#define F0900_P2_R2ADJOFF_32APSK  0xf22b0040
+#define F0900_P2_R1ADJOFF_32APSK  0xf22b0020
+#define F0900_P2_RADJ_32APSK  0xf22b001f
+
+/*P2_AGC2O*/
+#define R0900_P2_AGC2O  0xf22c
+#define F0900_P2_AGC2REF_ADJUSTING  0xf22c0080
+#define F0900_P2_AGC2_COARSEFAST  0xf22c0040
+#define F0900_P2_AGC2_LKSQRT  0xf22c0020
+#define F0900_P2_AGC2_LKMODE  0xf22c0010
+#define F0900_P2_AGC2_LKEQUA  0xf22c0008
+#define F0900_P2_AGC2_COEF  0xf22c0007
+
+/*P2_AGC2REF*/
+#define R0900_P2_AGC2REF  0xf22d
+#define F0900_P2_AGC2_REF  0xf22d00ff
+
+/*P2_AGC1ADJ*/
+#define R0900_P2_AGC1ADJ  0xf22e
+#define F0900_P2_AGC1ADJ_MANUAL  0xf22e0080
+#define F0900_P2_AGC1_ADJUSTED  0xf22e017f
+
+/*P2_AGC2I1*/
+#define R0900_P2_AGC2I1  0xf236
+#define F0900_P2_AGC2_INTEGRATOR1  0xf23600ff
+
+/*P2_AGC2I0*/
+#define R0900_P2_AGC2I0  0xf237
+#define F0900_P2_AGC2_INTEGRATOR0  0xf23700ff
+
+/*P2_CARCFG*/
+#define R0900_P2_CARCFG  0xf238
+#define F0900_P2_CFRUPLOW_AUTO  0xf2380080
+#define F0900_P2_CFRUPLOW_TEST  0xf2380040
+#define F0900_P2_EN_CAR2CENTER  0xf2380020
+#define F0900_P2_CARHDR_NODIV8  0xf2380010
+#define F0900_P2_I2C_ROTA  0xf2380008
+#define F0900_P2_ROTAON  0xf2380004
+#define F0900_P2_PH_DET_ALGO  0xf2380003
+
+/*P2_ACLC*/
+#define R0900_P2_ACLC  0xf239
+#define F0900_P2_STOP_S2ALPHA  0xf23900c0
+#define F0900_P2_CAR_ALPHA_MANT  0xf2390030
+#define F0900_P2_CAR_ALPHA_EXP  0xf239000f
+
+/*P2_BCLC*/
+#define R0900_P2_BCLC  0xf23a
+#define F0900_P2_STOP_S2BETA  0xf23a00c0
+#define F0900_P2_CAR_BETA_MANT  0xf23a0030
+#define F0900_P2_CAR_BETA_EXP  0xf23a000f
+
+/*P2_CARFREQ*/
+#define R0900_P2_CARFREQ  0xf23d
+#define F0900_P2_KC_COARSE_EXP  0xf23d00f0
+#define F0900_P2_BETA_FREQ  0xf23d000f
+
+/*P2_CARHDR*/
+#define R0900_P2_CARHDR  0xf23e
+#define F0900_P2_K_FREQ_HDR  0xf23e00ff
+
+/*P2_LDT*/
+#define R0900_P2_LDT  0xf23f
+#define F0900_P2_CARLOCK_THRES  0xf23f01ff
+
+/*P2_LDT2*/
+#define R0900_P2_LDT2  0xf240
+#define F0900_P2_CARLOCK_THRES2  0xf24001ff
+
+/*P2_CFRICFG*/
+#define R0900_P2_CFRICFG  0xf241
+#define F0900_P2_CFRINIT_UNVALRNG  0xf2410080
+#define F0900_P2_CFRINIT_LUNVALCPT  0xf2410040
+#define F0900_P2_CFRINIT_ABORTDBL  0xf2410020
+#define F0900_P2_CFRINIT_ABORTPRED  0xf2410010
+#define F0900_P2_CFRINIT_UNVALSKIP  0xf2410008
+#define F0900_P2_CFRINIT_CSTINC  0xf2410004
+#define F0900_P2_NEG_CFRSTEP  0xf2410001
+
+/*P2_CFRUP1*/
+#define R0900_P2_CFRUP1  0xf242
+#define F0900_P2_CFR_UP1  0xf24201ff
+
+/*P2_CFRUP0*/
+#define R0900_P2_CFRUP0  0xf243
+#define F0900_P2_CFR_UP0  0xf24300ff
+
+/*P2_CFRLOW1*/
+#define R0900_P2_CFRLOW1  0xf246
+#define F0900_P2_CFR_LOW1  0xf24601ff
+
+/*P2_CFRLOW0*/
+#define R0900_P2_CFRLOW0  0xf247
+#define F0900_P2_CFR_LOW0  0xf24700ff
+
+/*P2_CFRINIT1*/
+#define R0900_P2_CFRINIT1  0xf248
+#define F0900_P2_CFR_INIT1  0xf24801ff
+
+/*P2_CFRINIT0*/
+#define R0900_P2_CFRINIT0  0xf249
+#define F0900_P2_CFR_INIT0  0xf24900ff
+
+/*P2_CFRINC1*/
+#define R0900_P2_CFRINC1  0xf24a
+#define F0900_P2_MANUAL_CFRINC  0xf24a0080
+#define F0900_P2_CFR_INC1  0xf24a017f
+
+/*P2_CFRINC0*/
+#define R0900_P2_CFRINC0  0xf24b
+#define F0900_P2_CFR_INC0  0xf24b00f0
+
+/*P2_CFR2*/
+#define R0900_P2_CFR2  0xf24c
+#define F0900_P2_CAR_FREQ2  0xf24c01ff
+
+/*P2_CFR1*/
+#define R0900_P2_CFR1  0xf24d
+#define F0900_P2_CAR_FREQ1  0xf24d00ff
+
+/*P2_CFR0*/
+#define R0900_P2_CFR0  0xf24e
+#define F0900_P2_CAR_FREQ0  0xf24e00ff
+
+/*P2_LDI*/
+#define R0900_P2_LDI  0xf24f
+#define F0900_P2_LOCK_DET_INTEGR  0xf24f01ff
+
+/*P2_TMGCFG*/
+#define R0900_P2_TMGCFG  0xf250
+#define F0900_P2_TMGLOCK_BETA  0xf25000c0
+#define F0900_P2_NOTMG_GROUPDELAY  0xf2500020
+#define F0900_P2_DO_TIMING_CORR  0xf2500010
+#define F0900_P2_MANUAL_SCAN  0xf250000c
+#define F0900_P2_TMG_MINFREQ  0xf2500003
+
+/*P2_RTC*/
+#define R0900_P2_RTC  0xf251
+#define F0900_P2_TMGALPHA_EXP  0xf25100f0
+#define F0900_P2_TMGBETA_EXP  0xf251000f
+
+/*P2_RTCS2*/
+#define R0900_P2_RTCS2  0xf252
+#define F0900_P2_TMGALPHAS2_EXP  0xf25200f0
+#define F0900_P2_TMGBETAS2_EXP  0xf252000f
+
+/*P2_TMGTHRISE*/
+#define R0900_P2_TMGTHRISE  0xf253
+#define F0900_P2_TMGLOCK_THRISE  0xf25300ff
+
+/*P2_TMGTHFALL*/
+#define R0900_P2_TMGTHFALL  0xf254
+#define F0900_P2_TMGLOCK_THFALL  0xf25400ff
+
+/*P2_SFRUPRATIO*/
+#define R0900_P2_SFRUPRATIO  0xf255
+#define F0900_P2_SFR_UPRATIO  0xf25500ff
+
+/*P2_SFRLOWRATIO*/
+#define R0900_P2_SFRLOWRATIO  0xf256
+#define F0900_P2_SFR_LOWRATIO  0xf25600ff
+
+/*P2_KREFTMG*/
+#define R0900_P2_KREFTMG  0xf258
+#define F0900_P2_KREF_TMG  0xf25800ff
+
+/*P2_SFRSTEP*/
+#define R0900_P2_SFRSTEP  0xf259
+#define F0900_P2_SFR_SCANSTEP  0xf25900f0
+#define F0900_P2_SFR_CENTERSTEP  0xf259000f
+
+/*P2_TMGCFG2*/
+#define R0900_P2_TMGCFG2  0xf25a
+#define F0900_P2_DIS_AUTOSAMP  0xf25a0008
+#define F0900_P2_SCANINIT_QUART  0xf25a0004
+#define F0900_P2_NOTMG_DVBS1DERAT  0xf25a0002
+#define F0900_P2_SFRRATIO_FINE  0xf25a0001
+
+/*P2_SFRINIT1*/
+#define R0900_P2_SFRINIT1  0xf25e
+#define F0900_P2_SFR_INIT1  0xf25e00ff
+
+/*P2_SFRINIT0*/
+#define R0900_P2_SFRINIT0  0xf25f
+#define F0900_P2_SFR_INIT0  0xf25f00ff
+
+/*P2_SFRUP1*/
+#define R0900_P2_SFRUP1  0xf260
+#define F0900_P2_AUTO_GUP  0xf2600080
+#define F0900_P2_SYMB_FREQ_UP1  0xf260007f
+
+/*P2_SFRUP0*/
+#define R0900_P2_SFRUP0  0xf261
+#define F0900_P2_SYMB_FREQ_UP0  0xf26100ff
+
+/*P2_SFRLOW1*/
+#define R0900_P2_SFRLOW1  0xf262
+#define F0900_P2_AUTO_GLOW  0xf2620080
+#define F0900_P2_SYMB_FREQ_LOW1  0xf262007f
+
+/*P2_SFRLOW0*/
+#define R0900_P2_SFRLOW0  0xf263
+#define F0900_P2_SYMB_FREQ_LOW0  0xf26300ff
+
+/*P2_SFR3*/
+#define R0900_P2_SFR3  0xf264
+#define F0900_P2_SYMB_FREQ3  0xf26400ff
+
+/*P2_SFR2*/
+#define R0900_P2_SFR2  0xf265
+#define F0900_P2_SYMB_FREQ2  0xf26500ff
+
+/*P2_SFR1*/
+#define R0900_P2_SFR1  0xf266
+#define F0900_P2_SYMB_FREQ1  0xf26600ff
+
+/*P2_SFR0*/
+#define R0900_P2_SFR0  0xf267
+#define F0900_P2_SYMB_FREQ0  0xf26700ff
+
+/*P2_TMGREG2*/
+#define R0900_P2_TMGREG2  0xf268
+#define F0900_P2_TMGREG2  0xf26800ff
+
+/*P2_TMGREG1*/
+#define R0900_P2_TMGREG1  0xf269
+#define F0900_P2_TMGREG1  0xf26900ff
+
+/*P2_TMGREG0*/
+#define R0900_P2_TMGREG0  0xf26a
+#define F0900_P2_TMGREG0  0xf26a00ff
+
+/*P2_TMGLOCK1*/
+#define R0900_P2_TMGLOCK1  0xf26b
+#define F0900_P2_TMGLOCK_LEVEL1  0xf26b01ff
+
+/*P2_TMGLOCK0*/
+#define R0900_P2_TMGLOCK0  0xf26c
+#define F0900_P2_TMGLOCK_LEVEL0  0xf26c00ff
+
+/*P2_TMGOBS*/
+#define R0900_P2_TMGOBS  0xf26d
+#define F0900_P2_ROLLOFF_STATUS  0xf26d00c0
+#define F0900_P2_SCAN_SIGN  0xf26d0030
+#define F0900_P2_TMG_SCANNING  0xf26d0008
+#define F0900_P2_CHCENTERING_MODE  0xf26d0004
+#define F0900_P2_TMG_SCANFAIL  0xf26d0002
+
+/*P2_EQUALCFG*/
+#define R0900_P2_EQUALCFG  0xf26f
+#define F0900_P2_NOTMG_NEGALWAIT  0xf26f0080
+#define F0900_P2_EQUAL_ON  0xf26f0040
+#define F0900_P2_SEL_EQUALCOR  0xf26f0038
+#define F0900_P2_MU_EQUALDFE  0xf26f0007
+
+/*P2_EQUAI1*/
+#define R0900_P2_EQUAI1  0xf270
+#define F0900_P2_EQUA_ACCI1  0xf27001ff
+
+/*P2_EQUAQ1*/
+#define R0900_P2_EQUAQ1  0xf271
+#define F0900_P2_EQUA_ACCQ1  0xf27101ff
+
+/*P2_EQUAI2*/
+#define R0900_P2_EQUAI2  0xf272
+#define F0900_P2_EQUA_ACCI2  0xf27201ff
+
+/*P2_EQUAQ2*/
+#define R0900_P2_EQUAQ2  0xf273
+#define F0900_P2_EQUA_ACCQ2  0xf27301ff
+
+/*P2_EQUAI3*/
+#define R0900_P2_EQUAI3  0xf274
+#define F0900_P2_EQUA_ACCI3  0xf27401ff
+
+/*P2_EQUAQ3*/
+#define R0900_P2_EQUAQ3  0xf275
+#define F0900_P2_EQUA_ACCQ3  0xf27501ff
+
+/*P2_EQUAI4*/
+#define R0900_P2_EQUAI4  0xf276
+#define F0900_P2_EQUA_ACCI4  0xf27601ff
+
+/*P2_EQUAQ4*/
+#define R0900_P2_EQUAQ4  0xf277
+#define F0900_P2_EQUA_ACCQ4  0xf27701ff
+
+/*P2_EQUAI5*/
+#define R0900_P2_EQUAI5  0xf278
+#define F0900_P2_EQUA_ACCI5  0xf27801ff
+
+/*P2_EQUAQ5*/
+#define R0900_P2_EQUAQ5  0xf279
+#define F0900_P2_EQUA_ACCQ5  0xf27901ff
+
+/*P2_EQUAI6*/
+#define R0900_P2_EQUAI6  0xf27a
+#define F0900_P2_EQUA_ACCI6  0xf27a01ff
+
+/*P2_EQUAQ6*/
+#define R0900_P2_EQUAQ6  0xf27b
+#define F0900_P2_EQUA_ACCQ6  0xf27b01ff
+
+/*P2_EQUAI7*/
+#define R0900_P2_EQUAI7  0xf27c
+#define F0900_P2_EQUA_ACCI7  0xf27c01ff
+
+/*P2_EQUAQ7*/
+#define R0900_P2_EQUAQ7  0xf27d
+#define F0900_P2_EQUA_ACCQ7  0xf27d01ff
+
+/*P2_EQUAI8*/
+#define R0900_P2_EQUAI8  0xf27e
+#define F0900_P2_EQUA_ACCI8  0xf27e01ff
+
+/*P2_EQUAQ8*/
+#define R0900_P2_EQUAQ8  0xf27f
+#define F0900_P2_EQUA_ACCQ8  0xf27f01ff
+
+/*P2_NNOSDATAT1*/
+#define R0900_P2_NNOSDATAT1  0xf280
+#define F0900_P2_NOSDATAT_NORMED1  0xf28000ff
+
+/*P2_NNOSDATAT0*/
+#define R0900_P2_NNOSDATAT0  0xf281
+#define F0900_P2_NOSDATAT_NORMED0  0xf28100ff
+
+/*P2_NNOSDATA1*/
+#define R0900_P2_NNOSDATA1  0xf282
+#define F0900_P2_NOSDATA_NORMED1  0xf28200ff
+
+/*P2_NNOSDATA0*/
+#define R0900_P2_NNOSDATA0  0xf283
+#define F0900_P2_NOSDATA_NORMED0  0xf28300ff
+
+/*P2_NNOSPLHT1*/
+#define R0900_P2_NNOSPLHT1  0xf284
+#define F0900_P2_NOSPLHT_NORMED1  0xf28400ff
+
+/*P2_NNOSPLHT0*/
+#define R0900_P2_NNOSPLHT0  0xf285
+#define F0900_P2_NOSPLHT_NORMED0  0xf28500ff
+
+/*P2_NNOSPLH1*/
+#define R0900_P2_NNOSPLH1  0xf286
+#define F0900_P2_NOSPLH_NORMED1  0xf28600ff
+
+/*P2_NNOSPLH0*/
+#define R0900_P2_NNOSPLH0  0xf287
+#define F0900_P2_NOSPLH_NORMED0  0xf28700ff
+
+/*P2_NOSDATAT1*/
+#define R0900_P2_NOSDATAT1  0xf288
+#define F0900_P2_NOSDATAT_UNNORMED1  0xf28800ff
+
+/*P2_NOSDATAT0*/
+#define R0900_P2_NOSDATAT0  0xf289
+#define F0900_P2_NOSDATAT_UNNORMED0  0xf28900ff
+
+/*P2_NOSDATA1*/
+#define R0900_P2_NOSDATA1  0xf28a
+#define F0900_P2_NOSDATA_UNNORMED1  0xf28a00ff
+
+/*P2_NOSDATA0*/
+#define R0900_P2_NOSDATA0  0xf28b
+#define F0900_P2_NOSDATA_UNNORMED0  0xf28b00ff
+
+/*P2_NOSPLHT1*/
+#define R0900_P2_NOSPLHT1  0xf28c
+#define F0900_P2_NOSPLHT_UNNORMED1  0xf28c00ff
+
+/*P2_NOSPLHT0*/
+#define R0900_P2_NOSPLHT0  0xf28d
+#define F0900_P2_NOSPLHT_UNNORMED0  0xf28d00ff
+
+/*P2_NOSPLH1*/
+#define R0900_P2_NOSPLH1  0xf28e
+#define F0900_P2_NOSPLH_UNNORMED1  0xf28e00ff
+
+/*P2_NOSPLH0*/
+#define R0900_P2_NOSPLH0  0xf28f
+#define F0900_P2_NOSPLH_UNNORMED0  0xf28f00ff
+
+/*P2_CAR2CFG*/
+#define R0900_P2_CAR2CFG  0xf290
+#define F0900_P2_DESCRAMB_OFF  0xf2900080
+#define F0900_P2_PN4_SELECT  0xf2900040
+#define F0900_P2_CFR2_STOPDVBS1  0xf2900020
+#define F0900_P2_STOP_CFR2UPDATE  0xf2900010
+#define F0900_P2_STOP_NCO2UPDATE  0xf2900008
+#define F0900_P2_ROTA2ON  0xf2900004
+#define F0900_P2_PH_DET_ALGO2  0xf2900003
+
+/*P2_ACLC2*/
+#define R0900_P2_ACLC2  0xf291
+#define F0900_P2_CAR2_PUNCT_ADERAT  0xf2910040
+#define F0900_P2_CAR2_ALPHA_MANT  0xf2910030
+#define F0900_P2_CAR2_ALPHA_EXP  0xf291000f
+
+/*P2_BCLC2*/
+#define R0900_P2_BCLC2  0xf292
+#define F0900_P2_DVBS2_NIP  0xf2920080
+#define F0900_P2_CAR2_PUNCT_BDERAT  0xf2920040
+#define F0900_P2_CAR2_BETA_MANT  0xf2920030
+#define F0900_P2_CAR2_BETA_EXP  0xf292000f
+
+/*P2_CFR22*/
+#define R0900_P2_CFR22  0xf293
+#define F0900_P2_CAR2_FREQ2  0xf29301ff
+
+/*P2_CFR21*/
+#define R0900_P2_CFR21  0xf294
+#define F0900_P2_CAR2_FREQ1  0xf29400ff
+
+/*P2_CFR20*/
+#define R0900_P2_CFR20  0xf295
+#define F0900_P2_CAR2_FREQ0  0xf29500ff
+
+/*P2_ACLC2S2Q*/
+#define R0900_P2_ACLC2S2Q  0xf297
+#define F0900_P2_ENAB_SPSKSYMB  0xf2970080
+#define F0900_P2_CAR2S2_QADERAT  0xf2970040
+#define F0900_P2_CAR2S2_Q_ALPH_M  0xf2970030
+#define F0900_P2_CAR2S2_Q_ALPH_E  0xf297000f
+
+/*P2_ACLC2S28*/
+#define R0900_P2_ACLC2S28  0xf298
+#define F0900_P2_OLDI3Q_MODE  0xf2980080
+#define F0900_P2_CAR2S2_8ADERAT  0xf2980040
+#define F0900_P2_CAR2S2_8_ALPH_M  0xf2980030
+#define F0900_P2_CAR2S2_8_ALPH_E  0xf298000f
+
+/*P2_ACLC2S216A*/
+#define R0900_P2_ACLC2S216A  0xf299
+#define F0900_P2_CAR2S2_16ADERAT  0xf2990040
+#define F0900_P2_CAR2S2_16A_ALPH_M  0xf2990030
+#define F0900_P2_CAR2S2_16A_ALPH_E  0xf299000f
+
+/*P2_ACLC2S232A*/
+#define R0900_P2_ACLC2S232A  0xf29a
+#define F0900_P2_CAR2S2_32ADERAT  0xf29a0040
+#define F0900_P2_CAR2S2_32A_ALPH_M  0xf29a0030
+#define F0900_P2_CAR2S2_32A_ALPH_E  0xf29a000f
+
+/*P2_BCLC2S2Q*/
+#define R0900_P2_BCLC2S2Q  0xf29c
+#define F0900_P2_DVBS2S2Q_NIP  0xf29c0080
+#define F0900_P2_CAR2S2_QBDERAT  0xf29c0040
+#define F0900_P2_CAR2S2_Q_BETA_M  0xf29c0030
+#define F0900_P2_CAR2S2_Q_BETA_E  0xf29c000f
+
+/*P2_BCLC2S28*/
+#define R0900_P2_BCLC2S28  0xf29d
+#define F0900_P2_DVBS2S28_NIP  0xf29d0080
+#define F0900_P2_CAR2S2_8BDERAT  0xf29d0040
+#define F0900_P2_CAR2S2_8_BETA_M  0xf29d0030
+#define F0900_P2_CAR2S2_8_BETA_E  0xf29d000f
+
+/*P2_BCLC2S216A*/
+#define R0900_P2_BCLC2S216A  0xf29e
+#define F0900_P2_DVBS2S216A_NIP  0xf29e0080
+#define F0900_P2_CAR2S2_16BDERAT  0xf29e0040
+#define F0900_P2_CAR2S2_16A_BETA_M  0xf29e0030
+#define F0900_P2_CAR2S2_16A_BETA_E  0xf29e000f
+
+/*P2_BCLC2S232A*/
+#define R0900_P2_BCLC2S232A  0xf29f
+#define F0900_P2_DVBS2S232A_NIP  0xf29f0080
+#define F0900_P2_CAR2S2_32BDERAT  0xf29f0040
+#define F0900_P2_CAR2S2_32A_BETA_M  0xf29f0030
+#define F0900_P2_CAR2S2_32A_BETA_E  0xf29f000f
+
+/*P2_PLROOT2*/
+#define R0900_P2_PLROOT2  0xf2ac
+#define F0900_P2_SHORTFR_DISABLE  0xf2ac0080
+#define F0900_P2_LONGFR_DISABLE  0xf2ac0040
+#define F0900_P2_DUMMYPL_DISABLE  0xf2ac0020
+#define F0900_P2_SHORTFR_AVOID  0xf2ac0010
+#define F0900_P2_PLSCRAMB_MODE  0xf2ac000c
+#define F0900_P2_PLSCRAMB_ROOT2  0xf2ac0003
+
+/*P2_PLROOT1*/
+#define R0900_P2_PLROOT1  0xf2ad
+#define F0900_P2_PLSCRAMB_ROOT1  0xf2ad00ff
+
+/*P2_PLROOT0*/
+#define R0900_P2_PLROOT0  0xf2ae
+#define F0900_P2_PLSCRAMB_ROOT0  0xf2ae00ff
+
+/*P2_MODCODLST0*/
+#define R0900_P2_MODCODLST0  0xf2b0
+#define F0900_P2_EN_TOKEN31  0xf2b00080
+#define F0900_P2_SYNCTAG_SELECT  0xf2b00040
+#define F0900_P2_MODCODRQ_MODE  0xf2b00030
+
+/*P2_MODCODLST1*/
+#define R0900_P2_MODCODLST1  0xf2b1
+#define F0900_P2_DIS_MODCOD29  0xf2b100f0
+#define F0900_P2_DIS_32PSK_9_10  0xf2b1000f
+
+/*P2_MODCODLST2*/
+#define R0900_P2_MODCODLST2  0xf2b2
+#define F0900_P2_DIS_32PSK_8_9  0xf2b200f0
+#define F0900_P2_DIS_32PSK_5_6  0xf2b2000f
+
+/*P2_MODCODLST3*/
+#define R0900_P2_MODCODLST3  0xf2b3
+#define F0900_P2_DIS_32PSK_4_5  0xf2b300f0
+#define F0900_P2_DIS_32PSK_3_4  0xf2b3000f
+
+/*P2_MODCODLST4*/
+#define R0900_P2_MODCODLST4  0xf2b4
+#define F0900_P2_DIS_16PSK_9_10  0xf2b400f0
+#define F0900_P2_DIS_16PSK_8_9  0xf2b4000f
+
+/*P2_MODCODLST5*/
+#define R0900_P2_MODCODLST5  0xf2b5
+#define F0900_P2_DIS_16PSK_5_6  0xf2b500f0
+#define F0900_P2_DIS_16PSK_4_5  0xf2b5000f
+
+/*P2_MODCODLST6*/
+#define R0900_P2_MODCODLST6  0xf2b6
+#define F0900_P2_DIS_16PSK_3_4  0xf2b600f0
+#define F0900_P2_DIS_16PSK_2_3  0xf2b6000f
+
+/*P2_MODCODLST7*/
+#define R0900_P2_MODCODLST7  0xf2b7
+#define F0900_P2_DIS_8P_9_10  0xf2b700f0
+#define F0900_P2_DIS_8P_8_9  0xf2b7000f
+
+/*P2_MODCODLST8*/
+#define R0900_P2_MODCODLST8  0xf2b8
+#define F0900_P2_DIS_8P_5_6  0xf2b800f0
+#define F0900_P2_DIS_8P_3_4  0xf2b8000f
+
+/*P2_MODCODLST9*/
+#define R0900_P2_MODCODLST9  0xf2b9
+#define F0900_P2_DIS_8P_2_3  0xf2b900f0
+#define F0900_P2_DIS_8P_3_5  0xf2b9000f
+
+/*P2_MODCODLSTA*/
+#define R0900_P2_MODCODLSTA  0xf2ba
+#define F0900_P2_DIS_QP_9_10  0xf2ba00f0
+#define F0900_P2_DIS_QP_8_9  0xf2ba000f
+
+/*P2_MODCODLSTB*/
+#define R0900_P2_MODCODLSTB  0xf2bb
+#define F0900_P2_DIS_QP_5_6  0xf2bb00f0
+#define F0900_P2_DIS_QP_4_5  0xf2bb000f
+
+/*P2_MODCODLSTC*/
+#define R0900_P2_MODCODLSTC  0xf2bc
+#define F0900_P2_DIS_QP_3_4  0xf2bc00f0
+#define F0900_P2_DIS_QP_2_3  0xf2bc000f
+
+/*P2_MODCODLSTD*/
+#define R0900_P2_MODCODLSTD  0xf2bd
+#define F0900_P2_DIS_QP_3_5  0xf2bd00f0
+#define F0900_P2_DIS_QP_1_2  0xf2bd000f
+
+/*P2_MODCODLSTE*/
+#define R0900_P2_MODCODLSTE  0xf2be
+#define F0900_P2_DIS_QP_2_5  0xf2be00f0
+#define F0900_P2_DIS_QP_1_3  0xf2be000f
+
+/*P2_MODCODLSTF*/
+#define R0900_P2_MODCODLSTF  0xf2bf
+#define F0900_P2_DIS_QP_1_4  0xf2bf00f0
+#define F0900_P2_DDEMOD_SET  0xf2bf0002
+#define F0900_P2_DDEMOD_MASK  0xf2bf0001
+
+/*P2_DMDRESCFG*/
+#define R0900_P2_DMDRESCFG  0xf2c6
+#define F0900_P2_DMDRES_RESET  0xf2c60080
+#define F0900_P2_DMDRES_NOISESQR  0xf2c60010
+#define F0900_P2_DMDRES_STRALL  0xf2c60008
+#define F0900_P2_DMDRES_NEWONLY  0xf2c60004
+#define F0900_P2_DMDRES_NOSTORE  0xf2c60002
+#define F0900_P2_DMDRES_AGC2MEM  0xf2c60001
+
+/*P2_DMDRESADR*/
+#define R0900_P2_DMDRESADR  0xf2c7
+#define F0900_P2_SUSP_PREDCANAL  0xf2c70080
+#define F0900_P2_DMDRES_VALIDCFR  0xf2c70040
+#define F0900_P2_DMDRES_MEMFULL  0xf2c70030
+#define F0900_P2_DMDRES_RESNBR  0xf2c7000f
+
+/*P2_DMDRESDATA7*/
+#define R0900_P2_DMDRESDATA7  0xf2c8
+#define F0900_P2_DMDRES_DATA7  0xf2c800ff
+
+/*P2_DMDRESDATA6*/
+#define R0900_P2_DMDRESDATA6  0xf2c9
+#define F0900_P2_DMDRES_DATA6  0xf2c900ff
+
+/*P2_DMDRESDATA5*/
+#define R0900_P2_DMDRESDATA5  0xf2ca
+#define F0900_P2_DMDRES_DATA5  0xf2ca00ff
+
+/*P2_DMDRESDATA4*/
+#define R0900_P2_DMDRESDATA4  0xf2cb
+#define F0900_P2_DMDRES_DATA4  0xf2cb00ff
+
+/*P2_DMDRESDATA3*/
+#define R0900_P2_DMDRESDATA3  0xf2cc
+#define F0900_P2_DMDRES_DATA3  0xf2cc00ff
+
+/*P2_DMDRESDATA2*/
+#define R0900_P2_DMDRESDATA2  0xf2cd
+#define F0900_P2_DMDRES_DATA2  0xf2cd00ff
+
+/*P2_DMDRESDATA1*/
+#define R0900_P2_DMDRESDATA1  0xf2ce
+#define F0900_P2_DMDRES_DATA1  0xf2ce00ff
+
+/*P2_DMDRESDATA0*/
+#define R0900_P2_DMDRESDATA0  0xf2cf
+#define F0900_P2_DMDRES_DATA0  0xf2cf00ff
+
+/*P2_FFEI1*/
+#define R0900_P2_FFEI1  0xf2d0
+#define F0900_P2_FFE_ACCI1  0xf2d001ff
+
+/*P2_FFEQ1*/
+#define R0900_P2_FFEQ1  0xf2d1
+#define F0900_P2_FFE_ACCQ1  0xf2d101ff
+
+/*P2_FFEI2*/
+#define R0900_P2_FFEI2  0xf2d2
+#define F0900_P2_FFE_ACCI2  0xf2d201ff
+
+/*P2_FFEQ2*/
+#define R0900_P2_FFEQ2  0xf2d3
+#define F0900_P2_FFE_ACCQ2  0xf2d301ff
+
+/*P2_FFEI3*/
+#define R0900_P2_FFEI3  0xf2d4
+#define F0900_P2_FFE_ACCI3  0xf2d401ff
+
+/*P2_FFEQ3*/
+#define R0900_P2_FFEQ3  0xf2d5
+#define F0900_P2_FFE_ACCQ3  0xf2d501ff
+
+/*P2_FFEI4*/
+#define R0900_P2_FFEI4  0xf2d6
+#define F0900_P2_FFE_ACCI4  0xf2d601ff
+
+/*P2_FFEQ4*/
+#define R0900_P2_FFEQ4  0xf2d7
+#define F0900_P2_FFE_ACCQ4  0xf2d701ff
+
+/*P2_FFECFG*/
+#define R0900_P2_FFECFG  0xf2d8
+#define F0900_P2_EQUALFFE_ON  0xf2d80040
+#define F0900_P2_EQUAL_USEDSYMB  0xf2d80030
+#define F0900_P2_MU_EQUALFFE  0xf2d80007
+
+/*P2_TNRCFG*/
+#define R0900_P2_TNRCFG  0xf2e0
+#define F0900_P2_TUN_ACKFAIL  0xf2e00080
+#define F0900_P2_TUN_TYPE  0xf2e00070
+#define F0900_P2_TUN_SECSTOP  0xf2e00008
+#define F0900_P2_TUN_VCOSRCH  0xf2e00004
+#define F0900_P2_TUN_MADDRESS  0xf2e00003
+
+/*P2_TNRCFG2*/
+#define R0900_P2_TNRCFG2  0xf2e1
+#define F0900_P2_TUN_IQSWAP  0xf2e10080
+#define F0900_P2_STB6110_STEP2MHZ  0xf2e10040
+#define F0900_P2_STB6120_DBLI2C  0xf2e10020
+#define F0900_P2_DIS_FCCK  0xf2e10010
+#define F0900_P2_DIS_LPEN  0xf2e10008
+#define F0900_P2_DIS_BWCALC  0xf2e10004
+#define F0900_P2_SHORT_WAITSTATES  0xf2e10002
+#define F0900_P2_DIS_2BWAGC1  0xf2e10001
+
+/*P2_TNRXTAL*/
+#define R0900_P2_TNRXTAL  0xf2e4
+#define F0900_P2_TUN_MCLKDECIMAL  0xf2e400e0
+#define F0900_P2_TUN_XTALFREQ  0xf2e4001f
+
+/*P2_TNRSTEPS*/
+#define R0900_P2_TNRSTEPS  0xf2e7
+#define F0900_P2_TUNER_BW1P6  0xf2e70080
+#define F0900_P2_BWINC_OFFSET  0xf2e70070
+#define F0900_P2_SOFTSTEP_RNG  0xf2e70008
+#define F0900_P2_TUN_BWOFFSET  0xf2e70107
+
+/*P2_TNRGAIN*/
+#define R0900_P2_TNRGAIN  0xf2e8
+#define F0900_P2_TUN_KDIVEN  0xf2e800c0
+#define F0900_P2_STB6X00_OCK  0xf2e80030
+#define F0900_P2_TUN_GAIN  0xf2e8000f
+
+/*P2_TNRRF1*/
+#define R0900_P2_TNRRF1  0xf2e9
+#define F0900_P2_TUN_RFFREQ2  0xf2e900ff
+
+/*P2_TNRRF0*/
+#define R0900_P2_TNRRF0  0xf2ea
+#define F0900_P2_TUN_RFFREQ1  0xf2ea00ff
+
+/*P2_TNRBW*/
+#define R0900_P2_TNRBW  0xf2eb
+#define F0900_P2_TUN_RFFREQ0  0xf2eb00c0
+#define F0900_P2_TUN_BW  0xf2eb003f
+
+/*P2_TNRADJ*/
+#define R0900_P2_TNRADJ  0xf2ec
+#define F0900_P2_STB61X0_RCLK  0xf2ec0080
+#define F0900_P2_STB61X0_CALTIME  0xf2ec0040
+#define F0900_P2_STB6X00_DLB  0xf2ec0038
+#define F0900_P2_STB6000_FCL  0xf2ec0007
+
+/*P2_TNRCTL2*/
+#define R0900_P2_TNRCTL2  0xf2ed
+#define F0900_P2_STB61X0_LCP1_RCCKOFF  0xf2ed0080
+#define F0900_P2_STB61X0_LCP0  0xf2ed0040
+#define F0900_P2_STB61X0_XTOUT_RFOUTS  0xf2ed0020
+#define F0900_P2_STB61X0_XTON_MCKDV  0xf2ed0010
+#define F0900_P2_STB61X0_CALOFF_DCOFF  0xf2ed0008
+#define F0900_P2_STB6110_LPT  0xf2ed0004
+#define F0900_P2_STB6110_RX  0xf2ed0002
+#define F0900_P2_STB6110_SYN  0xf2ed0001
+
+/*P2_TNRCFG3*/
+#define R0900_P2_TNRCFG3  0xf2ee
+#define F0900_P2_STB6120_DISCTRL1  0xf2ee0080
+#define F0900_P2_STB6120_INVORDER  0xf2ee0040
+#define F0900_P2_STB6120_ENCTRL6  0xf2ee0020
+#define F0900_P2_TUN_PLLFREQ  0xf2ee001c
+#define F0900_P2_TUN_I2CFREQ_MODE  0xf2ee0003
+
+/*P2_TNRLAUNCH*/
+#define R0900_P2_TNRLAUNCH  0xf2f0
+
+/*P2_TNRLD*/
+#define R0900_P2_TNRLD  0xf2f0
+#define F0900_P2_TUNLD_VCOING  0xf2f00080
+#define F0900_P2_TUN_REG1FAIL  0xf2f00040
+#define F0900_P2_TUN_REG2FAIL  0xf2f00020
+#define F0900_P2_TUN_REG3FAIL  0xf2f00010
+#define F0900_P2_TUN_REG4FAIL  0xf2f00008
+#define F0900_P2_TUN_REG5FAIL  0xf2f00004
+#define F0900_P2_TUN_BWING  0xf2f00002
+#define F0900_P2_TUN_LOCKED  0xf2f00001
+
+/*P2_TNROBSL*/
+#define R0900_P2_TNROBSL  0xf2f6
+#define F0900_P2_TUN_I2CABORTED  0xf2f60080
+#define F0900_P2_TUN_LPEN  0xf2f60040
+#define F0900_P2_TUN_FCCK  0xf2f60020
+#define F0900_P2_TUN_I2CLOCKED  0xf2f60010
+#define F0900_P2_TUN_PROGDONE  0xf2f6000c
+#define F0900_P2_TUN_RFRESTE1  0xf2f60003
+
+/*P2_TNRRESTE*/
+#define R0900_P2_TNRRESTE  0xf2f7
+#define F0900_P2_TUN_RFRESTE0  0xf2f700ff
+
+/*P2_SMAPCOEF7*/
+#define R0900_P2_SMAPCOEF7  0xf300
+#define F0900_P2_DIS_QSCALE  0xf3000080
+#define F0900_P2_SMAPCOEF_Q_LLR12  0xf300017f
+
+/*P2_SMAPCOEF6*/
+#define R0900_P2_SMAPCOEF6  0xf301
+#define F0900_P2_DIS_NEWSCALE  0xf3010008
+#define F0900_P2_ADJ_8PSKLLR1  0xf3010004
+#define F0900_P2_OLD_8PSKLLR1  0xf3010002
+#define F0900_P2_DIS_AB8PSK  0xf3010001
+
+/*P2_SMAPCOEF5*/
+#define R0900_P2_SMAPCOEF5  0xf302
+#define F0900_P2_DIS_8SCALE  0xf3020080
+#define F0900_P2_SMAPCOEF_8P_LLR23  0xf302017f
+
+/*P2_DMDPLHSTAT*/
+#define R0900_P2_DMDPLHSTAT  0xf320
+#define F0900_P2_PLH_STATISTIC  0xf32000ff
+
+/*P2_LOCKTIME3*/
+#define R0900_P2_LOCKTIME3  0xf322
+#define F0900_P2_DEMOD_LOCKTIME3  0xf32200ff
+
+/*P2_LOCKTIME2*/
+#define R0900_P2_LOCKTIME2  0xf323
+#define F0900_P2_DEMOD_LOCKTIME2  0xf32300ff
+
+/*P2_LOCKTIME1*/
+#define R0900_P2_LOCKTIME1  0xf324
+#define F0900_P2_DEMOD_LOCKTIME1  0xf32400ff
+
+/*P2_LOCKTIME0*/
+#define R0900_P2_LOCKTIME0  0xf325
+#define F0900_P2_DEMOD_LOCKTIME0  0xf32500ff
+
+/*P2_VITSCALE*/
+#define R0900_P2_VITSCALE  0xf332
+#define F0900_P2_NVTH_NOSRANGE  0xf3320080
+#define F0900_P2_VERROR_MAXMODE  0xf3320040
+#define F0900_P2_KDIV_MODE  0xf3320030
+#define F0900_P2_NSLOWSN_LOCKED  0xf3320008
+#define F0900_P2_DELOCK_PRFLOSS  0xf3320004
+#define F0900_P2_DIS_RSFLOCK  0xf3320002
+
+/*P2_FECM*/
+#define R0900_P2_FECM  0xf333
+#define F0900_P2_DSS_DVB  0xf3330080
+#define F0900_P2_DEMOD_BYPASS  0xf3330040
+#define F0900_P2_CMP_SLOWMODE  0xf3330020
+#define F0900_P2_DSS_SRCH  0xf3330010
+#define F0900_P2_DIFF_MODEVIT  0xf3330004
+#define F0900_P2_SYNCVIT  0xf3330002
+#define F0900_P2_IQINV  0xf3330001
+
+/*P2_VTH12*/
+#define R0900_P2_VTH12  0xf334
+#define F0900_P2_VTH12  0xf33400ff
+
+/*P2_VTH23*/
+#define R0900_P2_VTH23  0xf335
+#define F0900_P2_VTH23  0xf33500ff
+
+/*P2_VTH34*/
+#define R0900_P2_VTH34  0xf336
+#define F0900_P2_VTH34  0xf33600ff
+
+/*P2_VTH56*/
+#define R0900_P2_VTH56  0xf337
+#define F0900_P2_VTH56  0xf33700ff
+
+/*P2_VTH67*/
+#define R0900_P2_VTH67  0xf338
+#define F0900_P2_VTH67  0xf33800ff
+
+/*P2_VTH78*/
+#define R0900_P2_VTH78  0xf339
+#define F0900_P2_VTH78  0xf33900ff
+
+/*P2_VITCURPUN*/
+#define R0900_P2_VITCURPUN  0xf33a
+#define F0900_P2_VIT_MAPPING  0xf33a00e0
+#define F0900_P2_VIT_CURPUN  0xf33a001f
+
+/*P2_VERROR*/
+#define R0900_P2_VERROR  0xf33b
+#define F0900_P2_REGERR_VIT  0xf33b00ff
+
+/*P2_PRVIT*/
+#define R0900_P2_PRVIT  0xf33c
+#define F0900_P2_DIS_VTHLOCK  0xf33c0040
+#define F0900_P2_E7_8VIT  0xf33c0020
+#define F0900_P2_E6_7VIT  0xf33c0010
+#define F0900_P2_E5_6VIT  0xf33c0008
+#define F0900_P2_E3_4VIT  0xf33c0004
+#define F0900_P2_E2_3VIT  0xf33c0002
+#define F0900_P2_E1_2VIT  0xf33c0001
+
+/*P2_VAVSRVIT*/
+#define R0900_P2_VAVSRVIT  0xf33d
+#define F0900_P2_AMVIT  0xf33d0080
+#define F0900_P2_FROZENVIT  0xf33d0040
+#define F0900_P2_SNVIT  0xf33d0030
+#define F0900_P2_TOVVIT  0xf33d000c
+#define F0900_P2_HYPVIT  0xf33d0003
+
+/*P2_VSTATUSVIT*/
+#define R0900_P2_VSTATUSVIT  0xf33e
+#define F0900_P2_VITERBI_ON  0xf33e0080
+#define F0900_P2_END_LOOPVIT  0xf33e0040
+#define F0900_P2_VITERBI_DEPRF  0xf33e0020
+#define F0900_P2_PRFVIT  0xf33e0010
+#define F0900_P2_LOCKEDVIT  0xf33e0008
+#define F0900_P2_VITERBI_DELOCK  0xf33e0004
+#define F0900_P2_VIT_DEMODSEL  0xf33e0002
+#define F0900_P2_VITERBI_COMPOUT  0xf33e0001
+
+/*P2_VTHINUSE*/
+#define R0900_P2_VTHINUSE  0xf33f
+#define F0900_P2_VIT_INUSE  0xf33f00ff
+
+/*P2_KDIV12*/
+#define R0900_P2_KDIV12  0xf340
+#define F0900_P2_KDIV12_MANUAL  0xf3400080
+#define F0900_P2_K_DIVIDER_12  0xf340007f
+
+/*P2_KDIV23*/
+#define R0900_P2_KDIV23  0xf341
+#define F0900_P2_KDIV23_MANUAL  0xf3410080
+#define F0900_P2_K_DIVIDER_23  0xf341007f
+
+/*P2_KDIV34*/
+#define R0900_P2_KDIV34  0xf342
+#define F0900_P2_KDIV34_MANUAL  0xf3420080
+#define F0900_P2_K_DIVIDER_34  0xf342007f
+
+/*P2_KDIV56*/
+#define R0900_P2_KDIV56  0xf343
+#define F0900_P2_KDIV56_MANUAL  0xf3430080
+#define F0900_P2_K_DIVIDER_56  0xf343007f
+
+/*P2_KDIV67*/
+#define R0900_P2_KDIV67  0xf344
+#define F0900_P2_KDIV67_MANUAL  0xf3440080
+#define F0900_P2_K_DIVIDER_67  0xf344007f
+
+/*P2_KDIV78*/
+#define R0900_P2_KDIV78  0xf345
+#define F0900_P2_KDIV78_MANUAL  0xf3450080
+#define F0900_P2_K_DIVIDER_78  0xf345007f
+
+/*P2_PDELCTRL1*/
+#define R0900_P2_PDELCTRL1  0xf350
+#define F0900_P2_INV_MISMASK  0xf3500080
+#define F0900_P2_FORCE_ACCEPTED  0xf3500040
+#define F0900_P2_FILTER_EN  0xf3500020
+#define F0900_P2_FORCE_PKTDELINUSE  0xf3500010
+#define F0900_P2_HYSTEN  0xf3500008
+#define F0900_P2_HYSTSWRST  0xf3500004
+#define F0900_P2_EN_MIS00  0xf3500002
+#define F0900_P2_ALGOSWRST  0xf3500001
+
+/*P2_PDELCTRL2*/
+#define R0900_P2_PDELCTRL2  0xf351
+#define F0900_P2_FORCE_CONTINUOUS  0xf3510080
+#define F0900_P2_RESET_UPKO_COUNT  0xf3510040
+#define F0900_P2_USER_PKTDELIN_NB  0xf3510020
+#define F0900_P2_FORCE_LOCKED  0xf3510010
+#define F0900_P2_DATA_UNBBSCRAM  0xf3510008
+#define F0900_P2_FORCE_LONGPKT  0xf3510004
+#define F0900_P2_FRAME_MODE  0xf3510002
+
+/*P2_HYSTTHRESH*/
+#define R0900_P2_HYSTTHRESH  0xf354
+#define F0900_P2_UNLCK_THRESH  0xf35400f0
+#define F0900_P2_DELIN_LCK_THRESH  0xf354000f
+
+/*P2_ISIENTRY*/
+#define R0900_P2_ISIENTRY  0xf35e
+#define F0900_P2_ISI_ENTRY  0xf35e00ff
+
+/*P2_ISIBITENA*/
+#define R0900_P2_ISIBITENA  0xf35f
+#define F0900_P2_ISI_BIT_EN  0xf35f00ff
+
+/*P2_MATSTR1*/
+#define R0900_P2_MATSTR1  0xf360
+#define F0900_P2_MATYPE_CURRENT1  0xf36000ff
+
+/*P2_MATSTR0*/
+#define R0900_P2_MATSTR0  0xf361
+#define F0900_P2_MATYPE_CURRENT0  0xf36100ff
+
+/*P2_UPLSTR1*/
+#define R0900_P2_UPLSTR1  0xf362
+#define F0900_P2_UPL_CURRENT1  0xf36200ff
+
+/*P2_UPLSTR0*/
+#define R0900_P2_UPLSTR0  0xf363
+#define F0900_P2_UPL_CURRENT0  0xf36300ff
+
+/*P2_DFLSTR1*/
+#define R0900_P2_DFLSTR1  0xf364
+#define F0900_P2_DFL_CURRENT1  0xf36400ff
+
+/*P2_DFLSTR0*/
+#define R0900_P2_DFLSTR0  0xf365
+#define F0900_P2_DFL_CURRENT0  0xf36500ff
+
+/*P2_SYNCSTR*/
+#define R0900_P2_SYNCSTR  0xf366
+#define F0900_P2_SYNC_CURRENT  0xf36600ff
+
+/*P2_SYNCDSTR1*/
+#define R0900_P2_SYNCDSTR1  0xf367
+#define F0900_P2_SYNCD_CURRENT1  0xf36700ff
+
+/*P2_SYNCDSTR0*/
+#define R0900_P2_SYNCDSTR0  0xf368
+#define F0900_P2_SYNCD_CURRENT0  0xf36800ff
+
+/*P2_PDELSTATUS1*/
+#define R0900_P2_PDELSTATUS1  0xf369
+#define F0900_P2_PKTDELIN_DELOCK  0xf3690080
+#define F0900_P2_SYNCDUPDFL_BADDFL  0xf3690040
+#define F0900_P2_CONTINUOUS_STREAM  0xf3690020
+#define F0900_P2_UNACCEPTED_STREAM  0xf3690010
+#define F0900_P2_BCH_ERROR_FLAG  0xf3690008
+#define F0900_P2_BBHCRCKO  0xf3690004
+#define F0900_P2_PKTDELIN_LOCK  0xf3690002
+#define F0900_P2_FIRST_LOCK  0xf3690001
+
+/*P2_PDELSTATUS2*/
+#define R0900_P2_PDELSTATUS2  0xf36a
+#define F0900_P2_PKTDEL_DEMODSEL  0xf36a0080
+#define F0900_P2_FRAME_MODCOD  0xf36a007c
+#define F0900_P2_FRAME_TYPE  0xf36a0003
+
+/*P2_BBFCRCKO1*/
+#define R0900_P2_BBFCRCKO1  0xf36b
+#define F0900_P2_BBHCRC_KOCNT1  0xf36b00ff
+
+/*P2_BBFCRCKO0*/
+#define R0900_P2_BBFCRCKO0  0xf36c
+#define F0900_P2_BBHCRC_KOCNT0  0xf36c00ff
+
+/*P2_UPCRCKO1*/
+#define R0900_P2_UPCRCKO1  0xf36d
+#define F0900_P2_PKTCRC_KOCNT1  0xf36d00ff
+
+/*P2_UPCRCKO0*/
+#define R0900_P2_UPCRCKO0  0xf36e
+#define F0900_P2_PKTCRC_KOCNT0  0xf36e00ff
+
+/*P2_TSSTATEM*/
+#define R0900_P2_TSSTATEM  0xf370
+#define F0900_P2_TSDIL_ON  0xf3700080
+#define F0900_P2_TSSKIPRS_ON  0xf3700040
+#define F0900_P2_TSRS_ON  0xf3700020
+#define F0900_P2_TSDESCRAMB_ON  0xf3700010
+#define F0900_P2_TSFRAME_MODE  0xf3700008
+#define F0900_P2_TS_DISABLE  0xf3700004
+#define F0900_P2_TSACM_MODE  0xf3700002
+#define F0900_P2_TSOUT_NOSYNC  0xf3700001
+
+/*P2_TSCFGH*/
+#define R0900_P2_TSCFGH  0xf372
+#define F0900_P2_TSFIFO_DVBCI  0xf3720080
+#define F0900_P2_TSFIFO_SERIAL  0xf3720040
+#define F0900_P2_TSFIFO_TEIUPDATE  0xf3720020
+#define F0900_P2_TSFIFO_DUTY50  0xf3720010
+#define F0900_P2_TSFIFO_HSGNLOUT  0xf3720008
+#define F0900_P2_TSFIFO_ERRMODE  0xf3720006
+#define F0900_P2_RST_HWARE  0xf3720001
+
+/*P2_TSCFGM*/
+#define R0900_P2_TSCFGM  0xf373
+#define F0900_P2_TSFIFO_MANSPEED  0xf37300c0
+#define F0900_P2_TSFIFO_PERMDATA  0xf3730020
+#define F0900_P2_TSFIFO_NONEWSGNL  0xf3730010
+#define F0900_P2_TSFIFO_BITSPEED  0xf3730008
+#define F0900_P2_NPD_SPECDVBS2  0xf3730004
+#define F0900_P2_TSFIFO_STOPCKDIS  0xf3730002
+#define F0900_P2_TSFIFO_INVDATA  0xf3730001
+
+/*P2_TSCFGL*/
+#define R0900_P2_TSCFGL  0xf374
+#define F0900_P2_TSFIFO_BCLKDEL1CK  0xf37400c0
+#define F0900_P2_BCHERROR_MODE  0xf3740030
+#define F0900_P2_TSFIFO_NSGNL2DATA  0xf3740008
+#define F0900_P2_TSFIFO_EMBINDVB  0xf3740004
+#define F0900_P2_TSFIFO_DPUNACT  0xf3740002
+#define F0900_P2_TSFIFO_NPDOFF  0xf3740001
+
+/*P2_TSINSDELH*/
+#define R0900_P2_TSINSDELH  0xf376
+#define F0900_P2_TSDEL_SYNCBYTE  0xf3760080
+#define F0900_P2_TSDEL_XXHEADER  0xf3760040
+#define F0900_P2_TSDEL_BBHEADER  0xf3760020
+#define F0900_P2_TSDEL_DATAFIELD  0xf3760010
+#define F0900_P2_TSINSDEL_ISCR  0xf3760008
+#define F0900_P2_TSINSDEL_NPD  0xf3760004
+#define F0900_P2_TSINSDEL_RSPARITY  0xf3760002
+#define F0900_P2_TSINSDEL_CRC8  0xf3760001
+
+/*P2_TSSPEED*/
+#define R0900_P2_TSSPEED  0xf380
+#define F0900_P2_TSFIFO_OUTSPEED  0xf38000ff
+
+/*P2_TSSTATUS*/
+#define R0900_P2_TSSTATUS  0xf381
+#define F0900_P2_TSFIFO_LINEOK  0xf3810080
+#define F0900_P2_TSFIFO_ERROR  0xf3810040
+#define F0900_P2_TSFIFO_DATA7  0xf3810020
+#define F0900_P2_TSFIFO_NOSYNC  0xf3810010
+#define F0900_P2_ISCR_INITIALIZED  0xf3810008
+#define F0900_P2_ISCR_UPDATED  0xf3810004
+#define F0900_P2_SOFFIFO_UNREGUL  0xf3810002
+#define F0900_P2_DIL_READY  0xf3810001
+
+/*P2_TSSTATUS2*/
+#define R0900_P2_TSSTATUS2  0xf382
+#define F0900_P2_TSFIFO_DEMODSEL  0xf3820080
+#define F0900_P2_TSFIFOSPEED_STORE  0xf3820040
+#define F0900_P2_DILXX_RESET  0xf3820020
+#define F0900_P2_TSSERIAL_IMPOS  0xf3820010
+#define F0900_P2_TSFIFO_LINENOK  0xf3820008
+#define F0900_P2_BITSPEED_EVENT  0xf3820004
+#define F0900_P2_SCRAMBDETECT  0xf3820002
+#define F0900_P2_ULDTV67_FALSELOCK  0xf3820001
+
+/*P2_TSBITRATE1*/
+#define R0900_P2_TSBITRATE1  0xf383
+#define F0900_P2_TSFIFO_BITRATE1  0xf38300ff
+
+/*P2_TSBITRATE0*/
+#define R0900_P2_TSBITRATE0  0xf384
+#define F0900_P2_TSFIFO_BITRATE0  0xf38400ff
+
+/*P2_ERRCTRL1*/
+#define R0900_P2_ERRCTRL1  0xf398
+#define F0900_P2_ERR_SOURCE1  0xf39800f0
+#define F0900_P2_NUM_EVENT1  0xf3980007
+
+/*P2_ERRCNT12*/
+#define R0900_P2_ERRCNT12  0xf399
+#define F0900_P2_ERRCNT1_OLDVALUE  0xf3990080
+#define F0900_P2_ERR_CNT12  0xf399007f
+
+/*P2_ERRCNT11*/
+#define R0900_P2_ERRCNT11  0xf39a
+#define F0900_P2_ERR_CNT11  0xf39a00ff
+
+/*P2_ERRCNT10*/
+#define R0900_P2_ERRCNT10  0xf39b
+#define F0900_P2_ERR_CNT10  0xf39b00ff
+
+/*P2_ERRCTRL2*/
+#define R0900_P2_ERRCTRL2  0xf39c
+#define F0900_P2_ERR_SOURCE2  0xf39c00f0
+#define F0900_P2_NUM_EVENT2  0xf39c0007
+
+/*P2_ERRCNT22*/
+#define R0900_P2_ERRCNT22  0xf39d
+#define F0900_P2_ERRCNT2_OLDVALUE  0xf39d0080
+#define F0900_P2_ERR_CNT22  0xf39d007f
+
+/*P2_ERRCNT21*/
+#define R0900_P2_ERRCNT21  0xf39e
+#define F0900_P2_ERR_CNT21  0xf39e00ff
+
+/*P2_ERRCNT20*/
+#define R0900_P2_ERRCNT20  0xf39f
+#define F0900_P2_ERR_CNT20  0xf39f00ff
+
+/*P2_FECSPY*/
+#define R0900_P2_FECSPY  0xf3a0
+#define F0900_P2_SPY_ENABLE  0xf3a00080
+#define F0900_P2_NO_SYNCBYTE  0xf3a00040
+#define F0900_P2_SERIAL_MODE  0xf3a00020
+#define F0900_P2_UNUSUAL_PACKET  0xf3a00010
+#define F0900_P2_BER_PACKMODE  0xf3a00008
+#define F0900_P2_BERMETER_LMODE  0xf3a00002
+#define F0900_P2_BERMETER_RESET  0xf3a00001
+
+/*P2_FSPYCFG*/
+#define R0900_P2_FSPYCFG  0xf3a1
+#define F0900_P2_FECSPY_INPUT  0xf3a100c0
+#define F0900_P2_RST_ON_ERROR  0xf3a10020
+#define F0900_P2_ONE_SHOT  0xf3a10010
+#define F0900_P2_I2C_MODE  0xf3a1000c
+#define F0900_P2_SPY_HYSTERESIS  0xf3a10003
+
+/*P2_FSPYDATA*/
+#define R0900_P2_FSPYDATA  0xf3a2
+#define F0900_P2_SPY_STUFFING  0xf3a20080
+#define F0900_P2_NOERROR_PKTJITTER  0xf3a20040
+#define F0900_P2_SPY_CNULLPKT  0xf3a20020
+#define F0900_P2_SPY_OUTDATA_MODE  0xf3a2001f
+
+/*P2_FSPYOUT*/
+#define R0900_P2_FSPYOUT  0xf3a3
+#define F0900_P2_FSPY_DIRECT  0xf3a30080
+#define F0900_P2_SPY_OUTDATA_BUS  0xf3a30038
+#define F0900_P2_STUFF_MODE  0xf3a30007
+
+/*P2_FSTATUS*/
+#define R0900_P2_FSTATUS  0xf3a4
+#define F0900_P2_SPY_ENDSIM  0xf3a40080
+#define F0900_P2_VALID_SIM  0xf3a40040
+#define F0900_P2_FOUND_SIGNAL  0xf3a40020
+#define F0900_P2_DSS_SYNCBYTE  0xf3a40010
+#define F0900_P2_RESULT_STATE  0xf3a4000f
+
+/*P2_FBERCPT4*/
+#define R0900_P2_FBERCPT4  0xf3a8
+#define F0900_P2_FBERMETER_CPT4  0xf3a800ff
+
+/*P2_FBERCPT3*/
+#define R0900_P2_FBERCPT3  0xf3a9
+#define F0900_P2_FBERMETER_CPT3  0xf3a900ff
+
+/*P2_FBERCPT2*/
+#define R0900_P2_FBERCPT2  0xf3aa
+#define F0900_P2_FBERMETER_CPT2  0xf3aa00ff
+
+/*P2_FBERCPT1*/
+#define R0900_P2_FBERCPT1  0xf3ab
+#define F0900_P2_FBERMETER_CPT1  0xf3ab00ff
+
+/*P2_FBERCPT0*/
+#define R0900_P2_FBERCPT0  0xf3ac
+#define F0900_P2_FBERMETER_CPT0  0xf3ac00ff
+
+/*P2_FBERERR2*/
+#define R0900_P2_FBERERR2  0xf3ad
+#define F0900_P2_FBERMETER_ERR2  0xf3ad00ff
+
+/*P2_FBERERR1*/
+#define R0900_P2_FBERERR1  0xf3ae
+#define F0900_P2_FBERMETER_ERR1  0xf3ae00ff
+
+/*P2_FBERERR0*/
+#define R0900_P2_FBERERR0  0xf3af
+#define F0900_P2_FBERMETER_ERR0  0xf3af00ff
+
+/*P2_FSPYBER*/
+#define R0900_P2_FSPYBER  0xf3b2
+#define F0900_P2_FSPYOBS_XORREAD  0xf3b20040
+#define F0900_P2_FSPYBER_OBSMODE  0xf3b20020
+#define F0900_P2_FSPYBER_SYNCBYTE  0xf3b20010
+#define F0900_P2_FSPYBER_UNSYNC  0xf3b20008
+#define F0900_P2_FSPYBER_CTIME  0xf3b20007
+
+/*P1_IQCONST*/
+#define R0900_P1_IQCONST  0xf400
+#define F0900_P1_CONSTEL_SELECT  0xf4000060
+#define F0900_P1_IQSYMB_SEL  0xf400001f
+
+/*P1_NOSCFG*/
+#define R0900_P1_NOSCFG  0xf401
+#define F0900_P1_DUMMYPL_NOSDATA  0xf4010020
+#define F0900_P1_NOSPLH_BETA  0xf4010018
+#define F0900_P1_NOSDATA_BETA  0xf4010007
+
+/*P1_ISYMB*/
+#define R0900_P1_ISYMB  0xf402
+#define F0900_P1_I_SYMBOL  0xf40201ff
+
+/*P1_QSYMB*/
+#define R0900_P1_QSYMB  0xf403
+#define F0900_P1_Q_SYMBOL  0xf40301ff
+
+/*P1_AGC1CFG*/
+#define R0900_P1_AGC1CFG  0xf404
+#define F0900_P1_DC_FROZEN  0xf4040080
+#define F0900_P1_DC_CORRECT  0xf4040040
+#define F0900_P1_AMM_FROZEN  0xf4040020
+#define F0900_P1_AMM_CORRECT  0xf4040010
+#define F0900_P1_QUAD_FROZEN  0xf4040008
+#define F0900_P1_QUAD_CORRECT  0xf4040004
+#define F0900_P1_DCCOMP_SLOW  0xf4040002
+#define F0900_P1_IQMISM_SLOW  0xf4040001
+
+/*P1_AGC1CN*/
+#define R0900_P1_AGC1CN  0xf406
+#define F0900_P1_AGC1_LOCKED  0xf4060080
+#define F0900_P1_AGC1_OVERFLOW  0xf4060040
+#define F0900_P1_AGC1_NOSLOWLK  0xf4060020
+#define F0900_P1_AGC1_MINPOWER  0xf4060010
+#define F0900_P1_AGCOUT_FAST  0xf4060008
+#define F0900_P1_AGCIQ_BETA  0xf4060007
+
+/*P1_AGC1REF*/
+#define R0900_P1_AGC1REF  0xf407
+#define F0900_P1_AGCIQ_REF  0xf40700ff
+
+/*P1_IDCCOMP*/
+#define R0900_P1_IDCCOMP  0xf408
+#define F0900_P1_IAVERAGE_ADJ  0xf40801ff
+
+/*P1_QDCCOMP*/
+#define R0900_P1_QDCCOMP  0xf409
+#define F0900_P1_QAVERAGE_ADJ  0xf40901ff
+
+/*P1_POWERI*/
+#define R0900_P1_POWERI  0xf40a
+#define F0900_P1_POWER_I  0xf40a00ff
+
+/*P1_POWERQ*/
+#define R0900_P1_POWERQ  0xf40b
+#define F0900_P1_POWER_Q  0xf40b00ff
+
+/*P1_AGC1AMM*/
+#define R0900_P1_AGC1AMM  0xf40c
+#define F0900_P1_AMM_VALUE  0xf40c00ff
+
+/*P1_AGC1QUAD*/
+#define R0900_P1_AGC1QUAD  0xf40d
+#define F0900_P1_QUAD_VALUE  0xf40d01ff
+
+/*P1_AGCIQIN1*/
+#define R0900_P1_AGCIQIN1  0xf40e
+#define F0900_P1_AGCIQ_VALUE1  0xf40e00ff
+
+/*P1_AGCIQIN0*/
+#define R0900_P1_AGCIQIN0  0xf40f
+#define F0900_P1_AGCIQ_VALUE0  0xf40f00ff
+
+/*P1_DEMOD*/
+#define R0900_P1_DEMOD  0xf410
+#define F0900_P1_DEMOD_STOP  0xf4100040
+#define F0900_P1_SPECINV_CONTROL  0xf4100030
+#define F0900_P1_FORCE_ENASAMP  0xf4100008
+#define F0900_P1_MANUAL_ROLLOFF  0xf4100004
+#define F0900_P1_ROLLOFF_CONTROL  0xf4100003
+
+/*P1_DMDMODCOD*/
+#define R0900_P1_DMDMODCOD  0xf411
+#define F0900_P1_MANUAL_MODCOD  0xf4110080
+#define F0900_P1_DEMOD_MODCOD  0xf411007c
+#define F0900_P1_DEMOD_TYPE  0xf4110003
+
+/*P1_DSTATUS*/
+#define R0900_P1_DSTATUS  0xf412
+#define F0900_P1_CAR_LOCK  0xf4120080
+#define F0900_P1_TMGLOCK_QUALITY  0xf4120060
+#define F0900_P1_SDVBS1_ENABLE  0xf4120010
+#define F0900_P1_LOCK_DEFINITIF  0xf4120008
+#define F0900_P1_TIMING_IS_LOCKED  0xf4120004
+#define F0900_P1_COARSE_TMGLOCK  0xf4120002
+#define F0900_P1_COARSE_CARLOCK  0xf4120001
+
+/*P1_DSTATUS2*/
+#define R0900_P1_DSTATUS2  0xf413
+#define F0900_P1_DEMOD_DELOCK  0xf4130080
+#define F0900_P1_DEMOD_TIMEOUT  0xf4130040
+#define F0900_P1_MODCODRQ_SYNCTAG  0xf4130020
+#define F0900_P1_POLYPH_SATEVENT  0xf4130010
+#define F0900_P1_AGC1_NOSIGNALACK  0xf4130008
+#define F0900_P1_AGC2_OVERFLOW  0xf4130004
+#define F0900_P1_CFR_OVERFLOW  0xf4130002
+#define F0900_P1_GAMMA_OVERUNDER  0xf4130001
+
+/*P1_DMDCFGMD*/
+#define R0900_P1_DMDCFGMD  0xf414
+#define F0900_P1_DVBS2_ENABLE  0xf4140080
+#define F0900_P1_DVBS1_ENABLE  0xf4140040
+#define F0900_P1_CFR_AUTOSCAN  0xf4140020
+#define F0900_P1_SCAN_ENABLE  0xf4140010
+#define F0900_P1_TUN_AUTOSCAN  0xf4140008
+#define F0900_P1_NOFORCE_RELOCK  0xf4140004
+#define F0900_P1_TUN_RNG  0xf4140003
+
+/*P1_DMDCFG2*/
+#define R0900_P1_DMDCFG2  0xf415
+#define F0900_P1_AGC1_WAITLOCK  0xf4150080
+#define F0900_P1_S1S2_SEQUENTIAL  0xf4150040
+#define F0900_P1_OVERFLOW_TIMEOUT  0xf4150020
+#define F0900_P1_SCANFAIL_TIMEOUT  0xf4150010
+#define F0900_P1_DMDTOUT_BACK  0xf4150008
+#define F0900_P1_CARLOCK_S1ENABLE  0xf4150004
+#define F0900_P1_COARSE_LK3MODE  0xf4150002
+#define F0900_P1_COARSE_LK2MODE  0xf4150001
+
+/*P1_DMDISTATE*/
+#define R0900_P1_DMDISTATE  0xf416
+#define F0900_P1_I2C_NORESETDMODE  0xf4160080
+#define F0900_P1_FORCE_ETAPED  0xf4160040
+#define F0900_P1_SDMDRST_DIRCLK  0xf4160020
+#define F0900_P1_I2C_DEMOD_MODE  0xf416001f
+
+/*P1_DMDT0M*/
+#define R0900_P1_DMDT0M  0xf417
+#define F0900_P1_DMDT0_MIN  0xf41700ff
+
+/*P1_DMDSTATE*/
+#define R0900_P1_DMDSTATE  0xf41b
+#define F0900_P1_DEMOD_LOCKED  0xf41b0080
+#define F0900_P1_HEADER_MODE  0xf41b0060
+#define F0900_P1_DEMOD_MODE  0xf41b001f
+
+/*P1_DMDFLYW*/
+#define R0900_P1_DMDFLYW  0xf41c
+#define F0900_P1_I2C_IRQVAL  0xf41c00f0
+#define F0900_P1_FLYWHEEL_CPT  0xf41c000f
+
+/*P1_DSTATUS3*/
+#define R0900_P1_DSTATUS3  0xf41d
+#define F0900_P1_CFR_ZIGZAG  0xf41d0080
+#define F0900_P1_DEMOD_CFGMODE  0xf41d0060
+#define F0900_P1_GAMMA_LOWBAUDRATE  0xf41d0010
+#define F0900_P1_RELOCK_MODE  0xf41d0008
+#define F0900_P1_DEMOD_FAIL  0xf41d0004
+#define F0900_P1_ETAPE1A_DVBXMEM  0xf41d0003
+
+/*P1_DMDCFG3*/
+#define R0900_P1_DMDCFG3  0xf41e
+#define F0900_P1_DVBS1_TMGWAIT  0xf41e0080
+#define F0900_P1_NO_BWCENTERING  0xf41e0040
+#define F0900_P1_INV_SEQSRCH  0xf41e0020
+#define F0900_P1_DIS_SFRUPLOW_TRK  0xf41e0010
+#define F0900_P1_NOSTOP_FIFOFULL  0xf41e0008
+#define F0900_P1_LOCKTIME_MODE  0xf41e0007
+
+/*P1_DMDCFG4*/
+#define R0900_P1_DMDCFG4  0xf41f
+#define F0900_P1_TUNER_NRELAUNCH  0xf41f0008
+#define F0900_P1_DIS_CLKENABLE  0xf41f0004
+#define F0900_P1_DIS_HDRDIVLOCK  0xf41f0002
+#define F0900_P1_NO_TNRWBINIT  0xf41f0001
+
+/*P1_CORRELMANT*/
+#define R0900_P1_CORRELMANT  0xf420
+#define F0900_P1_CORREL_MANT  0xf42000ff
+
+/*P1_CORRELABS*/
+#define R0900_P1_CORRELABS  0xf421
+#define F0900_P1_CORREL_ABS  0xf42100ff
+
+/*P1_CORRELEXP*/
+#define R0900_P1_CORRELEXP  0xf422
+#define F0900_P1_CORREL_ABSEXP  0xf42200f0
+#define F0900_P1_CORREL_EXP  0xf422000f
+
+/*P1_PLHMODCOD*/
+#define R0900_P1_PLHMODCOD  0xf424
+#define F0900_P1_SPECINV_DEMOD  0xf4240080
+#define F0900_P1_PLH_MODCOD  0xf424007c
+#define F0900_P1_PLH_TYPE  0xf4240003
+
+/*P1_AGCK32*/
+#define R0900_P1_AGCK32  0xf42b
+#define F0900_P1_R3ADJOFF_32APSK  0xf42b0080
+#define F0900_P1_R2ADJOFF_32APSK  0xf42b0040
+#define F0900_P1_R1ADJOFF_32APSK  0xf42b0020
+#define F0900_P1_RADJ_32APSK  0xf42b001f
+
+/*P1_AGC2O*/
+#define R0900_P1_AGC2O  0xf42c
+#define F0900_P1_AGC2REF_ADJUSTING  0xf42c0080
+#define F0900_P1_AGC2_COARSEFAST  0xf42c0040
+#define F0900_P1_AGC2_LKSQRT  0xf42c0020
+#define F0900_P1_AGC2_LKMODE  0xf42c0010
+#define F0900_P1_AGC2_LKEQUA  0xf42c0008
+#define F0900_P1_AGC2_COEF  0xf42c0007
+
+/*P1_AGC2REF*/
+#define R0900_P1_AGC2REF  0xf42d
+#define F0900_P1_AGC2_REF  0xf42d00ff
+
+/*P1_AGC1ADJ*/
+#define R0900_P1_AGC1ADJ  0xf42e
+#define F0900_P1_AGC1ADJ_MANUAL  0xf42e0080
+#define F0900_P1_AGC1_ADJUSTED  0xf42e017f
+
+/*P1_AGC2I1*/
+#define R0900_P1_AGC2I1  0xf436
+#define F0900_P1_AGC2_INTEGRATOR1  0xf43600ff
+
+/*P1_AGC2I0*/
+#define R0900_P1_AGC2I0  0xf437
+#define F0900_P1_AGC2_INTEGRATOR0  0xf43700ff
+
+/*P1_CARCFG*/
+#define R0900_P1_CARCFG  0xf438
+#define F0900_P1_CFRUPLOW_AUTO  0xf4380080
+#define F0900_P1_CFRUPLOW_TEST  0xf4380040
+#define F0900_P1_EN_CAR2CENTER  0xf4380020
+#define F0900_P1_CARHDR_NODIV8  0xf4380010
+#define F0900_P1_I2C_ROTA  0xf4380008
+#define F0900_P1_ROTAON  0xf4380004
+#define F0900_P1_PH_DET_ALGO  0xf4380003
+
+/*P1_ACLC*/
+#define R0900_P1_ACLC  0xf439
+#define F0900_P1_STOP_S2ALPHA  0xf43900c0
+#define F0900_P1_CAR_ALPHA_MANT  0xf4390030
+#define F0900_P1_CAR_ALPHA_EXP  0xf439000f
+
+/*P1_BCLC*/
+#define R0900_P1_BCLC  0xf43a
+#define F0900_P1_STOP_S2BETA  0xf43a00c0
+#define F0900_P1_CAR_BETA_MANT  0xf43a0030
+#define F0900_P1_CAR_BETA_EXP  0xf43a000f
+
+/*P1_CARFREQ*/
+#define R0900_P1_CARFREQ  0xf43d
+#define F0900_P1_KC_COARSE_EXP  0xf43d00f0
+#define F0900_P1_BETA_FREQ  0xf43d000f
+
+/*P1_CARHDR*/
+#define R0900_P1_CARHDR  0xf43e
+#define F0900_P1_K_FREQ_HDR  0xf43e00ff
+
+/*P1_LDT*/
+#define R0900_P1_LDT  0xf43f
+#define F0900_P1_CARLOCK_THRES  0xf43f01ff
+
+/*P1_LDT2*/
+#define R0900_P1_LDT2  0xf440
+#define F0900_P1_CARLOCK_THRES2  0xf44001ff
+
+/*P1_CFRICFG*/
+#define R0900_P1_CFRICFG  0xf441
+#define F0900_P1_CFRINIT_UNVALRNG  0xf4410080
+#define F0900_P1_CFRINIT_LUNVALCPT  0xf4410040
+#define F0900_P1_CFRINIT_ABORTDBL  0xf4410020
+#define F0900_P1_CFRINIT_ABORTPRED  0xf4410010
+#define F0900_P1_CFRINIT_UNVALSKIP  0xf4410008
+#define F0900_P1_CFRINIT_CSTINC  0xf4410004
+#define F0900_P1_NEG_CFRSTEP  0xf4410001
+
+/*P1_CFRUP1*/
+#define R0900_P1_CFRUP1  0xf442
+#define F0900_P1_CFR_UP1  0xf44201ff
+
+/*P1_CFRUP0*/
+#define R0900_P1_CFRUP0  0xf443
+#define F0900_P1_CFR_UP0  0xf44300ff
+
+/*P1_CFRLOW1*/
+#define R0900_P1_CFRLOW1  0xf446
+#define F0900_P1_CFR_LOW1  0xf44601ff
+
+/*P1_CFRLOW0*/
+#define R0900_P1_CFRLOW0  0xf447
+#define F0900_P1_CFR_LOW0  0xf44700ff
+
+/*P1_CFRINIT1*/
+#define R0900_P1_CFRINIT1  0xf448
+#define F0900_P1_CFR_INIT1  0xf44801ff
+
+/*P1_CFRINIT0*/
+#define R0900_P1_CFRINIT0  0xf449
+#define F0900_P1_CFR_INIT0  0xf44900ff
+
+/*P1_CFRINC1*/
+#define R0900_P1_CFRINC1  0xf44a
+#define F0900_P1_MANUAL_CFRINC  0xf44a0080
+#define F0900_P1_CFR_INC1  0xf44a017f
+
+/*P1_CFRINC0*/
+#define R0900_P1_CFRINC0  0xf44b
+#define F0900_P1_CFR_INC0  0xf44b00f0
+
+/*P1_CFR2*/
+#define R0900_P1_CFR2  0xf44c
+#define F0900_P1_CAR_FREQ2  0xf44c01ff
+
+/*P1_CFR1*/
+#define R0900_P1_CFR1  0xf44d
+#define F0900_P1_CAR_FREQ1  0xf44d00ff
+
+/*P1_CFR0*/
+#define R0900_P1_CFR0  0xf44e
+#define F0900_P1_CAR_FREQ0  0xf44e00ff
+
+/*P1_LDI*/
+#define R0900_P1_LDI  0xf44f
+#define F0900_P1_LOCK_DET_INTEGR  0xf44f01ff
+
+/*P1_TMGCFG*/
+#define R0900_P1_TMGCFG  0xf450
+#define F0900_P1_TMGLOCK_BETA  0xf45000c0
+#define F0900_P1_NOTMG_GROUPDELAY  0xf4500020
+#define F0900_P1_DO_TIMING_CORR  0xf4500010
+#define F0900_P1_MANUAL_SCAN  0xf450000c
+#define F0900_P1_TMG_MINFREQ  0xf4500003
+
+/*P1_RTC*/
+#define R0900_P1_RTC  0xf451
+#define F0900_P1_TMGALPHA_EXP  0xf45100f0
+#define F0900_P1_TMGBETA_EXP  0xf451000f
+
+/*P1_RTCS2*/
+#define R0900_P1_RTCS2  0xf452
+#define F0900_P1_TMGALPHAS2_EXP  0xf45200f0
+#define F0900_P1_TMGBETAS2_EXP  0xf452000f
+
+/*P1_TMGTHRISE*/
+#define R0900_P1_TMGTHRISE  0xf453
+#define F0900_P1_TMGLOCK_THRISE  0xf45300ff
+
+/*P1_TMGTHFALL*/
+#define R0900_P1_TMGTHFALL  0xf454
+#define F0900_P1_TMGLOCK_THFALL  0xf45400ff
+
+/*P1_SFRUPRATIO*/
+#define R0900_P1_SFRUPRATIO  0xf455
+#define F0900_P1_SFR_UPRATIO  0xf45500ff
+
+/*P1_SFRLOWRATIO*/
+#define R0900_P1_SFRLOWRATIO  0xf456
+#define F0900_P1_SFR_LOWRATIO  0xf45600ff
+
+/*P1_KREFTMG*/
+#define R0900_P1_KREFTMG  0xf458
+#define F0900_P1_KREF_TMG  0xf45800ff
+
+/*P1_SFRSTEP*/
+#define R0900_P1_SFRSTEP  0xf459
+#define F0900_P1_SFR_SCANSTEP  0xf45900f0
+#define F0900_P1_SFR_CENTERSTEP  0xf459000f
+
+/*P1_TMGCFG2*/
+#define R0900_P1_TMGCFG2  0xf45a
+#define F0900_P1_DIS_AUTOSAMP  0xf45a0008
+#define F0900_P1_SCANINIT_QUART  0xf45a0004
+#define F0900_P1_NOTMG_DVBS1DERAT  0xf45a0002
+#define F0900_P1_SFRRATIO_FINE  0xf45a0001
+
+/*P1_SFRINIT1*/
+#define R0900_P1_SFRINIT1  0xf45e
+#define F0900_P1_SFR_INIT1  0xf45e00ff
+
+/*P1_SFRINIT0*/
+#define R0900_P1_SFRINIT0  0xf45f
+#define F0900_P1_SFR_INIT0  0xf45f00ff
+
+/*P1_SFRUP1*/
+#define R0900_P1_SFRUP1  0xf460
+#define F0900_P1_AUTO_GUP  0xf4600080
+#define F0900_P1_SYMB_FREQ_UP1  0xf460007f
+
+/*P1_SFRUP0*/
+#define R0900_P1_SFRUP0  0xf461
+#define F0900_P1_SYMB_FREQ_UP0  0xf46100ff
+
+/*P1_SFRLOW1*/
+#define R0900_P1_SFRLOW1  0xf462
+#define F0900_P1_AUTO_GLOW  0xf4620080
+#define F0900_P1_SYMB_FREQ_LOW1  0xf462007f
+
+/*P1_SFRLOW0*/
+#define R0900_P1_SFRLOW0  0xf463
+#define F0900_P1_SYMB_FREQ_LOW0  0xf46300ff
+
+/*P1_SFR3*/
+#define R0900_P1_SFR3  0xf464
+#define F0900_P1_SYMB_FREQ3  0xf46400ff
+
+/*P1_SFR2*/
+#define R0900_P1_SFR2  0xf465
+#define F0900_P1_SYMB_FREQ2  0xf46500ff
+
+/*P1_SFR1*/
+#define R0900_P1_SFR1  0xf466
+#define F0900_P1_SYMB_FREQ1  0xf46600ff
+
+/*P1_SFR0*/
+#define R0900_P1_SFR0  0xf467
+#define F0900_P1_SYMB_FREQ0  0xf46700ff
+
+/*P1_TMGREG2*/
+#define R0900_P1_TMGREG2  0xf468
+#define F0900_P1_TMGREG2  0xf46800ff
+
+/*P1_TMGREG1*/
+#define R0900_P1_TMGREG1  0xf469
+#define F0900_P1_TMGREG1  0xf46900ff
+
+/*P1_TMGREG0*/
+#define R0900_P1_TMGREG0  0xf46a
+#define F0900_P1_TMGREG0  0xf46a00ff
+
+/*P1_TMGLOCK1*/
+#define R0900_P1_TMGLOCK1  0xf46b
+#define F0900_P1_TMGLOCK_LEVEL1  0xf46b01ff
+
+/*P1_TMGLOCK0*/
+#define R0900_P1_TMGLOCK0  0xf46c
+#define F0900_P1_TMGLOCK_LEVEL0  0xf46c00ff
+
+/*P1_TMGOBS*/
+#define R0900_P1_TMGOBS  0xf46d
+#define F0900_P1_ROLLOFF_STATUS  0xf46d00c0
+#define F0900_P1_SCAN_SIGN  0xf46d0030
+#define F0900_P1_TMG_SCANNING  0xf46d0008
+#define F0900_P1_CHCENTERING_MODE  0xf46d0004
+#define F0900_P1_TMG_SCANFAIL  0xf46d0002
+
+/*P1_EQUALCFG*/
+#define R0900_P1_EQUALCFG  0xf46f
+#define F0900_P1_NOTMG_NEGALWAIT  0xf46f0080
+#define F0900_P1_EQUAL_ON  0xf46f0040
+#define F0900_P1_SEL_EQUALCOR  0xf46f0038
+#define F0900_P1_MU_EQUALDFE  0xf46f0007
+
+/*P1_EQUAI1*/
+#define R0900_P1_EQUAI1  0xf470
+#define F0900_P1_EQUA_ACCI1  0xf47001ff
+
+/*P1_EQUAQ1*/
+#define R0900_P1_EQUAQ1  0xf471
+#define F0900_P1_EQUA_ACCQ1  0xf47101ff
+
+/*P1_EQUAI2*/
+#define R0900_P1_EQUAI2  0xf472
+#define F0900_P1_EQUA_ACCI2  0xf47201ff
+
+/*P1_EQUAQ2*/
+#define R0900_P1_EQUAQ2  0xf473
+#define F0900_P1_EQUA_ACCQ2  0xf47301ff
+
+/*P1_EQUAI3*/
+#define R0900_P1_EQUAI3  0xf474
+#define F0900_P1_EQUA_ACCI3  0xf47401ff
+
+/*P1_EQUAQ3*/
+#define R0900_P1_EQUAQ3  0xf475
+#define F0900_P1_EQUA_ACCQ3  0xf47501ff
+
+/*P1_EQUAI4*/
+#define R0900_P1_EQUAI4  0xf476
+#define F0900_P1_EQUA_ACCI4  0xf47601ff
+
+/*P1_EQUAQ4*/
+#define R0900_P1_EQUAQ4  0xf477
+#define F0900_P1_EQUA_ACCQ4  0xf47701ff
+
+/*P1_EQUAI5*/
+#define R0900_P1_EQUAI5  0xf478
+#define F0900_P1_EQUA_ACCI5  0xf47801ff
+
+/*P1_EQUAQ5*/
+#define R0900_P1_EQUAQ5  0xf479
+#define F0900_P1_EQUA_ACCQ5  0xf47901ff
+
+/*P1_EQUAI6*/
+#define R0900_P1_EQUAI6  0xf47a
+#define F0900_P1_EQUA_ACCI6  0xf47a01ff
+
+/*P1_EQUAQ6*/
+#define R0900_P1_EQUAQ6  0xf47b
+#define F0900_P1_EQUA_ACCQ6  0xf47b01ff
+
+/*P1_EQUAI7*/
+#define R0900_P1_EQUAI7  0xf47c
+#define F0900_P1_EQUA_ACCI7  0xf47c01ff
+
+/*P1_EQUAQ7*/
+#define R0900_P1_EQUAQ7  0xf47d
+#define F0900_P1_EQUA_ACCQ7  0xf47d01ff
+
+/*P1_EQUAI8*/
+#define R0900_P1_EQUAI8  0xf47e
+#define F0900_P1_EQUA_ACCI8  0xf47e01ff
+
+/*P1_EQUAQ8*/
+#define R0900_P1_EQUAQ8  0xf47f
+#define F0900_P1_EQUA_ACCQ8  0xf47f01ff
+
+/*P1_NNOSDATAT1*/
+#define R0900_P1_NNOSDATAT1  0xf480
+#define F0900_P1_NOSDATAT_NORMED1  0xf48000ff
+
+/*P1_NNOSDATAT0*/
+#define R0900_P1_NNOSDATAT0  0xf481
+#define F0900_P1_NOSDATAT_NORMED0  0xf48100ff
+
+/*P1_NNOSDATA1*/
+#define R0900_P1_NNOSDATA1  0xf482
+#define F0900_P1_NOSDATA_NORMED1  0xf48200ff
+
+/*P1_NNOSDATA0*/
+#define R0900_P1_NNOSDATA0  0xf483
+#define F0900_P1_NOSDATA_NORMED0  0xf48300ff
+
+/*P1_NNOSPLHT1*/
+#define R0900_P1_NNOSPLHT1  0xf484
+#define F0900_P1_NOSPLHT_NORMED1  0xf48400ff
+
+/*P1_NNOSPLHT0*/
+#define R0900_P1_NNOSPLHT0  0xf485
+#define F0900_P1_NOSPLHT_NORMED0  0xf48500ff
+
+/*P1_NNOSPLH1*/
+#define R0900_P1_NNOSPLH1  0xf486
+#define F0900_P1_NOSPLH_NORMED1  0xf48600ff
+
+/*P1_NNOSPLH0*/
+#define R0900_P1_NNOSPLH0  0xf487
+#define F0900_P1_NOSPLH_NORMED0  0xf48700ff
+
+/*P1_NOSDATAT1*/
+#define R0900_P1_NOSDATAT1  0xf488
+#define F0900_P1_NOSDATAT_UNNORMED1  0xf48800ff
+
+/*P1_NOSDATAT0*/
+#define R0900_P1_NOSDATAT0  0xf489
+#define F0900_P1_NOSDATAT_UNNORMED0  0xf48900ff
+
+/*P1_NOSDATA1*/
+#define R0900_P1_NOSDATA1  0xf48a
+#define F0900_P1_NOSDATA_UNNORMED1  0xf48a00ff
+
+/*P1_NOSDATA0*/
+#define R0900_P1_NOSDATA0  0xf48b
+#define F0900_P1_NOSDATA_UNNORMED0  0xf48b00ff
+
+/*P1_NOSPLHT1*/
+#define R0900_P1_NOSPLHT1  0xf48c
+#define F0900_P1_NOSPLHT_UNNORMED1  0xf48c00ff
+
+/*P1_NOSPLHT0*/
+#define R0900_P1_NOSPLHT0  0xf48d
+#define F0900_P1_NOSPLHT_UNNORMED0  0xf48d00ff
+
+/*P1_NOSPLH1*/
+#define R0900_P1_NOSPLH1  0xf48e
+#define F0900_P1_NOSPLH_UNNORMED1  0xf48e00ff
+
+/*P1_NOSPLH0*/
+#define R0900_P1_NOSPLH0  0xf48f
+#define F0900_P1_NOSPLH_UNNORMED0  0xf48f00ff
+
+/*P1_CAR2CFG*/
+#define R0900_P1_CAR2CFG  0xf490
+#define F0900_P1_DESCRAMB_OFF  0xf4900080
+#define F0900_P1_PN4_SELECT  0xf4900040
+#define F0900_P1_CFR2_STOPDVBS1  0xf4900020
+#define F0900_P1_STOP_CFR2UPDATE  0xf4900010
+#define F0900_P1_STOP_NCO2UPDATE  0xf4900008
+#define F0900_P1_ROTA2ON  0xf4900004
+#define F0900_P1_PH_DET_ALGO2  0xf4900003
+
+/*P1_ACLC2*/
+#define R0900_P1_ACLC2  0xf491
+#define F0900_P1_CAR2_PUNCT_ADERAT  0xf4910040
+#define F0900_P1_CAR2_ALPHA_MANT  0xf4910030
+#define F0900_P1_CAR2_ALPHA_EXP  0xf491000f
+
+/*P1_BCLC2*/
+#define R0900_P1_BCLC2  0xf492
+#define F0900_P1_DVBS2_NIP  0xf4920080
+#define F0900_P1_CAR2_PUNCT_BDERAT  0xf4920040
+#define F0900_P1_CAR2_BETA_MANT  0xf4920030
+#define F0900_P1_CAR2_BETA_EXP  0xf492000f
+
+/*P1_CFR22*/
+#define R0900_P1_CFR22  0xf493
+#define F0900_P1_CAR2_FREQ2  0xf49301ff
+
+/*P1_CFR21*/
+#define R0900_P1_CFR21  0xf494
+#define F0900_P1_CAR2_FREQ1  0xf49400ff
+
+/*P1_CFR20*/
+#define R0900_P1_CFR20  0xf495
+#define F0900_P1_CAR2_FREQ0  0xf49500ff
+
+/*P1_ACLC2S2Q*/
+#define R0900_P1_ACLC2S2Q  0xf497
+#define F0900_P1_ENAB_SPSKSYMB  0xf4970080
+#define F0900_P1_CAR2S2_QADERAT  0xf4970040
+#define F0900_P1_CAR2S2_Q_ALPH_M  0xf4970030
+#define F0900_P1_CAR2S2_Q_ALPH_E  0xf497000f
+
+/*P1_ACLC2S28*/
+#define R0900_P1_ACLC2S28  0xf498
+#define F0900_P1_OLDI3Q_MODE  0xf4980080
+#define F0900_P1_CAR2S2_8ADERAT  0xf4980040
+#define F0900_P1_CAR2S2_8_ALPH_M  0xf4980030
+#define F0900_P1_CAR2S2_8_ALPH_E  0xf498000f
+
+/*P1_ACLC2S216A*/
+#define R0900_P1_ACLC2S216A  0xf499
+#define F0900_P1_CAR2S2_16ADERAT  0xf4990040
+#define F0900_P1_CAR2S2_16A_ALPH_M  0xf4990030
+#define F0900_P1_CAR2S2_16A_ALPH_E  0xf499000f
+
+/*P1_ACLC2S232A*/
+#define R0900_P1_ACLC2S232A  0xf49a
+#define F0900_P1_CAR2S2_32ADERAT  0xf49a0040
+#define F0900_P1_CAR2S2_32A_ALPH_M  0xf49a0030
+#define F0900_P1_CAR2S2_32A_ALPH_E  0xf49a000f
+
+/*P1_BCLC2S2Q*/
+#define R0900_P1_BCLC2S2Q  0xf49c
+#define F0900_P1_DVBS2S2Q_NIP  0xf49c0080
+#define F0900_P1_CAR2S2_QBDERAT  0xf49c0040
+#define F0900_P1_CAR2S2_Q_BETA_M  0xf49c0030
+#define F0900_P1_CAR2S2_Q_BETA_E  0xf49c000f
+
+/*P1_BCLC2S28*/
+#define R0900_P1_BCLC2S28  0xf49d
+#define F0900_P1_DVBS2S28_NIP  0xf49d0080
+#define F0900_P1_CAR2S2_8BDERAT  0xf49d0040
+#define F0900_P1_CAR2S2_8_BETA_M  0xf49d0030
+#define F0900_P1_CAR2S2_8_BETA_E  0xf49d000f
+
+/*P1_BCLC2S216A*/
+#define R0900_P1_BCLC2S216A  0xf49e
+#define F0900_P1_DVBS2S216A_NIP  0xf49e0080
+#define F0900_P1_CAR2S2_16BDERAT  0xf49e0040
+#define F0900_P1_CAR2S2_16A_BETA_M  0xf49e0030
+#define F0900_P1_CAR2S2_16A_BETA_E  0xf49e000f
+
+/*P1_BCLC2S232A*/
+#define R0900_P1_BCLC2S232A  0xf49f
+#define F0900_P1_DVBS2S232A_NIP  0xf49f0080
+#define F0900_P1_CAR2S2_32BDERAT  0xf49f0040
+#define F0900_P1_CAR2S2_32A_BETA_M  0xf49f0030
+#define F0900_P1_CAR2S2_32A_BETA_E  0xf49f000f
+
+/*P1_PLROOT2*/
+#define R0900_P1_PLROOT2  0xf4ac
+#define F0900_P1_SHORTFR_DISABLE  0xf4ac0080
+#define F0900_P1_LONGFR_DISABLE  0xf4ac0040
+#define F0900_P1_DUMMYPL_DISABLE  0xf4ac0020
+#define F0900_P1_SHORTFR_AVOID  0xf4ac0010
+#define F0900_P1_PLSCRAMB_MODE  0xf4ac000c
+#define F0900_P1_PLSCRAMB_ROOT2  0xf4ac0003
+
+/*P1_PLROOT1*/
+#define R0900_P1_PLROOT1  0xf4ad
+#define F0900_P1_PLSCRAMB_ROOT1  0xf4ad00ff
+
+/*P1_PLROOT0*/
+#define R0900_P1_PLROOT0  0xf4ae
+#define F0900_P1_PLSCRAMB_ROOT0  0xf4ae00ff
+
+/*P1_MODCODLST0*/
+#define R0900_P1_MODCODLST0  0xf4b0
+#define F0900_P1_EN_TOKEN31  0xf4b00080
+#define F0900_P1_SYNCTAG_SELECT  0xf4b00040
+#define F0900_P1_MODCODRQ_MODE  0xf4b00030
+
+/*P1_MODCODLST1*/
+#define R0900_P1_MODCODLST1  0xf4b1
+#define F0900_P1_DIS_MODCOD29  0xf4b100f0
+#define F0900_P1_DIS_32PSK_9_10  0xf4b1000f
+
+/*P1_MODCODLST2*/
+#define R0900_P1_MODCODLST2  0xf4b2
+#define F0900_P1_DIS_32PSK_8_9  0xf4b200f0
+#define F0900_P1_DIS_32PSK_5_6  0xf4b2000f
+
+/*P1_MODCODLST3*/
+#define R0900_P1_MODCODLST3  0xf4b3
+#define F0900_P1_DIS_32PSK_4_5  0xf4b300f0
+#define F0900_P1_DIS_32PSK_3_4  0xf4b3000f
+
+/*P1_MODCODLST4*/
+#define R0900_P1_MODCODLST4  0xf4b4
+#define F0900_P1_DIS_16PSK_9_10  0xf4b400f0
+#define F0900_P1_DIS_16PSK_8_9  0xf4b4000f
+
+/*P1_MODCODLST5*/
+#define R0900_P1_MODCODLST5  0xf4b5
+#define F0900_P1_DIS_16PSK_5_6  0xf4b500f0
+#define F0900_P1_DIS_16PSK_4_5  0xf4b5000f
+
+/*P1_MODCODLST6*/
+#define R0900_P1_MODCODLST6  0xf4b6
+#define F0900_P1_DIS_16PSK_3_4  0xf4b600f0
+#define F0900_P1_DIS_16PSK_2_3  0xf4b6000f
+
+/*P1_MODCODLST7*/
+#define R0900_P1_MODCODLST7  0xf4b7
+#define F0900_P1_DIS_8P_9_10  0xf4b700f0
+#define F0900_P1_DIS_8P_8_9  0xf4b7000f
+
+/*P1_MODCODLST8*/
+#define R0900_P1_MODCODLST8  0xf4b8
+#define F0900_P1_DIS_8P_5_6  0xf4b800f0
+#define F0900_P1_DIS_8P_3_4  0xf4b8000f
+
+/*P1_MODCODLST9*/
+#define R0900_P1_MODCODLST9  0xf4b9
+#define F0900_P1_DIS_8P_2_3  0xf4b900f0
+#define F0900_P1_DIS_8P_3_5  0xf4b9000f
+
+/*P1_MODCODLSTA*/
+#define R0900_P1_MODCODLSTA  0xf4ba
+#define F0900_P1_DIS_QP_9_10  0xf4ba00f0
+#define F0900_P1_DIS_QP_8_9  0xf4ba000f
+
+/*P1_MODCODLSTB*/
+#define R0900_P1_MODCODLSTB  0xf4bb
+#define F0900_P1_DIS_QP_5_6  0xf4bb00f0
+#define F0900_P1_DIS_QP_4_5  0xf4bb000f
+
+/*P1_MODCODLSTC*/
+#define R0900_P1_MODCODLSTC  0xf4bc
+#define F0900_P1_DIS_QP_3_4  0xf4bc00f0
+#define F0900_P1_DIS_QP_2_3  0xf4bc000f
+
+/*P1_MODCODLSTD*/
+#define R0900_P1_MODCODLSTD  0xf4bd
+#define F0900_P1_DIS_QP_3_5  0xf4bd00f0
+#define F0900_P1_DIS_QP_1_2  0xf4bd000f
+
+/*P1_MODCODLSTE*/
+#define R0900_P1_MODCODLSTE  0xf4be
+#define F0900_P1_DIS_QP_2_5  0xf4be00f0
+#define F0900_P1_DIS_QP_1_3  0xf4be000f
+
+/*P1_MODCODLSTF*/
+#define R0900_P1_MODCODLSTF  0xf4bf
+#define F0900_P1_DIS_QP_1_4  0xf4bf00f0
+#define F0900_P1_DDEMOD_SET  0xf4bf0002
+#define F0900_P1_DDEMOD_MASK  0xf4bf0001
+
+/*P1_DMDRESCFG*/
+#define R0900_P1_DMDRESCFG  0xf4c6
+#define F0900_P1_DMDRES_RESET  0xf4c60080
+#define F0900_P1_DMDRES_NOISESQR  0xf4c60010
+#define F0900_P1_DMDRES_STRALL  0xf4c60008
+#define F0900_P1_DMDRES_NEWONLY  0xf4c60004
+#define F0900_P1_DMDRES_NOSTORE  0xf4c60002
+#define F0900_P1_DMDRES_AGC2MEM  0xf4c60001
+
+/*P1_DMDRESADR*/
+#define R0900_P1_DMDRESADR  0xf4c7
+#define F0900_P1_SUSP_PREDCANAL  0xf4c70080
+#define F0900_P1_DMDRES_VALIDCFR  0xf4c70040
+#define F0900_P1_DMDRES_MEMFULL  0xf4c70030
+#define F0900_P1_DMDRES_RESNBR  0xf4c7000f
+
+/*P1_DMDRESDATA7*/
+#define R0900_P1_DMDRESDATA7  0xf4c8
+#define F0900_P1_DMDRES_DATA7  0xf4c800ff
+
+/*P1_DMDRESDATA6*/
+#define R0900_P1_DMDRESDATA6  0xf4c9
+#define F0900_P1_DMDRES_DATA6  0xf4c900ff
+
+/*P1_DMDRESDATA5*/
+#define R0900_P1_DMDRESDATA5  0xf4ca
+#define F0900_P1_DMDRES_DATA5  0xf4ca00ff
+
+/*P1_DMDRESDATA4*/
+#define R0900_P1_DMDRESDATA4  0xf4cb
+#define F0900_P1_DMDRES_DATA4  0xf4cb00ff
+
+/*P1_DMDRESDATA3*/
+#define R0900_P1_DMDRESDATA3  0xf4cc
+#define F0900_P1_DMDRES_DATA3  0xf4cc00ff
+
+/*P1_DMDRESDATA2*/
+#define R0900_P1_DMDRESDATA2  0xf4cd
+#define F0900_P1_DMDRES_DATA2  0xf4cd00ff
+
+/*P1_DMDRESDATA1*/
+#define R0900_P1_DMDRESDATA1  0xf4ce
+#define F0900_P1_DMDRES_DATA1  0xf4ce00ff
+
+/*P1_DMDRESDATA0*/
+#define R0900_P1_DMDRESDATA0  0xf4cf
+#define F0900_P1_DMDRES_DATA0  0xf4cf00ff
+
+/*P1_FFEI1*/
+#define R0900_P1_FFEI1  0xf4d0
+#define F0900_P1_FFE_ACCI1  0xf4d001ff
+
+/*P1_FFEQ1*/
+#define R0900_P1_FFEQ1  0xf4d1
+#define F0900_P1_FFE_ACCQ1  0xf4d101ff
+
+/*P1_FFEI2*/
+#define R0900_P1_FFEI2  0xf4d2
+#define F0900_P1_FFE_ACCI2  0xf4d201ff
+
+/*P1_FFEQ2*/
+#define R0900_P1_FFEQ2  0xf4d3
+#define F0900_P1_FFE_ACCQ2  0xf4d301ff
+
+/*P1_FFEI3*/
+#define R0900_P1_FFEI3  0xf4d4
+#define F0900_P1_FFE_ACCI3  0xf4d401ff
+
+/*P1_FFEQ3*/
+#define R0900_P1_FFEQ3  0xf4d5
+#define F0900_P1_FFE_ACCQ3  0xf4d501ff
+
+/*P1_FFEI4*/
+#define R0900_P1_FFEI4  0xf4d6
+#define F0900_P1_FFE_ACCI4  0xf4d601ff
+
+/*P1_FFEQ4*/
+#define R0900_P1_FFEQ4  0xf4d7
+#define F0900_P1_FFE_ACCQ4  0xf4d701ff
+
+/*P1_FFECFG*/
+#define R0900_P1_FFECFG  0xf4d8
+#define F0900_P1_EQUALFFE_ON  0xf4d80040
+#define F0900_P1_EQUAL_USEDSYMB  0xf4d80030
+#define F0900_P1_MU_EQUALFFE  0xf4d80007
+
+/*P1_TNRCFG*/
+#define R0900_P1_TNRCFG  0xf4e0
+#define F0900_P1_TUN_ACKFAIL  0xf4e00080
+#define F0900_P1_TUN_TYPE  0xf4e00070
+#define F0900_P1_TUN_SECSTOP  0xf4e00008
+#define F0900_P1_TUN_VCOSRCH  0xf4e00004
+#define F0900_P1_TUN_MADDRESS  0xf4e00003
+
+/*P1_TNRCFG2*/
+#define R0900_P1_TNRCFG2  0xf4e1
+#define F0900_P1_TUN_IQSWAP  0xf4e10080
+#define F0900_P1_STB6110_STEP2MHZ  0xf4e10040
+#define F0900_P1_STB6120_DBLI2C  0xf4e10020
+#define F0900_P1_DIS_FCCK  0xf4e10010
+#define F0900_P1_DIS_LPEN  0xf4e10008
+#define F0900_P1_DIS_BWCALC  0xf4e10004
+#define F0900_P1_SHORT_WAITSTATES  0xf4e10002
+#define F0900_P1_DIS_2BWAGC1  0xf4e10001
+
+/*P1_TNRXTAL*/
+#define R0900_P1_TNRXTAL  0xf4e4
+#define F0900_P1_TUN_MCLKDECIMAL  0xf4e400e0
+#define F0900_P1_TUN_XTALFREQ  0xf4e4001f
+
+/*P1_TNRSTEPS*/
+#define R0900_P1_TNRSTEPS  0xf4e7
+#define F0900_P1_TUNER_BW1P6  0xf4e70080
+#define F0900_P1_BWINC_OFFSET  0xf4e70070
+#define F0900_P1_SOFTSTEP_RNG  0xf4e70008
+#define F0900_P1_TUN_BWOFFSET  0xf4e70107
+
+/*P1_TNRGAIN*/
+#define R0900_P1_TNRGAIN  0xf4e8
+#define F0900_P1_TUN_KDIVEN  0xf4e800c0
+#define F0900_P1_STB6X00_OCK  0xf4e80030
+#define F0900_P1_TUN_GAIN  0xf4e8000f
+
+/*P1_TNRRF1*/
+#define R0900_P1_TNRRF1  0xf4e9
+#define F0900_P1_TUN_RFFREQ2  0xf4e900ff
+
+/*P1_TNRRF0*/
+#define R0900_P1_TNRRF0  0xf4ea
+#define F0900_P1_TUN_RFFREQ1  0xf4ea00ff
+
+/*P1_TNRBW*/
+#define R0900_P1_TNRBW  0xf4eb
+#define F0900_P1_TUN_RFFREQ0  0xf4eb00c0
+#define F0900_P1_TUN_BW  0xf4eb003f
+
+/*P1_TNRADJ*/
+#define R0900_P1_TNRADJ  0xf4ec
+#define F0900_P1_STB61X0_RCLK  0xf4ec0080
+#define F0900_P1_STB61X0_CALTIME  0xf4ec0040
+#define F0900_P1_STB6X00_DLB  0xf4ec0038
+#define F0900_P1_STB6000_FCL  0xf4ec0007
+
+/*P1_TNRCTL2*/
+#define R0900_P1_TNRCTL2  0xf4ed
+#define F0900_P1_STB61X0_LCP1_RCCKOFF  0xf4ed0080
+#define F0900_P1_STB61X0_LCP0  0xf4ed0040
+#define F0900_P1_STB61X0_XTOUT_RFOUTS  0xf4ed0020
+#define F0900_P1_STB61X0_XTON_MCKDV  0xf4ed0010
+#define F0900_P1_STB61X0_CALOFF_DCOFF  0xf4ed0008
+#define F0900_P1_STB6110_LPT  0xf4ed0004
+#define F0900_P1_STB6110_RX  0xf4ed0002
+#define F0900_P1_STB6110_SYN  0xf4ed0001
+
+/*P1_TNRCFG3*/
+#define R0900_P1_TNRCFG3  0xf4ee
+#define F0900_P1_STB6120_DISCTRL1  0xf4ee0080
+#define F0900_P1_STB6120_INVORDER  0xf4ee0040
+#define F0900_P1_STB6120_ENCTRL6  0xf4ee0020
+#define F0900_P1_TUN_PLLFREQ  0xf4ee001c
+#define F0900_P1_TUN_I2CFREQ_MODE  0xf4ee0003
+
+/*P1_TNRLAUNCH*/
+#define R0900_P1_TNRLAUNCH  0xf4f0
+
+/*P1_TNRLD*/
+#define R0900_P1_TNRLD  0xf4f0
+#define F0900_P1_TUNLD_VCOING  0xf4f00080
+#define F0900_P1_TUN_REG1FAIL  0xf4f00040
+#define F0900_P1_TUN_REG2FAIL  0xf4f00020
+#define F0900_P1_TUN_REG3FAIL  0xf4f00010
+#define F0900_P1_TUN_REG4FAIL  0xf4f00008
+#define F0900_P1_TUN_REG5FAIL  0xf4f00004
+#define F0900_P1_TUN_BWING  0xf4f00002
+#define F0900_P1_TUN_LOCKED  0xf4f00001
+
+/*P1_TNROBSL*/
+#define R0900_P1_TNROBSL  0xf4f6
+#define F0900_P1_TUN_I2CABORTED  0xf4f60080
+#define F0900_P1_TUN_LPEN  0xf4f60040
+#define F0900_P1_TUN_FCCK  0xf4f60020
+#define F0900_P1_TUN_I2CLOCKED  0xf4f60010
+#define F0900_P1_TUN_PROGDONE  0xf4f6000c
+#define F0900_P1_TUN_RFRESTE1  0xf4f60003
+
+/*P1_TNRRESTE*/
+#define R0900_P1_TNRRESTE  0xf4f7
+#define F0900_P1_TUN_RFRESTE0  0xf4f700ff
+
+/*P1_SMAPCOEF7*/
+#define R0900_P1_SMAPCOEF7  0xf500
+#define F0900_P1_DIS_QSCALE  0xf5000080
+#define F0900_P1_SMAPCOEF_Q_LLR12  0xf500017f
+
+/*P1_SMAPCOEF6*/
+#define R0900_P1_SMAPCOEF6  0xf501
+#define F0900_P1_DIS_NEWSCALE  0xf5010008
+#define F0900_P1_ADJ_8PSKLLR1  0xf5010004
+#define F0900_P1_OLD_8PSKLLR1  0xf5010002
+#define F0900_P1_DIS_AB8PSK  0xf5010001
+
+/*P1_SMAPCOEF5*/
+#define R0900_P1_SMAPCOEF5  0xf502
+#define F0900_P1_DIS_8SCALE  0xf5020080
+#define F0900_P1_SMAPCOEF_8P_LLR23  0xf502017f
+
+/*P1_DMDPLHSTAT*/
+#define R0900_P1_DMDPLHSTAT  0xf520
+#define F0900_P1_PLH_STATISTIC  0xf52000ff
+
+/*P1_LOCKTIME3*/
+#define R0900_P1_LOCKTIME3  0xf522
+#define F0900_P1_DEMOD_LOCKTIME3  0xf52200ff
+
+/*P1_LOCKTIME2*/
+#define R0900_P1_LOCKTIME2  0xf523
+#define F0900_P1_DEMOD_LOCKTIME2  0xf52300ff
+
+/*P1_LOCKTIME1*/
+#define R0900_P1_LOCKTIME1  0xf524
+#define F0900_P1_DEMOD_LOCKTIME1  0xf52400ff
+
+/*P1_LOCKTIME0*/
+#define R0900_P1_LOCKTIME0  0xf525
+#define F0900_P1_DEMOD_LOCKTIME0  0xf52500ff
+
+/*P1_VITSCALE*/
+#define R0900_P1_VITSCALE  0xf532
+#define F0900_P1_NVTH_NOSRANGE  0xf5320080
+#define F0900_P1_VERROR_MAXMODE  0xf5320040
+#define F0900_P1_KDIV_MODE  0xf5320030
+#define F0900_P1_NSLOWSN_LOCKED  0xf5320008
+#define F0900_P1_DELOCK_PRFLOSS  0xf5320004
+#define F0900_P1_DIS_RSFLOCK  0xf5320002
+
+/*P1_FECM*/
+#define R0900_P1_FECM  0xf533
+#define F0900_P1_DSS_DVB  0xf5330080
+#define F0900_P1_DEMOD_BYPASS  0xf5330040
+#define F0900_P1_CMP_SLOWMODE  0xf5330020
+#define F0900_P1_DSS_SRCH  0xf5330010
+#define F0900_P1_DIFF_MODEVIT  0xf5330004
+#define F0900_P1_SYNCVIT  0xf5330002
+#define F0900_P1_IQINV  0xf5330001
+
+/*P1_VTH12*/
+#define R0900_P1_VTH12  0xf534
+#define F0900_P1_VTH12  0xf53400ff
+
+/*P1_VTH23*/
+#define R0900_P1_VTH23  0xf535
+#define F0900_P1_VTH23  0xf53500ff
+
+/*P1_VTH34*/
+#define R0900_P1_VTH34  0xf536
+#define F0900_P1_VTH34  0xf53600ff
+
+/*P1_VTH56*/
+#define R0900_P1_VTH56  0xf537
+#define F0900_P1_VTH56  0xf53700ff
+
+/*P1_VTH67*/
+#define R0900_P1_VTH67  0xf538
+#define F0900_P1_VTH67  0xf53800ff
+
+/*P1_VTH78*/
+#define R0900_P1_VTH78  0xf539
+#define F0900_P1_VTH78  0xf53900ff
+
+/*P1_VITCURPUN*/
+#define R0900_P1_VITCURPUN  0xf53a
+#define F0900_P1_VIT_MAPPING  0xf53a00e0
+#define F0900_P1_VIT_CURPUN  0xf53a001f
+
+/*P1_VERROR*/
+#define R0900_P1_VERROR  0xf53b
+#define F0900_P1_REGERR_VIT  0xf53b00ff
+
+/*P1_PRVIT*/
+#define R0900_P1_PRVIT  0xf53c
+#define F0900_P1_DIS_VTHLOCK  0xf53c0040
+#define F0900_P1_E7_8VIT  0xf53c0020
+#define F0900_P1_E6_7VIT  0xf53c0010
+#define F0900_P1_E5_6VIT  0xf53c0008
+#define F0900_P1_E3_4VIT  0xf53c0004
+#define F0900_P1_E2_3VIT  0xf53c0002
+#define F0900_P1_E1_2VIT  0xf53c0001
+
+/*P1_VAVSRVIT*/
+#define R0900_P1_VAVSRVIT  0xf53d
+#define F0900_P1_AMVIT  0xf53d0080
+#define F0900_P1_FROZENVIT  0xf53d0040
+#define F0900_P1_SNVIT  0xf53d0030
+#define F0900_P1_TOVVIT  0xf53d000c
+#define F0900_P1_HYPVIT  0xf53d0003
+
+/*P1_VSTATUSVIT*/
+#define R0900_P1_VSTATUSVIT  0xf53e
+#define F0900_P1_VITERBI_ON  0xf53e0080
+#define F0900_P1_END_LOOPVIT  0xf53e0040
+#define F0900_P1_VITERBI_DEPRF  0xf53e0020
+#define F0900_P1_PRFVIT  0xf53e0010
+#define F0900_P1_LOCKEDVIT  0xf53e0008
+#define F0900_P1_VITERBI_DELOCK  0xf53e0004
+#define F0900_P1_VIT_DEMODSEL  0xf53e0002
+#define F0900_P1_VITERBI_COMPOUT  0xf53e0001
+
+/*P1_VTHINUSE*/
+#define R0900_P1_VTHINUSE  0xf53f
+#define F0900_P1_VIT_INUSE  0xf53f00ff
+
+/*P1_KDIV12*/
+#define R0900_P1_KDIV12  0xf540
+#define F0900_P1_KDIV12_MANUAL  0xf5400080
+#define F0900_P1_K_DIVIDER_12  0xf540007f
+
+/*P1_KDIV23*/
+#define R0900_P1_KDIV23  0xf541
+#define F0900_P1_KDIV23_MANUAL  0xf5410080
+#define F0900_P1_K_DIVIDER_23  0xf541007f
+
+/*P1_KDIV34*/
+#define R0900_P1_KDIV34  0xf542
+#define F0900_P1_KDIV34_MANUAL  0xf5420080
+#define F0900_P1_K_DIVIDER_34  0xf542007f
+
+/*P1_KDIV56*/
+#define R0900_P1_KDIV56  0xf543
+#define F0900_P1_KDIV56_MANUAL  0xf5430080
+#define F0900_P1_K_DIVIDER_56  0xf543007f
+
+/*P1_KDIV67*/
+#define R0900_P1_KDIV67  0xf544
+#define F0900_P1_KDIV67_MANUAL  0xf5440080
+#define F0900_P1_K_DIVIDER_67  0xf544007f
+
+/*P1_KDIV78*/
+#define R0900_P1_KDIV78  0xf545
+#define F0900_P1_KDIV78_MANUAL  0xf5450080
+#define F0900_P1_K_DIVIDER_78  0xf545007f
+
+/*P1_PDELCTRL1*/
+#define R0900_P1_PDELCTRL1  0xf550
+#define F0900_P1_INV_MISMASK  0xf5500080
+#define F0900_P1_FORCE_ACCEPTED  0xf5500040
+#define F0900_P1_FILTER_EN  0xf5500020
+#define F0900_P1_FORCE_PKTDELINUSE  0xf5500010
+#define F0900_P1_HYSTEN  0xf5500008
+#define F0900_P1_HYSTSWRST  0xf5500004
+#define F0900_P1_EN_MIS00  0xf5500002
+#define F0900_P1_ALGOSWRST  0xf5500001
+
+/*P1_PDELCTRL2*/
+#define R0900_P1_PDELCTRL2  0xf551
+#define F0900_P1_FORCE_CONTINUOUS  0xf5510080
+#define F0900_P1_RESET_UPKO_COUNT  0xf5510040
+#define F0900_P1_USER_PKTDELIN_NB  0xf5510020
+#define F0900_P1_FORCE_LOCKED  0xf5510010
+#define F0900_P1_DATA_UNBBSCRAM  0xf5510008
+#define F0900_P1_FORCE_LONGPKT  0xf5510004
+#define F0900_P1_FRAME_MODE  0xf5510002
+
+/*P1_HYSTTHRESH*/
+#define R0900_P1_HYSTTHRESH  0xf554
+#define F0900_P1_UNLCK_THRESH  0xf55400f0
+#define F0900_P1_DELIN_LCK_THRESH  0xf554000f
+
+/*P1_ISIENTRY*/
+#define R0900_P1_ISIENTRY  0xf55e
+#define F0900_P1_ISI_ENTRY  0xf55e00ff
+
+/*P1_ISIBITENA*/
+#define R0900_P1_ISIBITENA  0xf55f
+#define F0900_P1_ISI_BIT_EN  0xf55f00ff
+
+/*P1_MATSTR1*/
+#define R0900_P1_MATSTR1  0xf560
+#define F0900_P1_MATYPE_CURRENT1  0xf56000ff
+
+/*P1_MATSTR0*/
+#define R0900_P1_MATSTR0  0xf561
+#define F0900_P1_MATYPE_CURRENT0  0xf56100ff
+
+/*P1_UPLSTR1*/
+#define R0900_P1_UPLSTR1  0xf562
+#define F0900_P1_UPL_CURRENT1  0xf56200ff
+
+/*P1_UPLSTR0*/
+#define R0900_P1_UPLSTR0  0xf563
+#define F0900_P1_UPL_CURRENT0  0xf56300ff
+
+/*P1_DFLSTR1*/
+#define R0900_P1_DFLSTR1  0xf564
+#define F0900_P1_DFL_CURRENT1  0xf56400ff
+
+/*P1_DFLSTR0*/
+#define R0900_P1_DFLSTR0  0xf565
+#define F0900_P1_DFL_CURRENT0  0xf56500ff
+
+/*P1_SYNCSTR*/
+#define R0900_P1_SYNCSTR  0xf566
+#define F0900_P1_SYNC_CURRENT  0xf56600ff
+
+/*P1_SYNCDSTR1*/
+#define R0900_P1_SYNCDSTR1  0xf567
+#define F0900_P1_SYNCD_CURRENT1  0xf56700ff
+
+/*P1_SYNCDSTR0*/
+#define R0900_P1_SYNCDSTR0  0xf568
+#define F0900_P1_SYNCD_CURRENT0  0xf56800ff
+
+/*P1_PDELSTATUS1*/
+#define R0900_P1_PDELSTATUS1  0xf569
+#define F0900_P1_PKTDELIN_DELOCK  0xf5690080
+#define F0900_P1_SYNCDUPDFL_BADDFL  0xf5690040
+#define F0900_P1_CONTINUOUS_STREAM  0xf5690020
+#define F0900_P1_UNACCEPTED_STREAM  0xf5690010
+#define F0900_P1_BCH_ERROR_FLAG  0xf5690008
+#define F0900_P1_BBHCRCKO  0xf5690004
+#define F0900_P1_PKTDELIN_LOCK  0xf5690002
+#define F0900_P1_FIRST_LOCK  0xf5690001
+
+/*P1_PDELSTATUS2*/
+#define R0900_P1_PDELSTATUS2  0xf56a
+#define F0900_P1_PKTDEL_DEMODSEL  0xf56a0080
+#define F0900_P1_FRAME_MODCOD  0xf56a007c
+#define F0900_P1_FRAME_TYPE  0xf56a0003
+
+/*P1_BBFCRCKO1*/
+#define R0900_P1_BBFCRCKO1  0xf56b
+#define F0900_P1_BBHCRC_KOCNT1  0xf56b00ff
+
+/*P1_BBFCRCKO0*/
+#define R0900_P1_BBFCRCKO0  0xf56c
+#define F0900_P1_BBHCRC_KOCNT0  0xf56c00ff
+
+/*P1_UPCRCKO1*/
+#define R0900_P1_UPCRCKO1  0xf56d
+#define F0900_P1_PKTCRC_KOCNT1  0xf56d00ff
+
+/*P1_UPCRCKO0*/
+#define R0900_P1_UPCRCKO0  0xf56e
+#define F0900_P1_PKTCRC_KOCNT0  0xf56e00ff
+
+/*P1_TSSTATEM*/
+#define R0900_P1_TSSTATEM  0xf570
+#define F0900_P1_TSDIL_ON  0xf5700080
+#define F0900_P1_TSSKIPRS_ON  0xf5700040
+#define F0900_P1_TSRS_ON  0xf5700020
+#define F0900_P1_TSDESCRAMB_ON  0xf5700010
+#define F0900_P1_TSFRAME_MODE  0xf5700008
+#define F0900_P1_TS_DISABLE  0xf5700004
+#define F0900_P1_TSACM_MODE  0xf5700002
+#define F0900_P1_TSOUT_NOSYNC  0xf5700001
+
+/*P1_TSCFGH*/
+#define R0900_P1_TSCFGH  0xf572
+#define F0900_P1_TSFIFO_DVBCI  0xf5720080
+#define F0900_P1_TSFIFO_SERIAL  0xf5720040
+#define F0900_P1_TSFIFO_TEIUPDATE  0xf5720020
+#define F0900_P1_TSFIFO_DUTY50  0xf5720010
+#define F0900_P1_TSFIFO_HSGNLOUT  0xf5720008
+#define F0900_P1_TSFIFO_ERRMODE  0xf5720006
+#define F0900_P1_RST_HWARE  0xf5720001
+
+/*P1_TSCFGM*/
+#define R0900_P1_TSCFGM  0xf573
+#define F0900_P1_TSFIFO_MANSPEED  0xf57300c0
+#define F0900_P1_TSFIFO_PERMDATA  0xf5730020
+#define F0900_P1_TSFIFO_NONEWSGNL  0xf5730010
+#define F0900_P1_TSFIFO_BITSPEED  0xf5730008
+#define F0900_P1_NPD_SPECDVBS2  0xf5730004
+#define F0900_P1_TSFIFO_STOPCKDIS  0xf5730002
+#define F0900_P1_TSFIFO_INVDATA  0xf5730001
+
+/*P1_TSCFGL*/
+#define R0900_P1_TSCFGL  0xf574
+#define F0900_P1_TSFIFO_BCLKDEL1CK  0xf57400c0
+#define F0900_P1_BCHERROR_MODE  0xf5740030
+#define F0900_P1_TSFIFO_NSGNL2DATA  0xf5740008
+#define F0900_P1_TSFIFO_EMBINDVB  0xf5740004
+#define F0900_P1_TSFIFO_DPUNACT  0xf5740002
+#define F0900_P1_TSFIFO_NPDOFF  0xf5740001
+
+/*P1_TSINSDELH*/
+#define R0900_P1_TSINSDELH  0xf576
+#define F0900_P1_TSDEL_SYNCBYTE  0xf5760080
+#define F0900_P1_TSDEL_XXHEADER  0xf5760040
+#define F0900_P1_TSDEL_BBHEADER  0xf5760020
+#define F0900_P1_TSDEL_DATAFIELD  0xf5760010
+#define F0900_P1_TSINSDEL_ISCR  0xf5760008
+#define F0900_P1_TSINSDEL_NPD  0xf5760004
+#define F0900_P1_TSINSDEL_RSPARITY  0xf5760002
+#define F0900_P1_TSINSDEL_CRC8  0xf5760001
+
+/*P1_TSSPEED*/
+#define R0900_P1_TSSPEED  0xf580
+#define F0900_P1_TSFIFO_OUTSPEED  0xf58000ff
+
+/*P1_TSSTATUS*/
+#define R0900_P1_TSSTATUS  0xf581
+#define F0900_P1_TSFIFO_LINEOK  0xf5810080
+#define F0900_P1_TSFIFO_ERROR  0xf5810040
+#define F0900_P1_TSFIFO_DATA7  0xf5810020
+#define F0900_P1_TSFIFO_NOSYNC  0xf5810010
+#define F0900_P1_ISCR_INITIALIZED  0xf5810008
+#define F0900_P1_ISCR_UPDATED  0xf5810004
+#define F0900_P1_SOFFIFO_UNREGUL  0xf5810002
+#define F0900_P1_DIL_READY  0xf5810001
+
+/*P1_TSSTATUS2*/
+#define R0900_P1_TSSTATUS2  0xf582
+#define F0900_P1_TSFIFO_DEMODSEL  0xf5820080
+#define F0900_P1_TSFIFOSPEED_STORE  0xf5820040
+#define F0900_P1_DILXX_RESET  0xf5820020
+#define F0900_P1_TSSERIAL_IMPOS  0xf5820010
+#define F0900_P1_TSFIFO_LINENOK  0xf5820008
+#define F0900_P1_BITSPEED_EVENT  0xf5820004
+#define F0900_P1_SCRAMBDETECT  0xf5820002
+#define F0900_P1_ULDTV67_FALSELOCK  0xf5820001
+
+/*P1_TSBITRATE1*/
+#define R0900_P1_TSBITRATE1  0xf583
+#define F0900_P1_TSFIFO_BITRATE1  0xf58300ff
+
+/*P1_TSBITRATE0*/
+#define R0900_P1_TSBITRATE0  0xf584
+#define F0900_P1_TSFIFO_BITRATE0  0xf58400ff
+
+/*P1_ERRCTRL1*/
+#define R0900_P1_ERRCTRL1  0xf598
+#define F0900_P1_ERR_SOURCE1  0xf59800f0
+#define F0900_P1_NUM_EVENT1  0xf5980007
+
+/*P1_ERRCNT12*/
+#define R0900_P1_ERRCNT12  0xf599
+#define F0900_P1_ERRCNT1_OLDVALUE  0xf5990080
+#define F0900_P1_ERR_CNT12  0xf599007f
+
+/*P1_ERRCNT11*/
+#define R0900_P1_ERRCNT11  0xf59a
+#define F0900_P1_ERR_CNT11  0xf59a00ff
+
+/*P1_ERRCNT10*/
+#define R0900_P1_ERRCNT10  0xf59b
+#define F0900_P1_ERR_CNT10  0xf59b00ff
+
+/*P1_ERRCTRL2*/
+#define R0900_P1_ERRCTRL2  0xf59c
+#define F0900_P1_ERR_SOURCE2  0xf59c00f0
+#define F0900_P1_NUM_EVENT2  0xf59c0007
+
+/*P1_ERRCNT22*/
+#define R0900_P1_ERRCNT22  0xf59d
+#define F0900_P1_ERRCNT2_OLDVALUE  0xf59d0080
+#define F0900_P1_ERR_CNT22  0xf59d007f
+
+/*P1_ERRCNT21*/
+#define R0900_P1_ERRCNT21  0xf59e
+#define F0900_P1_ERR_CNT21  0xf59e00ff
+
+/*P1_ERRCNT20*/
+#define R0900_P1_ERRCNT20  0xf59f
+#define F0900_P1_ERR_CNT20  0xf59f00ff
+
+/*P1_FECSPY*/
+#define R0900_P1_FECSPY  0xf5a0
+#define F0900_P1_SPY_ENABLE  0xf5a00080
+#define F0900_P1_NO_SYNCBYTE  0xf5a00040
+#define F0900_P1_SERIAL_MODE  0xf5a00020
+#define F0900_P1_UNUSUAL_PACKET  0xf5a00010
+#define F0900_P1_BER_PACKMODE  0xf5a00008
+#define F0900_P1_BERMETER_LMODE  0xf5a00002
+#define F0900_P1_BERMETER_RESET  0xf5a00001
+
+/*P1_FSPYCFG*/
+#define R0900_P1_FSPYCFG  0xf5a1
+#define F0900_P1_FECSPY_INPUT  0xf5a100c0
+#define F0900_P1_RST_ON_ERROR  0xf5a10020
+#define F0900_P1_ONE_SHOT  0xf5a10010
+#define F0900_P1_I2C_MODE  0xf5a1000c
+#define F0900_P1_SPY_HYSTERESIS  0xf5a10003
+
+/*P1_FSPYDATA*/
+#define R0900_P1_FSPYDATA  0xf5a2
+#define F0900_P1_SPY_STUFFING  0xf5a20080
+#define F0900_P1_NOERROR_PKTJITTER  0xf5a20040
+#define F0900_P1_SPY_CNULLPKT  0xf5a20020
+#define F0900_P1_SPY_OUTDATA_MODE  0xf5a2001f
+
+/*P1_FSPYOUT*/
+#define R0900_P1_FSPYOUT  0xf5a3
+#define F0900_P1_FSPY_DIRECT  0xf5a30080
+#define F0900_P1_SPY_OUTDATA_BUS  0xf5a30038
+#define F0900_P1_STUFF_MODE  0xf5a30007
+
+/*P1_FSTATUS*/
+#define R0900_P1_FSTATUS  0xf5a4
+#define F0900_P1_SPY_ENDSIM  0xf5a40080
+#define F0900_P1_VALID_SIM  0xf5a40040
+#define F0900_P1_FOUND_SIGNAL  0xf5a40020
+#define F0900_P1_DSS_SYNCBYTE  0xf5a40010
+#define F0900_P1_RESULT_STATE  0xf5a4000f
+
+/*P1_FBERCPT4*/
+#define R0900_P1_FBERCPT4  0xf5a8
+#define F0900_P1_FBERMETER_CPT4  0xf5a800ff
+
+/*P1_FBERCPT3*/
+#define R0900_P1_FBERCPT3  0xf5a9
+#define F0900_P1_FBERMETER_CPT3  0xf5a900ff
+
+/*P1_FBERCPT2*/
+#define R0900_P1_FBERCPT2  0xf5aa
+#define F0900_P1_FBERMETER_CPT2  0xf5aa00ff
+
+/*P1_FBERCPT1*/
+#define R0900_P1_FBERCPT1  0xf5ab
+#define F0900_P1_FBERMETER_CPT1  0xf5ab00ff
+
+/*P1_FBERCPT0*/
+#define R0900_P1_FBERCPT0  0xf5ac
+#define F0900_P1_FBERMETER_CPT0  0xf5ac00ff
+
+/*P1_FBERERR2*/
+#define R0900_P1_FBERERR2  0xf5ad
+#define F0900_P1_FBERMETER_ERR2  0xf5ad00ff
+
+/*P1_FBERERR1*/
+#define R0900_P1_FBERERR1  0xf5ae
+#define F0900_P1_FBERMETER_ERR1  0xf5ae00ff
+
+/*P1_FBERERR0*/
+#define R0900_P1_FBERERR0  0xf5af
+#define F0900_P1_FBERMETER_ERR0  0xf5af00ff
+
+/*P1_FSPYBER*/
+#define R0900_P1_FSPYBER  0xf5b2
+#define F0900_P1_FSPYOBS_XORREAD  0xf5b20040
+#define F0900_P1_FSPYBER_OBSMODE  0xf5b20020
+#define F0900_P1_FSPYBER_SYNCBYTE  0xf5b20010
+#define F0900_P1_FSPYBER_UNSYNC  0xf5b20008
+#define F0900_P1_FSPYBER_CTIME  0xf5b20007
+
+/*RCCFGH*/
+#define R0900_RCCFGH  0xf600
+#define F0900_TSRCFIFO_DVBCI  0xf6000080
+#define F0900_TSRCFIFO_SERIAL  0xf6000040
+#define F0900_TSRCFIFO_DISABLE  0xf6000020
+#define F0900_TSFIFO_2TORC  0xf6000010
+#define F0900_TSRCFIFO_HSGNLOUT  0xf6000008
+#define F0900_TSRCFIFO_ERRMODE  0xf6000006
+
+/*TSGENERAL*/
+#define R0900_TSGENERAL  0xf630
+#define F0900_TSFIFO_BCLK1ALL  0xf6300020
+#define F0900_MUXSTREAM_OUTMODE  0xf6300008
+#define F0900_TSFIFO_PERMPARAL  0xf6300006
+#define F0900_RST_REEDSOLO  0xf6300001
+
+/*TSGENERAL1X*/
+#define R0900_TSGENERAL1X  0xf670
+#define F0900_TSFIFO1X_BCLK1ALL  0xf6700020
+#define F0900_MUXSTREAM1X_OUTMODE  0xf6700008
+#define F0900_TSFIFO1X_PERMPARAL  0xf6700006
+#define F0900_RST1X_REEDSOLO  0xf6700001
+
+/*NBITER_NF4*/
+#define R0900_NBITER_NF4  0xfa03
+#define F0900_NBITER_NF_QP_1_2  0xfa0300ff
+
+/*NBITER_NF5*/
+#define R0900_NBITER_NF5  0xfa04
+#define F0900_NBITER_NF_QP_3_5  0xfa0400ff
+
+/*NBITER_NF6*/
+#define R0900_NBITER_NF6  0xfa05
+#define F0900_NBITER_NF_QP_2_3  0xfa0500ff
+
+/*NBITER_NF7*/
+#define R0900_NBITER_NF7  0xfa06
+#define F0900_NBITER_NF_QP_3_4  0xfa0600ff
+
+/*NBITER_NF8*/
+#define R0900_NBITER_NF8  0xfa07
+#define F0900_NBITER_NF_QP_4_5  0xfa0700ff
+
+/*NBITER_NF9*/
+#define R0900_NBITER_NF9  0xfa08
+#define F0900_NBITER_NF_QP_5_6  0xfa0800ff
+
+/*NBITER_NF10*/
+#define R0900_NBITER_NF10  0xfa09
+#define F0900_NBITER_NF_QP_8_9  0xfa0900ff
+
+/*NBITER_NF11*/
+#define R0900_NBITER_NF11  0xfa0a
+#define F0900_NBITER_NF_QP_9_10  0xfa0a00ff
+
+/*NBITER_NF12*/
+#define R0900_NBITER_NF12  0xfa0b
+#define F0900_NBITER_NF_8P_3_5  0xfa0b00ff
+
+/*NBITER_NF13*/
+#define R0900_NBITER_NF13  0xfa0c
+#define F0900_NBITER_NF_8P_2_3  0xfa0c00ff
+
+/*NBITER_NF14*/
+#define R0900_NBITER_NF14  0xfa0d
+#define F0900_NBITER_NF_8P_3_4  0xfa0d00ff
+
+/*NBITER_NF15*/
+#define R0900_NBITER_NF15  0xfa0e
+#define F0900_NBITER_NF_8P_5_6  0xfa0e00ff
+
+/*NBITER_NF16*/
+#define R0900_NBITER_NF16  0xfa0f
+#define F0900_NBITER_NF_8P_8_9  0xfa0f00ff
+
+/*NBITER_NF17*/
+#define R0900_NBITER_NF17  0xfa10
+#define F0900_NBITER_NF_8P_9_10  0xfa1000ff
+
+/*NBITERNOERR*/
+#define R0900_NBITERNOERR  0xfa3f
+#define F0900_NBITER_STOP_CRIT  0xfa3f000f
+
+/*GAINLLR_NF4*/
+#define R0900_GAINLLR_NF4  0xfa43
+#define F0900_GAINLLR_NF_QP_1_2  0xfa43007f
+
+/*GAINLLR_NF5*/
+#define R0900_GAINLLR_NF5  0xfa44
+#define F0900_GAINLLR_NF_QP_3_5  0xfa44007f
+
+/*GAINLLR_NF6*/
+#define R0900_GAINLLR_NF6  0xfa45
+#define F0900_GAINLLR_NF_QP_2_3  0xfa45007f
+
+/*GAINLLR_NF7*/
+#define R0900_GAINLLR_NF7  0xfa46
+#define F0900_GAINLLR_NF_QP_3_4  0xfa46007f
+
+/*GAINLLR_NF8*/
+#define R0900_GAINLLR_NF8  0xfa47
+#define F0900_GAINLLR_NF_QP_4_5  0xfa47007f
+
+/*GAINLLR_NF9*/
+#define R0900_GAINLLR_NF9  0xfa48
+#define F0900_GAINLLR_NF_QP_5_6  0xfa48007f
+
+/*GAINLLR_NF10*/
+#define R0900_GAINLLR_NF10  0xfa49
+#define F0900_GAINLLR_NF_QP_8_9  0xfa49007f
+
+/*GAINLLR_NF11*/
+#define R0900_GAINLLR_NF11  0xfa4a
+#define F0900_GAINLLR_NF_QP_9_10  0xfa4a007f
+
+/*GAINLLR_NF12*/
+#define R0900_GAINLLR_NF12  0xfa4b
+#define F0900_GAINLLR_NF_8P_3_5  0xfa4b007f
+
+/*GAINLLR_NF13*/
+#define R0900_GAINLLR_NF13  0xfa4c
+#define F0900_GAINLLR_NF_8P_2_3  0xfa4c007f
+
+/*GAINLLR_NF14*/
+#define R0900_GAINLLR_NF14  0xfa4d
+#define F0900_GAINLLR_NF_8P_3_4  0xfa4d007f
+
+/*GAINLLR_NF15*/
+#define R0900_GAINLLR_NF15  0xfa4e
+#define F0900_GAINLLR_NF_8P_5_6  0xfa4e007f
+
+/*GAINLLR_NF16*/
+#define R0900_GAINLLR_NF16  0xfa4f
+#define F0900_GAINLLR_NF_8P_8_9  0xfa4f007f
+
+/*GAINLLR_NF17*/
+#define R0900_GAINLLR_NF17  0xfa50
+#define F0900_GAINLLR_NF_8P_9_10  0xfa50007f
+
+/*CFGEXT*/
+#define R0900_CFGEXT  0xfa80
+#define F0900_STAGMODE  0xfa800080
+#define F0900_BYPBCH  0xfa800040
+#define F0900_BYPLDPC  0xfa800020
+#define F0900_LDPCMODE  0xfa800010
+#define F0900_INVLLRSIGN  0xfa800008
+#define F0900_SHORTMULT  0xfa800004
+#define F0900_EXTERNTX  0xfa800001
+
+/*GENCFG*/
+#define R0900_GENCFG  0xfa86
+#define F0900_BROADCAST  0xfa860010
+#define F0900_NOSHFRD2  0xfa860008
+#define F0900_BCHERRFLAG  0xfa860004
+#define F0900_PRIORITY  0xfa860002
+#define F0900_DDEMOD  0xfa860001
+
+/*LDPCERR1*/
+#define R0900_LDPCERR1  0xfa96
+#define F0900_LDPC_ERRORS_COUNTER1  0xfa9600ff
+
+/*LDPCERR0*/
+#define R0900_LDPCERR0  0xfa97
+#define F0900_LDPC_ERRORS_COUNTER0  0xfa9700ff
+
+/*BCHERR*/
+#define R0900_BCHERR  0xfa98
+#define F0900_ERRORFLAG  0xfa980010
+#define F0900_BCH_ERRORS_COUNTER  0xfa98000f
+
+/*TSTRES0*/
+#define R0900_TSTRES0  0xff11
+#define F0900_FRESFEC  0xff110080
+#define F0900_FRESTS  0xff110040
+#define F0900_FRESVIT1  0xff110020
+#define F0900_FRESVIT2  0xff110010
+#define F0900_FRESSYM1  0xff110008
+#define F0900_FRESSYM2  0xff110004
+#define F0900_FRESMAS  0xff110002
+#define F0900_FRESINT  0xff110001
+
+/*P2_TSTDISRX*/
+#define R0900_P2_TSTDISRX  0xff65
+#define F0900_P2_EN_DISRX  0xff650080
+#define F0900_P2_TST_CURRSRC  0xff650040
+#define F0900_P2_IN_DIGSIGNAL  0xff650020
+#define F0900_P2_HIZ_CURRENTSRC  0xff650010
+#define F0900_TST_P2_PIN_SELECT  0xff650008
+#define F0900_P2_TST_DISRX  0xff650007
+
+/*P1_TSTDISRX*/
+#define R0900_P1_TSTDISRX  0xff67
+#define F0900_P1_EN_DISRX  0xff670080
+#define F0900_P1_TST_CURRSRC  0xff670040
+#define F0900_P1_IN_DIGSIGNAL  0xff670020
+#define F0900_P1_HIZ_CURRENTSRC  0xff670010
+#define F0900_TST_P1_PIN_SELECT  0xff670008
+#define F0900_P1_TST_DISRX  0xff670007
+
+#define STV0900_NBREGS		684
+#define STV0900_NBFIELDS		1702
+
+#endif
+
diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c
new file mode 100644
index 0000000..a5a3153
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0900_sw.c
@@ -0,0 +1,2847 @@
+/*
+ * stv0900_sw.c
+ *
+ * Driver for ST STV0900 satellite demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 "stv0900.h"
+#include "stv0900_reg.h"
+#include "stv0900_priv.h"
+
+int stv0900_check_signal_presence(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 carr_offset,
+	agc2_integr,
+	max_carrier;
+
+	int no_signal;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		carr_offset = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8)
+						| stv0900_read_reg(i_params,
+						R0900_P1_CFR1);
+		carr_offset = ge2comp(carr_offset, 16);
+		agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8)
+						| stv0900_read_reg(i_params,
+						R0900_P1_AGC2I0);
+		max_carrier = i_params->dmd1_srch_range / 1000;
+		break;
+	case STV0900_DEMOD_2:
+		carr_offset = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8)
+						| stv0900_read_reg(i_params,
+						R0900_P2_CFR1);
+		carr_offset = ge2comp(carr_offset, 16);
+		agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8)
+						| stv0900_read_reg(i_params,
+						R0900_P2_AGC2I0);
+		max_carrier = i_params->dmd2_srch_range / 1000;
+		break;
+	}
+
+	max_carrier += (max_carrier / 10);
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= i_params->mclk / 1000;
+	if (max_carrier > 0x4000)
+		max_carrier = 0x4000;
+
+	if ((agc2_integr > 0x2000)
+			|| (carr_offset > + 2*max_carrier)
+			|| (carr_offset < -2*max_carrier))
+		no_signal = TRUE;
+	else
+		no_signal = FALSE;
+
+	return no_signal;
+}
+
+static void stv0900_get_sw_loop_params(struct stv0900_internal *i_params,
+				s32 *frequency_inc, s32 *sw_timeout,
+				s32 *steps,
+				enum fe_stv0900_demod_num demod)
+{
+	s32 timeout, freq_inc, max_steps, srate, max_carrier;
+
+	enum fe_stv0900_search_standard	standard;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		srate = i_params->dmd1_symbol_rate;
+		max_carrier = i_params->dmd1_srch_range / 1000;
+		max_carrier += max_carrier / 10;
+		standard = i_params->dmd1_srch_standard;
+		break;
+	case STV0900_DEMOD_2:
+		srate = i_params->dmd2_symbol_rate;
+		max_carrier = i_params->dmd2_srch_range / 1000;
+		max_carrier += max_carrier / 10;
+		standard = i_params->dmd2_srch_stndrd;
+		break;
+	}
+
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= i_params->mclk / 1000;
+
+	if (max_carrier > 0x4000)
+		max_carrier = 0x4000;
+
+	freq_inc = srate;
+	freq_inc /= i_params->mclk >> 10;
+	freq_inc = freq_inc << 6;
+
+	switch (standard) {
+	case STV0900_SEARCH_DVBS1:
+	case STV0900_SEARCH_DSS:
+		freq_inc *= 3;
+		timeout = 20;
+		break;
+	case STV0900_SEARCH_DVBS2:
+		freq_inc *= 4;
+		timeout = 25;
+		break;
+	case STV0900_AUTO_SEARCH:
+	default:
+		freq_inc *= 3;
+		timeout = 25;
+		break;
+	}
+
+	freq_inc /= 100;
+
+	if ((freq_inc > max_carrier) || (freq_inc < 0))
+		freq_inc = max_carrier / 2;
+
+	timeout *= 27500;
+
+	if (srate > 0)
+		timeout /= srate / 1000;
+
+	if ((timeout > 100) || (timeout < 0))
+		timeout = 100;
+
+	max_steps = (max_carrier / freq_inc) + 1;
+
+	if ((max_steps > 100) || (max_steps < 0)) {
+		max_steps =  100;
+		freq_inc = max_carrier / max_steps;
+	}
+
+	*frequency_inc = freq_inc;
+	*sw_timeout = timeout;
+	*steps = max_steps;
+
+}
+
+static int stv0900_search_carr_sw_loop(struct stv0900_internal *i_params,
+				s32 FreqIncr, s32 Timeout, int zigzag,
+				s32 MaxStep, enum fe_stv0900_demod_num demod)
+{
+	int	no_signal,
+		lock = FALSE;
+	s32	stepCpt,
+		freqOffset,
+		max_carrier;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		max_carrier = i_params->dmd1_srch_range / 1000;
+		max_carrier += (max_carrier / 10);
+		break;
+	case STV0900_DEMOD_2:
+		max_carrier = i_params->dmd2_srch_range / 1000;
+		max_carrier += (max_carrier / 10);
+		break;
+	}
+
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= i_params->mclk / 1000;
+
+	if (max_carrier > 0x4000)
+		max_carrier = 0x4000;
+
+	if (zigzag == TRUE)
+		freqOffset = 0;
+	else
+		freqOffset = -max_carrier + FreqIncr;
+
+	stepCpt = 0;
+
+	do {
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT1,
+					(freqOffset / 256) & 0xFF);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT0,
+					 freqOffset & 0xFF);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+			stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 1);
+
+			if (i_params->chip_id == 0x12) {
+				stv0900_write_bits(i_params,
+						F0900_P1_RST_HWARE, 1);
+				stv0900_write_bits(i_params,
+						F0900_P1_RST_HWARE, 0);
+			}
+			break;
+		case STV0900_DEMOD_2:
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT1,
+					(freqOffset / 256) & 0xFF);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT0,
+					freqOffset & 0xFF);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+			stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 1);
+
+			if (i_params->chip_id == 0x12) {
+				stv0900_write_bits(i_params,
+						F0900_P2_RST_HWARE, 1);
+				stv0900_write_bits(i_params,
+						F0900_P2_RST_HWARE, 0);
+			}
+			break;
+		}
+
+		if (zigzag == TRUE) {
+			if (freqOffset >= 0)
+				freqOffset = -freqOffset - 2 * FreqIncr;
+			else
+				freqOffset = -freqOffset;
+		} else
+			freqOffset += + 2 * FreqIncr;
+
+		stepCpt++;
+		lock = stv0900_get_demod_lock(i_params, demod, Timeout);
+		no_signal = stv0900_check_signal_presence(i_params, demod);
+
+	} while ((lock == FALSE)
+			&& (no_signal == FALSE)
+			&& ((freqOffset - FreqIncr) <  max_carrier)
+			&& ((freqOffset + FreqIncr) > -max_carrier)
+			&& (stepCpt < MaxStep));
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_bits(i_params, F0900_P1_ALGOSWRST, 0);
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_bits(i_params, F0900_P2_ALGOSWRST, 0);
+		break;
+	}
+
+	return lock;
+}
+
+int stv0900_sw_algo(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+	int lock = FALSE;
+
+	int no_signal,
+	zigzag;
+	s32 dvbs2_fly_wheel;
+
+	s32 freqIncrement, softStepTimeout, trialCounter, max_steps;
+
+	stv0900_get_sw_loop_params(i_params, &freqIncrement, &softStepTimeout,
+					&max_steps, demod);
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		switch (i_params->dmd1_srch_standard) {
+		case STV0900_SEARCH_DVBS1:
+		case STV0900_SEARCH_DSS:
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ,
+						0x3B);
+			else
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ,
+						0xef);
+
+			stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x49);
+			zigzag = FALSE;
+			break;
+		case STV0900_SEARCH_DVBS2:
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P1_CORRELABS,
+						0x79);
+			else
+				stv0900_write_reg(i_params, R0900_P1_CORRELABS,
+						0x68);
+
+			stv0900_write_reg(i_params, R0900_P1_DMDCFGMD,
+						0x89);
+
+			zigzag = TRUE;
+			break;
+		case STV0900_AUTO_SEARCH:
+		default:
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ,
+							0x3B);
+				stv0900_write_reg(i_params, R0900_P1_CORRELABS,
+							0x79);
+			} else {
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ,
+							0xef);
+				stv0900_write_reg(i_params, R0900_P1_CORRELABS,
+							0x68);
+			}
+
+			stv0900_write_reg(i_params, R0900_P1_DMDCFGMD,
+							0xc9);
+			zigzag = FALSE;
+			break;
+		}
+
+		trialCounter = 0;
+		do {
+			lock = stv0900_search_carr_sw_loop(i_params,
+							freqIncrement,
+							softStepTimeout,
+							zigzag,
+							max_steps,
+							demod);
+			no_signal = stv0900_check_signal_presence(i_params,
+								demod);
+			trialCounter++;
+			if ((lock == TRUE)
+					|| (no_signal == TRUE)
+					|| (trialCounter == 2)) {
+
+				if (i_params->chip_id >= 0x20) {
+					stv0900_write_reg(i_params,
+							R0900_P1_CARFREQ,
+							0x49);
+					stv0900_write_reg(i_params,
+							R0900_P1_CORRELABS,
+							0x9e);
+				} else {
+					stv0900_write_reg(i_params,
+							R0900_P1_CARFREQ,
+							0xed);
+					stv0900_write_reg(i_params,
+							R0900_P1_CORRELABS,
+							0x88);
+				}
+
+				if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS2_FOUND)) {
+					msleep(softStepTimeout);
+					dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT);
+
+					if (dvbs2_fly_wheel < 0xd) {
+						msleep(softStepTimeout);
+						dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P1_FLYWHEEL_CPT);
+					}
+
+					if (dvbs2_fly_wheel < 0xd) {
+						lock = FALSE;
+
+						if (trialCounter < 2) {
+							if (i_params->chip_id >= 0x20)
+								stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x79);
+							else
+								stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x68);
+
+							stv0900_write_reg(i_params, R0900_P1_DMDCFGMD, 0x89);
+						}
+					}
+				}
+			}
+
+		} while ((lock == FALSE)
+			&& (trialCounter < 2)
+			&& (no_signal == FALSE));
+
+		break;
+	case STV0900_DEMOD_2:
+		switch (i_params->dmd2_srch_stndrd) {
+		case STV0900_SEARCH_DVBS1:
+		case STV0900_SEARCH_DSS:
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ,
+						0x3b);
+			else
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ,
+						0xef);
+
+			stv0900_write_reg(i_params, R0900_P2_DMDCFGMD,
+						0x49);
+			zigzag = FALSE;
+			break;
+		case STV0900_SEARCH_DVBS2:
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P2_CORRELABS,
+						0x79);
+			else
+				stv0900_write_reg(i_params, R0900_P2_CORRELABS,
+						0x68);
+
+			stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89);
+			zigzag = TRUE;
+			break;
+		case STV0900_AUTO_SEARCH:
+		default:
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ,
+						0x3b);
+				stv0900_write_reg(i_params, R0900_P2_CORRELABS,
+						0x79);
+			} else {
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ,
+						0xef);
+				stv0900_write_reg(i_params, R0900_P2_CORRELABS,
+						0x68);
+			}
+
+			stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0xc9);
+
+			zigzag = FALSE;
+			break;
+		}
+
+		trialCounter = 0;
+
+		do {
+			lock = stv0900_search_carr_sw_loop(i_params,
+							freqIncrement,
+							softStepTimeout,
+							zigzag,
+							max_steps,
+							demod);
+			no_signal = stv0900_check_signal_presence(i_params,
+								demod);
+			trialCounter++;
+			if ((lock == TRUE)
+					|| (no_signal == TRUE)
+					|| (trialCounter == 2)) {
+				if (i_params->chip_id >= 0x20) {
+					stv0900_write_reg(i_params,
+							R0900_P2_CARFREQ,
+							0x49);
+					stv0900_write_reg(i_params,
+							R0900_P2_CORRELABS,
+							0x9e);
+				} else {
+					stv0900_write_reg(i_params,
+							R0900_P2_CARFREQ,
+							0xed);
+					stv0900_write_reg(i_params,
+							R0900_P2_CORRELABS,
+							0x88);
+				}
+
+				if ((lock == TRUE) && (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS2_FOUND)) {
+					msleep(softStepTimeout);
+					dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT);
+					if (dvbs2_fly_wheel < 0xd) {
+						msleep(softStepTimeout);
+						dvbs2_fly_wheel = stv0900_get_bits(i_params, F0900_P2_FLYWHEEL_CPT);
+					}
+
+					if (dvbs2_fly_wheel < 0xd) {
+						lock = FALSE;
+						if (trialCounter < 2) {
+							if (i_params->chip_id >= 0x20)
+								stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x79);
+							else
+								stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x68);
+
+							stv0900_write_reg(i_params, R0900_P2_DMDCFGMD, 0x89);
+						}
+					}
+				}
+			}
+
+		} while ((lock == FALSE) && (trialCounter < 2) && (no_signal == FALSE));
+
+		break;
+	}
+
+	return lock;
+}
+
+static u32 stv0900_get_symbol_rate(struct stv0900_internal *i_params,
+					u32 mclk,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 sfr_field3, sfr_field2, sfr_field1, sfr_field0,
+	rem1, rem2, intval1, intval2, srate;
+
+	dmd_reg(sfr_field3, F0900_P1_SYMB_FREQ3, F0900_P2_SYMB_FREQ3);
+	dmd_reg(sfr_field2, F0900_P1_SYMB_FREQ2, F0900_P2_SYMB_FREQ2);
+	dmd_reg(sfr_field1, F0900_P1_SYMB_FREQ1, F0900_P2_SYMB_FREQ1);
+	dmd_reg(sfr_field0, F0900_P1_SYMB_FREQ0, F0900_P2_SYMB_FREQ0);
+
+	srate = (stv0900_get_bits(i_params, sfr_field3) << 24) +
+		(stv0900_get_bits(i_params, sfr_field2) << 16) +
+		(stv0900_get_bits(i_params, sfr_field1) << 8) +
+		(stv0900_get_bits(i_params, sfr_field0));
+	dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n",
+		srate, stv0900_get_bits(i_params, sfr_field0),
+		stv0900_get_bits(i_params, sfr_field1),
+		stv0900_get_bits(i_params, sfr_field2),
+		stv0900_get_bits(i_params, sfr_field3));
+
+	intval1 = (mclk) >> 16;
+	intval2 = (srate) >> 16;
+
+	rem1 = (mclk) % 0x10000;
+	rem2 = (srate) % 0x10000;
+	srate =	(intval1 * intval2) +
+		((intval1 * rem2) >> 16) +
+		((intval2 * rem1) >> 16);
+
+	return srate;
+}
+
+static void stv0900_set_symbol_rate(struct stv0900_internal *i_params,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 sfr_init_reg;
+	u32 symb;
+
+	dprintk(KERN_INFO "%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk,
+							srate, demod);
+
+	dmd_reg(sfr_init_reg, R0900_P1_SFRINIT1, R0900_P2_SFRINIT1);
+
+	if (srate > 60000000) {
+		symb = srate << 4;
+		symb /= (mclk >> 12);
+	} else if (srate > 6000000) {
+		symb = srate << 6;
+		symb /= (mclk >> 10);
+	} else {
+		symb = srate << 9;
+		symb /= (mclk >> 7);
+	}
+
+	stv0900_write_reg(i_params, sfr_init_reg, (symb >> 8) & 0x7F);
+	stv0900_write_reg(i_params, sfr_init_reg + 1, (symb & 0xFF));
+}
+
+static void stv0900_set_max_symbol_rate(struct stv0900_internal *i_params,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 sfr_max_reg;
+	u32 symb;
+
+	dmd_reg(sfr_max_reg, R0900_P1_SFRUP1, R0900_P2_SFRUP1);
+
+	srate = 105 * (srate / 100);
+
+	if (srate > 60000000) {
+		symb = srate << 4;
+		symb /= (mclk >> 12);
+	} else if (srate > 6000000) {
+		symb = srate << 6;
+		symb /= (mclk >> 10);
+	} else {
+		symb = srate << 9;
+		symb /= (mclk >> 7);
+	}
+
+	if (symb < 0x7fff) {
+		stv0900_write_reg(i_params, sfr_max_reg, (symb >> 8) & 0x7F);
+		stv0900_write_reg(i_params, sfr_max_reg + 1, (symb & 0xFF));
+	} else {
+		stv0900_write_reg(i_params, sfr_max_reg, 0x7F);
+		stv0900_write_reg(i_params, sfr_max_reg + 1, 0xFF);
+	}
+}
+
+static void stv0900_set_min_symbol_rate(struct stv0900_internal *i_params,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 sfr_min_reg;
+	u32	symb;
+
+	dmd_reg(sfr_min_reg, R0900_P1_SFRLOW1, R0900_P2_SFRLOW1);
+
+	srate = 95 * (srate / 100);
+	if (srate > 60000000) {
+		symb = srate << 4;
+		symb /= (mclk >> 12);
+
+	} else if (srate > 6000000) {
+		symb = srate << 6;
+		symb /= (mclk >> 10);
+
+	} else {
+		symb = srate << 9;
+		symb /= (mclk >> 7);
+	}
+
+	stv0900_write_reg(i_params, sfr_min_reg, (symb >> 8) & 0xFF);
+	stv0900_write_reg(i_params, sfr_min_reg + 1, (symb & 0xFF));
+}
+
+static s32 stv0900_get_timing_offst(struct stv0900_internal *i_params,
+					u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 tmgreg,
+	timingoffset;
+
+	dmd_reg(tmgreg, R0900_P1_TMGREG2, R0900_P2_TMGREG2);
+
+	timingoffset = (stv0900_read_reg(i_params, tmgreg) << 16) +
+		       (stv0900_read_reg(i_params, tmgreg + 1) << 8) +
+		       (stv0900_read_reg(i_params, tmgreg + 2));
+
+	timingoffset = ge2comp(timingoffset, 24);
+
+
+	if (timingoffset == 0)
+		timingoffset = 1;
+
+	timingoffset = ((s32)srate * 10) / ((s32)0x1000000 / timingoffset);
+	timingoffset /= 320;
+
+	return timingoffset;
+}
+
+static void stv0900_set_dvbs2_rolloff(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 rolloff, man_fld, matstr_reg, rolloff_ctl_fld;
+
+	dmd_reg(man_fld, F0900_P1_MANUAL_ROLLOFF, F0900_P2_MANUAL_ROLLOFF);
+	dmd_reg(matstr_reg, R0900_P1_MATSTR1, R0900_P2_MATSTR1);
+	dmd_reg(rolloff_ctl_fld, F0900_P1_ROLLOFF_CONTROL,
+				F0900_P2_ROLLOFF_CONTROL);
+
+	if (i_params->chip_id == 0x10) {
+		stv0900_write_bits(i_params, man_fld, 1);
+		rolloff = stv0900_read_reg(i_params, matstr_reg) & 0x03;
+		stv0900_write_bits(i_params, rolloff_ctl_fld, rolloff);
+	} else
+		stv0900_write_bits(i_params, man_fld, 0);
+}
+
+static u32 stv0900_carrier_width(u32 srate, enum fe_stv0900_rolloff ro)
+{
+	u32 rolloff;
+
+	switch (ro) {
+	case STV0900_20:
+		rolloff = 20;
+		break;
+	case STV0900_25:
+		rolloff = 25;
+		break;
+	case STV0900_35:
+	default:
+		rolloff = 35;
+		break;
+	}
+
+	return srate  + (srate * rolloff) / 100;
+}
+
+static int stv0900_check_timing_lock(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod)
+{
+	int timingLock = FALSE;
+	s32 i,
+	timingcpt = 0;
+	u8 carFreq,
+	tmgTHhigh,
+	tmgTHLow;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		carFreq = stv0900_read_reg(i_params, R0900_P1_CARFREQ);
+		tmgTHhigh = stv0900_read_reg(i_params, R0900_P1_TMGTHRISE);
+		tmgTHLow = stv0900_read_reg(i_params, R0900_P1_TMGTHFALL);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x0);
+		stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0);
+		stv0900_write_reg(i_params, R0900_P1_RTC, 0x80);
+		stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x40);
+		stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x0);
+		stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0x0);
+		stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0x0);
+		stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x65);
+		stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+		msleep(7);
+
+		for (i = 0; i < 10; i++) {
+			if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2)
+				timingcpt++;
+
+			msleep(1);
+		}
+
+		if (timingcpt >= 3)
+			timingLock = TRUE;
+
+		stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38);
+		stv0900_write_reg(i_params, R0900_P1_RTC, 0x88);
+		stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x68);
+		stv0900_write_reg(i_params, R0900_P1_CARFREQ, carFreq);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, tmgTHhigh);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, tmgTHLow);
+		break;
+	case STV0900_DEMOD_2:
+		carFreq = stv0900_read_reg(i_params, R0900_P2_CARFREQ);
+		tmgTHhigh = stv0900_read_reg(i_params, R0900_P2_TMGTHRISE);
+		tmgTHLow = stv0900_read_reg(i_params, R0900_P2_TMGTHFALL);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0);
+		stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0);
+		stv0900_write_reg(i_params, R0900_P2_RTC, 0x80);
+		stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x40);
+		stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x0);
+		stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0x0);
+		stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0x0);
+		stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x65);
+		stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+		msleep(5);
+		for (i = 0; i < 10; i++) {
+			if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2)
+				timingcpt++;
+
+			msleep(1);
+		}
+
+		if (timingcpt >= 3)
+			timingLock = TRUE;
+
+		stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38);
+		stv0900_write_reg(i_params, R0900_P2_RTC, 0x88);
+		stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x68);
+		stv0900_write_reg(i_params, R0900_P2_CARFREQ, carFreq);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, tmgTHhigh);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, tmgTHLow);
+		break;
+	}
+
+	return	timingLock;
+}
+
+static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe,
+					s32 demod_timeout)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	int lock = FALSE;
+	s32 srate, search_range, locktimeout,
+		currier_step, nb_steps, current_step,
+		direction, tuner_freq, timeout;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		srate = i_params->dmd1_symbol_rate;
+		search_range = i_params->dmd1_srch_range;
+		break;
+
+	case STV0900_DEMOD_2:
+		srate = i_params->dmd2_symbol_rate;
+		search_range = i_params->dmd2_srch_range;
+		break;
+	}
+
+	if (srate >= 10000000)
+		locktimeout = demod_timeout / 3;
+	else
+		locktimeout = demod_timeout / 2;
+
+	lock = stv0900_get_demod_lock(i_params, demod, locktimeout);
+
+	if (lock == FALSE) {
+		if (srate >= 10000000) {
+			if (stv0900_check_timing_lock(i_params, demod) == TRUE) {
+				switch (demod) {
+				case STV0900_DEMOD_1:
+				default:
+					stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1f);
+					stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15);
+					break;
+				case STV0900_DEMOD_2:
+					stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1f);
+					stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15);
+					break;
+				}
+
+				lock = stv0900_get_demod_lock(i_params, demod, demod_timeout);
+			} else
+				lock = FALSE;
+		} else {
+			if (srate <= 4000000)
+				currier_step = 1000;
+			else if (srate <= 7000000)
+				currier_step = 2000;
+			else if (srate <= 10000000)
+				currier_step = 3000;
+			else
+				currier_step = 5000;
+
+			nb_steps = ((search_range / 1000) / currier_step);
+			nb_steps /= 2;
+			nb_steps = (2 * (nb_steps + 1));
+			if (nb_steps < 0)
+				nb_steps = 2;
+			else if (nb_steps > 12)
+				nb_steps = 12;
+
+			current_step = 1;
+			direction = 1;
+			timeout = (demod_timeout / 3);
+			if (timeout > 1000)
+				timeout = 1000;
+
+			switch (demod) {
+			case STV0900_DEMOD_1:
+			default:
+				if (lock == FALSE) {
+					tuner_freq = i_params->tuner1_freq;
+					i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + i_params->dmd1_symbol_rate;
+
+					while ((current_step <= nb_steps) && (lock == FALSE)) {
+
+						if (direction > 0)
+							tuner_freq += (current_step * currier_step);
+						else
+							tuner_freq -= (current_step * currier_step);
+
+						stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw);
+						stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C);
+						if (i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS2) {
+							stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0);
+							stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+							stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+							stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1);
+						}
+
+						stv0900_write_reg(i_params, R0900_P1_CFRINIT1, 0);
+						stv0900_write_reg(i_params, R0900_P1_CFRINIT0, 0);
+						stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F);
+						stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15);
+						lock = stv0900_get_demod_lock(i_params, demod, timeout);
+						direction *= -1;
+						current_step++;
+					}
+				}
+				break;
+			case STV0900_DEMOD_2:
+				if (lock == FALSE) {
+					tuner_freq = i_params->tuner2_freq;
+					i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + srate;
+
+					while ((current_step <= nb_steps) && (lock == FALSE)) {
+
+						if (direction > 0)
+							tuner_freq += (current_step * currier_step);
+						else
+							tuner_freq -= (current_step * currier_step);
+
+						stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw);
+						stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C);
+						if (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS2) {
+							stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0);
+							stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+							stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+							stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1);
+						}
+
+						stv0900_write_reg(i_params, R0900_P2_CFRINIT1, 0);
+						stv0900_write_reg(i_params, R0900_P2_CFRINIT0, 0);
+						stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F);
+						stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15);
+						lock = stv0900_get_demod_lock(i_params, demod, timeout);
+						direction *= -1;
+						current_step++;
+					}
+				}
+				break;
+			}
+		}
+	}
+
+	return	lock;
+}
+
+static void stv0900_get_lock_timeout(s32 *demod_timeout, s32 *fec_timeout,
+					s32 srate,
+					enum fe_stv0900_search_algo algo)
+{
+	switch (algo) {
+	case STV0900_BLIND_SEARCH:
+		if (srate <= 1500000) {
+			(*demod_timeout) = 1500;
+			(*fec_timeout) = 400;
+		} else if (srate <= 5000000) {
+			(*demod_timeout) = 1000;
+			(*fec_timeout) = 300;
+		} else {
+			(*demod_timeout) = 700;
+			(*fec_timeout) = 100;
+		}
+
+		break;
+	case STV0900_COLD_START:
+	case STV0900_WARM_START:
+	default:
+		if (srate <= 1000000) {
+			(*demod_timeout) = 3000;
+			(*fec_timeout) = 1700;
+		} else if (srate <= 2000000) {
+			(*demod_timeout) = 2500;
+			(*fec_timeout) = 1100;
+		} else if (srate <= 5000000) {
+			(*demod_timeout) = 1000;
+			(*fec_timeout) = 550;
+		} else if (srate <= 10000000) {
+			(*demod_timeout) = 700;
+			(*fec_timeout) = 250;
+		} else if (srate <= 20000000) {
+			(*demod_timeout) = 400;
+			(*fec_timeout) = 130;
+		}
+
+		else {
+			(*demod_timeout) = 300;
+			(*fec_timeout) = 100;
+		}
+
+		break;
+
+	}
+
+	if (algo == STV0900_WARM_START)
+		(*demod_timeout) /= 2;
+}
+
+static void stv0900_set_viterbi_tracq(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+
+	s32 vth_reg;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12);
+
+	stv0900_write_reg(i_params, vth_reg++, 0xd0);
+	stv0900_write_reg(i_params, vth_reg++, 0x7d);
+	stv0900_write_reg(i_params, vth_reg++, 0x53);
+	stv0900_write_reg(i_params, vth_reg++, 0x2F);
+	stv0900_write_reg(i_params, vth_reg++, 0x24);
+	stv0900_write_reg(i_params, vth_reg++, 0x1F);
+}
+
+static void stv0900_set_viterbi_standard(struct stv0900_internal *i_params,
+				   enum fe_stv0900_search_standard Standard,
+				   enum fe_stv0900_fec PunctureRate,
+				   enum fe_stv0900_demod_num demod)
+{
+
+	s32 fecmReg,
+	prvitReg;
+
+	dprintk(KERN_INFO "%s: ViterbiStandard = ", __func__);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		fecmReg = R0900_P1_FECM;
+		prvitReg = R0900_P1_PRVIT;
+		break;
+	case STV0900_DEMOD_2:
+		fecmReg = R0900_P2_FECM;
+		prvitReg = R0900_P2_PRVIT;
+		break;
+	}
+
+	switch (Standard) {
+	case STV0900_AUTO_SEARCH:
+		dprintk("Auto\n");
+		stv0900_write_reg(i_params, fecmReg, 0x10);
+		stv0900_write_reg(i_params, prvitReg, 0x3F);
+		break;
+	case STV0900_SEARCH_DVBS1:
+		dprintk("DVBS1\n");
+		stv0900_write_reg(i_params, fecmReg, 0x00);
+		switch (PunctureRate) {
+		case STV0900_FEC_UNKNOWN:
+		default:
+			stv0900_write_reg(i_params, prvitReg, 0x2F);
+			break;
+		case STV0900_FEC_1_2:
+			stv0900_write_reg(i_params, prvitReg, 0x01);
+			break;
+		case STV0900_FEC_2_3:
+			stv0900_write_reg(i_params, prvitReg, 0x02);
+			break;
+		case STV0900_FEC_3_4:
+			stv0900_write_reg(i_params, prvitReg, 0x04);
+			break;
+		case STV0900_FEC_5_6:
+			stv0900_write_reg(i_params, prvitReg, 0x08);
+			break;
+		case STV0900_FEC_7_8:
+			stv0900_write_reg(i_params, prvitReg, 0x20);
+			break;
+		}
+
+		break;
+	case STV0900_SEARCH_DSS:
+		dprintk("DSS\n");
+		stv0900_write_reg(i_params, fecmReg, 0x80);
+		switch (PunctureRate) {
+		case STV0900_FEC_UNKNOWN:
+		default:
+			stv0900_write_reg(i_params, prvitReg, 0x13);
+			break;
+		case STV0900_FEC_1_2:
+			stv0900_write_reg(i_params, prvitReg, 0x01);
+			break;
+		case STV0900_FEC_2_3:
+			stv0900_write_reg(i_params, prvitReg, 0x02);
+			break;
+		case STV0900_FEC_6_7:
+			stv0900_write_reg(i_params, prvitReg, 0x10);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void stv0900_track_optimization(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32 srate, pilots, aclc, freq1, freq0,
+		i = 0, timed, timef, blindTunSw = 0;
+
+	enum fe_stv0900_rolloff rolloff;
+	enum fe_stv0900_modcode foundModcod;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+	srate += stv0900_get_timing_offst(i_params, srate, demod);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		switch (i_params->dmd1_rslts.standard) {
+		case STV0900_DVBS1_STANDARD:
+			if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) {
+				stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+				stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+			}
+
+			stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff);
+			stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1);
+			stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75);
+			break;
+		case STV0900_DSS_STANDARD:
+			if (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH) {
+				stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+				stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+			}
+
+			stv0900_write_bits(i_params, F0900_P1_ROLLOFF_CONTROL, i_params->rolloff);
+			stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1);
+			stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75);
+			break;
+		case STV0900_DVBS2_STANDARD:
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1);
+			stv0900_write_reg(i_params, R0900_P1_ACLC, 0);
+			stv0900_write_reg(i_params, R0900_P1_BCLC, 0);
+			if (i_params->dmd1_rslts.frame_length == STV0900_LONG_FRAME) {
+				foundModcod = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD);
+				pilots = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01;
+				aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id);
+				if (foundModcod <= STV0900_QPSK_910)
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc);
+				else if (foundModcod <= STV0900_8PSK_910) {
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc);
+				}
+
+				if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) {
+					if (foundModcod <= STV0900_16APSK_910) {
+						stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+						stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc);
+					} else if (foundModcod <= STV0900_32APSK_910) {
+						stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+						stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc);
+					}
+				}
+
+			} else {
+				aclc = stv0900_get_optim_short_carr_loop(srate, i_params->dmd1_rslts.modulation, i_params->chip_id);
+				if (i_params->dmd1_rslts.modulation == STV0900_QPSK)
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, aclc);
+
+				else if (i_params->dmd1_rslts.modulation == STV0900_8PSK) {
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S28, aclc);
+				} else if (i_params->dmd1_rslts.modulation == STV0900_16APSK) {
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S216A, aclc);
+				} else if (i_params->dmd1_rslts.modulation == STV0900_32APSK) {
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P1_ACLC2S232A, aclc);
+				}
+
+			}
+
+			if (i_params->chip_id <= 0x11) {
+				if (i_params->demod_mode != STV0900_SINGLE)
+					stv0900_activate_s2_modcode(i_params, demod);
+
+			}
+
+			stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67);
+			break;
+		case STV0900_UNKNOWN_STANDARD:
+		default:
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1);
+			break;
+		}
+
+		freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2);
+		freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1);
+		rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS);
+		if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) {
+			stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x00);
+			stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0);
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01);
+			stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod);
+			stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod);
+			stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod);
+			blindTunSw = 1;
+		}
+
+		if (i_params->chip_id >= 0x20) {
+			if ((i_params->dmd1_srch_standard == STV0900_SEARCH_DVBS1) || (i_params->dmd1_srch_standard == STV0900_SEARCH_DSS) || (i_params->dmd1_srch_standard == STV0900_AUTO_SEARCH)) {
+				stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0a);
+				stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x0);
+			}
+		}
+
+		if (i_params->chip_id < 0x20)
+			stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x08);
+
+		if (i_params->chip_id == 0x10)
+			stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0x0A);
+
+		stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38);
+
+		if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd1_symbol_rate < 10000000)) {
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0);
+			i_params->tuner1_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000;
+
+			if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) {
+				if (i_params->dmd1_srch_algo != STV0900_WARM_START)
+					stv0900_set_bandwidth(fe, i_params->tuner1_bw);
+			}
+
+			if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000))
+				msleep(50);
+			else
+				msleep(5);
+
+			stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START);
+
+			if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) {
+				stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F);
+				stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1);
+				stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0);
+				stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+				i = 0;
+				while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) {
+					stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F);
+					stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1);
+					stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0);
+					stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+					i++;
+				}
+			}
+
+		}
+
+		if (i_params->chip_id >= 0x20)
+			stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49);
+
+		if ((i_params->dmd1_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd1_rslts.standard == STV0900_DSS_STANDARD))
+			stv0900_set_viterbi_tracq(i_params, demod);
+
+		break;
+
+	case STV0900_DEMOD_2:
+		switch (i_params->dmd2_rslts.standard) {
+		case STV0900_DVBS1_STANDARD:
+
+			if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) {
+				stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+				stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+			}
+
+			stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff);
+			stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1);
+			stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75);
+			break;
+		case STV0900_DSS_STANDARD:
+			if (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH) {
+				stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+				stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+			}
+
+			stv0900_write_bits(i_params, F0900_P2_ROLLOFF_CONTROL, i_params->rolloff);
+			stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1);
+			stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75);
+			break;
+		case STV0900_DVBS2_STANDARD:
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1);
+			stv0900_write_reg(i_params, R0900_P2_ACLC, 0);
+			stv0900_write_reg(i_params, R0900_P2_BCLC, 0);
+			if (i_params->dmd2_rslts.frame_length == STV0900_LONG_FRAME) {
+				foundModcod = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD);
+				pilots = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01;
+				aclc = stv0900_get_optim_carr_loop(srate, foundModcod, pilots, i_params->chip_id);
+				if (foundModcod <= STV0900_QPSK_910)
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc);
+				else if (foundModcod <= STV0900_8PSK_910) {
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc);
+				}
+
+				if ((i_params->demod_mode == STV0900_SINGLE) && (foundModcod > STV0900_8PSK_910)) {
+					if (foundModcod <= STV0900_16APSK_910) {
+						stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+						stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc);
+					} else if (foundModcod <= STV0900_32APSK_910) {
+						stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+						stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc);
+					}
+
+				}
+
+			} else {
+				aclc = stv0900_get_optim_short_carr_loop(srate,
+									i_params->dmd2_rslts.modulation,
+									i_params->chip_id);
+
+				if (i_params->dmd2_rslts.modulation == STV0900_QPSK)
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, aclc);
+
+				else if (i_params->dmd2_rslts.modulation == STV0900_8PSK) {
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S28, aclc);
+				} else if (i_params->dmd2_rslts.modulation == STV0900_16APSK) {
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S216A, aclc);
+				} else if (i_params->dmd2_rslts.modulation == STV0900_32APSK) {
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S2Q, 0x2a);
+					stv0900_write_reg(i_params, R0900_P2_ACLC2S232A, aclc);
+				}
+			}
+
+			stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67);
+
+			break;
+		case STV0900_UNKNOWN_STANDARD:
+		default:
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1);
+			break;
+		}
+
+		freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2);
+		freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1);
+		rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS);
+		if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) {
+			stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x00);
+			stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0);
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01);
+			stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod);
+			stv0900_set_max_symbol_rate(i_params, i_params->mclk, srate, demod);
+			stv0900_set_min_symbol_rate(i_params, i_params->mclk, srate, demod);
+			blindTunSw = 1;
+		}
+
+		if (i_params->chip_id >= 0x20) {
+			if ((i_params->dmd2_srch_stndrd == STV0900_SEARCH_DVBS1) || (i_params->dmd2_srch_stndrd == STV0900_SEARCH_DSS) || (i_params->dmd2_srch_stndrd == STV0900_AUTO_SEARCH)) {
+				stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0a);
+				stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x0);
+			}
+		}
+
+		if (i_params->chip_id < 0x20)
+			stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x08);
+
+		if (i_params->chip_id == 0x10)
+			stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0x0a);
+
+		stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38);
+		if ((i_params->chip_id >= 0x20) || (blindTunSw == 1) || (i_params->dmd2_symbol_rate < 10000000)) {
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0);
+			i_params->tuner2_bw = stv0900_carrier_width(srate, i_params->rolloff) + 10000000;
+
+			if ((i_params->chip_id >= 0x20) || (blindTunSw == 1)) {
+				if (i_params->dmd2_srch_algo != STV0900_WARM_START)
+					stv0900_set_bandwidth(fe, i_params->tuner2_bw);
+			}
+
+			if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000))
+				msleep(50);
+			else
+				msleep(5);
+
+			stv0900_get_lock_timeout(&timed, &timef, srate, STV0900_WARM_START);
+			if (stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) {
+				stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F);
+				stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1);
+				stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0);
+				stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+				i = 0;
+				while ((stv0900_get_demod_lock(i_params, demod, timed / 2) == FALSE) && (i <= 2)) {
+					stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F);
+					stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1);
+					stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0);
+					stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+					i++;
+				}
+			}
+		}
+
+		if (i_params->chip_id >= 0x20)
+			stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49);
+
+		if ((i_params->dmd2_rslts.standard == STV0900_DVBS1_STANDARD) || (i_params->dmd2_rslts.standard == STV0900_DSS_STANDARD))
+			stv0900_set_viterbi_tracq(i_params, demod);
+
+		break;
+	}
+}
+
+static int stv0900_get_fec_lock(struct stv0900_internal *i_params, enum fe_stv0900_demod_num demod, s32 time_out)
+{
+	s32 timer = 0, lock = 0, header_field, pktdelin_field, lock_vit_field;
+
+	enum fe_stv0900_search_state dmd_state;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(header_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE);
+	dmd_reg(pktdelin_field, F0900_P1_PKTDELIN_LOCK, F0900_P2_PKTDELIN_LOCK);
+	dmd_reg(lock_vit_field, F0900_P1_LOCKEDVIT, F0900_P2_LOCKEDVIT);
+
+	dmd_state = stv0900_get_bits(i_params, header_field);
+
+	while ((timer < time_out) && (lock == 0)) {
+		switch (dmd_state) {
+		case STV0900_SEARCH:
+		case STV0900_PLH_DETECTED:
+		default:
+			lock = 0;
+			break;
+		case STV0900_DVBS2_FOUND:
+			lock = stv0900_get_bits(i_params, pktdelin_field);
+			break;
+		case STV0900_DVBS_FOUND:
+			lock = stv0900_get_bits(i_params, lock_vit_field);
+			break;
+		}
+
+		if (lock == 0) {
+			msleep(10);
+			timer += 10;
+		}
+	}
+
+	if (lock)
+		dprintk("DEMOD FEC LOCK OK\n");
+	else
+		dprintk("DEMOD FEC LOCK FAIL\n");
+
+	return lock;
+}
+
+static int stv0900_wait_for_lock(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod,
+				s32 dmd_timeout, s32 fec_timeout)
+{
+
+	s32 timer = 0, lock = 0, str_merg_rst_fld, str_merg_lock_fld;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(str_merg_rst_fld, F0900_P1_RST_HWARE, F0900_P2_RST_HWARE);
+	dmd_reg(str_merg_lock_fld, F0900_P1_TSFIFO_LINEOK, F0900_P2_TSFIFO_LINEOK);
+
+	lock = stv0900_get_demod_lock(i_params, demod, dmd_timeout);
+
+	if (lock)
+		lock = lock && stv0900_get_fec_lock(i_params, demod, fec_timeout);
+
+	if (lock) {
+		lock = 0;
+
+		dprintk(KERN_INFO "%s: Timer = %d, time_out = %d\n", __func__, timer, fec_timeout);
+
+		while ((timer < fec_timeout) && (lock == 0)) {
+			lock = stv0900_get_bits(i_params, str_merg_lock_fld);
+			msleep(1);
+			timer++;
+		}
+	}
+
+	if (lock)
+		dprintk(KERN_INFO "%s: DEMOD LOCK OK\n", __func__);
+	else
+		dprintk(KERN_INFO "%s: DEMOD LOCK FAIL\n", __func__);
+
+	if (lock)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+enum fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe,
+						enum fe_stv0900_demod_num demod)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_tracking_standard fnd_standard;
+	s32 state_field,
+	dss_dvb_field;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(state_field, F0900_P1_HEADER_MODE, F0900_P2_HEADER_MODE);
+	dmd_reg(dss_dvb_field, F0900_P1_DSS_DVB, F0900_P2_DSS_DVB);
+
+	if (stv0900_get_bits(i_params, state_field) == 2)
+		fnd_standard = STV0900_DVBS2_STANDARD;
+
+	else if (stv0900_get_bits(i_params, state_field) == 3) {
+		if (stv0900_get_bits(i_params, dss_dvb_field) == 1)
+			fnd_standard = STV0900_DSS_STANDARD;
+		else
+			fnd_standard = STV0900_DVBS1_STANDARD;
+	} else
+		fnd_standard = STV0900_UNKNOWN_STANDARD;
+
+	return fnd_standard;
+}
+
+static s32 stv0900_get_carr_freq(struct stv0900_internal *i_params, u32 mclk,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 cfr_field2, cfr_field1, cfr_field0,
+		derot, rem1, rem2, intval1, intval2;
+
+	dmd_reg(cfr_field2, F0900_P1_CAR_FREQ2, F0900_P2_CAR_FREQ2);
+	dmd_reg(cfr_field1, F0900_P1_CAR_FREQ1, F0900_P2_CAR_FREQ1);
+	dmd_reg(cfr_field0, F0900_P1_CAR_FREQ0, F0900_P2_CAR_FREQ0);
+
+	derot = (stv0900_get_bits(i_params, cfr_field2) << 16) +
+		(stv0900_get_bits(i_params, cfr_field1) << 8) +
+		(stv0900_get_bits(i_params, cfr_field0));
+
+	derot = ge2comp(derot, 24);
+	intval1 = mclk >> 12;
+	intval2 = derot >> 12;
+	rem1 = mclk % 0x1000;
+	rem2 = derot % 0x1000;
+	derot = (intval1 * intval2) +
+		((intval1 * rem2) >> 12) +
+		((intval2 * rem1) >> 12);
+
+	return derot;
+}
+
+static u32 stv0900_get_tuner_freq(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops *tuner_ops = NULL;
+	u32 frequency = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+
+	if (tuner_ops->get_frequency) {
+		if ((tuner_ops->get_frequency(fe, &frequency)) < 0)
+			dprintk("%s: Invalid parameter\n", __func__);
+		else
+			dprintk("%s: Frequency=%d\n", __func__, frequency);
+
+	}
+
+	return frequency;
+}
+
+static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *i_params,
+						enum fe_stv0900_demod_num demod)
+{
+	s32 rate_fld, vit_curpun_fld;
+	enum fe_stv0900_fec prate;
+
+	dmd_reg(vit_curpun_fld, F0900_P1_VIT_CURPUN, F0900_P2_VIT_CURPUN);
+	rate_fld = stv0900_get_bits(i_params, vit_curpun_fld);
+
+	switch (rate_fld) {
+	case 13:
+		prate = STV0900_FEC_1_2;
+		break;
+	case 18:
+		prate = STV0900_FEC_2_3;
+		break;
+	case 21:
+		prate = STV0900_FEC_3_4;
+		break;
+	case 24:
+		prate = STV0900_FEC_5_6;
+		break;
+	case 25:
+		prate = STV0900_FEC_6_7;
+		break;
+	case 26:
+		prate = STV0900_FEC_7_8;
+		break;
+	default:
+		prate = STV0900_FEC_UNKNOWN;
+		break;
+	}
+
+	return prate;
+}
+
+static enum fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE;
+	s32 offsetFreq,
+	srate_offset,
+	i = 0;
+
+	u8 timing;
+
+	msleep(5);
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) {
+			timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2);
+			i = 0;
+			stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x5c);
+
+			while ((i <= 50) && (timing != 0) && (timing != 0xFF)) {
+				timing = stv0900_read_reg(i_params, R0900_P1_TMGREG2);
+				msleep(5);
+				i += 5;
+			}
+		}
+
+		i_params->dmd1_rslts.standard = stv0900_get_standard(fe, demod);
+		i_params->dmd1_rslts.frequency = stv0900_get_tuner_freq(fe);
+		offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000;
+		i_params->dmd1_rslts.frequency += offsetFreq;
+		i_params->dmd1_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+		srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd1_rslts.symbol_rate, demod);
+		i_params->dmd1_rslts.symbol_rate += srate_offset;
+		i_params->dmd1_rslts.fec = stv0900_get_vit_fec(i_params, demod);
+		i_params->dmd1_rslts.modcode = stv0900_get_bits(i_params, F0900_P1_DEMOD_MODCOD);
+		i_params->dmd1_rslts.pilot = stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE) & 0x01;
+		i_params->dmd1_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P1_DEMOD_TYPE)) >> 1;
+		i_params->dmd1_rslts.rolloff = stv0900_get_bits(i_params, F0900_P1_ROLLOFF_STATUS);
+		switch (i_params->dmd1_rslts.standard) {
+		case STV0900_DVBS2_STANDARD:
+			i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_SPECINV_DEMOD);
+			if (i_params->dmd1_rslts.modcode <= STV0900_QPSK_910)
+				i_params->dmd1_rslts.modulation = STV0900_QPSK;
+			else if (i_params->dmd1_rslts.modcode <= STV0900_8PSK_910)
+				i_params->dmd1_rslts.modulation = STV0900_8PSK;
+			else if (i_params->dmd1_rslts.modcode <= STV0900_16APSK_910)
+				i_params->dmd1_rslts.modulation = STV0900_16APSK;
+			else if (i_params->dmd1_rslts.modcode <= STV0900_32APSK_910)
+				i_params->dmd1_rslts.modulation = STV0900_32APSK;
+			else
+				i_params->dmd1_rslts.modulation = STV0900_UNKNOWN;
+			break;
+		case STV0900_DVBS1_STANDARD:
+		case STV0900_DSS_STANDARD:
+			i_params->dmd1_rslts.spectrum = stv0900_get_bits(i_params, F0900_P1_IQINV);
+			i_params->dmd1_rslts.modulation = STV0900_QPSK;
+			break;
+		default:
+			break;
+		}
+
+		if ((i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd1_symbol_rate < 10000000)) {
+			offsetFreq =	i_params->dmd1_rslts.frequency - i_params->tuner1_freq;
+			i_params->tuner1_freq = stv0900_get_tuner_freq(fe);
+			if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500))
+				range = STV0900_RANGEOK;
+			else
+				if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd1_rslts.symbol_rate, i_params->dmd1_rslts.rolloff) / 2000))
+					range = STV0900_RANGEOK;
+				else
+					range = STV0900_OUTOFRANGE;
+
+		} else {
+			if (ABS(offsetFreq) <= ((i_params->dmd1_srch_range / 2000) + 500))
+				range = STV0900_RANGEOK;
+			else
+				range = STV0900_OUTOFRANGE;
+		}
+		break;
+	case STV0900_DEMOD_2:
+		if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) {
+			timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2);
+			i = 0;
+			stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x5c);
+
+			while ((i <= 50) && (timing != 0) && (timing != 0xff)) {
+				timing = stv0900_read_reg(i_params, R0900_P2_TMGREG2);
+				msleep(5);
+				i += 5;
+			}
+		}
+
+		i_params->dmd2_rslts.standard = stv0900_get_standard(fe, demod);
+		i_params->dmd2_rslts.frequency = stv0900_get_tuner_freq(fe);
+		offsetFreq = stv0900_get_carr_freq(i_params, i_params->mclk, demod) / 1000;
+		i_params->dmd2_rslts.frequency += offsetFreq;
+		i_params->dmd2_rslts.symbol_rate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+		srate_offset = stv0900_get_timing_offst(i_params, i_params->dmd2_rslts.symbol_rate, demod);
+		i_params->dmd2_rslts.symbol_rate += srate_offset;
+		i_params->dmd2_rslts.fec = stv0900_get_vit_fec(i_params, demod);
+		i_params->dmd2_rslts.modcode = stv0900_get_bits(i_params, F0900_P2_DEMOD_MODCOD);
+		i_params->dmd2_rslts.pilot = stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE) & 0x01;
+		i_params->dmd2_rslts.frame_length = ((u32)stv0900_get_bits(i_params, F0900_P2_DEMOD_TYPE)) >> 1;
+		i_params->dmd2_rslts.rolloff = stv0900_get_bits(i_params, F0900_P2_ROLLOFF_STATUS);
+		switch (i_params->dmd2_rslts.standard) {
+		case STV0900_DVBS2_STANDARD:
+			i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_SPECINV_DEMOD);
+			if (i_params->dmd2_rslts.modcode <= STV0900_QPSK_910)
+				i_params->dmd2_rslts.modulation = STV0900_QPSK;
+			else if (i_params->dmd2_rslts.modcode <= STV0900_8PSK_910)
+				i_params->dmd2_rslts.modulation = STV0900_8PSK;
+			else if (i_params->dmd2_rslts.modcode <= STV0900_16APSK_910)
+				i_params->dmd2_rslts.modulation = STV0900_16APSK;
+			else if (i_params->dmd2_rslts.modcode <= STV0900_32APSK_910)
+				i_params->dmd2_rslts.modulation = STV0900_32APSK;
+			else
+				i_params->dmd2_rslts.modulation = STV0900_UNKNOWN;
+			break;
+		case STV0900_DVBS1_STANDARD:
+		case STV0900_DSS_STANDARD:
+			i_params->dmd2_rslts.spectrum = stv0900_get_bits(i_params, F0900_P2_IQINV);
+			i_params->dmd2_rslts.modulation = STV0900_QPSK;
+			break;
+		default:
+			break;
+		}
+
+		if ((i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) || (i_params->dmd2_symbol_rate < 10000000)) {
+			offsetFreq =	i_params->dmd2_rslts.frequency - i_params->tuner2_freq;
+			i_params->tuner2_freq = stv0900_get_tuner_freq(fe);
+
+			if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500))
+				range = STV0900_RANGEOK;
+			else
+				if (ABS(offsetFreq) <= (stv0900_carrier_width(i_params->dmd2_rslts.symbol_rate, i_params->dmd2_rslts.rolloff) / 2000))
+					range = STV0900_RANGEOK;
+				else
+					range = STV0900_OUTOFRANGE;
+		} else {
+			if (ABS(offsetFreq) <= ((i_params->dmd2_srch_range / 2000) + 500))
+				range = STV0900_RANGEOK;
+			else
+				range = STV0900_OUTOFRANGE;
+		}
+
+		break;
+	}
+
+	return range;
+}
+
+static enum fe_stv0900_signal_type stv0900_dvbs1_acq_workaround(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32 srate, demod_timeout,
+		fec_timeout, freq1, freq0;
+	enum fe_stv0900_signal_type signal_type = STV0900_NODATA;;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		i_params->dmd1_rslts.locked = FALSE;
+		if (stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) {
+			srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+			srate += stv0900_get_timing_offst(i_params, srate, demod);
+			if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH)
+				stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod);
+
+			stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START);
+			freq1 = stv0900_read_reg(i_params, R0900_P1_CFR2);
+			freq0 = stv0900_read_reg(i_params, R0900_P1_CFR1);
+			stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0);
+			stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1C);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+			if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) {
+				i_params->dmd1_rslts.locked = TRUE;
+				signal_type = stv0900_get_signal_params(fe);
+				stv0900_track_optimization(fe);
+			} else {
+				stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL);
+				stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1c);
+				stv0900_write_reg(i_params, R0900_P1_CFRINIT1, freq1);
+				stv0900_write_reg(i_params, R0900_P1_CFRINIT0, freq0);
+				stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x18);
+				if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) {
+					i_params->dmd1_rslts.locked = TRUE;
+					signal_type = stv0900_get_signal_params(fe);
+					stv0900_track_optimization(fe);
+				}
+
+			}
+
+		} else
+			i_params->dmd1_rslts.locked = FALSE;
+
+		break;
+	case STV0900_DEMOD_2:
+		i_params->dmd2_rslts.locked = FALSE;
+		if (stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) {
+			srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+			srate += stv0900_get_timing_offst(i_params, srate, demod);
+
+			if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH)
+				stv0900_set_symbol_rate(i_params, i_params->mclk, srate, demod);
+
+			stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, srate, STV0900_WARM_START);
+			freq1 = stv0900_read_reg(i_params, R0900_P2_CFR2);
+			freq0 = stv0900_read_reg(i_params, R0900_P2_CFR1);
+			stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0);
+			stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_SWAPPED);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1C);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+
+			if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) {
+				i_params->dmd2_rslts.locked = TRUE;
+				signal_type = stv0900_get_signal_params(fe);
+				stv0900_track_optimization(fe);
+			} else {
+				stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, STV0900_IQ_FORCE_NORMAL);
+				stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1c);
+				stv0900_write_reg(i_params, R0900_P2_CFRINIT1, freq1);
+				stv0900_write_reg(i_params, R0900_P2_CFRINIT0, freq0);
+				stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x18);
+
+				if (stv0900_wait_for_lock(i_params, demod, demod_timeout, fec_timeout) == TRUE) {
+					i_params->dmd2_rslts.locked = TRUE;
+					signal_type = stv0900_get_signal_params(fe);
+					stv0900_track_optimization(fe);
+				}
+
+			}
+
+		} else
+			i_params->dmd1_rslts.locked = FALSE;
+
+		break;
+	}
+
+	return signal_type;
+}
+
+static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 minagc2level = 0xffff,
+		agc2level,
+		init_freq, freq_step;
+
+	s32 i, j, nb_steps, direction;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38);
+		stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1);
+		stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1);
+
+		stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83);
+		stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0);
+
+		stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82);
+		stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0);
+		stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0);
+
+		stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod);
+		nb_steps = -1 + (i_params->dmd1_srch_range / 1000000);
+		nb_steps /= 2;
+		nb_steps = (2 * nb_steps) + 1;
+
+		if (nb_steps < 0)
+			nb_steps = 1;
+
+		direction = 1;
+
+		freq_step = (1000000 << 8) / (i_params->mclk >> 8);
+
+		init_freq = 0;
+
+		for (i = 0; i < nb_steps; i++) {
+			if (direction > 0)
+				init_freq = init_freq + (freq_step * i);
+			else
+				init_freq = init_freq - (freq_step * i);
+
+			direction *= -1;
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (init_freq >> 8) & 0xff);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT0, init_freq  & 0xff);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x58);
+			msleep(10);
+			agc2level = 0;
+
+			for (j = 0; j < 10; j++)
+				agc2level += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8)
+						| stv0900_read_reg(i_params, R0900_P1_AGC2I0);
+
+			agc2level /= 10;
+
+			if (agc2level < minagc2level)
+				minagc2level = agc2level;
+		}
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38);
+		stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1);
+		stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1);
+		stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83);
+		stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0);
+		stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82);
+		stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0);
+		stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0);
+		stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod);
+		nb_steps = -1 + (i_params->dmd2_srch_range / 1000000);
+		nb_steps /= 2;
+		nb_steps = (2 * nb_steps) + 1;
+
+		if (nb_steps < 0)
+			nb_steps = 1;
+
+		direction = 1;
+		freq_step = (1000000 << 8) / (i_params->mclk >> 8);
+		init_freq = 0;
+		for (i = 0; i < nb_steps; i++) {
+			if (direction > 0)
+				init_freq = init_freq + (freq_step * i);
+			else
+				init_freq = init_freq - (freq_step * i);
+
+			direction *= -1;
+
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (init_freq >> 8) & 0xff);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT0, init_freq  & 0xff);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x58);
+
+			msleep(10);
+			agc2level = 0;
+			for (j = 0; j < 10; j++)
+				agc2level += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8)
+						| stv0900_read_reg(i_params, R0900_P2_AGC2I0);
+
+			agc2level /= 10;
+
+			if (agc2level < minagc2level)
+				minagc2level = agc2level;
+		}
+		break;
+	}
+
+	return (u16)minagc2level;
+}
+
+static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	int timingLock = FALSE;
+	s32 i, timingcpt = 0,
+		direction = 1,
+		nb_steps,
+		current_step = 0,
+		tuner_freq;
+
+	u32 coarse_srate = 0, agc2_integr = 0, currier_step = 1200;
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x1F);
+		stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0x12);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0xf0);
+		stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0xe0);
+		stv0900_write_bits(i_params, F0900_P1_SCAN_ENABLE, 1);
+		stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 1);
+		stv0900_write_reg(i_params, R0900_P1_SFRUP1, 0x83);
+		stv0900_write_reg(i_params, R0900_P1_SFRUP0, 0xc0);
+		stv0900_write_reg(i_params, R0900_P1_SFRLOW1, 0x82);
+		stv0900_write_reg(i_params, R0900_P1_SFRLOW0, 0xa0);
+		stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x0);
+		stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x50);
+
+		if (i_params->chip_id >= 0x20) {
+			stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x6a);
+			stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x95);
+		} else {
+			stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed);
+			stv0900_write_reg(i_params, R0900_P1_SFRSTEP, 0x73);
+		}
+
+		if (i_params->dmd1_symbol_rate <= 2000000)
+			currier_step = 1000;
+		else if (i_params->dmd1_symbol_rate <= 5000000)
+			currier_step = 2000;
+		else if (i_params->dmd1_symbol_rate <= 12000000)
+			currier_step = 3000;
+		else
+			currier_step = 5000;
+
+		nb_steps = -1 + ((i_params->dmd1_srch_range / 1000) / currier_step);
+		nb_steps /= 2;
+		nb_steps = (2 * nb_steps) + 1;
+
+		if (nb_steps < 0)
+			nb_steps = 1;
+
+		else if (nb_steps > 10) {
+			nb_steps = 11;
+			currier_step = (i_params->dmd1_srch_range / 1000) / 10;
+		}
+
+		current_step = 0;
+
+		direction = 1;
+		tuner_freq = i_params->tuner1_freq;
+
+		while ((timingLock == FALSE) && (current_step < nb_steps)) {
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5F);
+			stv0900_write_bits(i_params, F0900_P1_I2C_DEMOD_MODE, 0x0);
+
+			msleep(50);
+
+			for (i = 0; i < 10; i++) {
+				if (stv0900_get_bits(i_params, F0900_P1_TMGLOCK_QUALITY) >= 2)
+					timingcpt++;
+
+				agc2_integr += (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8) | stv0900_read_reg(i_params, R0900_P1_AGC2I0);
+
+			}
+
+			agc2_integr /= 10;
+			coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+			current_step++;
+			direction *= -1;
+
+			dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started. tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n", tuner_freq, agc2_integr, coarse_srate, timingcpt);
+
+			if ((timingcpt >= 5) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000)) {
+				timingLock = TRUE;
+			}
+
+			else if (current_step < nb_steps) {
+				if (direction > 0)
+					tuner_freq += (current_step * currier_step);
+				else
+					tuner_freq -= (current_step * currier_step);
+
+				stv0900_set_tuner(fe, tuner_freq, i_params->tuner1_bw);
+			}
+		}
+
+		if (timingLock == FALSE)
+			coarse_srate = 0;
+		else
+			coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+		break;
+	case STV0900_DEMOD_2:
+		stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x1F);
+		stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0x12);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0xf0);
+		stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0xe0);
+		stv0900_write_bits(i_params, F0900_P2_SCAN_ENABLE, 1);
+		stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 1);
+		stv0900_write_reg(i_params, R0900_P2_SFRUP1, 0x83);
+		stv0900_write_reg(i_params, R0900_P2_SFRUP0, 0xc0);
+		stv0900_write_reg(i_params, R0900_P2_SFRLOW1, 0x82);
+		stv0900_write_reg(i_params, R0900_P2_SFRLOW0, 0xa0);
+		stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x0);
+		stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x50);
+
+		if (i_params->chip_id >= 0x20) {
+			stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x6a);
+			stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x95);
+		} else {
+			stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed);
+			stv0900_write_reg(i_params, R0900_P2_SFRSTEP, 0x73);
+		}
+
+		if (i_params->dmd2_symbol_rate <= 2000000)
+			currier_step = 1000;
+		else if (i_params->dmd2_symbol_rate <= 5000000)
+			currier_step = 2000;
+		else if (i_params->dmd2_symbol_rate <= 12000000)
+			currier_step = 3000;
+		else
+			currier_step = 5000;
+
+
+		nb_steps = -1 + ((i_params->dmd2_srch_range / 1000) / currier_step);
+		nb_steps /= 2;
+		nb_steps = (2 * nb_steps) + 1;
+
+		if (nb_steps < 0)
+			nb_steps = 1;
+		else if (nb_steps > 10) {
+			nb_steps = 11;
+			currier_step = (i_params->dmd2_srch_range / 1000) / 10;
+		}
+
+		current_step = 0;
+		direction = 1;
+		tuner_freq = i_params->tuner2_freq;
+
+		while ((timingLock == FALSE) && (current_step < nb_steps)) {
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5F);
+			stv0900_write_bits(i_params, F0900_P2_I2C_DEMOD_MODE, 0x0);
+
+			msleep(50);
+			timingcpt = 0;
+
+			for (i = 0; i < 20; i++) {
+				if (stv0900_get_bits(i_params, F0900_P2_TMGLOCK_QUALITY) >= 2)
+					timingcpt++;
+				agc2_integr += (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8)
+								| stv0900_read_reg(i_params, R0900_P2_AGC2I0);
+			}
+
+			agc2_integr /= 20;
+			coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+			if ((timingcpt >= 10) && (agc2_integr < 0x1F00) && (coarse_srate < 55000000) && (coarse_srate > 850000))
+				timingLock = TRUE;
+			else {
+				current_step++;
+				direction *= -1;
+
+				if (direction > 0)
+					tuner_freq += (current_step * currier_step);
+				else
+					tuner_freq -= (current_step * currier_step);
+
+				stv0900_set_tuner(fe, tuner_freq, i_params->tuner2_bw);
+			}
+		}
+
+		if (timingLock == FALSE)
+			coarse_srate = 0;
+		else
+			coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+		break;
+	}
+
+	return coarse_srate;
+}
+
+static u32 stv0900_search_srate_fine(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u32 coarse_srate,
+	coarse_freq,
+	symb;
+
+	coarse_srate = stv0900_get_symbol_rate(i_params, i_params->mclk, demod);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		coarse_freq = (stv0900_read_reg(i_params, R0900_P1_CFR2) << 8)
+						| stv0900_read_reg(i_params, R0900_P1_CFR1);
+		symb = 13 * (coarse_srate / 10);
+
+		if (symb < i_params->dmd1_symbol_rate)
+			coarse_srate = 0;
+		else {
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x1F);
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01);
+			stv0900_write_reg(i_params, R0900_P1_TMGTHRISE, 0x20);
+			stv0900_write_reg(i_params, R0900_P1_TMGTHFALL, 0x00);
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2);
+			stv0900_write_bits(i_params, F0900_P1_CFR_AUTOSCAN, 0);
+
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0x49);
+			else
+				stv0900_write_reg(i_params, R0900_P1_CARFREQ, 0xed);
+
+			if (coarse_srate > 3000000) {
+				symb = 13 * (coarse_srate / 10);
+				symb = (symb / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+				stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF));
+
+				symb = 10 * (coarse_srate / 13);
+				symb = (symb / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+
+				stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF));
+
+				symb = (coarse_srate / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+				stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF);
+				stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF));
+			} else {
+				symb = 13 * (coarse_srate / 10);
+				symb = (symb / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P1_SFRUP1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P1_SFRUP0, (symb & 0xFF));
+
+				symb = 10 * (coarse_srate / 14);
+				symb = (symb / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P1_SFRLOW1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P1_SFRLOW0, (symb & 0xFF));
+
+				symb = (coarse_srate / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P1_SFRINIT1, (symb >> 8) & 0xFF);
+				stv0900_write_reg(i_params, R0900_P1_SFRINIT0, (symb & 0xFF));
+			}
+
+			stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT1, (coarse_freq >> 8) & 0xff);
+			stv0900_write_reg(i_params, R0900_P1_CFRINIT0, coarse_freq  & 0xff);
+			stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x15);
+		}
+		break;
+	case STV0900_DEMOD_2:
+		coarse_freq = (stv0900_read_reg(i_params, R0900_P2_CFR2) << 8)
+						| stv0900_read_reg(i_params, R0900_P2_CFR1);
+
+		symb = 13 * (coarse_srate / 10);
+
+		if (symb < i_params->dmd2_symbol_rate)
+			coarse_srate = 0;
+		else {
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x1F);
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01);
+			stv0900_write_reg(i_params, R0900_P2_TMGTHRISE, 0x20);
+			stv0900_write_reg(i_params, R0900_P2_TMGTHFALL, 0x00);
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2);
+			stv0900_write_bits(i_params, F0900_P2_CFR_AUTOSCAN, 0);
+
+			if (i_params->chip_id >= 0x20)
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0x49);
+			else
+				stv0900_write_reg(i_params, R0900_P2_CARFREQ, 0xed);
+
+			if (coarse_srate > 3000000) {
+				symb = 13 * (coarse_srate / 10);
+				symb = (symb / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+				stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF));
+
+				symb = 10 * (coarse_srate / 13);
+				symb = (symb / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+
+				stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF));
+
+				symb = (coarse_srate / 1000) * 65536;
+				symb /= (i_params->mclk / 1000);
+				stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF);
+				stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF));
+			} else {
+				symb = 13 * (coarse_srate / 10);
+				symb = (symb / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P2_SFRUP1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P2_SFRUP0, (symb & 0xFF));
+
+				symb = 10 * (coarse_srate / 14);
+				symb = (symb / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P2_SFRLOW1, (symb >> 8) & 0x7F);
+				stv0900_write_reg(i_params, R0900_P2_SFRLOW0, (symb & 0xFF));
+
+				symb = (coarse_srate / 100) * 65536;
+				symb /= (i_params->mclk / 100);
+				stv0900_write_reg(i_params, R0900_P2_SFRINIT1, (symb >> 8) & 0xFF);
+				stv0900_write_reg(i_params, R0900_P2_SFRINIT0, (symb & 0xFF));
+			}
+
+			stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT1, (coarse_freq >> 8) & 0xff);
+			stv0900_write_reg(i_params, R0900_P2_CFRINIT0, coarse_freq  & 0xff);
+			stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x15);
+		}
+
+		break;
+	}
+
+	return coarse_srate;
+}
+
+static int stv0900_blind_search_algo(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u8 k_ref_tmg, k_ref_tmg_max, k_ref_tmg_min;
+	u32 coarse_srate;
+	int lock = FALSE, coarse_fail = FALSE;
+	s32 demod_timeout = 500, fec_timeout = 50, kref_tmg_reg, fail_cpt, i, agc2_overflow;
+	u16 agc2_integr;
+	u8 dstatus2;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	if (i_params->chip_id < 0x20) {
+		k_ref_tmg_max = 233;
+		k_ref_tmg_min = 143;
+	} else {
+		k_ref_tmg_max = 120;
+		k_ref_tmg_min = 30;
+	}
+
+	agc2_integr = stv0900_blind_check_agc2_min_level(i_params, demod);
+
+	if (agc2_integr > STV0900_BLIND_SEARCH_AGC2_TH) {
+		lock = FALSE;
+
+	} else {
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			if (i_params->chip_id == 0x10)
+				stv0900_write_reg(i_params, R0900_P1_CORRELEXP, 0xAA);
+
+			if (i_params->chip_id < 0x20)
+				stv0900_write_reg(i_params, R0900_P1_CARHDR, 0x55);
+
+			stv0900_write_reg(i_params, R0900_P1_CARCFG, 0xC4);
+			stv0900_write_reg(i_params, R0900_P1_RTCS2, 0x44);
+
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P1_EQUALCFG, 0x41);
+				stv0900_write_reg(i_params, R0900_P1_FFECFG, 0x41);
+				stv0900_write_reg(i_params, R0900_P1_VITSCALE, 0x82);
+				stv0900_write_reg(i_params, R0900_P1_VAVSRVIT, 0x0);
+			}
+
+			kref_tmg_reg = R0900_P1_KREFTMG;
+			break;
+		case STV0900_DEMOD_2:
+			if (i_params->chip_id == 0x10)
+				stv0900_write_reg(i_params, R0900_P2_CORRELEXP, 0xAA);
+
+			if (i_params->chip_id < 0x20)
+				stv0900_write_reg(i_params, R0900_P2_CARHDR, 0x55);
+
+			stv0900_write_reg(i_params, R0900_P2_CARCFG, 0xC4);
+			stv0900_write_reg(i_params, R0900_P2_RTCS2, 0x44);
+
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P2_EQUALCFG, 0x41);
+				stv0900_write_reg(i_params, R0900_P2_FFECFG, 0x41);
+				stv0900_write_reg(i_params, R0900_P2_VITSCALE, 0x82);
+				stv0900_write_reg(i_params, R0900_P2_VAVSRVIT, 0x0);
+			}
+
+			kref_tmg_reg = R0900_P2_KREFTMG;
+			break;
+		}
+
+		k_ref_tmg = k_ref_tmg_max;
+
+		do {
+			stv0900_write_reg(i_params, kref_tmg_reg, k_ref_tmg);
+			if (stv0900_search_srate_coarse(fe) != 0) {
+				coarse_srate = stv0900_search_srate_fine(fe);
+
+				if (coarse_srate != 0) {
+					stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, coarse_srate, STV0900_BLIND_SEARCH);
+					lock = stv0900_get_demod_lock(i_params, demod, demod_timeout);
+				} else
+					lock = FALSE;
+			} else {
+				fail_cpt = 0;
+				agc2_overflow = 0;
+
+				switch (demod) {
+				case STV0900_DEMOD_1:
+				default:
+					for (i = 0; i < 10; i++) {
+						agc2_integr = (stv0900_read_reg(i_params, R0900_P1_AGC2I1) << 8)
+								| stv0900_read_reg(i_params, R0900_P1_AGC2I0);
+
+						if (agc2_integr >= 0xff00)
+							agc2_overflow++;
+
+						dstatus2 = stv0900_read_reg(i_params, R0900_P1_DSTATUS2);
+
+						if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1))
+							fail_cpt++;
+					}
+					break;
+				case STV0900_DEMOD_2:
+					for (i = 0; i < 10; i++) {
+						agc2_integr = (stv0900_read_reg(i_params, R0900_P2_AGC2I1) << 8)
+								| stv0900_read_reg(i_params, R0900_P2_AGC2I0);
+
+						if (agc2_integr >= 0xff00)
+							agc2_overflow++;
+
+						dstatus2 = stv0900_read_reg(i_params, R0900_P2_DSTATUS2);
+
+						if (((dstatus2 & 0x1) == 0x1) && ((dstatus2 >> 7) == 1))
+							fail_cpt++;
+					}
+					break;
+				}
+
+				if ((fail_cpt > 7) || (agc2_overflow > 7))
+					coarse_fail = TRUE;
+
+				lock = FALSE;
+			}
+			k_ref_tmg -= 30;
+		} while ((k_ref_tmg >= k_ref_tmg_min) && (lock == FALSE) && (coarse_fail == FALSE));
+	}
+
+	return lock;
+}
+
+static void stv0900_set_viterbi_acq(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 vth_reg;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	dmd_reg(vth_reg, R0900_P1_VTH12, R0900_P2_VTH12);
+
+	stv0900_write_reg(i_params, vth_reg++, 0x96);
+	stv0900_write_reg(i_params, vth_reg++, 0x64);
+	stv0900_write_reg(i_params, vth_reg++, 0x36);
+	stv0900_write_reg(i_params, vth_reg++, 0x23);
+	stv0900_write_reg(i_params, vth_reg++, 0x1E);
+	stv0900_write_reg(i_params, vth_reg++, 0x19);
+}
+
+static void stv0900_set_search_standard(struct stv0900_internal *i_params,
+					enum fe_stv0900_demod_num demod)
+{
+
+	int sstndrd;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	sstndrd = i_params->dmd1_srch_standard;
+	if (demod == 1)
+		sstndrd = i_params->dmd2_srch_stndrd;
+
+	switch (sstndrd) {
+	case STV0900_SEARCH_DVBS1:
+		dprintk("Search Standard = DVBS1\n");
+		break;
+	case STV0900_SEARCH_DSS:
+		dprintk("Search Standard = DSS\n");
+	case STV0900_SEARCH_DVBS2:
+		break;
+		dprintk("Search Standard = DVBS2\n");
+	case STV0900_AUTO_SEARCH:
+	default:
+		dprintk("Search Standard = AUTO\n");
+		break;
+	}
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		switch (i_params->dmd1_srch_standard) {
+		case STV0900_SEARCH_DVBS1:
+		case STV0900_SEARCH_DSS:
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0);
+			stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x22);
+
+			stv0900_set_viterbi_acq(i_params, demod);
+			stv0900_set_viterbi_standard(i_params,
+						i_params->dmd1_srch_standard,
+						i_params->dmd1_fec, demod);
+
+			break;
+		case STV0900_SEARCH_DVBS2:
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 1);
+			stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26);
+			if (i_params->demod_mode != STV0900_SINGLE) {
+				if (i_params->chip_id <= 0x11)
+					stv0900_stop_all_s2_modcod(i_params, demod);
+				else
+					stv0900_activate_s2_modcode(i_params, demod);
+
+			} else
+				stv0900_activate_s2_modcode_single(i_params, demod);
+
+			stv0900_set_viterbi_tracq(i_params, demod);
+
+			break;
+		case STV0900_AUTO_SEARCH:
+		default:
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P1_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P1_DVBS2_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT1, 0);
+			stv0900_write_reg(i_params, R0900_P1_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P1_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P1_CAR2CFG, 0x26);
+			if (i_params->demod_mode != STV0900_SINGLE) {
+				if (i_params->chip_id <= 0x11)
+					stv0900_stop_all_s2_modcod(i_params, demod);
+				else
+					stv0900_activate_s2_modcode(i_params, demod);
+
+			} else
+				stv0900_activate_s2_modcode_single(i_params, demod);
+
+			if (i_params->dmd1_symbol_rate >= 2000000)
+				stv0900_set_viterbi_acq(i_params, demod);
+			else
+				stv0900_set_viterbi_tracq(i_params, demod);
+
+			stv0900_set_viterbi_standard(i_params, i_params->dmd1_srch_standard, i_params->dmd1_fec, demod);
+
+			break;
+		}
+		break;
+	case STV0900_DEMOD_2:
+		switch (i_params->dmd2_srch_stndrd) {
+		case STV0900_SEARCH_DVBS1:
+		case STV0900_SEARCH_DSS:
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0);
+			stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x22);
+			stv0900_set_viterbi_acq(i_params, demod);
+			stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod);
+			break;
+		case STV0900_SEARCH_DVBS2:
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 1);
+			stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26);
+			if (i_params->demod_mode != STV0900_SINGLE)
+				stv0900_activate_s2_modcode(i_params, demod);
+			else
+				stv0900_activate_s2_modcode_single(i_params, demod);
+
+			stv0900_set_viterbi_tracq(i_params, demod);
+			break;
+		case STV0900_AUTO_SEARCH:
+		default:
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 0);
+			stv0900_write_bits(i_params, F0900_P2_DVBS1_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_P2_DVBS2_ENABLE, 1);
+			stv0900_write_bits(i_params, F0900_STOP_CLKVIT2, 0);
+			stv0900_write_reg(i_params, R0900_P2_ACLC, 0x1a);
+			stv0900_write_reg(i_params, R0900_P2_BCLC, 0x09);
+			stv0900_write_reg(i_params, R0900_P2_CAR2CFG, 0x26);
+			if (i_params->demod_mode != STV0900_SINGLE)
+				stv0900_activate_s2_modcode(i_params, demod);
+			else
+				stv0900_activate_s2_modcode_single(i_params, demod);
+
+			if (i_params->dmd2_symbol_rate >= 2000000)
+				stv0900_set_viterbi_acq(i_params, demod);
+			else
+				stv0900_set_viterbi_tracq(i_params, demod);
+
+			stv0900_set_viterbi_standard(i_params, i_params->dmd2_srch_stndrd, i_params->dmd2_fec, demod);
+
+			break;
+		}
+
+		break;
+	}
+}
+
+enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *i_params = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32 demod_timeout = 500, fec_timeout = 50, stream_merger_field;
+
+	int lock = FALSE, low_sr = FALSE;
+
+	enum fe_stv0900_signal_type signal_type = STV0900_NOCARRIER;
+	enum fe_stv0900_search_algo algo;
+	int no_signal = FALSE;
+
+	dprintk(KERN_INFO "%s\n", __func__);
+
+	switch (demod) {
+	case STV0900_DEMOD_1:
+	default:
+		algo = i_params->dmd1_srch_algo;
+
+		stv0900_write_bits(i_params, F0900_P1_RST_HWARE, 1);
+		stream_merger_field = F0900_P1_RST_HWARE;
+
+		stv0900_write_reg(i_params, R0900_P1_DMDISTATE, 0x5C);
+
+		if (i_params->chip_id >= 0x20)
+			stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x9e);
+		else
+			stv0900_write_reg(i_params, R0900_P1_CORRELABS, 0x88);
+
+		stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd1_symbol_rate, i_params->dmd1_srch_algo);
+
+		if (i_params->dmd1_srch_algo == STV0900_BLIND_SEARCH) {
+			i_params->tuner1_bw = 2 * 36000000;
+
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x00);
+			stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70);
+
+			stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod);
+		} else {
+			stv0900_write_reg(i_params, R0900_P1_DMDT0M, 0x20);
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG, 0xd2);
+
+			if (i_params->dmd1_symbol_rate < 2000000)
+				stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x63);
+			else
+				stv0900_write_reg(i_params, R0900_P1_CORRELMANT, 0x70);
+
+			stv0900_write_reg(i_params, R0900_P1_AGC2REF, 0x38);
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0x5a);
+
+				if (i_params->dmd1_srch_algo == STV0900_COLD_START)
+					i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10;
+				else if (i_params->dmd1_srch_algo == STV0900_WARM_START)
+					i_params->tuner1_bw = stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000;
+			} else {
+				stv0900_write_reg(i_params, R0900_P1_KREFTMG, 0xc1);
+				i_params->tuner1_bw = (15 * (stv0900_carrier_width(i_params->dmd1_symbol_rate, i_params->rolloff) + 10000000)) / 10;
+			}
+
+			stv0900_write_reg(i_params, R0900_P1_TMGCFG2, 0x01);
+
+			stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod);
+			stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod);
+			stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd1_symbol_rate, demod);
+			if (i_params->dmd1_symbol_rate >= 10000000)
+				low_sr = FALSE;
+			else
+				low_sr = TRUE;
+
+		}
+
+		stv0900_set_tuner(fe, i_params->tuner1_freq, i_params->tuner1_bw);
+
+		stv0900_write_bits(i_params, F0900_P1_SPECINV_CONTROL, i_params->dmd1_srch_iq_inv);
+		stv0900_write_bits(i_params, F0900_P1_MANUAL_ROLLOFF, 1);
+
+		stv0900_set_search_standard(i_params, demod);
+
+		if (i_params->dmd1_srch_algo != STV0900_BLIND_SEARCH)
+			stv0900_start_search(i_params, demod);
+		break;
+	case STV0900_DEMOD_2:
+		algo = i_params->dmd2_srch_algo;
+
+		stv0900_write_bits(i_params, F0900_P2_RST_HWARE, 1);
+
+		stream_merger_field = F0900_P2_RST_HWARE;
+
+		stv0900_write_reg(i_params, R0900_P2_DMDISTATE, 0x5C);
+
+		if (i_params->chip_id >= 0x20)
+			stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x9e);
+		else
+			stv0900_write_reg(i_params, R0900_P2_CORRELABS, 0x88);
+
+		stv0900_get_lock_timeout(&demod_timeout, &fec_timeout, i_params->dmd2_symbol_rate, i_params->dmd2_srch_algo);
+
+		if (i_params->dmd2_srch_algo == STV0900_BLIND_SEARCH) {
+			i_params->tuner2_bw = 2 * 36000000;
+
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x00);
+			stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70);
+
+			stv0900_set_symbol_rate(i_params, i_params->mclk, 1000000, demod);
+		} else {
+			stv0900_write_reg(i_params, R0900_P2_DMDT0M, 0x20);
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG, 0xd2);
+
+			if (i_params->dmd2_symbol_rate < 2000000)
+				stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x63);
+			else
+				stv0900_write_reg(i_params, R0900_P2_CORRELMANT, 0x70);
+
+			if (i_params->dmd2_symbol_rate >= 10000000)
+				stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x38);
+			else
+				stv0900_write_reg(i_params, R0900_P2_AGC2REF, 0x60);
+
+			if (i_params->chip_id >= 0x20) {
+				stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0x5a);
+
+				if (i_params->dmd2_srch_algo == STV0900_COLD_START)
+					i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate,
+							i_params->rolloff) + 10000000)) / 10;
+				else if (i_params->dmd2_srch_algo == STV0900_WARM_START)
+					i_params->tuner2_bw = stv0900_carrier_width(i_params->dmd2_symbol_rate,
+							i_params->rolloff) + 10000000;
+			} else {
+				stv0900_write_reg(i_params, R0900_P2_KREFTMG, 0xc1);
+				i_params->tuner2_bw = (15 * (stv0900_carrier_width(i_params->dmd2_symbol_rate,
+									i_params->rolloff) + 10000000)) / 10;
+			}
+
+			stv0900_write_reg(i_params, R0900_P2_TMGCFG2, 0x01);
+
+			stv0900_set_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod);
+			stv0900_set_max_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod);
+			stv0900_set_min_symbol_rate(i_params, i_params->mclk, i_params->dmd2_symbol_rate, demod);
+			if (i_params->dmd2_symbol_rate >= 10000000)
+				low_sr = FALSE;
+			else
+				low_sr = TRUE;
+
+		}
+
+		stv0900_set_tuner(fe, i_params->tuner2_freq, i_params->tuner2_bw);
+
+		stv0900_write_bits(i_params, F0900_P2_SPECINV_CONTROL, i_params->dmd2_srch_iq_inv);
+		stv0900_write_bits(i_params, F0900_P2_MANUAL_ROLLOFF, 1);
+
+		stv0900_set_search_standard(i_params, demod);
+
+		if (i_params->dmd2_srch_algo != STV0900_BLIND_SEARCH)
+			stv0900_start_search(i_params, demod);
+		break;
+	}
+
+	if (i_params->chip_id == 0x12) {
+		stv0900_write_bits(i_params, stream_merger_field, 0);
+		msleep(3);
+		stv0900_write_bits(i_params, stream_merger_field, 1);
+		stv0900_write_bits(i_params, stream_merger_field, 0);
+	}
+
+	if (algo == STV0900_BLIND_SEARCH)
+		lock = stv0900_blind_search_algo(fe);
+	else if (algo == STV0900_COLD_START)
+		lock = stv0900_get_demod_cold_lock(fe, demod_timeout);
+	else if (algo == STV0900_WARM_START)
+		lock = stv0900_get_demod_lock(i_params, demod, demod_timeout);
+
+	if ((lock == FALSE) && (algo == STV0900_COLD_START)) {
+		if (low_sr == FALSE) {
+			if (stv0900_check_timing_lock(i_params, demod) == TRUE)
+				lock = stv0900_sw_algo(i_params, demod);
+		}
+	}
+
+	if (lock == TRUE)
+		signal_type = stv0900_get_signal_params(fe);
+
+	if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) {
+		stv0900_track_optimization(fe);
+		if (i_params->chip_id <= 0x11) {
+			if ((stv0900_get_standard(fe, STV0900_DEMOD_1) == STV0900_DVBS1_STANDARD) && (stv0900_get_standard(fe, STV0900_DEMOD_2) == STV0900_DVBS1_STANDARD)) {
+				msleep(20);
+				stv0900_write_bits(i_params, stream_merger_field, 0);
+			} else {
+				stv0900_write_bits(i_params, stream_merger_field, 0);
+				msleep(3);
+				stv0900_write_bits(i_params, stream_merger_field, 1);
+				stv0900_write_bits(i_params, stream_merger_field, 0);
+			}
+		} else if (i_params->chip_id == 0x20) {
+			stv0900_write_bits(i_params, stream_merger_field, 0);
+			msleep(3);
+			stv0900_write_bits(i_params, stream_merger_field, 1);
+			stv0900_write_bits(i_params, stream_merger_field, 0);
+		}
+
+		if (stv0900_wait_for_lock(i_params, demod, fec_timeout, fec_timeout) == TRUE) {
+			lock = TRUE;
+			switch (demod) {
+			case STV0900_DEMOD_1:
+			default:
+				i_params->dmd1_rslts.locked = TRUE;
+				if (i_params->dmd1_rslts.standard == STV0900_DVBS2_STANDARD) {
+					stv0900_set_dvbs2_rolloff(i_params, demod);
+					stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0x40);
+					stv0900_write_reg(i_params, R0900_P1_PDELCTRL2, 0);
+					stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x67);
+				} else {
+					stv0900_write_reg(i_params, R0900_P1_ERRCTRL1, 0x75);
+				}
+
+				stv0900_write_reg(i_params, R0900_P1_FBERCPT4, 0);
+				stv0900_write_reg(i_params, R0900_P1_ERRCTRL2, 0xc1);
+				break;
+			case STV0900_DEMOD_2:
+				i_params->dmd2_rslts.locked = TRUE;
+
+				if (i_params->dmd2_rslts.standard == STV0900_DVBS2_STANDARD) {
+					stv0900_set_dvbs2_rolloff(i_params, demod);
+					stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x60);
+					stv0900_write_reg(i_params, R0900_P2_PDELCTRL2, 0x20);
+					stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x67);
+				} else {
+					stv0900_write_reg(i_params, R0900_P2_ERRCTRL1, 0x75);
+				}
+
+				stv0900_write_reg(i_params, R0900_P2_FBERCPT4, 0);
+
+				stv0900_write_reg(i_params, R0900_P2_ERRCTRL2, 0xc1);
+				break;
+			}
+		} else {
+			lock = FALSE;
+			signal_type = STV0900_NODATA;
+			no_signal = stv0900_check_signal_presence(i_params, demod);
+
+			switch (demod) {
+			case STV0900_DEMOD_1:
+			default:
+				i_params->dmd1_rslts.locked = FALSE;
+				break;
+			case STV0900_DEMOD_2:
+				i_params->dmd2_rslts.locked = FALSE;
+				break;
+			}
+		}
+	}
+
+	if ((signal_type == STV0900_NODATA) && (no_signal == FALSE)) {
+		switch (demod) {
+		case STV0900_DEMOD_1:
+		default:
+			if (i_params->chip_id <= 0x11) {
+				if ((stv0900_get_bits(i_params, F0900_P1_HEADER_MODE) == STV0900_DVBS_FOUND) &&
+						(i_params->dmd1_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST))
+					signal_type = stv0900_dvbs1_acq_workaround(fe);
+			} else
+				i_params->dmd1_rslts.locked = FALSE;
+
+			break;
+		case STV0900_DEMOD_2:
+			if (i_params->chip_id <= 0x11) {
+				if ((stv0900_get_bits(i_params, F0900_P2_HEADER_MODE) == STV0900_DVBS_FOUND) &&
+						(i_params->dmd2_srch_iq_inv <= STV0900_IQ_AUTO_NORMAL_FIRST))
+					signal_type = stv0900_dvbs1_acq_workaround(fe);
+			} else
+				i_params->dmd2_rslts.locked = FALSE;
+			break;
+		}
+	}
+
+	return signal_type;
+}
+
diff --git a/drivers/media/dvb/frontends/stv6110.c b/drivers/media/dvb/frontends/stv6110.c
new file mode 100644
index 0000000..70efac8
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110.c
@@ -0,0 +1,456 @@
+/*
+ * stv6110.c
+ *
+ * Driver for ST STV6110 satellite tuner IC.
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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/dvb/frontend.h>
+
+#include <linux/types.h>
+
+#include "stv6110.h"
+
+static int debug;
+
+struct stv6110_priv {
+	int i2c_address;
+	struct i2c_adapter *i2c;
+
+	u32 mclk;
+	u8 regs[8];
+};
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+static s32 abssub(s32 a, s32 b)
+{
+	if (a > b)
+		return a - b;
+	else
+		return b - a;
+};
+
+static int stv6110_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[],
+							int start, int len)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	int rc;
+	u8 cmdbuf[len + 1];
+	struct i2c_msg msg = {
+		.addr	= priv->i2c_address,
+		.flags	= 0,
+		.buf	= cmdbuf,
+		.len	= len + 1
+	};
+
+	dprintk("%s\n", __func__);
+
+	if (start + len > 8)
+		return -EINVAL;
+
+	memcpy(&cmdbuf[1], buf, len);
+	cmdbuf[0] = start;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	rc = i2c_transfer(priv->i2c, &msg, 1);
+	if (rc != 1)
+		dprintk("%s: i2c error\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int stv6110_read_regs(struct dvb_frontend *fe, u8 regs[],
+							int start, int len)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	int rc;
+	u8 reg[] = { start };
+	struct i2c_msg msg_wr = {
+		.addr	= priv->i2c_address,
+		.flags	= 0,
+		.buf	= reg,
+		.len	= 1,
+	};
+
+	struct i2c_msg msg_rd = {
+		.addr	= priv->i2c_address,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= len,
+	};
+	/* write subaddr */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	rc = i2c_transfer(priv->i2c, &msg_wr, 1);
+	if (rc != 1)
+		dprintk("%s: i2c error\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	/* read registers */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	rc = i2c_transfer(priv->i2c, &msg_rd, 1);
+	if (rc != 1)
+		dprintk("%s: i2c error\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	memcpy(&priv->regs[start], regs, len);
+
+	return 0;
+}
+
+static int stv6110_read_reg(struct dvb_frontend *fe, int start)
+{
+	u8 buf[] = { 0 };
+	stv6110_read_regs(fe, buf, start, 1);
+
+	return buf[0];
+}
+
+static int stv6110_sleep(struct dvb_frontend *fe)
+{
+	u8 reg[] = { 0 };
+	stv6110_write_regs(fe, reg, 0, 1);
+
+	return 0;
+}
+
+static u32 carrier_width(u32 symbol_rate, fe_rolloff_t rolloff)
+{
+	u32 rlf;
+
+	switch (rolloff) {
+	case ROLLOFF_20:
+		rlf = 20;
+		break;
+	case ROLLOFF_25:
+		rlf = 25;
+		break;
+	default:
+		rlf = 35;
+		break;
+	}
+
+	return symbol_rate  + ((symbol_rate * rlf) / 100);
+}
+
+static int stv6110_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	u8 r8, ret = 0x04;
+	int i;
+
+	if ((bandwidth / 2) > 36000000) /*BW/2 max=31+5=36 mhz for r8=31*/
+		r8 = 31;
+	else if ((bandwidth / 2) < 5000000) /* BW/2 min=5Mhz for F=0 */
+		r8 = 0;
+	else /*if 5 < BW/2 < 36*/
+		r8 = (bandwidth / 2) / 1000000 - 5;
+
+	/* ctrl3, RCCLKOFF = 0 Activate the calibration Clock */
+	/* ctrl3, CF = r8 Set the LPF value */
+	priv->regs[RSTV6110_CTRL3] &= ~((1 << 6) | 0x1f);
+	priv->regs[RSTV6110_CTRL3] |= (r8 & 0x1f);
+	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1);
+	/* stat1, CALRCSTRT = 1 Start LPF auto calibration*/
+	priv->regs[RSTV6110_STAT1] |= 0x02;
+	stv6110_write_regs(fe, &priv->regs[RSTV6110_STAT1], RSTV6110_STAT1, 1);
+
+	i = 0;
+	/* Wait for CALRCSTRT == 0 */
+	while ((i < 10) && (ret != 0)) {
+		ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x02);
+		mdelay(1);	/* wait for LPF auto calibration */
+		i++;
+	}
+
+	/* RCCLKOFF = 1 calibration done, desactivate the calibration Clock */
+	priv->regs[RSTV6110_CTRL3] |= (1 << 6);
+	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL3], RSTV6110_CTRL3, 1);
+	return 0;
+}
+
+static int stv6110_init(struct dvb_frontend *fe)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	u8 buf0[] = { 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e };
+
+	memcpy(priv->regs, buf0, 8);
+	/* K = (Reference / 1000000) - 16 */
+	priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3);
+	priv->regs[RSTV6110_CTRL1] |=
+				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
+
+	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1], RSTV6110_CTRL1, 8);
+	msleep(1);
+	stv6110_set_bandwidth(fe, 72000000);
+
+	return 0;
+}
+
+static int stv6110_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	u32 nbsteps, divider, psd2, freq;
+	u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+	stv6110_read_regs(fe, regs, 0, 8);
+	/*N*/
+	divider = (priv->regs[RSTV6110_TUNING2] & 0x0f) << 8;
+	divider += priv->regs[RSTV6110_TUNING1];
+
+	/*R*/
+	nbsteps  = (priv->regs[RSTV6110_TUNING2] >> 6) & 3;
+	/*p*/
+	psd2  = (priv->regs[RSTV6110_TUNING2] >> 4) & 1;
+
+	freq = divider * (priv->mclk / 1000);
+	freq /= (1 << (nbsteps + psd2));
+	freq /= 4;
+
+	*frequency = freq;
+
+	return 0;
+}
+
+static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 ret = 0x04;
+	u32 divider, ref, p, presc, i, result_freq, vco_freq;
+	s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val;
+	s32 srate; u8 gain;
+
+	dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__,
+						frequency, priv->mclk);
+
+	/* K = (Reference / 1000000) - 16 */
+	priv->regs[RSTV6110_CTRL1] &= ~(0x1f << 3);
+	priv->regs[RSTV6110_CTRL1] |=
+				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
+
+	/* BB_GAIN = db/2 */
+	if (fe->ops.set_property && fe->ops.get_property) {
+		srate = c->symbol_rate;
+		dprintk("%s: Get Frontend parameters: srate=%d\n",
+							__func__, srate);
+	} else
+		srate = 15000000;
+
+	if (srate >= 15000000)
+		gain = 3; /* +6 dB */
+	else if (srate >= 5000000)
+		gain = 3; /* +6 dB */
+	else
+		gain = 3; /* +6 dB */
+
+	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
+	priv->regs[RSTV6110_CTRL2] |= (gain & 0x0f);
+
+	if (frequency <= 1023000) {
+		p = 1;
+		presc = 0;
+	} else if (frequency <= 1300000) {
+		p = 1;
+		presc = 1;
+	} else if (frequency <= 2046000) {
+		p = 0;
+		presc = 0;
+	} else {
+		p = 0;
+		presc = 1;
+	}
+	/* DIV4SEL = p*/
+	priv->regs[RSTV6110_TUNING2] &= ~(1 << 4);
+	priv->regs[RSTV6110_TUNING2] |= (p << 4);
+
+	/* PRESC32ON = presc */
+	priv->regs[RSTV6110_TUNING2] &= ~(1 << 5);
+	priv->regs[RSTV6110_TUNING2] |= (presc << 5);
+
+	p_val = (int)(1 << (p + 1)) * 10;/* P = 2 or P = 4 */
+	for (r_div = 0; r_div <= 3; r_div++) {
+		p_calc = (priv->mclk / 100000);
+		p_calc /= (1 << (r_div + 1));
+		if ((abssub(p_calc, p_val)) < (abssub(p_calc_opt, p_val)))
+			r_div_opt = r_div;
+
+		p_calc_opt = (priv->mclk / 100000);
+		p_calc_opt /= (1 << (r_div_opt + 1));
+	}
+
+	ref = priv->mclk / ((1 << (r_div_opt + 1))  * (1 << (p + 1)));
+	divider = (((frequency * 1000) + (ref >> 1)) / ref);
+
+	/* RDIV = r_div_opt */
+	priv->regs[RSTV6110_TUNING2] &= ~(3 << 6);
+	priv->regs[RSTV6110_TUNING2] |= (((r_div_opt) & 3) << 6);
+
+	/* NDIV_MSB = MSB(divider) */
+	priv->regs[RSTV6110_TUNING2] &= ~0x0f;
+	priv->regs[RSTV6110_TUNING2] |= (((divider) >> 8) & 0x0f);
+
+	/* NDIV_LSB, LSB(divider) */
+	priv->regs[RSTV6110_TUNING1] = (divider & 0xff);
+
+	/* CALVCOSTRT = 1 VCO Auto Calibration */
+	priv->regs[RSTV6110_STAT1] |= 0x04;
+	stv6110_write_regs(fe, &priv->regs[RSTV6110_CTRL1],
+						RSTV6110_CTRL1, 8);
+
+	i = 0;
+	/* Wait for CALVCOSTRT == 0 */
+	while ((i < 10) && (ret != 0)) {
+		ret = ((stv6110_read_reg(fe, RSTV6110_STAT1)) & 0x04);
+		msleep(1); /* wait for VCO auto calibration */
+		i++;
+	}
+
+	ret = stv6110_read_reg(fe, RSTV6110_STAT1);
+	stv6110_get_frequency(fe, &result_freq);
+
+	vco_freq = divider * ((priv->mclk / 1000) / ((1 << (r_div_opt + 1))));
+	dprintk("%s, stat1=%x, lo_freq=%d kHz, vco_frec=%d kHz\n", __func__,
+						ret, result_freq, vco_freq);
+
+	return 0;
+}
+
+static int stv6110_set_params(struct dvb_frontend *fe,
+			      struct dvb_frontend_parameters *params)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 bandwidth = carrier_width(c->symbol_rate, c->rolloff);
+
+	stv6110_set_frequency(fe, c->frequency);
+	stv6110_set_bandwidth(fe, bandwidth);
+
+	return 0;
+}
+
+static int stv6110_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct stv6110_priv *priv = fe->tuner_priv;
+	u8 r8 = 0;
+	u8 regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+	stv6110_read_regs(fe, regs, 0, 8);
+
+	/* CF */
+	r8 = priv->regs[RSTV6110_CTRL3] & 0x1f;
+	*bandwidth = (r8 + 5) * 2000000;/* x2 for ZIF tuner BW/2 = F+5 Mhz */
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stv6110_tuner_ops = {
+	.info = {
+		.name = "ST STV6110",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_step = 1000,
+	},
+	.init = stv6110_init,
+	.release = stv6110_release,
+	.sleep = stv6110_sleep,
+	.set_params = stv6110_set_params,
+	.get_frequency = stv6110_get_frequency,
+	.set_frequency = stv6110_set_frequency,
+	.get_bandwidth = stv6110_get_bandwidth,
+	.set_bandwidth = stv6110_set_bandwidth,
+
+};
+
+struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
+					const struct stv6110_config *config,
+					struct i2c_adapter *i2c)
+{
+	struct stv6110_priv *priv = NULL;
+	u8 reg0[] = { 0x00, 0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = config->i2c_address,
+			.flags = 0,
+			.buf = reg0,
+			.len = 9
+		}
+	};
+	int ret;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	ret = i2c_transfer(i2c, msg, 1);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 1)
+		return NULL;
+
+	priv = kzalloc(sizeof(struct stv6110_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->i2c_address = config->i2c_address;
+	priv->i2c = i2c;
+	priv->mclk = config->mclk;
+
+	memcpy(&priv->regs, &reg0[1], 8);
+
+	memcpy(&fe->ops.tuner_ops, &stv6110_tuner_ops,
+				sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = priv;
+	printk(KERN_INFO "STV6110 attached on addr=%x!\n", priv->i2c_address);
+
+	return fe;
+}
+EXPORT_SYMBOL(stv6110_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("ST STV6110 driver");
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv6110.h b/drivers/media/dvb/frontends/stv6110.h
new file mode 100644
index 0000000..1c0314d
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv6110.h
@@ -0,0 +1,62 @@
+/*
+ * stv6110.h
+ *
+ * Driver for ST STV6110 satellite tuner IC.
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 __DVB_STV6110_H__
+#define __DVB_STV6110_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/* registers */
+#define RSTV6110_CTRL1		0
+#define RSTV6110_CTRL2		1
+#define RSTV6110_TUNING1	2
+#define RSTV6110_TUNING2	3
+#define RSTV6110_CTRL3		4
+#define RSTV6110_STAT1		5
+#define RSTV6110_STAT2		6
+#define RSTV6110_STAT3		7
+
+struct stv6110_config {
+	u8 i2c_address;
+	u32 mclk;
+	int iq_wiring;
+};
+
+#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \
+							&& defined(MODULE))
+extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
+					const struct stv6110_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
+					const struct stv6110_config *config,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 1465ff7..4981cef8 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -162,7 +162,7 @@
 	if (ret != 2) {
 		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
 			ret);
-		return -1;
+		return -EINVAL;
 	}
 
 	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
@@ -481,16 +481,18 @@
 static int tda10046_fwupload(struct dvb_frontend* fe)
 {
 	struct tda1004x_state* state = fe->demodulator_priv;
-	int ret;
+	int ret, confc4;
 	const struct firmware *fw;
 
 	/* reset + wake up chip */
 	if (state->config->xtal_freq == TDA10046_XTAL_4M) {
-		tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
+		confc4 = 0;
 	} else {
 		dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
-		tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80);
+		confc4 = 0x80;
 	}
+	tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4);
+
 	tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
 	/* set GPIO 1 and 3 */
 	if (state->config->gpio_config != TDA10046_GPTRI) {
@@ -508,13 +510,29 @@
 	if (tda1004x_check_upload_ok(state) == 0)
 		return 0;
 
+	/*
+	   For i2c normal work, we need to slow down the bus speed.
+	   However, the slow down breaks the eeprom firmware load.
+	   So, use normal speed for eeprom booting and then restore the
+	   i2c speed after that. Tested with MSI TV @nyware A/D board,
+	   that comes with firmware version 29 inside their eeprom.
+
+	   It should also be noticed that no other I2C transfer should
+	   be in course while booting from eeprom, otherwise, tda10046
+	   goes into an instable state. So, proper locking are needed
+	   at the i2c bus master.
+	 */
 	printk(KERN_INFO "tda1004x: trying to boot from eeprom\n");
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
+	tda1004x_write_byteI(state, TDA1004X_CONFC4, 4);
 	msleep(300);
-	/* don't re-upload unless necessary */
+	tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4);
+
+	/* Checks if eeprom firmware went without troubles */
 	if (tda1004x_check_upload_ok(state) == 0)
 		return 0;
 
+	/* eeprom firmware didn't work. Load one manually. */
+
 	if (state->config->request_firmware != NULL) {
 		/* request the firmware, this will block until someone uploads it */
 		printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c
new file mode 100644
index 0000000..e22a0b3
--- /dev/null
+++ b/drivers/media/dvb/frontends/zl10036.c
@@ -0,0 +1,519 @@
+/**
+ * Driver for Zarlink zl10036 DVB-S silicon tuner
+ *
+ * Copyright (C) 2006 Tino Reichardt
+ * Copyright (C) 2007-2009 Matthias Schwarzott <zzam@gentoo.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ **
+ * The data sheet for this tuner can be found at:
+ *    http://www.mcmilk.de/projects/dvb-card/datasheets/ZL10036.pdf
+ *
+ * This one is working: (at my Avermedia DVB-S Pro)
+ * - zl10036 (40pin, FTA)
+ *
+ * A driver for zl10038 should be very similar.
+ */
+
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "zl10036.h"
+
+static int zl10036_debug;
+#define dprintk(level, args...) \
+	do { if (zl10036_debug & level) printk(KERN_DEBUG "zl10036: " args); \
+	} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define deb_i2c(args...)  dprintk(0x02, args)
+
+struct zl10036_state {
+	struct i2c_adapter *i2c;
+	const struct zl10036_config *config;
+	u32 frequency;
+	u8 br, bf;
+};
+
+
+/* This driver assumes the tuner is driven by a 10.111MHz Cristal */
+#define _XTAL 10111
+
+/* Some of the possible dividers:
+ *   64, (write 0x05 to reg), freq step size   158kHz
+ *   10, (write 0x0a to reg), freq step size 1.011kHz (used here)
+ *    5, (write 0x09 to reg), freq step size 2.022kHz
+ */
+
+#define _RDIV 10
+#define _RDIV_REG 0x0a
+#define _FR   (_XTAL/_RDIV)
+
+#define STATUS_POR 0x80 /* Power on Reset */
+#define STATUS_FL  0x40 /* Frequency & Phase Lock */
+
+/* read/write for zl10036 and zl10038 */
+
+static int zl10036_read_status_reg(struct zl10036_state *state)
+{
+	u8 status;
+	struct i2c_msg msg[1] = {
+		{ .addr = state->config->tuner_address, .flags = I2C_M_RD,
+		  .buf = &status, .len = sizeof(status) },
+	};
+
+	if (i2c_transfer(state->i2c, msg, 1) != 1) {
+		printk(KERN_ERR "%s: i2c read failed at addr=%02x\n",
+			__func__, state->config->tuner_address);
+		return -EIO;
+	}
+
+	deb_i2c("R(status): %02x  [FL=%d]\n", status,
+		(status & STATUS_FL) ? 1 : 0);
+	if (status & STATUS_POR)
+		deb_info("%s: Power-On-Reset bit enabled - "
+			"need to initialize the tuner\n", __func__);
+
+	return status;
+}
+
+static int zl10036_write(struct zl10036_state *state, u8 buf[], u8 count)
+{
+	struct i2c_msg msg[1] = {
+		{ .addr = state->config->tuner_address, .flags = 0,
+		  .buf = buf, .len = count },
+	};
+	u8 reg = 0;
+	int ret;
+
+	if (zl10036_debug & 0x02) {
+		/* every 8bit-value satisifes this!
+		 * so only check for debug log */
+		if ((buf[0] & 0x80) == 0x00)
+			reg = 2;
+		else if ((buf[0] & 0xc0) == 0x80)
+			reg = 4;
+		else if ((buf[0] & 0xf0) == 0xc0)
+			reg = 6;
+		else if ((buf[0] & 0xf0) == 0xd0)
+			reg = 8;
+		else if ((buf[0] & 0xf0) == 0xe0)
+			reg = 10;
+		else if ((buf[0] & 0xf0) == 0xf0)
+			reg = 12;
+
+		deb_i2c("W(%d):", reg);
+		{
+			int i;
+			for (i = 0; i < count; i++)
+				printk(KERN_CONT " %02x", buf[i]);
+			printk(KERN_CONT "\n");
+		}
+	}
+
+	ret = i2c_transfer(state->i2c, msg, 1);
+	if (ret != 1) {
+		printk(KERN_ERR "%s: i2c error, ret=%d\n", __func__, ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int zl10036_release(struct dvb_frontend *fe)
+{
+	struct zl10036_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+
+	return 0;
+}
+
+static int zl10036_sleep(struct dvb_frontend *fe)
+{
+	struct zl10036_state *state = fe->tuner_priv;
+	u8 buf[] = { 0xf0, 0x80 }; /* regs 12/13 */
+	int ret;
+
+	deb_info("%s\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	ret = zl10036_write(state, buf, sizeof(buf));
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	return ret;
+}
+
+/**
+ * register map of the ZL10036/ZL10038
+ *
+ * reg[default] content
+ *  2[0x00]:   0 | N14 | N13 | N12 | N11 | N10 |  N9 |  N8
+ *  3[0x00]:  N7 |  N6 |  N5 |  N4 |  N3 |  N2 |  N1 |  N0
+ *  4[0x80]:   1 |   0 | RFG | BA1 | BA0 | BG1 | BG0 | LEN
+ *  5[0x00]:  P0 |  C1 |  C0 |  R4 |  R3 |  R2 |  R1 |  R0
+ *  6[0xc0]:   1 |   1 |   0 |   0 | RSD |   0 |   0 |   0
+ *  7[0x20]:  P1 | BF6 | BF5 | BF4 | BF3 | BF2 | BF1 |   0
+ *  8[0xdb]:   1 |   1 |   0 |   1 |   0 |  CC |   1 |   1
+ *  9[0x30]: VSD |  V2 |  V1 |  V0 |  S3 |  S2 |  S1 |  S0
+ * 10[0xe1]:   1 |   1 |   1 |   0 |   0 | LS2 | LS1 | LS0
+ * 11[0xf5]:  WS | WH2 | WH1 | WH0 | WL2 | WL1 | WL0 | WRE
+ * 12[0xf0]:   1 |   1 |   1 |   1 |   0 |   0 |   0 |   0
+ * 13[0x28]:  PD | BR4 | BR3 | BR2 | BR1 | BR0 | CLR |  TL
+ */
+
+static int zl10036_set_frequency(struct zl10036_state *state, u32 frequency)
+{
+	u8 buf[2];
+	u32 div, foffset;
+
+	div = (frequency + _FR/2) / _FR;
+	state->frequency = div * _FR;
+
+	foffset = frequency - state->frequency;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = (div >> 0) & 0xff;
+
+	deb_info("%s: ftodo=%u fpriv=%u ferr=%d div=%u\n", __func__,
+		frequency, state->frequency, foffset, div);
+
+	return zl10036_write(state, buf, sizeof(buf));
+}
+
+static int zl10036_set_bandwidth(struct zl10036_state *state, u32 fbw)
+{
+	/* fbw is measured in kHz */
+	u8 br, bf;
+	int ret;
+	u8 buf_bf[] = {
+		0xc0, 0x00, /*   6/7: rsd=0 bf=0 */
+	};
+	u8 buf_br[] = {
+		0xf0, 0x00, /* 12/13: br=0xa clr=0 tl=0*/
+	};
+	u8 zl10036_rsd_off[] = { 0xc8 }; /* set RSD=1 */
+
+	/* ensure correct values */
+	if (fbw > 35000)
+		fbw = 35000;
+	if (fbw <  8000)
+		fbw =  8000;
+
+#define _BR_MAXIMUM (_XTAL/575) /* _XTAL / 575kHz = 17 */
+
+	/* <= 28,82 MHz */
+	if (fbw <= 28820) {
+		br = _BR_MAXIMUM;
+	} else {
+		/**
+		 *  f(bw)=34,6MHz f(xtal)=10.111MHz
+		 *  br = (10111/34600) * 63 * 1/K = 14;
+		 */
+		br = ((_XTAL * 21 * 1000) / (fbw * 419));
+	}
+
+	/* ensure correct values */
+	if (br < 4)
+		br = 4;
+	if (br > _BR_MAXIMUM)
+		br = _BR_MAXIMUM;
+
+	/*
+	 * k = 1.257
+	 * bf = fbw/_XTAL * br * k - 1 */
+
+	bf = (fbw * br * 1257) / (_XTAL * 1000) - 1;
+
+	/* ensure correct values */
+	if (bf > 62)
+		bf = 62;
+
+	buf_bf[1] = (bf << 1) & 0x7e;
+	buf_br[1] = (br << 2) & 0x7c;
+	deb_info("%s: BW=%d br=%u bf=%u\n", __func__, fbw, br, bf);
+
+	if (br != state->br) {
+		ret = zl10036_write(state, buf_br, sizeof(buf_br));
+		if (ret < 0)
+			return ret;
+	}
+
+	if (bf != state->bf) {
+		ret = zl10036_write(state, buf_bf, sizeof(buf_bf));
+		if (ret < 0)
+			return ret;
+
+		/* time = br/(32* fxtal) */
+		/* minimal sleep time to be calculated
+		 * maximum br is 63 -> max time = 2 /10 MHz = 2e-7 */
+		msleep(1);
+
+		ret = zl10036_write(state, zl10036_rsd_off,
+			sizeof(zl10036_rsd_off));
+		if (ret < 0)
+			return ret;
+	}
+
+	state->br = br;
+	state->bf = bf;
+
+	return 0;
+}
+
+static int zl10036_set_gain_params(struct zl10036_state *state,
+	int c)
+{
+	u8 buf[2];
+	u8 rfg, ba, bg;
+
+	/* default values */
+	rfg = 0; /* enable when using an lna */
+	ba = 1;
+	bg = 1;
+
+	/* reg 4 */
+	buf[0] = 0x80 | ((rfg << 5) & 0x20)
+		| ((ba  << 3) & 0x18) | ((bg  << 1) & 0x06);
+
+	if (!state->config->rf_loop_enable)
+		buf[0] |= 0x01;
+
+	/* P0=0 */
+	buf[1] = _RDIV_REG | ((c << 5) & 0x60);
+
+	deb_info("%s: c=%u rfg=%u ba=%u bg=%u\n", __func__, c, rfg, ba, bg);
+	return zl10036_write(state, buf, sizeof(buf));
+}
+
+static int zl10036_set_params(struct dvb_frontend *fe,
+		struct dvb_frontend_parameters *params)
+{
+	struct zl10036_state *state = fe->tuner_priv;
+	int ret = 0;
+	u32 frequency = params->frequency;
+	u32 fbw;
+	int i;
+	u8 c;
+
+	/* ensure correct values
+	 * maybe redundant as core already checks this */
+	if ((frequency < fe->ops.info.frequency_min)
+	||  (frequency > fe->ops.info.frequency_max))
+		return -EINVAL;
+
+	/**
+	 * alpha = 1.35 for dvb-s
+	 * fBW = (alpha*symbolrate)/(2*0.8)
+	 * 1.35 / (2*0.8) = 27 / 32
+	 */
+	fbw = (27 * params->u.qpsk.symbol_rate) / 32;
+
+	/* scale to kHz */
+	fbw /= 1000;
+
+	/* Add safe margin of 3MHz */
+	fbw += 3000;
+
+	/* setting the charge pump - guessed values */
+	if (frequency < 950000)
+		return -EINVAL;
+	else if (frequency < 1250000)
+		c = 0;
+	else if (frequency < 1750000)
+		c = 1;
+	else if (frequency < 2175000)
+		c = 2;
+	else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	ret = zl10036_set_gain_params(state, c);
+	if (ret < 0)
+		goto error;
+
+	ret = zl10036_set_frequency(state, params->frequency);
+	if (ret < 0)
+		goto error;
+
+	ret = zl10036_set_bandwidth(state, fbw);
+	if (ret < 0)
+		goto error;
+
+	/* wait for tuner lock - no idea if this is really needed */
+	for (i = 0; i < 20; i++) {
+		ret = zl10036_read_status_reg(state);
+		if (ret < 0)
+			goto error;
+
+		/* check Frequency & Phase Lock Bit */
+		if (ret & STATUS_FL)
+			break;
+
+		msleep(10);
+	}
+
+error:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	return ret;
+}
+
+static int zl10036_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct zl10036_state *state = fe->tuner_priv;
+
+	*frequency = state->frequency;
+
+	return 0;
+}
+
+static int zl10036_init_regs(struct zl10036_state *state)
+{
+	int ret;
+	int i;
+
+	/* could also be one block from reg 2 to 13 and additional 10/11 */
+	u8 zl10036_init_tab[][2] = {
+		{ 0x04, 0x00 },		/*   2/3: div=0x400 - arbitrary value */
+		{ 0x8b, _RDIV_REG },	/*   4/5: rfg=0 ba=1 bg=1 len=? */
+					/*        p0=0 c=0 r=_RDIV_REG */
+		{ 0xc0, 0x20 },		/*   6/7: rsd=0 bf=0x10 */
+		{ 0xd3, 0x40 },		/*   8/9: from datasheet */
+		{ 0xe3, 0x5b },		/* 10/11: lock window level */
+		{ 0xf0, 0x28 },		/* 12/13: br=0xa clr=0 tl=0*/
+		{ 0xe3, 0xf9 },		/* 10/11: unlock window level */
+	};
+
+	/* invalid values to trigger writing */
+	state->br = 0xff;
+	state->bf = 0xff;
+
+	if (!state->config->rf_loop_enable)
+		zl10036_init_tab[1][2] |= 0x01;
+
+	deb_info("%s\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(zl10036_init_tab); i++) {
+		ret = zl10036_write(state, zl10036_init_tab[i], 2);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int zl10036_init(struct dvb_frontend *fe)
+{
+	struct zl10036_state *state = fe->tuner_priv;
+	int ret = 0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	ret = zl10036_read_status_reg(state);
+	if (ret < 0)
+		return ret;
+
+	/* Only init if Power-on-Reset bit is set? */
+	ret = zl10036_init_regs(state);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	return ret;
+}
+
+static struct dvb_tuner_ops zl10036_tuner_ops = {
+	.info = {
+		.name = "Zarlink ZL10036",
+		.frequency_min = 950000,
+		.frequency_max = 2175000
+	},
+	.init = zl10036_init,
+	.release = zl10036_release,
+	.sleep = zl10036_sleep,
+	.set_params = zl10036_set_params,
+	.get_frequency = zl10036_get_frequency,
+};
+
+struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
+				    const struct zl10036_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct zl10036_state *state = NULL;
+	int ret;
+
+	if (NULL == config) {
+		printk(KERN_ERR "%s: no config specified", __func__);
+		goto error;
+	}
+
+	state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL);
+	if (NULL == state)
+		return NULL;
+
+	state->config = config;
+	state->i2c = i2c;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+	ret = zl10036_read_status_reg(state);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: No zl10036 found\n", __func__);
+		goto error;
+	}
+
+	ret = zl10036_init_regs(state);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: tuner initialization failed\n",
+			__func__);
+		goto error;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+	fe->tuner_priv = state;
+
+	memcpy(&fe->ops.tuner_ops, &zl10036_tuner_ops,
+		sizeof(struct dvb_tuner_ops));
+	printk(KERN_INFO "%s: tuner initialization (%s addr=0x%02x) ok\n",
+		__func__, fe->ops.tuner_ops.info.name, config->tuner_address);
+
+	return fe;
+
+error:
+	zl10036_release(fe);
+	return NULL;
+}
+EXPORT_SYMBOL(zl10036_attach);
+
+module_param_named(debug, zl10036_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+MODULE_DESCRIPTION("DVB ZL10036 driver");
+MODULE_AUTHOR("Tino Reichardt");
+MODULE_AUTHOR("Matthias Schwarzott");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/zl10036.h b/drivers/media/dvb/frontends/zl10036.h
new file mode 100644
index 0000000..d84b8f8
--- /dev/null
+++ b/drivers/media/dvb/frontends/zl10036.h
@@ -0,0 +1,53 @@
+/**
+ * Driver for Zarlink ZL10036 DVB-S silicon tuner
+ *
+ * Copyright (C) 2006 Tino Reichardt
+ * Copyright (C) 2007-2009 Matthias Schwarzott <zzam@gentoo.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 DVB_ZL10036_H
+#define DVB_ZL10036_H
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a zl10036 tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param config zl10036_config structure
+ * @return FE pointer on success, NULL on failure.
+ */
+
+struct zl10036_config {
+	u8 tuner_address;
+	int rf_loop_enable;
+};
+
+#if defined(CONFIG_DVB_ZL10036) || \
+	(defined(CONFIG_DVB_ZL10036_MODULE) && defined(MODULE))
+extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
+	const struct zl10036_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
+	const struct zl10036_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* DVB_ZL10036_H */
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index b150ed3..148b6f7 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -572,6 +572,10 @@
 		zl10353_dump_regs(fe);
 	if (state->config.parallel_ts)
 		zl10353_reset_attach[2] &= ~0x20;
+	if (state->config.clock_ctl_1)
+		zl10353_reset_attach[3] = state->config.clock_ctl_1;
+	if (state->config.pll_0)
+		zl10353_reset_attach[4] = state->config.pll_0;
 
 	/* Do a "hard" reset if not already done */
 	if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
@@ -614,6 +618,7 @@
 				    struct i2c_adapter *i2c)
 {
 	struct zl10353_state *state = NULL;
+	int id;
 
 	/* allocate memory for the internal state */
 	state = kzalloc(sizeof(struct zl10353_state), GFP_KERNEL);
@@ -625,7 +630,8 @@
 	memcpy(&state->config, config, sizeof(struct zl10353_config));
 
 	/* check if the demod is there */
-	if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353)
+	id = zl10353_read_register(state, CHIP_ID);
+	if ((id != ID_ZL10353) && (id != ID_CE6230) && (id != ID_CE6231))
 		goto error;
 
 	/* create dvb_frontend */
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
index 2287bac..6e3ca9e 100644
--- a/drivers/media/dvb/frontends/zl10353.h
+++ b/drivers/media/dvb/frontends/zl10353.h
@@ -41,6 +41,10 @@
 
 	/* set if i2c_gate_ctrl disable is required */
 	u8 disable_i2c_gate_ctrl:1;
+
+	/* clock control registers (0x51-0x54) */
+	u8 clock_ctl_1;  /* default: 0x46 */
+	u8 pll_0;        /* default: 0x15 */
 };
 
 #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
index 055ff1f..e0dd1d3 100644
--- a/drivers/media/dvb/frontends/zl10353_priv.h
+++ b/drivers/media/dvb/frontends/zl10353_priv.h
@@ -22,7 +22,9 @@
 #ifndef _ZL10353_PRIV_
 #define _ZL10353_PRIV_
 
-#define ID_ZL10353	0x14
+#define ID_ZL10353	0x14 /* Zarlink ZL10353 */
+#define ID_CE6230	0x18 /* Intel CE6230 */
+#define ID_CE6231	0x19 /* Intel CE6231 */
 
 #define msb(x) (((x) >> 8) & 0xff)
 #define lsb(x) ((x) & 0xff)
@@ -50,6 +52,10 @@
 	TPS_RECEIVED_0     = 0x1E,
 	TPS_CURRENT_1      = 0x1F,
 	TPS_CURRENT_0      = 0x20,
+	CLOCK_CTL_0        = 0x51,
+	CLOCK_CTL_1        = 0x52,
+	PLL_0              = 0x53,
+	PLL_1              = 0x54,
 	RESET              = 0x55,
 	AGC_TARGET         = 0x56,
 	MCLK_RATIO         = 0x5C,
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index d101b30..ee89623 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -116,6 +116,7 @@
 
 	/* irq */
 	unsigned int overflow;
+	unsigned int dead;
 
 	/* dma */
 	dma_addr_t dma_addr;
@@ -336,8 +337,10 @@
 		return IRQ_NONE;
 
 	if (tscr == 0xffffffff) {
-		// FIXME: maybe recover somehow
-		dev_err(&pluto->pdev->dev, "card hung up :(\n");
+		if (pluto->dead == 0)
+			dev_err(&pluto->pdev->dev, "card has hung or been ejected.\n");
+		/* It's dead Jim */
+		pluto->dead = 1;
 		return IRQ_HANDLED;
 	}
 
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
index ee0737a..bcf93f4 100644
--- a/drivers/media/dvb/siano/Makefile
+++ b/drivers/media/dvb/siano/Makefile
@@ -1,6 +1,8 @@
-sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o
+sms1xxx-objs := smscoreapi.o sms-cards.o
 
 obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
+obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o
+obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 4307e4e..63e4d0e 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -19,50 +19,9 @@
 
 #include "sms-cards.h"
 
-struct usb_device_id smsusb_id_table[] = {
-#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
-	{ USB_DEVICE(0x187f, 0x0010),
-		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
-	{ USB_DEVICE(0x187f, 0x0100),
-		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
-	{ USB_DEVICE(0x187f, 0x0200),
-		.driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
-	{ USB_DEVICE(0x187f, 0x0201),
-		.driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
-	{ USB_DEVICE(0x187f, 0x0300),
-		.driver_info = SMS1XXX_BOARD_SIANO_VEGA },
-#endif
-	{ USB_DEVICE(0x2040, 0x1700),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
-	{ USB_DEVICE(0x2040, 0x1800),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
-	{ USB_DEVICE(0x2040, 0x1801),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
-	{ USB_DEVICE(0x2040, 0x2000),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
-	{ USB_DEVICE(0x2040, 0x2009),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 },
-	{ USB_DEVICE(0x2040, 0x200a),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
-	{ USB_DEVICE(0x2040, 0x2010),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
-	{ USB_DEVICE(0x2040, 0x2019),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
-	{ USB_DEVICE(0x2040, 0x5500),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0x5510),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0x5520),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0x5530),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0x5580),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0x5590),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, smsusb_id_table);
+static int sms_dbg;
+module_param_named(cards_dbg, sms_dbg, int, 0644);
+MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
 
 static struct sms_board sms_boards[] = {
 	[SMS_BOARD_UNKNOWN] = {
@@ -115,6 +74,7 @@
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
 		.lna_ctrl  = 29,
+		.rf_switch = 17,
 	},
 	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
 		.name	= "Hauppauge WinTV MiniCard",
@@ -130,6 +90,7 @@
 
 	return &sms_boards[id];
 }
+EXPORT_SYMBOL_GPL(sms_get_board);
 
 static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
 {
@@ -182,6 +143,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(sms_board_setup);
 
 int sms_board_power(struct smscore_device_t *coredev, int onoff)
 {
@@ -197,12 +159,13 @@
 	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
 	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
 		/* LNA */
-		sms_set_gpio(coredev,
-			     board->lna_ctrl, onoff ? 1 : 0);
+		if (!onoff)
+			sms_set_gpio(coredev, board->lna_ctrl, 0);
 		break;
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(sms_board_power);
 
 int sms_board_led_feedback(struct smscore_device_t *coredev, int led)
 {
@@ -225,3 +188,40 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(sms_board_led_feedback);
+
+int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled");
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+		sms_set_gpio(coredev,
+			     board->rf_switch, onoff ? 1 : 0);
+		return sms_set_gpio(coredev,
+				    board->lna_ctrl, onoff ? 1 : 0);
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(sms_board_lna_control);
+
+int sms_board_load_modules(int id)
+{
+	switch (id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT:
+	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A:
+	case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B:
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		request_module("smsdvb");
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_load_modules);
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
index 8e0fe9f..64d74c5 100644
--- a/drivers/media/dvb/siano/sms-cards.h
+++ b/drivers/media/dvb/siano/sms-cards.h
@@ -40,7 +40,7 @@
 	char *name, *fw[DEVICE_MODE_MAX];
 
 	/* gpios */
-	int led_power, led_hi, led_lo, lna_ctrl;
+	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
 };
 
 struct sms_board *sms_get_board(int id);
@@ -52,7 +52,8 @@
 #define SMS_LED_HI  2
 int sms_board_led_feedback(struct smscore_device_t *coredev, int led);
 int sms_board_power(struct smscore_device_t *coredev, int onoff);
+int sms_board_lna_control(struct smscore_device_t *coredev, int onoff);
 
-extern struct usb_device_id smsusb_id_table[];
+extern int sms_board_load_modules(int id);
 
 #endif /* __SMS_CARDS_H__ */
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index cf613f2..7bd4d1d 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -3,7 +3,7 @@
  *
  *  This file contains implementation for the interface to sms core component
  *
- *  author: Anatoly Greenblat
+ *  author: Uri Shkolnik
  *
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
@@ -34,8 +34,8 @@
 #include "smscoreapi.h"
 #include "sms-cards.h"
 
-int sms_debug;
-module_param_named(debug, sms_debug, int, 0644);
+static int sms_dbg;
+module_param_named(debug, sms_dbg, int, 0644);
 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
 
 struct smscore_device_notifyee_t {
@@ -105,11 +105,13 @@
 		core->led_state = led;
 	return core->led_state;
 }
+EXPORT_SYMBOL_GPL(smscore_set_board_id);
 
 int smscore_get_board_id(struct smscore_device_t *core)
 {
 	return core->board_id;
 }
+EXPORT_SYMBOL_GPL(smscore_get_board_id);
 
 struct smscore_registry_entry_t {
 	struct list_head entry;
@@ -170,6 +172,7 @@
 
 	return default_mode;
 }
+EXPORT_SYMBOL_GPL(smscore_registry_getmode);
 
 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
 {
@@ -261,6 +264,7 @@
 
 	return rc;
 }
+EXPORT_SYMBOL_GPL(smscore_register_hotplug);
 
 /**
  * unregister a client callback that called when device plugged in/unplugged
@@ -289,6 +293,7 @@
 
 	kmutex_unlock(&g_smscore_deviceslock);
 }
+EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
 
 static void smscore_notify_clients(struct smscore_device_t *coredev)
 {
@@ -432,6 +437,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(smscore_register_device);
 
 /**
  * sets initial device mode and notifies client hotplugs that device is ready
@@ -460,6 +466,7 @@
 
 	return rc;
 }
+EXPORT_SYMBOL_GPL(smscore_start_device);
 
 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 					void *buffer, size_t size,
@@ -688,6 +695,7 @@
 
 	sms_info("device %p destroyed", coredev);
 }
+EXPORT_SYMBOL_GPL(smscore_unregister_device);
 
 static int smscore_detect_mode(struct smscore_device_t *coredev)
 {
@@ -732,7 +740,7 @@
 	/*DVBH*/
 	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
 	/*TDMB*/
-	{"none", "tdmb_nova_12mhz.inp", "none", "none"},
+	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
 	/*DABIP*/
 	{"none", "none", "none", "none"},
 	/*BDA*/
@@ -879,6 +887,7 @@
 {
 	return coredev->mode;
 }
+EXPORT_SYMBOL_GPL(smscore_get_device_mode);
 
 /**
  * find client by response id & type within the clients list.
@@ -1006,6 +1015,7 @@
 		smscore_putbuffer(coredev, cb);
 	}
 }
+EXPORT_SYMBOL_GPL(smscore_onresponse);
 
 /**
  * return pointer to next free buffer descriptor from core pool
@@ -1031,6 +1041,7 @@
 
 	return cb;
 }
+EXPORT_SYMBOL_GPL(smscore_getbuffer);
 
 /**
  * return buffer descriptor to a pool
@@ -1045,6 +1056,7 @@
 {
 	list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
 }
+EXPORT_SYMBOL_GPL(smscore_putbuffer);
 
 static int smscore_validate_client(struct smscore_device_t *coredev,
 				   struct smscore_client_t *client,
@@ -1124,6 +1136,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(smscore_register_client);
 
 /**
  * frees smsclient object and all subclients associated with it
@@ -1154,6 +1167,7 @@
 
 	spin_unlock_irqrestore(&coredev->clientslock, flags);
 }
+EXPORT_SYMBOL_GPL(smscore_unregister_client);
 
 /**
  * verifies that source id is not taken by another client,
@@ -1193,6 +1207,7 @@
 
 	return coredev->sendrequest_handler(coredev->context, buffer, size);
 }
+EXPORT_SYMBOL_GPL(smsclient_sendrequest);
 
 
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
@@ -1276,12 +1291,12 @@
 	INIT_LIST_HEAD(&g_smscore_registry);
 	kmutex_init(&g_smscore_registrylock);
 
-	/* USB Register */
-	rc = smsusb_register();
 
-	/* DVB Register */
-	rc = smsdvb_register();
 
+
+
+
+	return rc;
 	sms_debug("rc %d", rc);
 
 	return rc;
@@ -1290,6 +1305,10 @@
 static void __exit smscore_module_exit(void)
 {
 
+
+
+
+
 	kmutex_lock(&g_smscore_deviceslock);
 	while (!list_empty(&g_smscore_notifyees)) {
 		struct smscore_device_notifyee_t *notifyee =
@@ -1312,18 +1331,12 @@
 	}
 	kmutex_unlock(&g_smscore_registrylock);
 
-	/* DVB UnRegister */
-	smsdvb_unregister();
-
-	/* Unregister USB */
-	smsusb_unregister();
-
 	sms_debug("");
 }
 
 module_init(smscore_module_init);
 module_exit(smscore_module_exit);
 
-MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
-MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
+MODULE_DESCRIPTION("Siano MDTV Core module");
+MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index 760e233..548de90 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -29,13 +29,13 @@
 #include <linux/scatterlist.h>
 #include <linux/types.h>
 #include <asm/page.h>
+#include <linux/mutex.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
 
-#include <linux/mutex.h>
 
 #define kmutex_init(_p_) mutex_init(_p_)
 #define kmutex_lock(_p_) mutex_lock(_p_)
@@ -369,27 +369,6 @@
 	u8 outputdriving;
 };
 
-struct smsdvb_client_t {
-	struct list_head entry;
-
-	struct smscore_device_t	*coredev;
-	struct smscore_client_t	*smsclient;
-
-	struct dvb_adapter	adapter;
-	struct dvb_demux	demux;
-	struct dmxdev		dmxdev;
-	struct dvb_frontend	frontend;
-
-	fe_status_t		fe_status;
-	int			fe_ber, fe_snr, fe_unc, fe_signal_strength;
-
-	struct completion	tune_done, stat_done;
-
-	/* todo: save freq/band instead whole struct */
-	struct dvb_frontend_parameters fe_params;
-
-};
-
 extern void smscore_registry_setmode(char *devpath, int mode);
 extern int smscore_registry_getmode(char *devpath);
 
@@ -418,6 +397,13 @@
 extern void smscore_onresponse(struct smscore_device_t *coredev,
 			       struct smscore_buffer_t *cb);
 
+extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev);
+extern int smscore_map_common_buffer(struct smscore_device_t *coredev,
+				      struct vm_area_struct *vma);
+extern int smscore_get_fw_filename(struct smscore_device_t *coredev,
+				   int mode, char *filename);
+extern int smscore_send_fw_file(struct smscore_device_t *coredev,
+				u8 *ufwbuf, int size);
 
 extern
 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
@@ -433,18 +419,9 @@
 
 int smscore_led_state(struct smscore_device_t *core, int led);
 
-/* smsdvb.c */
-int smsdvb_register(void);
-void smsdvb_unregister(void);
-
-/* smsusb.c */
-int smsusb_register(void);
-void smsusb_unregister(void);
 
 /* ------------------------------------------------------------------------ */
 
-extern int sms_debug;
-
 #define DBG_INFO 1
 #define DBG_ADV  2
 
@@ -452,7 +429,7 @@
 	printk(kern "%s: " fmt "\n", __func__, ##arg)
 
 #define dprintk(kern, lvl, fmt, arg...) do {\
-	if (sms_debug & lvl) \
+	if (sms_dbg & lvl) \
 		sms_printk(kern, fmt, ##arg); } while (0)
 
 #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 2da953a..ba080b9 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -1,7 +1,7 @@
 /*
  *  Driver for the Siano SMS1xxx USB dongle
  *
- *  author: Anatoly Greenblat
+ *  Author: Uri Shkolni
  *
  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  *
@@ -27,9 +27,33 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct smsdvb_client_t {
+	struct list_head entry;
+
+	struct smscore_device_t *coredev;
+	struct smscore_client_t *smsclient;
+
+	struct dvb_adapter      adapter;
+	struct dvb_demux        demux;
+	struct dmxdev           dmxdev;
+	struct dvb_frontend     frontend;
+
+	fe_status_t             fe_status;
+	int                     fe_ber, fe_snr, fe_unc, fe_signal_strength;
+
+	struct completion       tune_done, stat_done;
+
+	/* todo: save freq/band instead whole struct */
+	struct dvb_frontend_parameters fe_params;
+};
+
 static struct list_head g_smsdvb_clients;
 static struct mutex g_smsdvb_clientslock;
 
+static int sms_dbg;
+module_param_named(debug, sms_dbg, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 {
 	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
@@ -262,6 +286,7 @@
 		struct SmsMsgHdr_ST	Msg;
 		u32		Data[3];
 	} Msg;
+	int ret;
 
 	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
 	Msg.Msg.msgDstId  = HIF_TASK;
@@ -282,6 +307,24 @@
 	default: return -EINVAL;
 	}
 
+	/* Disable LNA, if any. An error is returned if no LNA is present */
+	ret = sms_board_lna_control(client->coredev, 0);
+	if (ret == 0) {
+		fe_status_t status;
+
+		/* tune with LNA off at first */
+		ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+						  &client->tune_done);
+
+		smsdvb_read_status(fe, &status);
+
+		if (status & FE_HAS_LOCK)
+			return ret;
+
+		/* previous tune didnt lock - enable LNA and tune again */
+		sms_board_lna_control(client->coredev, 1);
+	}
+
 	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
 					   &client->tune_done);
 }
@@ -329,7 +372,7 @@
 
 static struct dvb_frontend_ops smsdvb_fe_ops = {
 	.info = {
-		.name			= "Siano Mobile Digital SMS1xxx",
+		.name			= "Siano Mobile Digital MDTV Receiver",
 		.type			= FE_OFDM,
 		.frequency_min		= 44250000,
 		.frequency_max		= 867250000,
@@ -371,7 +414,7 @@
 	if (!arrival)
 		return 0;
 
-	if (smscore_get_device_mode(coredev) != 4) {
+	if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) {
 		sms_err("SMS Device mode is not set for "
 			"DVB operation.");
 		return 0;
@@ -473,7 +516,7 @@
 	return rc;
 }
 
-int smsdvb_register(void)
+int smsdvb_module_init(void)
 {
 	int rc;
 
@@ -487,7 +530,7 @@
 	return rc;
 }
 
-void smsdvb_unregister(void)
+void smsdvb_module_exit(void)
 {
 	smscore_unregister_hotplug(smsdvb_hotplug);
 
@@ -499,3 +542,10 @@
 
 	kmutex_unlock(&g_smsdvb_clientslock);
 }
+
+module_init(smsdvb_module_init);
+module_exit(smsdvb_module_exit);
+
+MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
+MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 5d7ca34..71c65f5 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -27,6 +27,10 @@
 #include "smscoreapi.h"
 #include "sms-cards.h"
 
+static int sms_dbg;
+module_param_named(debug, sms_dbg, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
 #define USB1_BUFFER_SIZE		0x1000
 #define USB2_BUFFER_SIZE		0x4000
 
@@ -424,6 +428,7 @@
 
 	rc = smsusb_init_device(intf, id->driver_info);
 	sms_info("rc %d", rc);
+	sms_board_load_modules(id->driver_info);
 	return rc;
 }
 
@@ -436,7 +441,7 @@
 {
 	struct smsusb_device_t *dev =
 		(struct smsusb_device_t *)usb_get_intfdata(intf);
-	printk(KERN_INFO "%s  Entering status %d.\n", __func__, msg.event);
+	printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event);
 	smsusb_stop_streaming(dev);
 	return 0;
 }
@@ -448,7 +453,7 @@
 		(struct smsusb_device_t *)usb_get_intfdata(intf);
 	struct usb_device *udev = interface_to_usbdev(intf);
 
-	printk(KERN_INFO "%s  Entering.\n", __func__);
+	printk(KERN_INFO "%s: Entering.\n", __func__);
 	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
 	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
 
@@ -463,9 +468,8 @@
 				       intf->cur_altsetting->desc.
 				       bInterfaceNumber, 0);
 		if (rc < 0) {
-			printk(KERN_INFO
-			       "%s usb_set_interface failed, rc %d\n",
-			       __func__, rc);
+			printk(KERN_INFO "%s usb_set_interface failed, "
+			       "rc %d\n", __func__, rc);
 			return rc;
 		}
 	}
@@ -474,8 +478,55 @@
 	return 0;
 }
 
+struct usb_device_id smsusb_id_table[] = {
+#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
+	{ USB_DEVICE(0x187f, 0x0010),
+		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+	{ USB_DEVICE(0x187f, 0x0100),
+		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+	{ USB_DEVICE(0x187f, 0x0200),
+		.driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
+	{ USB_DEVICE(0x187f, 0x0201),
+		.driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
+	{ USB_DEVICE(0x187f, 0x0300),
+		.driver_info = SMS1XXX_BOARD_SIANO_VEGA },
+#endif
+	{ USB_DEVICE(0x2040, 0x1700),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
+	{ USB_DEVICE(0x2040, 0x1800),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
+	{ USB_DEVICE(0x2040, 0x1801),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
+	{ USB_DEVICE(0x2040, 0x2000),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2009),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 },
+	{ USB_DEVICE(0x2040, 0x200a),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2010),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2011),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2019),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x5500),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5510),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5520),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5530),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5580),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0x5590),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, smsusb_id_table);
+
 static struct usb_driver smsusb_driver = {
-	.name			= "sms1xxx",
+	.name			= "smsusb",
 	.probe			= smsusb_probe,
 	.disconnect		= smsusb_disconnect,
 	.id_table		= smsusb_id_table,
@@ -484,7 +535,7 @@
 	.resume			= smsusb_resume,
 };
 
-int smsusb_register(void)
+int smsusb_module_init(void)
 {
 	int rc = usb_register(&smsusb_driver);
 	if (rc)
@@ -495,10 +546,16 @@
 	return rc;
 }
 
-void smsusb_unregister(void)
+void smsusb_module_exit(void)
 {
 	sms_debug("");
 	/* Regular USB Cleanup */
 	usb_deregister(&smsusb_driver);
 }
 
+module_init(smsusb_module_init);
+module_exit(smsusb_module_exit);
+
+MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
+MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index ab0bcd2..7729904 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -108,7 +108,7 @@
 	select DVB_STB6100 if !DVB_FE_CUSTOMISE
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
 	select VIDEO_IR
 	help
 	  Support for simple SAA7146 based DVB cards
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index aa1ff52..4624cee 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -725,7 +725,7 @@
 }
 
 
-static struct file_operations dvb_osd_fops = {
+static const struct file_operations dvb_osd_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= dvb_generic_ioctl,
 	.open		= dvb_generic_open,
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index bdc62ac..e4d0900 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1456,7 +1456,7 @@
  * driver registration
  ******************************************************************************/
 
-static struct file_operations dvb_video_fops = {
+static const struct file_operations dvb_video_fops = {
 	.owner		= THIS_MODULE,
 	.write		= dvb_video_write,
 	.ioctl		= dvb_generic_ioctl,
@@ -1474,7 +1474,7 @@
 	.kernel_ioctl	= dvb_video_ioctl,
 };
 
-static struct file_operations dvb_audio_fops = {
+static const struct file_operations dvb_audio_fops = {
 	.owner		= THIS_MODULE,
 	.write		= dvb_audio_write,
 	.ioctl		= dvb_generic_ioctl,
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 261135d..c7a65b1 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -345,7 +345,7 @@
 	return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
 }
 
-static struct file_operations dvb_ca_fops = {
+static const struct file_operations dvb_ca_fops = {
 	.owner		= THIS_MODULE,
 	.read		= dvb_ca_read,
 	.write		= dvb_ca_write,
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index c5b9c70..2210cff 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -316,253 +316,261 @@
 	return 0;
 }
 
-static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
 {
-	struct saa7146_dev *dev = fh->dev;
-	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-	dprintk(4, "saa7146_dev: %p\n", dev);
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+	u16 stereo_det;
+	s8 stereo;
 
-	switch (cmd) {
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-		u16 stereo_det;
-		s8 stereo;
+	dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
 
-		dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
+	if (!av7110->analog_tuner_flags || t->index != 0)
+		return -EINVAL;
 
-		if (!av7110->analog_tuner_flags || t->index != 0)
-			return -EINVAL;
+	memset(t, 0, sizeof(*t));
+	strcpy((char *)t->name, "Television");
 
-		memset(t, 0, sizeof(*t));
-		strcpy((char *)t->name, "Television");
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
+		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+	t->rangelow = 772;	/* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
+	t->rangehigh = 13684;	/* 855.25 MHz / 62.5 kHz = 13684 */
+	/* FIXME: add the real signal strength here */
+	t->signal = 0xffff;
+	t->afc = 0;
 
-		t->type = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
-			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-		t->rangelow = 772;	/* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
-		t->rangehigh = 13684;	/* 855.25 MHz / 62.5 kHz = 13684 */
-		/* FIXME: add the real signal strength here */
-		t->signal = 0xffff;
-		t->afc = 0;
+	/* FIXME: standard / stereo detection is still broken */
+	msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
+	dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
+	msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
+	dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
+	stereo = (s8)(stereo_det >> 8);
+	if (stereo > 0x10) {
+		/* stereo */
+		t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+		t->audmode = V4L2_TUNER_MODE_STEREO;
+	} else if (stereo < -0x10) {
+		/* bilingual */
+		t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+		t->audmode = V4L2_TUNER_MODE_LANG1;
+	} else /* mono */
+		t->rxsubchans = V4L2_TUNER_SUB_MONO;
 
-		// FIXME: standard / stereo detection is still broken
-		msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
-		dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
-		msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
-		dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
-		stereo = (s8)(stereo_det >> 8);
-		if (stereo > 0x10) {
-			/* stereo */
-			t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
-			t->audmode = V4L2_TUNER_MODE_STEREO;
-		}
-		else if (stereo < -0x10) {
-			/* bilingual */
-			t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-			t->audmode = V4L2_TUNER_MODE_LANG1;
-		}
-		else /* mono */
-			t->rxsubchans = V4L2_TUNER_SUB_MONO;
+	return 0;
+}
 
-		return 0;
-	}
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-		u16 fm_matrix, src;
-		dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
+static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+	u16 fm_matrix, src;
+	dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
 
-		if (!av7110->analog_tuner_flags || av7110->current_input != 1)
-			return -EINVAL;
+	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+		return -EINVAL;
 
-		switch (t->audmode) {
-		case V4L2_TUNER_MODE_STEREO:
-			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
-			fm_matrix = 0x3001; // stereo
-			src = 0x0020;
-			break;
-		case V4L2_TUNER_MODE_LANG1_LANG2:
-			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
-			fm_matrix = 0x3000; // bilingual
-			src = 0x0020;
-			break;
-		case V4L2_TUNER_MODE_LANG1:
-			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
-			fm_matrix = 0x3000; // mono
-			src = 0x0000;
-			break;
-		case V4L2_TUNER_MODE_LANG2:
-			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
-			fm_matrix = 0x3000; // mono
-			src = 0x0010;
-			break;
-		default: /* case V4L2_TUNER_MODE_MONO: */
-			dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
-			fm_matrix = 0x3000; // mono
-			src = 0x0030;
-			break;
-		}
-		msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
-		msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
-		msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
-		msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
-		return 0;
-	}
-	case VIDIOC_G_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
-
-		if (!av7110->analog_tuner_flags || av7110->current_input != 1)
-			return -EINVAL;
-
-		memset(f, 0, sizeof(*f));
-		f->type = V4L2_TUNER_ANALOG_TV;
-		f->frequency =	av7110->current_freq;
-		return 0;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
-
-		if (!av7110->analog_tuner_flags || av7110->current_input != 1)
-			return -EINVAL;
-
-		if (V4L2_TUNER_ANALOG_TV != f->type)
-			return -EINVAL;
-
-		msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); // fast mute
-		msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
-
-		/* tune in desired frequency */
-		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
-			ves1820_set_tv_freq(dev, f->frequency);
-		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-			stv0297_set_tv_freq(dev, f->frequency);
-		}
-		av7110->current_freq = f->frequency;
-
-		msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); // start stereo detection
-		msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
-		msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
-		msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
-		return 0;
-	}
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *i = arg;
-
-		dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
-
-		if (av7110->analog_tuner_flags) {
-			if (i->index < 0 || i->index >= 4)
-				return -EINVAL;
-		} else {
-			if (i->index != 0)
-				return -EINVAL;
-		}
-
-		memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
-
-		return 0;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		int *input = (int *)arg;
-		*input = av7110->current_input;
-		dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
-		return 0;
-	}
-	case VIDIOC_S_INPUT:
-	{
-		int input = *(int *)arg;
-
-		dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
-
-		if (!av7110->analog_tuner_flags)
-			return 0;
-
-		if (input < 0 || input >= 4)
-			return -EINVAL;
-
-		av7110->current_input = input;
-		return av7110_dvb_c_switch(fh);
-	}
-	case VIDIOC_G_AUDIO:
-	{
-		struct v4l2_audio *a = arg;
-
-		dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
-		if (a->index != 0)
-			return -EINVAL;
-		memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
+	switch (t->audmode) {
+	case V4L2_TUNER_MODE_STEREO:
+		dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
+		fm_matrix = 0x3001; /* stereo */
+		src = 0x0020;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n");
+		fm_matrix = 0x3000; /* bilingual */
+		src = 0x0020;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
+		fm_matrix = 0x3000; /* mono */
+		src = 0x0000;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
+		fm_matrix = 0x3000; /* mono */
+		src = 0x0010;
+		break;
+	default: /* case V4L2_TUNER_MODE_MONO: */
+		dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
+		fm_matrix = 0x3000; /* mono */
+		src = 0x0030;
 		break;
 	}
-	case VIDIOC_S_AUDIO:
-	{
-		struct v4l2_audio *a = arg;
-		dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
-		break;
+	msp_writereg(av7110, MSP_WR_DSP, 0x000e, fm_matrix);
+	msp_writereg(av7110, MSP_WR_DSP, 0x0008, src);
+	msp_writereg(av7110, MSP_WR_DSP, 0x0009, src);
+	msp_writereg(av7110, MSP_WR_DSP, 0x000a, src);
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
+
+	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+		return -EINVAL;
+
+	memset(f, 0, sizeof(*f));
+	f->type = V4L2_TUNER_ANALOG_TV;
+	f->frequency =	av7110->current_freq;
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
+
+	if (!av7110->analog_tuner_flags || av7110->current_input != 1)
+		return -EINVAL;
+
+	if (V4L2_TUNER_ANALOG_TV != f->type)
+		return -EINVAL;
+
+	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0xffe0); /* fast mute */
+	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0xffe0);
+
+	/* tune in desired frequency */
+	if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820)
+		ves1820_set_tv_freq(dev, f->frequency);
+	else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297)
+		stv0297_set_tv_freq(dev, f->frequency);
+	av7110->current_freq = f->frequency;
+
+	msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x003f); /* start stereo detection */
+	msp_writereg(av7110, MSP_WR_DSP, 0x0015, 0x0000);
+	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); /* loudspeaker + headphone */
+	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); /* SCART 1 volume */
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
+
+	if (av7110->analog_tuner_flags) {
+		if (i->index < 0 || i->index >= 4)
+			return -EINVAL;
+	} else {
+		if (i->index != 0)
+			return -EINVAL;
 	}
-	case VIDIOC_G_SLICED_VBI_CAP:
-	{
-		struct v4l2_sliced_vbi_cap *cap = arg;
-		dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
-		memset(cap, 0, sizeof *cap);
-		if (FW_VERSION(av7110->arm_app) >= 0x2623) {
-			cap->service_set = V4L2_SLICED_WSS_625;
-			cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
-		}
-		break;
+
+	memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	*input = av7110->current_input;
+	dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
+
+	if (!av7110->analog_tuner_flags)
+		return 0;
+
+	if (input < 0 || input >= 4)
+		return -EINVAL;
+
+	av7110->current_input = input;
+	return av7110_dvb_c_switch(fh);
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
+	if (a->index != 0)
+		return -EINVAL;
+	memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
+	return 0;
+}
+
+static int vidioc_g_sliced_vbi_cap(struct file *file, void *fh,
+					struct v4l2_sliced_vbi_cap *cap)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
+	if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
+		return -EINVAL;
+	if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+		cap->service_set = V4L2_SLICED_WSS_625;
+		cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
 	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = arg;
-		dprintk(2, "VIDIOC_G_FMT:\n");
-		if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
-		    FW_VERSION(av7110->arm_app) < 0x2623)
-			return -EAGAIN; /* handled by core driver */
-		memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
-		if (av7110->wssMode) {
-			f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
-			f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
-			f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
-		}
-		break;
+	return 0;
+}
+
+static int vidioc_g_fmt_sliced_vbi_out(struct file *file, void *fh,
+					struct v4l2_format *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_G_FMT:\n");
+	if (FW_VERSION(av7110->arm_app) < 0x2623)
+		return -EINVAL;
+	memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+	if (av7110->wssMode) {
+		f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+		f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+		f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
 	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-		dprintk(2, "VIDIOC_S_FMT\n");
-		if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
-		    FW_VERSION(av7110->arm_app) < 0x2623)
-			return -EAGAIN; /* handled by core driver */
-		if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
-		    f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
-			memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
-			/* WSS controlled by firmware */
-			av7110->wssMode = 0;
-			av7110->wssData = 0;
-			return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
-					     SetWSSConfig, 1, 0);
-		} else {
-			memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
-			f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
-			f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
-			f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
-			/* WSS controlled by userspace */
-			av7110->wssMode = 1;
-			av7110->wssData = 0;
-		}
-		break;
-	}
-	default:
-		printk("no such ioctl\n");
-		return -ENOIOCTLCMD;
+	return 0;
+}
+
+static int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh,
+					struct v4l2_format *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
+
+	dprintk(2, "VIDIOC_S_FMT\n");
+	if (FW_VERSION(av7110->arm_app) < 0x2623)
+		return -EINVAL;
+	if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
+	    f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
+		memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+		/* WSS controlled by firmware */
+		av7110->wssMode = 0;
+		av7110->wssData = 0;
+		return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
+				     SetWSSConfig, 1, 0);
+	} else {
+		memset(&f->fmt.sliced, 0, sizeof(f->fmt.sliced));
+		f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+		f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+		f->fmt.sliced.io_size = sizeof(struct v4l2_sliced_vbi_data);
+		/* WSS controlled by userspace */
+		av7110->wssMode = 1;
+		av7110->wssData = 0;
 	}
 	return 0;
 }
@@ -609,22 +617,6 @@
  * INITIALIZATION
  ****************************************************************************/
 
-static struct saa7146_extension_ioctls ioctls[] = {
-	{ VIDIOC_ENUMINPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_FREQUENCY,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_TUNER,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_TUNER,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_AUDIO,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_AUDIO,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_FMT,		SAA7146_BEFORE },
-	{ VIDIOC_S_FMT,		SAA7146_BEFORE },
-	{ 0, 0 }
-};
-
 static u8 saa7113_init_regs[] = {
 	0x02, 0xd0,
 	0x03, 0x23,
@@ -788,20 +780,34 @@
 int av7110_init_v4l(struct av7110 *av7110)
 {
 	struct saa7146_dev* dev = av7110->dev;
+	struct saa7146_ext_vv *vv_data;
 	int ret;
 
 	/* special case DVB-C: these cards have an analog tuner
 	   plus need some special handling, so we have separate
 	   saa7146_ext_vv data for these... */
 	if (av7110->analog_tuner_flags)
-		ret = saa7146_vv_init(dev, &av7110_vv_data_c);
+		vv_data = &av7110_vv_data_c;
 	else
-		ret = saa7146_vv_init(dev, &av7110_vv_data_st);
+		vv_data = &av7110_vv_data_st;
+	ret = saa7146_vv_init(dev, vv_data);
 
 	if (ret) {
 		ERR(("cannot init capture device. skipping.\n"));
 		return -ENODEV;
 	}
+	vv_data->ops.vidioc_enum_input = vidioc_enum_input;
+	vv_data->ops.vidioc_g_input = vidioc_g_input;
+	vv_data->ops.vidioc_s_input = vidioc_s_input;
+	vv_data->ops.vidioc_g_tuner = vidioc_g_tuner;
+	vv_data->ops.vidioc_s_tuner = vidioc_s_tuner;
+	vv_data->ops.vidioc_g_frequency = vidioc_g_frequency;
+	vv_data->ops.vidioc_s_frequency = vidioc_s_frequency;
+	vv_data->ops.vidioc_g_audio = vidioc_g_audio;
+	vv_data->ops.vidioc_s_audio = vidioc_s_audio;
+	vv_data->ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
+	vv_data->ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
+	vv_data->ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
 
 	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
 		ERR(("cannot register capture device. skipping.\n"));
@@ -900,9 +906,6 @@
 	.num_stds	= ARRAY_SIZE(standard),
 	.std_callback	= &std_callback,
 
-	.ioctls		= &ioctls[0],
-	.ioctl		= av7110_ioctl,
-
 	.vbi_fops.open	= av7110_vbi_reset,
 	.vbi_fops.release = av7110_vbi_reset,
 	.vbi_fops.write	= av7110_vbi_write,
@@ -918,9 +921,6 @@
 	.num_stds	= ARRAY_SIZE(standard),
 	.std_callback	= &std_callback,
 
-	.ioctls		= &ioctls[0],
-	.ioctl		= av7110_ioctl,
-
 	.vbi_fops.open	= av7110_vbi_reset,
 	.vbi_fops.release = av7110_vbi_reset,
 	.vbi_fops.write	= av7110_vbi_write,
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 4182121..855fe74 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1404,6 +1404,41 @@
 	return err;
 }
 
+#define KNC1_INPUTS 2
+static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
+	{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+	{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+};
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+	if (i->index < 0 || i->index >= KNC1_INPUTS)
+		return -EINVAL;
+	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
+
+	*i = budget_av->cur_input;
+
+	dprintk(1, "VIDIOC_G_INPUT %d.\n", *i);
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct budget_av *budget_av = (struct budget_av *)dev->ext_priv;
+
+	dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+	return saa7113_setinput(budget_av, input);
+}
+
 static struct saa7146_ext_vv vv_data;
 
 static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
@@ -1442,6 +1477,9 @@
 			ERR(("cannot init vv subsystem.\n"));
 			return err;
 		}
+		vv_data.ops.vidioc_enum_input = vidioc_enum_input;
+		vv_data.ops.vidioc_g_input = vidioc_g_input;
+		vv_data.ops.vidioc_s_input = vidioc_s_input;
 
 		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
 			/* fixme: proper cleanup here */
@@ -1480,54 +1518,6 @@
 	return 0;
 }
 
-#define KNC1_INPUTS 2
-static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
-	{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
-	{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
-};
-
-static struct saa7146_extension_ioctls ioctls[] = {
-	{VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
-	{VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
-	{VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
-	{0, 0}
-};
-
-static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
-
-	switch (cmd) {
-	case VIDIOC_ENUMINPUT:{
-		struct v4l2_input *i = arg;
-
-		dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
-		if (i->index < 0 || i->index >= KNC1_INPUTS) {
-			return -EINVAL;
-		}
-		memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
-		return 0;
-	}
-	case VIDIOC_G_INPUT:{
-		int *input = (int *) arg;
-
-		*input = budget_av->cur_input;
-
-		dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
-		return 0;
-	}
-	case VIDIOC_S_INPUT:{
-		int input = *(int *) arg;
-		dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
-		return saa7113_setinput(budget_av, input);
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
 static struct saa7146_standard standard[] = {
 	{.name = "PAL",.id = V4L2_STD_PAL,
 	 .v_offset = 0x17,.v_field = 288,
@@ -1546,8 +1536,6 @@
 	.flags = 0,
 	.stds = &standard[0],
 	.num_stds = ARRAY_SIZE(standard),
-	.ioctls = &ioctls[0],
-	.ioctl = av_ioctl,
 };
 
 static struct saa7146_extension budget_extension;
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index bcbc5d4..371a716 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1076,6 +1076,10 @@
 	.deltaf = 0xa511,
 };
 
+static struct tda827x_config tda827x_config = {
+	.config = 0,
+};
+
 /* TT S2-3200 DVB-S (STB0899) Inittab */
 static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
 
@@ -1414,7 +1418,7 @@
 	case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
 		budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
 		if (budget_ci->budget.dvb_frontend) {
-			if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) {
+			if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) {
 				printk(KERN_ERR "%s: No tda827x found!\n", __func__);
 				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
 				budget_ci->budget.dvb_frontend = NULL;
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 2014ebc..cc54ed4 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -390,9 +390,11 @@
 static int vidioc_querycap(struct file *file, void *priv,
 					struct v4l2_capability *v)
 {
+	struct dsbr100_device *radio = video_drvdata(file);
+
 	strlcpy(v->driver, "dsbr100", sizeof(v->driver));
 	strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
-	sprintf(v->bus_info, "USB");
+	usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
 	v->capabilities = V4L2_CAP_TUNER;
 	return 0;
@@ -450,7 +452,10 @@
 	if (radio->removed)
 		return -EIO;
 
+	mutex_lock(&radio->lock);
 	radio->curfreq = f->frequency;
+	mutex_unlock(&radio->lock);
+
 	retval = dsbr100_setfreq(radio, radio->curfreq);
 	if (retval < 0)
 		dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
@@ -601,7 +606,10 @@
 	if (!radio)
 		return -ENODEV;
 
+	mutex_lock(&radio->lock);
 	radio->users = 0;
+	mutex_unlock(&radio->lock);
+
 	if (!radio->removed) {
 		retval = dsbr100_stop(radio);
 		if (retval < 0) {
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index bfa13b8..ac82e33 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -32,14 +32,15 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
+#include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+MODULE_AUTHOR("M.Kirkwood");
+MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
+MODULE_LICENSE("GPL");
 
 #ifndef CONFIG_RADIO_RTRACK_PORT
 #define CONFIG_RADIO_RTRACK_PORT -1
@@ -47,86 +48,95 @@
 
 static int io = CONFIG_RADIO_RTRACK_PORT;
 static int radio_nr = -1;
-static struct mutex lock;
 
-struct rt_device
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct rtrack
 {
-	unsigned long in_use;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
 	int port;
 	int curvol;
 	unsigned long curfreq;
 	int muted;
+	int io;
+	struct mutex lock;
 };
 
+static struct rtrack rtrack_card;
 
 /* local things */
 
 static void sleep_delay(long n)
 {
 	/* Sleep nicely for 'n' uS */
-	int d=n/msecs_to_jiffies(1000);
-	if(!d)
+	int d = n / msecs_to_jiffies(1000);
+	if (!d)
 		udelay(n);
 	else
 		msleep(jiffies_to_msecs(d));
 }
 
-static void rt_decvol(void)
+static void rt_decvol(struct rtrack *rt)
 {
-	outb(0x58, io);		/* volume down + sigstr + on	*/
+	outb(0x58, rt->io);		/* volume down + sigstr + on	*/
 	sleep_delay(100000);
-	outb(0xd8, io);		/* volume steady + sigstr + on	*/
+	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
-static void rt_incvol(void)
+static void rt_incvol(struct rtrack *rt)
 {
-	outb(0x98, io);		/* volume up + sigstr + on	*/
+	outb(0x98, rt->io);		/* volume up + sigstr + on	*/
 	sleep_delay(100000);
-	outb(0xd8, io);		/* volume steady + sigstr + on	*/
+	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
-static void rt_mute(struct rt_device *dev)
+static void rt_mute(struct rtrack *rt)
 {
-	dev->muted = 1;
-	mutex_lock(&lock);
-	outb(0xd0, io);			/* volume steady, off		*/
-	mutex_unlock(&lock);
+	rt->muted = 1;
+	mutex_lock(&rt->lock);
+	outb(0xd0, rt->io);		/* volume steady, off		*/
+	mutex_unlock(&rt->lock);
 }
 
-static int rt_setvol(struct rt_device *dev, int vol)
+static int rt_setvol(struct rtrack *rt, int vol)
 {
 	int i;
 
-	mutex_lock(&lock);
+	mutex_lock(&rt->lock);
 
-	if(vol == dev->curvol) {	/* requested volume = current */
-		if (dev->muted) {	/* user is unmuting the card  */
-			dev->muted = 0;
-			outb (0xd8, io);	/* enable card */
+	if (vol == rt->curvol) {	/* requested volume = current */
+		if (rt->muted) {	/* user is unmuting the card  */
+			rt->muted = 0;
+			outb(0xd8, rt->io);	/* enable card */
 		}
-		mutex_unlock(&lock);
+		mutex_unlock(&rt->lock);
 		return 0;
 	}
 
-	if(vol == 0) {			/* volume = 0 means mute the card */
-		outb(0x48, io);		/* volume down but still "on"	*/
+	if (vol == 0) {			/* volume = 0 means mute the card */
+		outb(0x48, rt->io);	/* volume down but still "on"	*/
 		sleep_delay(2000000);	/* make sure it's totally down	*/
-		outb(0xd0, io);		/* volume steady, off		*/
-		dev->curvol = 0;	/* track the volume state!	*/
-		mutex_unlock(&lock);
+		outb(0xd0, rt->io);	/* volume steady, off		*/
+		rt->curvol = 0;		/* track the volume state!	*/
+		mutex_unlock(&rt->lock);
 		return 0;
 	}
 
-	dev->muted = 0;
-	if(vol > dev->curvol)
-		for(i = dev->curvol; i < vol; i++)
-			rt_incvol();
+	rt->muted = 0;
+	if (vol > rt->curvol)
+		for (i = rt->curvol; i < vol; i++)
+			rt_incvol(rt);
 	else
-		for(i = dev->curvol; i > vol; i--)
-			rt_decvol();
+		for (i = rt->curvol; i > vol; i--)
+			rt_decvol(rt);
 
-	dev->curvol = vol;
-	mutex_unlock(&lock);
+	rt->curvol = vol;
+	mutex_unlock(&rt->lock);
 	return 0;
 }
 
@@ -135,155 +145,137 @@
  * and bit 4 (+16) is to keep the signal strength meter enabled
  */
 
-static void send_0_byte(int port, struct rt_device *dev)
+static void send_0_byte(struct rtrack *rt)
 {
-	if ((dev->curvol == 0) || (dev->muted)) {
-		outb_p(128+64+16+  1, port);   /* wr-enable + data low */
-		outb_p(128+64+16+2+1, port);   /* clock */
+	if (rt->curvol == 0 || rt->muted) {
+		outb_p(128+64+16+  1, rt->io);   /* wr-enable + data low */
+		outb_p(128+64+16+2+1, rt->io);   /* clock */
 	}
 	else {
-		outb_p(128+64+16+8+  1, port);  /* on + wr-enable + data low */
-		outb_p(128+64+16+8+2+1, port);  /* clock */
+		outb_p(128+64+16+8+  1, rt->io);  /* on + wr-enable + data low */
+		outb_p(128+64+16+8+2+1, rt->io);  /* clock */
 	}
 	sleep_delay(1000);
 }
 
-static void send_1_byte(int port, struct rt_device *dev)
+static void send_1_byte(struct rtrack *rt)
 {
-	if ((dev->curvol == 0) || (dev->muted)) {
-		outb_p(128+64+16+4  +1, port);   /* wr-enable+data high */
-		outb_p(128+64+16+4+2+1, port);   /* clock */
+	if (rt->curvol == 0 || rt->muted) {
+		outb_p(128+64+16+4  +1, rt->io);   /* wr-enable+data high */
+		outb_p(128+64+16+4+2+1, rt->io);   /* clock */
 	}
 	else {
-		outb_p(128+64+16+8+4  +1, port); /* on+wr-enable+data high */
-		outb_p(128+64+16+8+4+2+1, port); /* clock */
+		outb_p(128+64+16+8+4  +1, rt->io); /* on+wr-enable+data high */
+		outb_p(128+64+16+8+4+2+1, rt->io); /* clock */
 	}
 
 	sleep_delay(1000);
 }
 
-static int rt_setfreq(struct rt_device *dev, unsigned long freq)
+static int rt_setfreq(struct rtrack *rt, unsigned long freq)
 {
 	int i;
 
-	/* adapted from radio-aztech.c */
+	mutex_lock(&rt->lock);			/* Stop other ops interfering */
+
+	rt->curfreq = freq;
 
 	/* now uses VIDEO_TUNER_LOW for fine tuning */
 
 	freq += 171200;			/* Add 10.7 MHz IF 		*/
 	freq /= 800;			/* Convert to 50 kHz units	*/
 
-	mutex_lock(&lock);			/* Stop other ops interfering */
-
-	send_0_byte (io, dev);		/*  0: LSB of frequency		*/
+	send_0_byte(rt);		/*  0: LSB of frequency		*/
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)	*/
 		if (freq & (1 << i))
-			send_1_byte (io, dev);
+			send_1_byte(rt);
 		else
-			send_0_byte (io, dev);
+			send_0_byte(rt);
 
-	send_0_byte (io, dev);		/* 14: test bit - always 0    */
-	send_0_byte (io, dev);		/* 15: test bit - always 0    */
+	send_0_byte(rt);		/* 14: test bit - always 0    */
+	send_0_byte(rt);		/* 15: test bit - always 0    */
 
-	send_0_byte (io, dev);		/* 16: band data 0 - always 0 */
-	send_0_byte (io, dev);		/* 17: band data 1 - always 0 */
-	send_0_byte (io, dev);		/* 18: band data 2 - always 0 */
-	send_0_byte (io, dev);		/* 19: time base - always 0   */
+	send_0_byte(rt);		/* 16: band data 0 - always 0 */
+	send_0_byte(rt);		/* 17: band data 1 - always 0 */
+	send_0_byte(rt);		/* 18: band data 2 - always 0 */
+	send_0_byte(rt);		/* 19: time base - always 0   */
 
-	send_0_byte (io, dev);		/* 20: spacing (0 = 25 kHz)   */
-	send_1_byte (io, dev);		/* 21: spacing (1 = 25 kHz)   */
-	send_0_byte (io, dev);		/* 22: spacing (0 = 25 kHz)   */
-	send_1_byte (io, dev);		/* 23: AM/FM (FM = 1, always) */
+	send_0_byte(rt);		/* 20: spacing (0 = 25 kHz)   */
+	send_1_byte(rt);		/* 21: spacing (1 = 25 kHz)   */
+	send_0_byte(rt);		/* 22: spacing (0 = 25 kHz)   */
+	send_1_byte(rt);		/* 23: AM/FM (FM = 1, always) */
 
-	if ((dev->curvol == 0) || (dev->muted))
-		outb (0xd0, io);	/* volume steady + sigstr */
+	if (rt->curvol == 0 || rt->muted)
+		outb(0xd0, rt->io);	/* volume steady + sigstr */
 	else
-		outb (0xd8, io);	/* volume steady + sigstr + on */
+		outb(0xd8, rt->io);	/* volume steady + sigstr + on */
 
-	mutex_unlock(&lock);
+	mutex_unlock(&rt->lock);
 
 	return 0;
 }
 
-static int rt_getsigstr(struct rt_device *dev)
+static int rt_getsigstr(struct rtrack *rt)
 {
-	if (inb(io) & 2)	/* bit set = no signal present	*/
-		return 0;
-	return 1;		/* signal present		*/
-}
+	int sig = 1;
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 0xff,
-		.step          = 1,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
+	mutex_lock(&rt->lock);
+	if (inb(rt->io) & 2)	/* bit set = no signal present	*/
+		sig = 0;
+	mutex_unlock(&rt->lock);
+	return sig;
+}
 
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *v)
 {
 	strlcpy(v->driver, "radio-aimslab", sizeof(v->driver));
 	strlcpy(v->card, "RadioTrack", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack *rt = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (87*16000);
-	v->rangehigh = (108*16000);
+	v->rangelow = 87 * 16000;
+	v->rangehigh = 108 * 16000;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	v->capability = V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = 0xffff*rt_getsigstr(rt);
+	v->signal = 0xffff * rt_getsigstr(rt);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack *rt = video_drvdata(file);
 
-	rt->curfreq = f->frequency;
-	rt_setfreq(rt, rt->curfreq);
+	rt_setfreq(rt, f->frequency);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack *rt = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = rt->curfreq;
@@ -293,14 +285,11 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
 	}
 	return -EINVAL;
 }
@@ -308,14 +297,14 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack *rt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		ctrl->value = rt->muted;
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = rt->curvol * 6554;
+		ctrl->value = rt->curvol;
 		return 0;
 	}
 	return -EINVAL;
@@ -324,33 +313,22 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack *rt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value)
 			rt_mute(rt);
 		else
-			rt_setvol(rt,rt->curvol);
+			rt_setvol(rt, rt->curvol);
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		rt_setvol(rt,ctrl->value);
+		rt_setvol(rt, ctrl->value);
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio (struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -359,36 +337,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int rtrack_open(struct file *file)
+{
 	return 0;
 }
 
-static struct rt_device rtrack_unit;
-
-static int rtrack_exclusive_open(struct file *file)
+static int rtrack_release(struct file *file)
 {
-	return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
-}
-
-static int rtrack_exclusive_release(struct file *file)
-{
-	clear_bit(0, &rtrack_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations rtrack_fops = {
 	.owner		= THIS_MODULE,
-	.open           = rtrack_exclusive_open,
-	.release        = rtrack_exclusive_release,
+	.open           = rtrack_open,
+	.release        = rtrack_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -407,64 +387,69 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device rtrack_radio = {
-	.name		= "RadioTrack radio",
-	.fops           = &rtrack_fops,
-	.ioctl_ops 	= &rtrack_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init rtrack_init(void)
 {
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+	struct rtrack *rt = &rtrack_card;
+	struct v4l2_device *v4l2_dev = &rt->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name));
+	rt->io = io;
+
+	if (rt->io == -1) {
+		v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n");
 		return -EINVAL;
 	}
 
-	if (!request_region(io, 2, "rtrack"))
-	{
-		printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
+	if (!request_region(rt->io, 2, "rtrack")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io);
 		return -EBUSY;
 	}
 
-	video_set_drvdata(&rtrack_radio, &rtrack_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(rt->io, 2);
+		v4l2_err(v4l2_dev, "could not register v4l2_device\n");
+		return res;
+	}
 
-	if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 2);
+	strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name));
+	rt->vdev.v4l2_dev = v4l2_dev;
+	rt->vdev.fops = &rtrack_fops;
+	rt->vdev.ioctl_ops = &rtrack_ioctl_ops;
+	rt->vdev.release = video_device_release_empty;
+	video_set_drvdata(&rt->vdev, rt);
+
+	if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(&rt->v4l2_dev);
+		release_region(rt->io, 2);
 		return -EINVAL;
 	}
-	printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n");
+	v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
 
 	/* Set up the I/O locking */
 
-	mutex_init(&lock);
+	mutex_init(&rt->lock);
 
 	/* mute card - prevents noisy bootups */
 
 	/* this ensures that the volume is all the way down  */
-	outb(0x48, io);		/* volume down but still "on"	*/
+	outb(0x48, rt->io);		/* volume down but still "on"	*/
 	sleep_delay(2000000);	/* make sure it's totally down	*/
-	outb(0xc0, io);		/* steady volume, mute card	*/
-	rtrack_unit.curvol = 0;
+	outb(0xc0, rt->io);		/* steady volume, mute card	*/
 
 	return 0;
 }
 
-MODULE_AUTHOR("M.Kirkwood");
-MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
-module_param(radio_nr, int, 0);
-
-static void __exit cleanup_rtrack_module(void)
+static void __exit rtrack_exit(void)
 {
-	video_unregister_device(&rtrack_radio);
-	release_region(io,2);
+	struct rtrack *rt = &rtrack_card;
+
+	video_unregister_device(&rt->vdev);
+	v4l2_device_unregister(&rt->v4l2_dev);
+	release_region(rt->io, 2);
 }
 
 module_init(rtrack_init);
-module_exit(cleanup_rtrack_module);
+module_exit(rtrack_exit);
 
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 5604e88..49299f7 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -29,33 +29,15 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 0xff,
-		.step          = 1,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
+MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the Aztech radio card.");
+MODULE_LICENSE("GPL");
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -66,55 +48,64 @@
 static int io = CONFIG_RADIO_AZTECH_PORT;
 static int radio_nr = -1;
 static int radio_wait_time = 1000;
-static struct mutex lock;
 
-struct az_device
+module_param(io, int, 0);
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct aztech
 {
-	unsigned long in_use;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
 	int curvol;
 	unsigned long curfreq;
 	int stereo;
+	struct mutex lock;
 };
 
+static struct aztech aztech_card;
+
 static int volconvert(int level)
 {
-	level>>=14;		/* Map 16bits down to 2 bit */
-	level&=3;
+	level >>= 14;		/* Map 16bits down to 2 bit */
+	level &= 3;
 
 	/* convert to card-friendly values */
-	switch (level)
-	{
-		case 0:
-			return 0;
-		case 1:
-			return 1;
-		case 2:
-			return 4;
-		case 3:
-			return 5;
+	switch (level) {
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	case 2:
+		return 4;
+	case 3:
+		return 5;
 	}
 	return 0;	/* Quieten gcc */
 }
 
-static void send_0_byte (struct az_device *dev)
+static void send_0_byte(struct aztech *az)
 {
 	udelay(radio_wait_time);
-	outb_p(2+volconvert(dev->curvol), io);
-	outb_p(64+2+volconvert(dev->curvol), io);
+	outb_p(2 + volconvert(az->curvol), az->io);
+	outb_p(64 + 2 + volconvert(az->curvol), az->io);
 }
 
-static void send_1_byte (struct az_device *dev)
+static void send_1_byte(struct aztech *az)
 {
 	udelay (radio_wait_time);
-	outb_p(128+2+volconvert(dev->curvol), io);
-	outb_p(128+64+2+volconvert(dev->curvol), io);
+	outb_p(128 + 2 + volconvert(az->curvol), az->io);
+	outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io);
 }
 
-static int az_setvol(struct az_device *dev, int vol)
+static int az_setvol(struct aztech *az, int vol)
 {
-	mutex_lock(&lock);
-	outb (volconvert(vol), io);
-	mutex_unlock(&lock);
+	mutex_lock(&az->lock);
+	outb(volconvert(vol), az->io);
+	mutex_unlock(&az->lock);
 	return 0;
 }
 
@@ -126,116 +117,110 @@
  *
  */
 
-static int az_getsigstr(struct az_device *dev)
+static int az_getsigstr(struct aztech *az)
 {
-	if (inb(io) & 2)	/* bit set = no signal present */
-		return 0;
-	return 1;		/* signal present */
+	int sig = 1;
+
+	mutex_lock(&az->lock);
+	if (inb(az->io) & 2)	/* bit set = no signal present */
+		sig = 0;
+	mutex_unlock(&az->lock);
+	return sig;
 }
 
-static int az_getstereo(struct az_device *dev)
+static int az_getstereo(struct aztech *az)
 {
-	if (inb(io) & 1) 	/* bit set = mono */
-		return 0;
-	return 1;		/* stereo */
+	int stereo = 1;
+
+	mutex_lock(&az->lock);
+	if (inb(az->io) & 1) 	/* bit set = mono */
+		stereo = 0;
+	mutex_unlock(&az->lock);
+	return stereo;
 }
 
-static int az_setfreq(struct az_device *dev, unsigned long frequency)
+static int az_setfreq(struct aztech *az, unsigned long frequency)
 {
 	int  i;
 
+	mutex_lock(&az->lock);
+
+	az->curfreq = frequency;
 	frequency += 171200;		/* Add 10.7 MHz IF		*/
 	frequency /= 800;		/* Convert to 50 kHz units	*/
 
-	mutex_lock(&lock);
-
-	send_0_byte (dev);		/*  0: LSB of frequency       */
+	send_0_byte(az);		/*  0: LSB of frequency       */
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)  */
 		if (frequency & (1 << i))
-			send_1_byte (dev);
+			send_1_byte(az);
 		else
-			send_0_byte (dev);
+			send_0_byte(az);
 
-	send_0_byte (dev);		/* 14: test bit - always 0    */
-	send_0_byte (dev);		/* 15: test bit - always 0    */
-	send_0_byte (dev);		/* 16: band data 0 - always 0 */
-	if (dev->stereo)		/* 17: stereo (1 to enable)   */
-		send_1_byte (dev);
+	send_0_byte(az);		/* 14: test bit - always 0    */
+	send_0_byte(az);		/* 15: test bit - always 0    */
+	send_0_byte(az);		/* 16: band data 0 - always 0 */
+	if (az->stereo)		/* 17: stereo (1 to enable)   */
+		send_1_byte(az);
 	else
-		send_0_byte (dev);
+		send_0_byte(az);
 
-	send_1_byte (dev);		/* 18: band data 1 - unknown  */
-	send_0_byte (dev);		/* 19: time base - always 0   */
-	send_0_byte (dev);		/* 20: spacing (0 = 25 kHz)   */
-	send_1_byte (dev);		/* 21: spacing (1 = 25 kHz)   */
-	send_0_byte (dev);		/* 22: spacing (0 = 25 kHz)   */
-	send_1_byte (dev);		/* 23: AM/FM (FM = 1, always) */
+	send_1_byte(az);		/* 18: band data 1 - unknown  */
+	send_0_byte(az);		/* 19: time base - always 0   */
+	send_0_byte(az);		/* 20: spacing (0 = 25 kHz)   */
+	send_1_byte(az);		/* 21: spacing (1 = 25 kHz)   */
+	send_0_byte(az);		/* 22: spacing (0 = 25 kHz)   */
+	send_1_byte(az);		/* 23: AM/FM (FM = 1, always) */
 
 	/* latch frequency */
 
-	udelay (radio_wait_time);
-	outb_p(128+64+volconvert(dev->curvol), io);
+	udelay(radio_wait_time);
+	outb_p(128 + 64 + volconvert(az->curvol), az->io);
 
-	mutex_unlock(&lock);
+	mutex_unlock(&az->lock);
 
 	return 0;
 }
 
-static int vidioc_querycap (struct file *file, void  *priv,
+static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *v)
 {
-	strlcpy(v->driver, "radio-aztech", sizeof (v->driver));
-	strlcpy(v->card, "Aztech Radio", sizeof (v->card));
-	sprintf(v->bus_info,"ISA");
+	strlcpy(v->driver, "radio-aztech", sizeof(v->driver));
+	strlcpy(v->card, "Aztech Radio", sizeof(v->card));
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
-static int vidioc_g_tuner (struct file *file, void *priv,
+static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	struct az_device *az = video_drvdata(file);
+	struct aztech *az = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 
-	v->rangelow=(87*16000);
-	v->rangehigh=(108*16000);
-	v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-	v->capability=V4L2_TUNER_CAP_LOW;
-	if(az_getstereo(az))
+	v->rangelow = 87 * 16000;
+	v->rangehigh = 108 * 16000;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+	v->capability = V4L2_TUNER_CAP_LOW;
+	if (az_getstereo(az))
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 	else
 		v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal=0xFFFF*az_getsigstr(az);
+	v->signal = 0xFFFF * az_getsigstr(az);
 
 	return 0;
 }
 
-
-static int vidioc_s_tuner (struct file *file, void *priv,
+static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int vidioc_g_audio (struct file *file, void *priv,
-			   struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
@@ -246,113 +231,107 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
-	return 0;
+	return i ? -EINVAL : 0;
 }
 
-
-static int vidioc_s_audio (struct file *file, void *priv,
+static int vidioc_g_audio(struct file *file, void *priv,
 			   struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
-
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
-static int vidioc_s_frequency (struct file *file, void *priv,
+static int vidioc_s_audio(struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct az_device *az = video_drvdata(file);
+	struct aztech *az = video_drvdata(file);
 
-	az->curfreq = f->frequency;
-	az_setfreq(az, az->curfreq);
+	az_setfreq(az, f->frequency);
 	return 0;
 }
 
-static int vidioc_g_frequency (struct file *file, void *priv,
+static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct az_device *az = video_drvdata(file);
+	struct aztech *az = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = az->curfreq;
-
 	return 0;
 }
 
-static int vidioc_queryctrl (struct file *file, void *priv,
+static int vidioc_queryctrl(struct file *file, void *priv,
 			    struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return (0);
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_ctrl (struct file *file, void *priv,
+static int vidioc_g_ctrl(struct file *file, void *priv,
 			    struct v4l2_control *ctrl)
 {
-	struct az_device *az = video_drvdata(file);
+	struct aztech *az = video_drvdata(file);
 
 	switch (ctrl->id) {
-		case V4L2_CID_AUDIO_MUTE:
-			if (az->curvol==0)
-				ctrl->value=1;
-			else
-				ctrl->value=0;
-			return (0);
-		case V4L2_CID_AUDIO_VOLUME:
-			ctrl->value=az->curvol * 6554;
-			return (0);
+	case V4L2_CID_AUDIO_MUTE:
+		if (az->curvol == 0)
+			ctrl->value = 1;
+		else
+			ctrl->value = 0;
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		ctrl->value = az->curvol * 6554;
+		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_s_ctrl (struct file *file, void *priv,
+static int vidioc_s_ctrl(struct file *file, void *priv,
 			    struct v4l2_control *ctrl)
 {
-	struct az_device *az = video_drvdata(file);
+	struct aztech *az = video_drvdata(file);
 
 	switch (ctrl->id) {
-		case V4L2_CID_AUDIO_MUTE:
-			if (ctrl->value) {
-				az_setvol(az,0);
-			} else {
-				az_setvol(az,az->curvol);
-			}
-			return (0);
-		case V4L2_CID_AUDIO_VOLUME:
-			az_setvol(az,ctrl->value);
-			return (0);
+	case V4L2_CID_AUDIO_MUTE:
+		if (ctrl->value)
+			az_setvol(az, 0);
+		else
+			az_setvol(az, az->curvol);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		az_setvol(az, ctrl->value);
+		return 0;
 	}
 	return -EINVAL;
 }
 
-static struct az_device aztech_unit;
-
-static int aztech_exclusive_open(struct file *file)
+static int aztech_open(struct file *file)
 {
-	return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
+	return 0;
 }
 
-static int aztech_exclusive_release(struct file *file)
+static int aztech_release(struct file *file)
 {
-	clear_bit(0, &aztech_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations aztech_fops = {
 	.owner		= THIS_MODULE,
-	.open           = aztech_exclusive_open,
-	.release        = aztech_exclusive_release,
+	.open           = aztech_open,
+	.release        = aztech_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -371,57 +350,60 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device aztech_radio = {
-	.name		= "Aztech radio",
-	.fops           = &aztech_fops,
-	.ioctl_ops 	= &aztech_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
-module_param_named(debug,aztech_radio.debug, int, 0644);
-MODULE_PARM_DESC(debug,"activates debug info");
-
 static int __init aztech_init(void)
 {
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+	struct aztech *az = &aztech_card;
+	struct v4l2_device *v4l2_dev = &az->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name));
+	az->io = io;
+
+	if (az->io == -1) {
+		v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n");
 		return -EINVAL;
 	}
 
-	if (!request_region(io, 2, "aztech"))
-	{
-		printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
+	if (!request_region(az->io, 2, "aztech")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io);
 		return -EBUSY;
 	}
 
-	mutex_init(&lock);
-	video_set_drvdata(&aztech_radio, &aztech_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(az->io, 2);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
 
-	if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io,2);
+	mutex_init(&az->lock);
+	strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name));
+	az->vdev.v4l2_dev = v4l2_dev;
+	az->vdev.fops = &aztech_fops;
+	az->vdev.ioctl_ops = &aztech_ioctl_ops;
+	az->vdev.release = video_device_release_empty;
+	video_set_drvdata(&az->vdev, az);
+
+	if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(az->io, 2);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
+	v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
 	/* mute card - prevents noisy bootups */
-	outb (0, io);
+	outb(0, az->io);
 	return 0;
 }
 
-MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the Aztech radio card.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-module_param(radio_nr, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)");
-
-static void __exit aztech_cleanup(void)
+static void __exit aztech_exit(void)
 {
-	video_unregister_device(&aztech_radio);
-	release_region(io,2);
+	struct aztech *az = &aztech_card;
+
+	video_unregister_device(&az->vdev);
+	v4l2_device_unregister(&az->v4l2_dev);
+	release_region(az->io, 2);
 }
 
 module_init(aztech_init);
-module_exit(aztech_cleanup);
+module_exit(aztech_exit);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index cb3075a..d30fc0c 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -35,333 +35,318 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* V4L2 API defs		*/
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
+MODULE_LICENSE("GPL");
+
+static int io = -1;		/* default to isapnp activation */
+static int radio_nr = -1;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
+module_param(radio_nr, int, 0);
+
+#define CADET_VERSION KERNEL_VERSION(0, 3, 3)
 
 #define RDS_BUFFER 256
 #define RDS_RX_FLAG 1
 #define MBS_RX_FLAG 2
 
-#define CADET_VERSION KERNEL_VERSION(0,3,3)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 0xff,
-		.step          = 1,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
+struct cadet {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
+	int users;
+	int curtuner;
+	int tunestat;
+	int sigstrength;
+	wait_queue_head_t read_queue;
+	struct timer_list readtimer;
+	__u8 rdsin, rdsout, rdsstat;
+	unsigned char rdsbuf[RDS_BUFFER];
+	struct mutex lock;
+	int reading;
 };
 
-static int io=-1;		/* default to isapnp activation */
-static int radio_nr = -1;
-static int users;
-static int curtuner;
-static int tunestat;
-static int sigstrength;
-static wait_queue_head_t read_queue;
-static struct timer_list readtimer;
-static __u8 rdsin, rdsout, rdsstat;
-static unsigned char rdsbuf[RDS_BUFFER];
-static spinlock_t cadet_io_lock;
-
-static int cadet_probe(void);
+static struct cadet cadet_card;
 
 /*
  * Signal Strength Threshold Values
  * The V4L API spec does not define any particular unit for the signal
  * strength value.  These values are in microvolts of RF at the tuner's input.
  */
-static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}};
+static __u16 sigtable[2][4] = {
+	{  5, 10, 30,  150 },
+	{ 28, 40, 63, 1000 }
+};
 
 
-static int
-cadet_getstereo(void)
+static int cadet_getstereo(struct cadet *dev)
 {
 	int ret = V4L2_TUNER_SUB_MONO;
-	if(curtuner != 0)	/* Only FM has stereo capability! */
+
+	if (dev->curtuner != 0)	/* Only FM has stereo capability! */
 		return V4L2_TUNER_SUB_MONO;
 
-	spin_lock(&cadet_io_lock);
-	outb(7,io);          /* Select tuner control */
-	if( (inb(io+1) & 0x40) == 0)
+	mutex_lock(&dev->lock);
+	outb(7, dev->io);          /* Select tuner control */
+	if ((inb(dev->io + 1) & 0x40) == 0)
 		ret = V4L2_TUNER_SUB_STEREO;
-	spin_unlock(&cadet_io_lock);
+	mutex_unlock(&dev->lock);
 	return ret;
 }
 
-static unsigned
-cadet_gettune(void)
+static unsigned cadet_gettune(struct cadet *dev)
 {
-	int curvol,i;
-	unsigned fifo=0;
+	int curvol, i;
+	unsigned fifo = 0;
 
 	/*
 	 * Prepare for read
 	 */
 
-	spin_lock(&cadet_io_lock);
+	mutex_lock(&dev->lock);
 
-	outb(7,io);       /* Select tuner control */
-	curvol=inb(io+1); /* Save current volume/mute setting */
-	outb(0x00,io+1);  /* Ensure WRITE-ENABLE is LOW */
-	tunestat=0xffff;
+	outb(7, dev->io);       /* Select tuner control */
+	curvol = inb(dev->io + 1); /* Save current volume/mute setting */
+	outb(0x00, dev->io + 1);  /* Ensure WRITE-ENABLE is LOW */
+	dev->tunestat = 0xffff;
 
 	/*
 	 * Read the shift register
 	 */
-	for(i=0;i<25;i++) {
-		fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
-		if(i<24) {
-			outb(0x01,io+1);
-			tunestat&=inb(io+1);
-			outb(0x00,io+1);
+	for (i = 0; i < 25; i++) {
+		fifo = (fifo << 1) | ((inb(dev->io + 1) >> 7) & 0x01);
+		if (i < 24) {
+			outb(0x01, dev->io + 1);
+			dev->tunestat &= inb(dev->io + 1);
+			outb(0x00, dev->io + 1);
 		}
 	}
 
 	/*
 	 * Restore volume/mute setting
 	 */
-	outb(curvol,io+1);
-	spin_unlock(&cadet_io_lock);
+	outb(curvol, dev->io + 1);
+	mutex_unlock(&dev->lock);
 
 	return fifo;
 }
 
-static unsigned
-cadet_getfreq(void)
+static unsigned cadet_getfreq(struct cadet *dev)
 {
 	int i;
-	unsigned freq=0,test,fifo=0;
+	unsigned freq = 0, test, fifo = 0;
 
 	/*
 	 * Read current tuning
 	 */
-	fifo=cadet_gettune();
+	fifo = cadet_gettune(dev);
 
 	/*
 	 * Convert to actual frequency
 	 */
-	if(curtuner==0) {    /* FM */
-		test=12500;
-		for(i=0;i<14;i++) {
-			if((fifo&0x01)!=0) {
-				freq+=test;
-			}
-			test=test<<1;
-			fifo=fifo>>1;
+	if (dev->curtuner == 0) {    /* FM */
+		test = 12500;
+		for (i = 0; i < 14; i++) {
+			if ((fifo & 0x01) != 0)
+				freq += test;
+			test = test << 1;
+			fifo = fifo >> 1;
 		}
-		freq-=10700000;           /* IF frequency is 10.7 MHz */
-		freq=(freq*16)/1000000;   /* Make it 1/16 MHz */
+		freq -= 10700000;           /* IF frequency is 10.7 MHz */
+		freq = (freq * 16) / 1000000;   /* Make it 1/16 MHz */
 	}
-	if(curtuner==1) {    /* AM */
-		freq=((fifo&0x7fff)-2010)*16;
-	}
+	if (dev->curtuner == 1)    /* AM */
+		freq = ((fifo & 0x7fff) - 2010) * 16;
 
 	return freq;
 }
 
-static void
-cadet_settune(unsigned fifo)
+static void cadet_settune(struct cadet *dev, unsigned fifo)
 {
 	int i;
 	unsigned test;
 
-	spin_lock(&cadet_io_lock);
+	mutex_lock(&dev->lock);
 
-	outb(7,io);                /* Select tuner control */
+	outb(7, dev->io);                /* Select tuner control */
 	/*
 	 * Write the shift register
 	 */
-	test=0;
-	test=(fifo>>23)&0x02;      /* Align data for SDO */
-	test|=0x1c;                /* SDM=1, SWE=1, SEN=1, SCK=0 */
-	outb(7,io);                /* Select tuner control */
-	outb(test,io+1);           /* Initialize for write */
-	for(i=0;i<25;i++) {
-		test|=0x01;              /* Toggle SCK High */
-		outb(test,io+1);
-		test&=0xfe;              /* Toggle SCK Low */
-		outb(test,io+1);
-		fifo=fifo<<1;            /* Prepare the next bit */
-		test=0x1c|((fifo>>23)&0x02);
-		outb(test,io+1);
+	test = 0;
+	test = (fifo >> 23) & 0x02;      /* Align data for SDO */
+	test |= 0x1c;                /* SDM=1, SWE=1, SEN=1, SCK=0 */
+	outb(7, dev->io);                /* Select tuner control */
+	outb(test, dev->io + 1);           /* Initialize for write */
+	for (i = 0; i < 25; i++) {
+		test |= 0x01;              /* Toggle SCK High */
+		outb(test, dev->io + 1);
+		test &= 0xfe;              /* Toggle SCK Low */
+		outb(test, dev->io + 1);
+		fifo = fifo << 1;            /* Prepare the next bit */
+		test = 0x1c | ((fifo >> 23) & 0x02);
+		outb(test, dev->io + 1);
 	}
-	spin_unlock(&cadet_io_lock);
+	mutex_unlock(&dev->lock);
 }
 
-static void
-cadet_setfreq(unsigned freq)
+static void cadet_setfreq(struct cadet *dev, unsigned freq)
 {
 	unsigned fifo;
-	int i,j,test;
+	int i, j, test;
 	int curvol;
 
 	/*
 	 * Formulate a fifo command
 	 */
-	fifo=0;
-	if(curtuner==0) {    /* FM */
-		test=102400;
-		freq=(freq*1000)/16;       /* Make it kHz */
-		freq+=10700;               /* IF is 10700 kHz */
-		for(i=0;i<14;i++) {
-			fifo=fifo<<1;
-			if(freq>=test) {
-				fifo|=0x01;
-				freq-=test;
+	fifo = 0;
+	if (dev->curtuner == 0) {    /* FM */
+		test = 102400;
+		freq = (freq * 1000) / 16;       /* Make it kHz */
+		freq += 10700;               /* IF is 10700 kHz */
+		for (i = 0; i < 14; i++) {
+			fifo = fifo << 1;
+			if (freq >= test) {
+				fifo |= 0x01;
+				freq -= test;
 			}
-			test=test>>1;
+			test = test >> 1;
 		}
 	}
-	if(curtuner==1) {    /* AM */
-		fifo=(freq/16)+2010;            /* Make it kHz */
-		fifo|=0x100000;            /* Select AM Band */
+	if (dev->curtuner == 1) {    /* AM */
+		fifo = (freq / 16) + 2010;            /* Make it kHz */
+		fifo |= 0x100000;            /* Select AM Band */
 	}
 
 	/*
 	 * Save current volume/mute setting
 	 */
 
-	spin_lock(&cadet_io_lock);
-	outb(7,io);                /* Select tuner control */
-	curvol=inb(io+1);
-	spin_unlock(&cadet_io_lock);
+	mutex_lock(&dev->lock);
+	outb(7, dev->io);                /* Select tuner control */
+	curvol = inb(dev->io + 1);
+	mutex_unlock(&dev->lock);
 
 	/*
 	 * Tune the card
 	 */
-	for(j=3;j>-1;j--) {
-		cadet_settune(fifo|(j<<16));
+	for (j = 3; j > -1; j--) {
+		cadet_settune(dev, fifo | (j << 16));
 
-		spin_lock(&cadet_io_lock);
-		outb(7,io);         /* Select tuner control */
-		outb(curvol,io+1);
-		spin_unlock(&cadet_io_lock);
+		mutex_lock(&dev->lock);
+		outb(7, dev->io);         /* Select tuner control */
+		outb(curvol, dev->io + 1);
+		mutex_unlock(&dev->lock);
 
 		msleep(100);
 
-		cadet_gettune();
-		if((tunestat & 0x40) == 0) {   /* Tuned */
-			sigstrength=sigtable[curtuner][j];
+		cadet_gettune(dev);
+		if ((dev->tunestat & 0x40) == 0) {   /* Tuned */
+			dev->sigstrength = sigtable[dev->curtuner][j];
 			return;
 		}
 	}
-	sigstrength=0;
+	dev->sigstrength = 0;
 }
 
 
-static int
-cadet_getvol(void)
+static int cadet_getvol(struct cadet *dev)
 {
 	int ret = 0;
 
-	spin_lock(&cadet_io_lock);
+	mutex_lock(&dev->lock);
 
-	outb(7,io);                /* Select tuner control */
-	if((inb(io + 1) & 0x20) != 0)
+	outb(7, dev->io);                /* Select tuner control */
+	if ((inb(dev->io + 1) & 0x20) != 0)
 		ret = 0xffff;
 
-	spin_unlock(&cadet_io_lock);
+	mutex_unlock(&dev->lock);
 	return ret;
 }
 
 
-static void
-cadet_setvol(int vol)
+static void cadet_setvol(struct cadet *dev, int vol)
 {
-	spin_lock(&cadet_io_lock);
-	outb(7,io);                /* Select tuner control */
-	if(vol>0)
-		outb(0x20,io+1);
+	mutex_lock(&dev->lock);
+	outb(7, dev->io);                /* Select tuner control */
+	if (vol > 0)
+		outb(0x20, dev->io + 1);
 	else
-		outb(0x00,io+1);
-	spin_unlock(&cadet_io_lock);
+		outb(0x00, dev->io + 1);
+	mutex_unlock(&dev->lock);
 }
 
-static void
-cadet_handler(unsigned long data)
+static void cadet_handler(unsigned long data)
 {
-	/*
-	 * Service the RDS fifo
-	 */
+	struct cadet *dev = (void *)data;
 
-	if(spin_trylock(&cadet_io_lock))
-	{
-		outb(0x3,io);       /* Select RDS Decoder Control */
-		if((inb(io+1)&0x20)!=0) {
+	/* Service the RDS fifo */
+	if (mutex_trylock(&dev->lock)) {
+		outb(0x3, dev->io);       /* Select RDS Decoder Control */
+		if ((inb(dev->io + 1) & 0x20) != 0)
 			printk(KERN_CRIT "cadet: RDS fifo overflow\n");
-		}
-		outb(0x80,io);      /* Select RDS fifo */
-		while((inb(io)&0x80)!=0) {
-			rdsbuf[rdsin]=inb(io+1);
-			if(rdsin==rdsout)
+		outb(0x80, dev->io);      /* Select RDS fifo */
+		while ((inb(dev->io) & 0x80) != 0) {
+			dev->rdsbuf[dev->rdsin] = inb(dev->io + 1);
+			if (dev->rdsin == dev->rdsout)
 				printk(KERN_WARNING "cadet: RDS buffer overflow\n");
 			else
-				rdsin++;
+				dev->rdsin++;
 		}
-		spin_unlock(&cadet_io_lock);
+		mutex_unlock(&dev->lock);
 	}
 
 	/*
 	 * Service pending read
 	 */
-	if( rdsin!=rdsout)
-		wake_up_interruptible(&read_queue);
+	if (dev->rdsin != dev->rdsout)
+		wake_up_interruptible(&dev->read_queue);
 
 	/*
 	 * Clean up and exit
 	 */
-	init_timer(&readtimer);
-	readtimer.function=cadet_handler;
-	readtimer.data=(unsigned long)0;
-	readtimer.expires=jiffies+msecs_to_jiffies(50);
-	add_timer(&readtimer);
+	init_timer(&dev->readtimer);
+	dev->readtimer.function = cadet_handler;
+	dev->readtimer.data = (unsigned long)0;
+	dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
+	add_timer(&dev->readtimer);
 }
 
 
-
-static ssize_t
-cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
-	int i=0;
+	struct cadet *dev = video_drvdata(file);
 	unsigned char readbuf[RDS_BUFFER];
+	int i = 0;
 
-	if(rdsstat==0) {
-		spin_lock(&cadet_io_lock);
-		rdsstat=1;
-		outb(0x80,io);        /* Select RDS fifo */
-		spin_unlock(&cadet_io_lock);
-		init_timer(&readtimer);
-		readtimer.function=cadet_handler;
-		readtimer.data=(unsigned long)0;
-		readtimer.expires=jiffies+msecs_to_jiffies(50);
-		add_timer(&readtimer);
+	if (dev->rdsstat == 0) {
+		mutex_lock(&dev->lock);
+		dev->rdsstat = 1;
+		outb(0x80, dev->io);        /* Select RDS fifo */
+		mutex_unlock(&dev->lock);
+		init_timer(&dev->readtimer);
+		dev->readtimer.function = cadet_handler;
+		dev->readtimer.data = (unsigned long)dev;
+		dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
+		add_timer(&dev->readtimer);
 	}
-	if(rdsin==rdsout) {
+	if (dev->rdsin == dev->rdsout) {
 		if (file->f_flags & O_NONBLOCK)
 			return -EWOULDBLOCK;
-		interruptible_sleep_on(&read_queue);
+		interruptible_sleep_on(&dev->read_queue);
 	}
-	while( i<count && rdsin!=rdsout)
-		readbuf[i++]=rdsbuf[rdsout++];
+	while (i < count && dev->rdsin != dev->rdsout)
+		readbuf[i++] = dev->rdsbuf[dev->rdsout++];
 
-	if (copy_to_user(data,readbuf,i))
+	if (copy_to_user(data, readbuf, i))
 		return -EFAULT;
 	return i;
 }
@@ -370,38 +355,40 @@
 static int vidioc_querycap(struct file *file, void *priv,
 				struct v4l2_capability *v)
 {
-	v->capabilities =
-		V4L2_CAP_TUNER |
-		V4L2_CAP_READWRITE;
+	strlcpy(v->driver, "ADS Cadet", sizeof(v->driver));
+	strlcpy(v->card, "ADS Cadet", sizeof(v->card));
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = CADET_VERSION;
-	strcpy(v->driver, "ADS Cadet");
-	strcpy(v->card, "ADS Cadet");
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
+	struct cadet *dev = video_drvdata(file);
+
 	v->type = V4L2_TUNER_RADIO;
 	switch (v->index) {
 	case 0:
-		strcpy(v->name, "FM");
+		strlcpy(v->name, "FM", sizeof(v->name));
 		v->capability = V4L2_TUNER_CAP_STEREO;
 		v->rangelow = 1400;     /* 87.5 MHz */
 		v->rangehigh = 1728;    /* 108.0 MHz */
-		v->rxsubchans=cadet_getstereo();
-		switch (v->rxsubchans){
+		v->rxsubchans = cadet_getstereo(dev);
+		switch (v->rxsubchans) {
 		case V4L2_TUNER_SUB_MONO:
 			v->audmode = V4L2_TUNER_MODE_MONO;
 			break;
 		case V4L2_TUNER_SUB_STEREO:
 			v->audmode = V4L2_TUNER_MODE_STEREO;
 			break;
-		default: ;
+		default:
+			break;
 		}
 		break;
 	case 1:
-		strcpy(v->name, "AM");
+		strlcpy(v->name, "AM", sizeof(v->name));
 		v->capability = V4L2_TUNER_CAP_LOW;
 		v->rangelow = 8320;      /* 520 kHz */
 		v->rangehigh = 26400;    /* 1650 kHz */
@@ -411,25 +398,29 @@
 	default:
 		return -EINVAL;
 	}
-	v->signal = sigstrength; /* We might need to modify scaling of this */
+	v->signal = dev->sigstrength; /* We might need to modify scaling of this */
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	if((v->index != 0)&&(v->index != 1))
+	struct cadet *dev = video_drvdata(file);
+
+	if (v->index != 0 && v->index != 1)
 		return -EINVAL;
-	curtuner = v->index;
+	dev->curtuner = v->index;
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	f->tuner = curtuner;
+	struct cadet *dev = video_drvdata(file);
+
+	f->tuner = dev->curtuner;
 	f->type = V4L2_TUNER_RADIO;
-	f->frequency = cadet_getfreq();
+	f->frequency = cadet_getfreq(dev);
 	return 0;
 }
 
@@ -437,27 +428,26 @@
 static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
+	struct cadet *dev = video_drvdata(file);
+
 	if (f->type != V4L2_TUNER_RADIO)
 		return -EINVAL;
-	if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728)))
+	if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728))
 		return -EINVAL;
-	if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400)))
+	if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400))
 		return -EINVAL;
-	cadet_setfreq(f->frequency);
+	cadet_setfreq(dev, f->frequency);
 	return 0;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
 				struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff);
 	}
 	return -EINVAL;
 }
@@ -465,12 +455,14 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
-	switch (ctrl->id){
+	struct cadet *dev = video_drvdata(file);
+
+	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
-		ctrl->value = (cadet_getvol() == 0);
+		ctrl->value = (cadet_getvol(dev) == 0);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = cadet_getvol();
+		ctrl->value = cadet_getvol(dev);
 		break;
 	default:
 		return -EINVAL;
@@ -481,15 +473,17 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
+	struct cadet *dev = video_drvdata(file);
+
 	switch (ctrl->id){
 	case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
 		if (ctrl->value)
-			cadet_setvol(0);
+			cadet_setvol(dev, 0);
 		else
-			cadet_setvol(0xffff);
+			cadet_setvol(dev, 0xffff);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
-		cadet_setvol(ctrl->value);
+		cadet_setvol(dev, ctrl->value);
 		break;
 	default:
 		return -EINVAL;
@@ -497,16 +491,6 @@
 	return 0;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-				struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -515,43 +499,52 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 				struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int cadet_open(struct file *file)
+{
+	struct cadet *dev = video_drvdata(file);
+
+	dev->users++;
+	if (1 == dev->users)
+		init_waitqueue_head(&dev->read_queue);
 	return 0;
 }
 
-static int
-cadet_open(struct file *file)
+static int cadet_release(struct file *file)
 {
-	users++;
-	if (1 == users) init_waitqueue_head(&read_queue);
-	return 0;
-}
+	struct cadet *dev = video_drvdata(file);
 
-static int
-cadet_release(struct file *file)
-{
-	users--;
-	if (0 == users){
-		del_timer_sync(&readtimer);
-		rdsstat=0;
+	dev->users--;
+	if (0 == dev->users) {
+		del_timer_sync(&dev->readtimer);
+		dev->rdsstat = 0;
 	}
 	return 0;
 }
 
-static unsigned int
-cadet_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait)
 {
-	poll_wait(file,&read_queue,wait);
-	if(rdsin != rdsout)
+	struct cadet *dev = video_drvdata(file);
+
+	poll_wait(file, &dev->read_queue, wait);
+	if (dev->rdsin != dev->rdsout)
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
@@ -581,13 +574,6 @@
 	.vidioc_s_input     = vidioc_s_input,
 };
 
-static struct video_device cadet_radio = {
-	.name		= "Cadet radio",
-	.fops           = &cadet_fops,
-	.ioctl_ops 	= &cadet_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 #ifdef CONFIG_PNP
 
 static struct pnp_device_id cadet_pnp_devices[] = {
@@ -598,7 +584,7 @@
 
 MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices);
 
-static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id)
+static int cadet_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	if (!dev)
 		return -ENODEV;
@@ -606,13 +592,12 @@
 	if (io > 0)
 		return -EBUSY;
 
-	if (!pnp_port_valid(dev, 0)) {
+	if (!pnp_port_valid(dev, 0))
 		return -ENODEV;
-	}
 
 	io = pnp_port_start(dev, 0);
 
-	printk ("radio-cadet: PnP reports device at %#x\n", io);
+	printk(KERN_INFO "radio-cadet: PnP reports device at %#x\n", io);
 
 	return io;
 }
@@ -628,23 +613,23 @@
 static struct pnp_driver cadet_pnp_driver;
 #endif
 
-static int cadet_probe(void)
+static void cadet_probe(struct cadet *dev)
 {
-	static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
+	static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e };
 	int i;
 
-	for(i=0;i<8;i++) {
-		io=iovals[i];
-		if (request_region(io, 2, "cadet-probe")) {
-			cadet_setfreq(1410);
-			if(cadet_getfreq()==1410) {
-				release_region(io, 2);
-				return io;
+	for (i = 0; i < 8; i++) {
+		dev->io = iovals[i];
+		if (request_region(dev->io, 2, "cadet-probe")) {
+			cadet_setfreq(dev, 1410);
+			if (cadet_getfreq(dev) == 1410) {
+				release_region(dev->io, 2);
+				return;
 			}
-			release_region(io, 2);
+			release_region(dev->io, 2);
 		}
 	}
-	return -1;
+	dev->io = -1;
 }
 
 /*
@@ -654,59 +639,69 @@
 
 static int __init cadet_init(void)
 {
-	spin_lock_init(&cadet_io_lock);
+	struct cadet *dev = &cadet_card;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	int res;
 
-	/*
-	 *	If a probe was requested then probe ISAPnP first (safest)
-	 */
+	strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name));
+	mutex_init(&dev->lock);
+
+	/* If a probe was requested then probe ISAPnP first (safest) */
 	if (io < 0)
 		pnp_register_driver(&cadet_pnp_driver);
-	/*
-	 *	If that fails then probe unsafely if probe is requested
-	 */
-	if(io < 0)
-		io = cadet_probe ();
+	dev->io = io;
 
-	/*
-	 *	Else we bail out
-	 */
+	/* If that fails then probe unsafely if probe is requested */
+	if (dev->io < 0)
+		cadet_probe(dev);
 
-	if(io < 0) {
+	/* Else we bail out */
+	if (dev->io < 0) {
 #ifdef MODULE
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+		v4l2_err(v4l2_dev, "you must set an I/O address with io=0x330, 0x332, 0x334,\n");
+		v4l2_err(v4l2_dev, "0x336, 0x338, 0x33a, 0x33c or 0x33e\n");
 #endif
 		goto fail;
 	}
-	if (!request_region(io,2,"cadet"))
+	if (!request_region(dev->io, 2, "cadet"))
 		goto fail;
-	if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io,2);
+
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(dev->io, 2);
+		v4l2_err(v4l2_dev, "could not register v4l2_device\n");
 		goto fail;
 	}
-	printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
+
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.fops = &cadet_fops;
+	dev->vdev.ioctl_ops = &cadet_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	video_set_drvdata(&dev->vdev, dev);
+
+	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(dev->io, 2);
+		goto fail;
+	}
+	v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io);
 	return 0;
 fail:
 	pnp_unregister_driver(&cadet_pnp_driver);
-	return -1;
+	return -ENODEV;
 }
 
-
-
-MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
-module_param(radio_nr, int, 0);
-
-static void __exit cadet_cleanup_module(void)
+static void __exit cadet_exit(void)
 {
-	video_unregister_device(&cadet_radio);
-	release_region(io,2);
+	struct cadet *dev = &cadet_card;
+
+	video_unregister_device(&dev->vdev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	release_region(dev->io, 2);
 	pnp_unregister_driver(&cadet_pnp_driver);
 }
 
 module_init(cadet_init);
-module_exit(cadet_cleanup_module);
+module_exit(cadet_exit);
 
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 0c96bf8..09265d2 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -45,34 +45,25 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/errno.h>
-
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+#include <linux/io.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
+MODULE_AUTHOR("Vladimir Shebordaev <vshebordaev@mail.ru>");
+MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card");
+MODULE_LICENSE("GPL");
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
+static int nr_radio = -1;
+static int mx = 1;
+
+module_param(mx, bool, 0);
+MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not");
+module_param(nr_radio, int, 0);
+MODULE_PARM_DESC(nr_radio, "video4linux device number to use");
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
 
 #ifndef PCI_VENDOR_ID_GEMTEK
 #define PCI_VENDOR_ID_GEMTEK 0x5046
@@ -90,8 +81,11 @@
 #define GEMTEK_PCI_RANGE_HIGH (108*16000)
 #endif
 
-struct gemtek_pci_card {
-	struct video_device *videodev;
+struct gemtek_pci {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct mutex lock;
+	struct pci_dev *pdev;
 
 	u32 iobase;
 	u32 length;
@@ -100,116 +94,133 @@
 	u8  mute;
 };
 
-static int nr_radio = -1;
-static unsigned long in_use;
-
-static inline u8 gemtek_pci_out( u16 value, u32 port )
+static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev)
 {
-	outw( value, port );
+	return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev);
+}
+
+static inline u8 gemtek_pci_out(u16 value, u32 port)
+{
+	outw(value, port);
 
 	return (u8)value;
 }
 
-#define _b0( v ) *((u8 *)&v)
-static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
-{
-	register u8 byte = *last_byte;
+#define _b0(v) (*((u8 *)&v))
 
-	if ( !value ) {
-		if ( !keep )
+static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep)
+{
+	u8 byte = *last_byte;
+
+	if (!value) {
+		if (!keep)
 			value = (u16)port;
 		byte &= 0xfd;
 	} else
 		byte |= 2;
 
-	_b0( value ) = byte;
-	outw( value, port );
+	_b0(value) = byte;
+	outw(value, port);
 	byte |= 1;
-	_b0( value ) = byte;
-	outw( value, port );
+	_b0(value) = byte;
+	outw(value, port);
 	byte &= 0xfe;
-	_b0( value ) = byte;
-	outw( value, port );
+	_b0(value) = byte;
+	outw(value, port);
 
 	*last_byte = byte;
 }
 
-static inline void gemtek_pci_nil( u32 port, u8 *last_byte )
+static inline void gemtek_pci_nil(u32 port, u8 *last_byte)
 {
-	__gemtek_pci_cmd( 0x00, port, last_byte, false );
+	__gemtek_pci_cmd(0x00, port, last_byte, false);
 }
 
-static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte )
+static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte)
 {
-	__gemtek_pci_cmd( cmd, port, last_byte, true );
+	__gemtek_pci_cmd(cmd, port, last_byte, true);
 }
 
-static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency )
+static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency)
 {
-	register int i;
-	register u32 value = frequency / 200 + 856;
-	register u16 mask = 0x8000;
+	int i;
+	u32 value = frequency / 200 + 856;
+	u16 mask = 0x8000;
 	u8 last_byte;
 	u32 port = card->iobase;
 
-	last_byte = gemtek_pci_out( 0x06, port );
+	mutex_lock(&card->lock);
+	card->current_frequency = frequency;
+	last_byte = gemtek_pci_out(0x06, port);
 
 	i = 0;
 	do {
-		gemtek_pci_nil( port, &last_byte );
+		gemtek_pci_nil(port, &last_byte);
 		i++;
-	} while ( i < 9 );
+	} while (i < 9);
 
 	i = 0;
 	do {
-		gemtek_pci_cmd( value & mask, port, &last_byte );
+		gemtek_pci_cmd(value & mask, port, &last_byte);
 		mask >>= 1;
 		i++;
-	} while ( i < 16 );
+	} while (i < 16);
 
-	outw( 0x10, port );
+	outw(0x10, port);
+	mutex_unlock(&card->lock);
 }
 
 
-static inline void gemtek_pci_mute( struct gemtek_pci_card *card )
+static void gemtek_pci_mute(struct gemtek_pci *card)
 {
-	outb( 0x1f, card->iobase );
+	mutex_lock(&card->lock);
+	outb(0x1f, card->iobase);
 	card->mute = true;
+	mutex_unlock(&card->lock);
 }
 
-static inline void gemtek_pci_unmute( struct gemtek_pci_card *card )
+static void gemtek_pci_unmute(struct gemtek_pci *card)
 {
-	if ( card->mute ) {
-		gemtek_pci_setfrequency( card, card->current_frequency );
+	mutex_lock(&card->lock);
+	if (card->mute) {
+		gemtek_pci_setfrequency(card, card->current_frequency);
 		card->mute = false;
 	}
+	mutex_unlock(&card->lock);
 }
 
-static inline unsigned int gemtek_pci_getsignal( struct gemtek_pci_card *card )
+static int gemtek_pci_getsignal(struct gemtek_pci *card)
 {
-	return ( inb( card->iobase ) & 0x08 ) ? 0 : 1;
+	int sig;
+
+	mutex_lock(&card->lock);
+	sig = (inb(card->iobase) & 0x08) ? 0 : 1;
+	mutex_unlock(&card->lock);
+	return sig;
 }
 
 static int vidioc_querycap(struct file *file, void *priv,
 					struct v4l2_capability *v)
 {
+	struct gemtek_pci *card = video_drvdata(file);
+
 	strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver));
 	strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	struct gemtek_pci_card *card = video_drvdata(file);
+	struct gemtek_pci *card = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 	v->rangelow = GEMTEK_PCI_RANGE_LOW;
 	v->rangehigh = GEMTEK_PCI_RANGE_HIGH;
@@ -223,21 +234,18 @@
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct gemtek_pci_card *card = video_drvdata(file);
+	struct gemtek_pci *card = video_drvdata(file);
 
-	if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) ||
-			(f->frequency > GEMTEK_PCI_RANGE_HIGH) )
+	if (f->frequency < GEMTEK_PCI_RANGE_LOW ||
+	    f->frequency > GEMTEK_PCI_RANGE_HIGH)
 		return -EINVAL;
 	gemtek_pci_setfrequency(card, f->frequency);
-	card->current_frequency = f->frequency;
 	card->mute = false;
 	return 0;
 }
@@ -245,7 +253,7 @@
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct gemtek_pci_card *card = video_drvdata(file);
+	struct gemtek_pci *card = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = card->current_frequency;
@@ -255,13 +263,11 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535);
 	}
 	return -EINVAL;
 }
@@ -269,7 +275,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct gemtek_pci_card *card = video_drvdata(file);
+	struct gemtek_pci *card = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -288,7 +294,7 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct gemtek_pci_card *card = video_drvdata(file);
+	struct gemtek_pci *card = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -307,17 +313,6 @@
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -326,17 +321,22 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
-	return 0;
+	return a->index ? -EINVAL : 0;
 }
 
 enum {
@@ -354,25 +354,22 @@
 	{ 0 }
 };
 
-MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
+MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
 
-static int mx = 1;
-
-static int gemtek_pci_exclusive_open(struct file *file)
+static int gemtek_pci_open(struct file *file)
 {
-	return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+	return 0;
 }
 
-static int gemtek_pci_exclusive_release(struct file *file)
+static int gemtek_pci_release(struct file *file)
 {
-	clear_bit(0, &in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations gemtek_pci_fops = {
 	.owner		= THIS_MODULE,
-	.open           = gemtek_pci_exclusive_open,
-	.release        = gemtek_pci_exclusive_release,
+	.open           = gemtek_pci_open,
+	.release        = gemtek_pci_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -391,108 +388,100 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device vdev_template = {
-	.name          	= "Gemtek PCI Radio",
-	.fops          	= &gemtek_pci_fops,
-	.ioctl_ops 	= &gemtek_pci_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
-static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
+static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
 {
-	struct gemtek_pci_card *card;
-	struct video_device *devradio;
+	struct gemtek_pci *card;
+	struct v4l2_device *v4l2_dev;
+	int res;
 
-	if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
-		printk( KERN_ERR "gemtek_pci: out of memory\n" );
+	card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL);
+	if (card == NULL) {
+		dev_err(&pdev->dev, "out of memory\n");
 		return -ENOMEM;
 	}
 
-	if ( pci_enable_device( pci_dev ) )
+	v4l2_dev = &card->v4l2_dev;
+	mutex_init(&card->lock);
+	card->pdev = pdev;
+
+	strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name));
+
+	res = v4l2_device_register(&pdev->dev, v4l2_dev);
+	if (res < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		kfree(card);
+		return res;
+	}
+
+	if (pci_enable_device(pdev))
 		goto err_pci;
 
-	card->iobase = pci_resource_start( pci_dev, 0 );
-	card->length = pci_resource_len( pci_dev, 0 );
+	card->iobase = pci_resource_start(pdev, 0);
+	card->length = pci_resource_len(pdev, 0);
 
-	if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) {
-		printk( KERN_ERR "gemtek_pci: i/o port already in use\n" );
+	if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
+		v4l2_err(v4l2_dev, "i/o port already in use\n");
 		goto err_pci;
 	}
 
-	pci_set_drvdata( pci_dev, card );
+	strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name));
+	card->vdev.v4l2_dev = v4l2_dev;
+	card->vdev.fops = &gemtek_pci_fops;
+	card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops;
+	card->vdev.release = video_device_release_empty;
+	video_set_drvdata(&card->vdev, card);
 
-	if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) {
-		printk( KERN_ERR "gemtek_pci: out of memory\n" );
+	if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
 		goto err_video;
-	}
-	*devradio = vdev_template;
 
-	if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) {
-		kfree( devradio );
-		goto err_video;
-	}
+	gemtek_pci_mute(card);
 
-	card->videodev = devradio;
-	video_set_drvdata(devradio, card);
-	gemtek_pci_mute( card );
-
-	printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
-		pci_dev->revision, card->iobase, card->iobase + card->length - 1 );
+	v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
+		pdev->revision, card->iobase, card->iobase + card->length - 1);
 
 	return 0;
 
 err_video:
-	release_region( card->iobase, card->length );
+	release_region(card->iobase, card->length);
 
 err_pci:
-	kfree( card );
+	v4l2_device_unregister(v4l2_dev);
+	kfree(card);
 	return -ENODEV;
 }
 
-static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev )
+static void __devexit gemtek_pci_remove(struct pci_dev *pdev)
 {
-	struct gemtek_pci_card *card = pci_get_drvdata( pci_dev );
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct gemtek_pci *card = to_gemtek_pci(v4l2_dev);
 
-	video_unregister_device( card->videodev );
-	kfree( card->videodev );
+	video_unregister_device(&card->vdev);
+	v4l2_device_unregister(v4l2_dev);
 
-	release_region( card->iobase, card->length );
+	release_region(card->iobase, card->length);
 
-	if ( mx )
-		gemtek_pci_mute( card );
+	if (mx)
+		gemtek_pci_mute(card);
 
-	kfree( card );
-
-	pci_set_drvdata( pci_dev, NULL );
+	kfree(card);
 }
 
-static struct pci_driver gemtek_pci_driver =
-{
+static struct pci_driver gemtek_pci_driver = {
 	.name		= "gemtek_pci",
 	.id_table	= gemtek_pci_id,
 	.probe		= gemtek_pci_probe,
 	.remove		= __devexit_p(gemtek_pci_remove),
 };
 
-static int __init gemtek_pci_init_module( void )
+static int __init gemtek_pci_init(void)
 {
-	return pci_register_driver( &gemtek_pci_driver );
+	return pci_register_driver(&gemtek_pci_driver);
 }
 
-static void __exit gemtek_pci_cleanup_module( void )
+static void __exit gemtek_pci_exit(void)
 {
 	pci_unregister_driver(&gemtek_pci_driver);
 }
 
-MODULE_AUTHOR( "Vladimir Shebordaev <vshebordaev@mail.ru>" );
-MODULE_DESCRIPTION( "The video4linux driver for the Gemtek PCI Radio Card" );
-MODULE_LICENSE("GPL");
-
-module_param(mx, bool, 0);
-MODULE_PARM_DESC( mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not" );
-module_param(nr_radio, int, 0);
-MODULE_PARM_DESC( nr_radio, "video4linux device number to use");
-
-module_init( gemtek_pci_init_module );
-module_exit( gemtek_pci_cleanup_module );
-
+module_init(gemtek_pci_init);
+module_exit(gemtek_pci_exit);
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 2b68be7..1504644 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -20,16 +20,14 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <linux/spinlock.h>
-
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
-#define RADIO_VERSION KERNEL_VERSION(0,0,3)
-#define RADIO_BANNER "GemTek Radio card driver: v0.0.3"
+#include <linux/mutex.h>
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 3)
 
 /*
  * Module info.
@@ -57,7 +55,6 @@
 static int keepmuted	= 1;
 static int initmute	= 1;
 static int radio_nr	= -1;
-static unsigned long in_use;
 
 module_param(io, int, 0444);
 MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
@@ -112,12 +109,19 @@
 #define SHORT_DELAY 5		/* usec */
 #define LONG_DELAY 75		/* usec */
 
-struct gemtek_device {
+struct gemtek {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct mutex lock;
 	unsigned long lastfreq;
 	int muted;
+	int verified;
+	int io;
 	u32 bu2614data;
 };
 
+static struct gemtek gemtek_card;
+
 #define BU2614_FREQ_BITS 	16 /* D0..D15, Frequency data		*/
 #define BU2614_PORT_BITS	3 /* P0..P2, Output port control data	*/
 #define BU2614_VOID_BITS	4 /* unused 				*/
@@ -153,10 +157,6 @@
 #define BU2614_FMUN_MASK	MKMASK(FMUN)
 #define BU2614_TEST_MASK	MKMASK(TEST)
 
-static struct gemtek_device gemtek_unit;
-
-static spinlock_t lock;
-
 /*
  * Set data which will be sent to BU2614FS.
  */
@@ -166,33 +166,33 @@
 /*
  * Transmit settings to BU2614FS over GemTek IC.
  */
-static void gemtek_bu2614_transmit(struct gemtek_device *dev)
+static void gemtek_bu2614_transmit(struct gemtek *gt)
 {
 	int i, bit, q, mute;
 
-	spin_lock(&lock);
+	mutex_lock(&gt->lock);
 
-	mute = dev->muted ? GEMTEK_MT : 0x00;
+	mute = gt->muted ? GEMTEK_MT : 0x00;
 
-	outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
+	outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
 	udelay(SHORT_DELAY);
-	outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
+	outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
 	udelay(LONG_DELAY);
 
-	for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) {
-	    bit = (q & 1) ? GEMTEK_DA : 0;
-	    outb_p(mute | GEMTEK_CE | bit, io);
-	    udelay(SHORT_DELAY);
-	    outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io);
-	    udelay(SHORT_DELAY);
+	for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) {
+		bit = (q & 1) ? GEMTEK_DA : 0;
+		outb_p(mute | GEMTEK_CE | bit, gt->io);
+		udelay(SHORT_DELAY);
+		outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io);
+		udelay(SHORT_DELAY);
 	}
 
-	outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
+	outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
 	udelay(SHORT_DELAY);
-	outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
+	outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
 	udelay(LONG_DELAY);
 
-	spin_unlock(&lock);
+	mutex_unlock(&gt->lock);
 }
 
 /*
@@ -206,107 +206,109 @@
 /*
  * Set FM-frequency.
  */
-static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
+static void gemtek_setfreq(struct gemtek *gt, unsigned long freq)
 {
-
-	if (keepmuted && hardmute && dev->muted)
+	if (keepmuted && hardmute && gt->muted)
 		return;
 
-	if (freq < GEMTEK_LOWFREQ)
-		freq = GEMTEK_LOWFREQ;
-	else if (freq > GEMTEK_HIGHFREQ)
-		freq = GEMTEK_HIGHFREQ;
+	freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ);
 
-	dev->lastfreq = freq;
-	dev->muted = 0;
+	gt->lastfreq = freq;
+	gt->muted = 0;
 
-	gemtek_bu2614_set(dev, BU2614_PORT, 0);
-	gemtek_bu2614_set(dev, BU2614_FMES, 0);
-	gemtek_bu2614_set(dev, BU2614_SWIN, 0);	/* FM-mode	*/
-	gemtek_bu2614_set(dev, BU2614_SWAL, 0);
-	gemtek_bu2614_set(dev, BU2614_FMUN, 1);	/* GT bit set	*/
-	gemtek_bu2614_set(dev, BU2614_TEST, 0);
+	gemtek_bu2614_set(gt, BU2614_PORT, 0);
+	gemtek_bu2614_set(gt, BU2614_FMES, 0);
+	gemtek_bu2614_set(gt, BU2614_SWIN, 0);	/* FM-mode	*/
+	gemtek_bu2614_set(gt, BU2614_SWAL, 0);
+	gemtek_bu2614_set(gt, BU2614_FMUN, 1);	/* GT bit set	*/
+	gemtek_bu2614_set(gt, BU2614_TEST, 0);
 
-	gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
-	gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq));
+	gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
+	gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq));
 
-	gemtek_bu2614_transmit(dev);
+	gemtek_bu2614_transmit(gt);
 }
 
 /*
  * Set mute flag.
  */
-static void gemtek_mute(struct gemtek_device *dev)
+static void gemtek_mute(struct gemtek *gt)
 {
 	int i;
-	dev->muted = 1;
+
+	gt->muted = 1;
 
 	if (hardmute) {
 		/* Turn off PLL, disable data output */
-		gemtek_bu2614_set(dev, BU2614_PORT, 0);
-		gemtek_bu2614_set(dev, BU2614_FMES, 0);	/* CT bit off	*/
-		gemtek_bu2614_set(dev, BU2614_SWIN, 0);	/* FM-mode	*/
-		gemtek_bu2614_set(dev, BU2614_SWAL, 0);
-		gemtek_bu2614_set(dev, BU2614_FMUN, 0);	/* GT bit off	*/
-		gemtek_bu2614_set(dev, BU2614_TEST, 0);
-		gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF);
-		gemtek_bu2614_set(dev, BU2614_FREQ, 0);
-		gemtek_bu2614_transmit(dev);
-	} else {
-		spin_lock(&lock);
-
-		/* Read bus contents (CE, CK and DA). */
-		i = inb_p(io);
-		/* Write it back with mute flag set. */
-		outb_p((i >> 5) | GEMTEK_MT, io);
-		udelay(SHORT_DELAY);
-
-		spin_unlock(&lock);
+		gemtek_bu2614_set(gt, BU2614_PORT, 0);
+		gemtek_bu2614_set(gt, BU2614_FMES, 0);	/* CT bit off	*/
+		gemtek_bu2614_set(gt, BU2614_SWIN, 0);	/* FM-mode	*/
+		gemtek_bu2614_set(gt, BU2614_SWAL, 0);
+		gemtek_bu2614_set(gt, BU2614_FMUN, 0);	/* GT bit off	*/
+		gemtek_bu2614_set(gt, BU2614_TEST, 0);
+		gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF);
+		gemtek_bu2614_set(gt, BU2614_FREQ, 0);
+		gemtek_bu2614_transmit(gt);
+		return;
 	}
+
+	mutex_lock(&gt->lock);
+
+	/* Read bus contents (CE, CK and DA). */
+	i = inb_p(gt->io);
+	/* Write it back with mute flag set. */
+	outb_p((i >> 5) | GEMTEK_MT, gt->io);
+	udelay(SHORT_DELAY);
+
+	mutex_unlock(&gt->lock);
 }
 
 /*
  * Unset mute flag.
  */
-static void gemtek_unmute(struct gemtek_device *dev)
+static void gemtek_unmute(struct gemtek *gt)
 {
 	int i;
-	dev->muted = 0;
 
+	gt->muted = 0;
 	if (hardmute) {
 		/* Turn PLL back on. */
-		gemtek_setfreq(dev, dev->lastfreq);
-	} else {
-		spin_lock(&lock);
-
-		i = inb_p(io);
-		outb_p(i >> 5, io);
-		udelay(SHORT_DELAY);
-
-		spin_unlock(&lock);
+		gemtek_setfreq(gt, gt->lastfreq);
+		return;
 	}
+	mutex_lock(&gt->lock);
+
+	i = inb_p(gt->io);
+	outb_p(i >> 5, gt->io);
+	udelay(SHORT_DELAY);
+
+	mutex_unlock(&gt->lock);
 }
 
 /*
  * Get signal strength (= stereo status).
  */
-static inline int gemtek_getsigstr(void)
+static inline int gemtek_getsigstr(struct gemtek *gt)
 {
-	return inb_p(io) & GEMTEK_NS ? 0 : 1;
+	int sig;
+
+	mutex_lock(&gt->lock);
+	sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1;
+	mutex_unlock(&gt->lock);
+	return sig;
 }
 
 /*
  * Check if requested card acts like GemTek Radio card.
  */
-static int gemtek_verify(int port)
+static int gemtek_verify(struct gemtek *gt, int port)
 {
-	static int verified = -1;
 	int i, q;
 
-	if (verified == port)
+	if (gt->verified == port)
 		return 1;
 
-	spin_lock(&lock);
+	mutex_lock(&gt->lock);
 
 	q = inb_p(port);	/* Read bus contents before probing. */
 	/* Try to turn on CE, CK and DA respectively and check if card responds
@@ -316,15 +318,15 @@
 		udelay(SHORT_DELAY);
 
 		if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
-			spin_unlock(&lock);
+			mutex_unlock(&gt->lock);
 			return 0;
 		}
 	}
 	outb_p(q >> 5, port);	/* Write bus contents back. */
 	udelay(SHORT_DELAY);
 
-	spin_unlock(&lock);
-	verified = port;
+	mutex_unlock(&gt->lock);
+	gt->verified = port;
 
 	return 1;
 }
@@ -332,83 +334,61 @@
 /*
  * Automatic probing for card.
  */
-static int gemtek_probe(void)
+static int gemtek_probe(struct gemtek *gt)
 {
+	struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
 	int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
 	int i;
 
 	if (!probe) {
-		printk(KERN_INFO "Automatic device probing disabled.\n");
+		v4l2_info(v4l2_dev, "Automatic device probing disabled.\n");
 		return -1;
 	}
 
-	printk(KERN_INFO "Automatic device probing enabled.\n");
+	v4l2_info(v4l2_dev, "Automatic device probing enabled.\n");
 
 	for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
-		printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]);
+		v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]);
 
 		if (!request_region(ioports[i], 1, "gemtek-probe")) {
-			printk(KERN_WARNING "I/O port 0x%x busy!\n",
+			v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n",
 			       ioports[i]);
 			continue;
 		}
 
-		if (gemtek_verify(ioports[i])) {
-			printk(KERN_INFO "Card found from I/O port "
+		if (gemtek_verify(gt, ioports[i])) {
+			v4l2_info(v4l2_dev, "Card found from I/O port "
 			       "0x%x!\n", ioports[i]);
 
 			release_region(ioports[i], 1);
-
-			io = ioports[i];
-			return io;
+			gt->io = ioports[i];
+			return gt->io;
 		}
 
 		release_region(ioports[i], 1);
 	}
 
-	printk(KERN_ERR "Automatic probing failed!\n");
-
+	v4l2_err(v4l2_dev, "Automatic probing failed!\n");
 	return -1;
 }
 
 /*
  * Video 4 Linux stuff.
  */
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id = V4L2_CID_AUDIO_MUTE,
-		.name = "Mute",
-		.minimum = 0,
-		.maximum = 1,
-		.default_value = 1,
-		.type = V4L2_CTRL_TYPE_BOOLEAN,
-	}, {
-		.id = V4L2_CID_AUDIO_VOLUME,
-		.name = "Volume",
-		.minimum = 0,
-		.maximum = 65535,
-		.step = 65535,
-		.default_value = 0xff,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
-
-static int gemtek_exclusive_open(struct file *file)
+static int gemtek_open(struct file *file)
 {
-	return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+	return 0;
 }
 
-static int gemtek_exclusive_release(struct file *file)
+static int gemtek_release(struct file *file)
 {
-	clear_bit(0, &in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations gemtek_fops = {
 	.owner		= THIS_MODULE,
-	.open		= gemtek_exclusive_open,
-	.release	= gemtek_exclusive_release,
+	.open		= gemtek_open,
+	.release	= gemtek_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -417,23 +397,25 @@
 {
 	strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
 	strlcpy(v->card, "GemTek", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 {
+	struct gemtek *gt = video_drvdata(file);
+
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 	v->rangelow = GEMTEK_LOWFREQ;
 	v->rangehigh = GEMTEK_HIGHFREQ;
 	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-	v->signal = 0xffff * gemtek_getsigstr();
+	v->signal = 0xffff * gemtek_getsigstr(gt);
 	if (v->signal) {
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 		v->rxsubchans = V4L2_TUNER_SUB_STEREO;
@@ -441,65 +423,56 @@
 		v->audmode = V4L2_TUNER_MODE_MONO;
 		v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	}
-
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 {
-	if (v->index > 0)
+	return (v->index != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f)
+{
+	struct gemtek *gt = video_drvdata(file);
+
+	if (f->tuner != 0)
 		return -EINVAL;
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = gt->lastfreq;
 	return 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 			      struct v4l2_frequency *f)
 {
-	struct gemtek_device *rt = video_drvdata(file);
+	struct gemtek *gt = video_drvdata(file);
 
-	gemtek_setfreq(rt, f->frequency);
-
-	return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-			      struct v4l2_frequency *f)
-{
-	struct gemtek_device *rt = video_drvdata(file);
-
-	f->type = V4L2_TUNER_RADIO;
-	f->frequency = rt->lastfreq;
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
+	gemtek_setfreq(gt, f->frequency);
 	return 0;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
 			    struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+	default:
+		return -EINVAL;
 	}
-	return -EINVAL;
 }
 
 static int vidioc_g_ctrl(struct file *file, void *priv,
 			 struct v4l2_control *ctrl)
 {
-	struct gemtek_device *rt = video_drvdata(file);
+	struct gemtek *gt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = rt->muted;
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (rt->muted)
-			ctrl->value = 0;
-		else
-			ctrl->value = 65535;
+		ctrl->value = gt->muted;
 		return 0;
 	}
 	return -EINVAL;
@@ -508,35 +481,19 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 			 struct v4l2_control *ctrl)
 {
-	struct gemtek_device *rt = video_drvdata(file);
+	struct gemtek *gt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value)
-			gemtek_mute(rt);
+			gemtek_mute(gt);
 		else
-			gemtek_unmute(rt);
-		return 0;
-	case V4L2_CID_AUDIO_VOLUME:
-		if (ctrl->value)
-			gemtek_unmute(rt);
-		else
-			gemtek_mute(rt);
+			gemtek_unmute(gt);
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -545,16 +502,20 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return (i != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
-	return 0;
+	return (a->index != 0) ? -EINVAL : 0;
 }
 
 static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
@@ -572,62 +533,73 @@
 	.vidioc_s_ctrl		= vidioc_s_ctrl
 };
 
-static struct video_device gemtek_radio = {
-	.name		= "GemTek Radio card",
-	.fops		= &gemtek_fops,
-	.ioctl_ops 	= &gemtek_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 /*
  * Initialization / cleanup related stuff.
  */
 
-/*
- * Initilize card.
- */
 static int __init gemtek_init(void)
 {
-	printk(KERN_INFO RADIO_BANNER "\n");
+	struct gemtek *gt = &gemtek_card;
+	struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
+	int res;
 
-	spin_lock_init(&lock);
+	strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name));
 
-	gemtek_probe();
-	if (io) {
-		if (!request_region(io, 1, "gemtek")) {
-			printk(KERN_ERR "I/O port 0x%x already in use.\n", io);
+	v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n");
+
+	mutex_init(&gt->lock);
+
+	gt->verified = -1;
+	gt->io = io;
+	gemtek_probe(gt);
+	if (gt->io) {
+		if (!request_region(gt->io, 1, "gemtek")) {
+			v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io);
 			return -EBUSY;
 		}
 
-		if (!gemtek_verify(io))
-			printk(KERN_WARNING "Card at I/O port 0x%x does not "
+		if (!gemtek_verify(gt, gt->io))
+			v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not "
 			       "respond properly, check your "
-			       "configuration.\n", io);
+			       "configuration.\n", gt->io);
 		else
-			printk(KERN_INFO "Using I/O port 0x%x.\n", io);
+			v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io);
 	} else if (probe) {
-		printk(KERN_ERR "Automatic probing failed and no "
+		v4l2_err(v4l2_dev, "Automatic probing failed and no "
 		       "fixed I/O port defined.\n");
 		return -ENODEV;
 	} else {
-		printk(KERN_ERR "Automatic probing disabled but no fixed "
+		v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed "
 		       "I/O port defined.");
 		return -EINVAL;
 	}
 
-	video_set_drvdata(&gemtek_radio, &gemtek_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		release_region(gt->io, 1);
+		return res;
+	}
 
-	if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 1);
+	strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name));
+	gt->vdev.v4l2_dev = v4l2_dev;
+	gt->vdev.fops = &gemtek_fops;
+	gt->vdev.ioctl_ops = &gemtek_ioctl_ops;
+	gt->vdev.release = video_device_release_empty;
+	video_set_drvdata(&gt->vdev, gt);
+
+	if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(gt->io, 1);
 		return -EBUSY;
 	}
 
 	/* Set defaults */
-	gemtek_unit.lastfreq = GEMTEK_LOWFREQ;
-	gemtek_unit.bu2614data = 0;
+	gt->lastfreq = GEMTEK_LOWFREQ;
+	gt->bu2614data = 0;
 
 	if (initmute)
-		gemtek_mute(&gemtek_unit);
+		gemtek_mute(gt);
 
 	return 0;
 }
@@ -637,15 +609,19 @@
  */
 static void __exit gemtek_exit(void)
 {
+	struct gemtek *gt = &gemtek_card;
+	struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
+
 	if (shutdown) {
 		hardmute = 1;	/* Turn off PLL */
-		gemtek_mute(&gemtek_unit);
+		gemtek_mute(gt);
 	} else {
-		printk(KERN_INFO "Module unloaded but card not muted!\n");
+		v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n");
 	}
 
-	video_unregister_device(&gemtek_radio);
-	release_region(io, 1);
+	video_unregister_device(&gt->vdev);
+	v4l2_device_unregister(&gt->v4l2_dev);
+	release_region(gt->io, 1);
 }
 
 module_init(gemtek_init);
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index ba3a13a..01a6d22 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -22,27 +22,22 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/pci.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <linux/io.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,6)
-#define DRIVER_VERSION	"0.06"
+MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
+MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
+MODULE_LICENSE("GPL");
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}
-};
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 6)
+#define DRIVER_VERSION	"0.06"
 
 #define GPIO_DATA	0x60   /* port offset from ESS_IO_BASE */
 
@@ -72,62 +67,27 @@
 
 #define BITS2FREQ(x)	((x) * FREQ_STEP - FREQ_IF)
 
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
+struct maestro {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct pci_dev *pdev;
+	struct mutex lock;
 
-static unsigned long in_use;
+	u16	io;	/* base of Maestro card radio io (GPIO_DATA)*/
+	u16	muted;	/* VIDEO_AUDIO_MUTE */
+	u16	stereo;	/* VIDEO_TUNER_STEREO_ON */
+	u16	tuned;	/* signal strength (0 or 0xffff) */
+};
 
-static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-static int maestro_exclusive_open(struct file *file)
+static inline struct maestro *to_maestro(struct v4l2_device *v4l2_dev)
 {
-	return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+	return container_of(v4l2_dev, struct maestro, v4l2_dev);
 }
 
-static int maestro_exclusive_release(struct file *file)
+static u32 radio_bits_get(struct maestro *dev)
 {
-	clear_bit(0, &in_use);
-	return 0;
-}
-
-static void maestro_remove(struct pci_dev *pdev);
-
-static struct pci_device_id maestro_r_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
-		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
-		.class_mask = 0xffff00 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
-		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
-		.class_mask = 0xffff00 },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
-
-static struct pci_driver maestro_r_driver = {
-	.name		= "maestro_radio",
-	.id_table	= maestro_r_pci_tbl,
-	.probe		= maestro_probe,
-	.remove		= __devexit_p(maestro_remove),
-};
-
-static const struct v4l2_file_operations maestro_fops = {
-	.owner		= THIS_MODULE,
-	.open           = maestro_exclusive_open,
-	.release        = maestro_exclusive_release,
-	.ioctl		= video_ioctl2,
-};
-
-struct radio_device {
-	u16	io,	/* base of Maestro card radio io (GPIO_DATA)*/
-		muted,	/* VIDEO_AUDIO_MUTE */
-		stereo,	/* VIDEO_TUNER_STEREO_ON */
-		tuned;	/* signal strength (0 or 0xffff) */
-};
-
-static u32 radio_bits_get(struct radio_device *dev)
-{
-	register u16 io=dev->io, l, rdata;
-	register u32 data=0;
+	u16 io = dev->io, l, rdata;
+	u32 data = 0;
 	u16 omask;
 
 	omask = inw(io + IO_MASK);
@@ -135,25 +95,23 @@
 	outw(0, io);
 	udelay(16);
 
-	for (l=24;l--;) {
+	for (l = 24; l--;) {
 		outw(STR_CLK, io);		/* HI state */
 		udelay(2);
-		if(!l)
+		if (!l)
 			dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
 		outw(0, io);			/* LO state */
 		udelay(2);
 		data <<= 1;			/* shift data */
 		rdata = inw(io);
-		if(!l)
-			dev->stereo =  rdata & STR_MOST ?
-			0 : 1;
-		else
-			if(rdata & STR_DATA)
-				data++;
+		if (!l)
+			dev->stereo = (rdata & STR_MOST) ?  0 : 1;
+		else if (rdata & STR_DATA)
+			data++;
 		udelay(2);
 	}
 
-	if(dev->muted)
+	if (dev->muted)
 		outw(STR_WREN, io);
 
 	udelay(4);
@@ -162,18 +120,18 @@
 	return data & 0x3ffe;
 }
 
-static void radio_bits_set(struct radio_device *dev, u32 data)
+static void radio_bits_set(struct maestro *dev, u32 data)
 {
-	register u16 io=dev->io, l, bits;
+	u16 io = dev->io, l, bits;
 	u16 omask, odir;
 
 	omask = inw(io + IO_MASK);
-	odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
+	odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
 	outw(odir | STR_DATA, io + IO_DIR);
 	outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
 	udelay(16);
-	for (l=25;l;l--) {
-		bits = ((data >> 18) & STR_DATA) | STR_WREN ;
+	for (l = 25; l; l--) {
+		bits = ((data >> 18) & STR_DATA) | STR_WREN;
 		data <<= 1;			/* shift data */
 		outw(bits, io);			/* start strobe */
 		udelay(2);
@@ -183,7 +141,7 @@
 		udelay(4);
 	}
 
-	if(!dev->muted)
+	if (!dev->muted)
 		outw(0, io);
 
 	udelay(4);
@@ -195,78 +153,79 @@
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *v)
 {
+	struct maestro *dev = video_drvdata(file);
+
 	strlcpy(v->driver, "radio-maestro", sizeof(v->driver));
 	strlcpy(v->card, "Maestro Radio", sizeof(v->card));
-	sprintf(v->bus_info, "PCI");
+	snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maestro *dev = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	(void)radio_bits_get(card);
+	mutex_lock(&dev->lock);
+	radio_bits_get(dev);
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 	v->rangelow = FREQ_LO;
 	v->rangehigh = FREQ_HI;
-	v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 	v->capability = V4L2_TUNER_CAP_LOW;
-	if(card->stereo)
+	if (dev->stereo)
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 	else
 		v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = card->tuned;
+	v->signal = dev->tuned;
+	mutex_unlock(&dev->lock);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maestro *dev = video_drvdata(file);
 
 	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
 		return -EINVAL;
-	radio_bits_set(card, FREQ2BITS(f->frequency));
+	mutex_lock(&dev->lock);
+	radio_bits_set(dev, FREQ2BITS(f->frequency));
+	mutex_unlock(&dev->lock);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maestro *dev = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
-	f->frequency = BITS2FREQ(radio_bits_get(card));
+	mutex_lock(&dev->lock);
+	f->frequency = BITS2FREQ(radio_bits_get(dev));
+	mutex_unlock(&dev->lock);
 	return 0;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
 	}
 	return -EINVAL;
 }
@@ -274,11 +233,11 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maestro *dev = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = card->muted;
+		ctrl->value = dev->muted;
 		return 0;
 	}
 	return -EINVAL;
@@ -287,34 +246,26 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct radio_device *card = video_drvdata(file);
-	register u16 io = card->io;
-	register u16 omask = inw(io + IO_MASK);
+	struct maestro *dev = video_drvdata(file);
+	u16 io = dev->io;
+	u16 omask;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
+		mutex_lock(&dev->lock);
+		omask = inw(io + IO_MASK);
 		outw(~STR_WREN, io + IO_MASK);
-		outw((card->muted = ctrl->value ) ?
-				STR_WREN : 0, io);
+		dev->muted = ctrl->value;
+		outw(dev->muted ? STR_WREN : 0, io);
 		udelay(4);
 		outw(omask, io + IO_MASK);
 		msleep(125);
+		mutex_unlock(&dev->lock);
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -323,20 +274,57 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int maestro_open(struct file *file)
+{
 	return 0;
 }
 
-static u16 __devinit radio_power_on(struct radio_device *dev)
+static int maestro_release(struct file *file)
+{
+	return 0;
+}
+
+static const struct v4l2_file_operations maestro_fops = {
+	.owner		= THIS_MODULE,
+	.open           = maestro_open,
+	.release        = maestro_release,
+	.ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+};
+
+static u16 __devinit radio_power_on(struct maestro *dev)
 {
 	register u16 io = dev->io;
 	register u32 ofreq;
@@ -360,33 +348,11 @@
 	return (ofreq == radio_bits_get(dev));
 }
 
-static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
-	.vidioc_querycap    = vidioc_querycap,
-	.vidioc_g_tuner     = vidioc_g_tuner,
-	.vidioc_s_tuner     = vidioc_s_tuner,
-	.vidioc_g_audio     = vidioc_g_audio,
-	.vidioc_s_audio     = vidioc_s_audio,
-	.vidioc_g_input     = vidioc_g_input,
-	.vidioc_s_input     = vidioc_s_input,
-	.vidioc_g_frequency = vidioc_g_frequency,
-	.vidioc_s_frequency = vidioc_s_frequency,
-	.vidioc_queryctrl   = vidioc_queryctrl,
-	.vidioc_g_ctrl      = vidioc_g_ctrl,
-	.vidioc_s_ctrl      = vidioc_s_ctrl,
-};
-
-static struct video_device maestro_radio = {
-	.name           = "Maestro radio",
-	.fops           = &maestro_fops,
-	.ioctl_ops 	= &maestro_ioctl_ops,
-	.release	= video_device_release,
-};
-
 static int __devinit maestro_probe(struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
-	struct radio_device *radio_unit;
-	struct video_device *maestro_radio_inst;
+	struct maestro *dev;
+	struct v4l2_device *v4l2_dev;
 	int retval;
 
 	retval = pci_enable_device(pdev);
@@ -397,46 +363,53 @@
 
 	retval = -ENOMEM;
 
-	radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL);
-	if (radio_unit == NULL) {
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
 		dev_err(&pdev->dev, "not enough memory\n");
 		goto err;
 	}
 
-	radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
+	v4l2_dev = &dev->v4l2_dev;
+	mutex_init(&dev->lock);
+	dev->pdev = pdev;
 
-	maestro_radio_inst = video_device_alloc();
-	if (maestro_radio_inst == NULL) {
-		dev_err(&pdev->dev, "not enough memory\n");
+	strlcpy(v4l2_dev->name, "maestro", sizeof(v4l2_dev->name));
+
+	retval = v4l2_device_register(&pdev->dev, v4l2_dev);
+	if (retval < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
 		goto errfr;
 	}
 
-	memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio));
-	video_set_drvdata(maestro_radio_inst, radio_unit);
-	pci_set_drvdata(pdev, maestro_radio_inst);
+	dev->io = pci_resource_start(pdev, 0) + GPIO_DATA;
 
-	retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr);
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.fops = &maestro_fops;
+	dev->vdev.ioctl_ops = &maestro_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	video_set_drvdata(&dev->vdev, dev);
+
+	retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
 	if (retval) {
-		printk(KERN_ERR "can't register video device!\n");
+		v4l2_err(v4l2_dev, "can't register video device!\n");
 		goto errfr1;
 	}
 
-	if (!radio_power_on(radio_unit)) {
+	if (!radio_power_on(dev)) {
 		retval = -EIO;
 		goto errunr;
 	}
 
-	dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ "  "
-		 __DATE__ "\n");
-	dev_info(&pdev->dev, "radio chip initialized\n");
+	v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
 
 	return 0;
 errunr:
-	video_unregister_device(maestro_radio_inst);
+	video_unregister_device(&dev->vdev);
 errfr1:
-	video_device_release(maestro_radio_inst);
+	v4l2_device_unregister(v4l2_dev);
 errfr:
-	kfree(radio_unit);
+	kfree(dev);
 err:
 	return retval;
 
@@ -444,11 +417,31 @@
 
 static void __devexit maestro_remove(struct pci_dev *pdev)
 {
-	struct video_device *vdev = pci_get_drvdata(pdev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct maestro *dev = to_maestro(v4l2_dev);
 
-	video_unregister_device(vdev);
+	video_unregister_device(&dev->vdev);
+	v4l2_device_unregister(&dev->v4l2_dev);
 }
 
+static struct pci_device_id maestro_r_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
+		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+		.class_mask = 0xffff00 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
+		.class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+		.class_mask = 0xffff00 },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
+
+static struct pci_driver maestro_r_driver = {
+	.name		= "maestro_radio",
+	.id_table	= maestro_r_pci_tbl,
+	.probe		= maestro_probe,
+	.remove		= __devexit_p(maestro_remove),
+};
+
 static int __init maestro_radio_init(void)
 {
 	int retval = pci_register_driver(&maestro_r_driver);
@@ -466,7 +459,3 @@
 
 module_init(maestro_radio_init);
 module_exit(maestro_radio_exit);
-
-MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
-MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index c5dc00a..2606f0b 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -37,38 +37,32 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 #include <linux/mutex.h>
-
 #include <linux/pci.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#include <linux/io.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
+MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
+MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
+MODULE_LICENSE("GPL");
+
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
 #define DRIVER_VERSION	"0.77"
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,7,7)
+#define RADIO_VERSION KERNEL_VERSION(0, 7, 7)
 
-static struct video_device maxiradio_radio;
-
-#define dprintk(num, fmt, arg...)                                          \
-	do {                                                               \
-		if (maxiradio_radio.debug >= num)                          \
-			printk(KERN_DEBUG "%s: " fmt,                      \
-				maxiradio_radio.name, ## arg); } while (0)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}
-};
+#define dprintk(dev, num, fmt, arg...) \
+	v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg)
 
 #ifndef PCI_VENDOR_ID_GUILLEMOT
 #define PCI_VENDOR_ID_GUILLEMOT 0x5046
@@ -80,90 +74,70 @@
 
 
 /* TEA5757 pin mappings */
-static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ;
+static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
 
-static int radio_nr = -1;
-module_param(radio_nr, int, 0);
-
-static unsigned long in_use;
-
-#define FREQ_LO		 50*16000
-#define FREQ_HI		150*16000
+#define FREQ_LO		(50 * 16000)
+#define FREQ_HI		(150 * 16000)
 
 #define FREQ_IF         171200 /* 10.7*16000   */
 #define FREQ_STEP       200    /* 12.5*16      */
 
 /* (x==fmhz*16*1000) -> bits */
-#define FREQ2BITS(x)	((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \
-			/(FREQ_STEP<<2))<<2)
+#define FREQ2BITS(x) \
+  ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2)
 
 #define BITS2FREQ(x)	((x) * FREQ_STEP - FREQ_IF)
 
 
-static int maxiradio_exclusive_open(struct file *file)
+struct maxiradio
 {
-	return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
-}
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct pci_dev *pdev;
 
-static int maxiradio_exclusive_release(struct file *file)
-{
-	clear_bit(0, &in_use);
-	return 0;
-}
-
-static const struct v4l2_file_operations maxiradio_fops = {
-	.owner		= THIS_MODULE,
-	.open           = maxiradio_exclusive_open,
-	.release        = maxiradio_exclusive_release,
-	.ioctl          = video_ioctl2,
-};
-
-static struct radio_device
-{
-	__u16	io,	/* base of radio io */
-		muted,	/* VIDEO_AUDIO_MUTE */
-		stereo,	/* VIDEO_TUNER_STEREO_ON */
-		tuned;	/* signal strength (0 or 0xffff) */
+	u16	io;	/* base of radio io */
+	u16	muted;	/* VIDEO_AUDIO_MUTE */
+	u16	stereo;	/* VIDEO_TUNER_STEREO_ON */
+	u16	tuned;	/* signal strength (0 or 0xffff) */
 
 	unsigned long freq;
 
 	struct mutex lock;
-} radio_unit = {
-	.muted =1,
-	.freq = FREQ_LO,
 };
 
-static void outbit(unsigned long bit, __u16 io)
+static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev)
 {
-	if (bit != 0)
-		{
-			outb(  power|wren|data     ,io); udelay(4);
-			outb(  power|wren|data|clk ,io); udelay(4);
-			outb(  power|wren|data     ,io); udelay(4);
-		}
-	else
-		{
-			outb(  power|wren          ,io); udelay(4);
-			outb(  power|wren|clk      ,io); udelay(4);
-			outb(  power|wren          ,io); udelay(4);
-		}
+	return container_of(v4l2_dev, struct maxiradio, v4l2_dev);
 }
 
-static void turn_power(__u16 io, int p)
+static void outbit(unsigned long bit, u16 io)
+{
+	int val = power | wren | (bit ? data : 0);
+
+	outb(val, io);
+	udelay(4);
+	outb(val | clk, io);
+	udelay(4);
+	outb(val, io);
+	udelay(4);
+}
+
+static void turn_power(struct maxiradio *dev, int p)
 {
 	if (p != 0) {
-		dprintk(1, "Radio powered on\n");
-		outb(power, io);
+		dprintk(dev, 1, "Radio powered on\n");
+		outb(power, dev->io);
 	} else {
-		dprintk(1, "Radio powered off\n");
-		outb(0,io);
+		dprintk(dev, 1, "Radio powered off\n");
+		outb(0, dev->io);
 	}
 }
 
-static void set_freq(__u16 io, __u32 freq)
+static void set_freq(struct maxiradio *dev, u32 freq)
 {
 	unsigned long int si;
 	int bl;
+	int io = dev->io;
 	int val = FREQ2BITS(freq);
 
 	/* TEA5757 shift register bits (see pdf) */
@@ -188,14 +162,14 @@
 		si >>= 1;
 	}
 
-	dprintk(1, "Radio freq set to %d.%02d MHz\n",
+	dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n",
 				freq / 16000,
 				freq % 16000 * 100 / 16000);
 
-	turn_power(io, 1);
+	turn_power(dev, 1);
 }
 
-static int get_stereo(__u16 io)
+static int get_stereo(u16 io)
 {
 	outb(power,io);
 	udelay(4);
@@ -203,7 +177,7 @@
 	return !(inb(io) & mo_st);
 }
 
-static int get_tune(__u16 io)
+static int get_tune(u16 io)
 {
 	outb(power+clk,io);
 	udelay(4);
@@ -212,95 +186,84 @@
 }
 
 
-static int vidioc_querycap (struct file *file, void  *priv,
+static int vidioc_querycap(struct file *file, void  *priv,
 			    struct v4l2_capability *v)
 {
-	strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver));
-	strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card));
-	sprintf(v->bus_info,"ISA");
-	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	struct maxiradio *dev = video_drvdata(file);
 
+	strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver));
+	strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card));
+	snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev));
+	v->version = RADIO_VERSION;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
-static int vidioc_g_tuner (struct file *file, void *priv,
+static int vidioc_g_tuner(struct file *file, void *priv,
 			   struct v4l2_tuner *v)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maxiradio *dev = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	memset(v,0,sizeof(*v));
-	strcpy(v->name, "FM");
+	mutex_lock(&dev->lock);
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-
-	v->rangelow=FREQ_LO;
-	v->rangehigh=FREQ_HI;
-	v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-	v->capability=V4L2_TUNER_CAP_LOW;
-	if(get_stereo(card->io))
+	v->rangelow = FREQ_LO;
+	v->rangehigh = FREQ_HI;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+	v->capability = V4L2_TUNER_CAP_LOW;
+	if (get_stereo(dev->io))
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 	else
 		v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal=0xffff*get_tune(card->io);
+	v->signal = 0xffff * get_tune(dev->io);
+	mutex_unlock(&dev->lock);
 
 	return 0;
 }
 
-static int vidioc_s_tuner (struct file *file, void *priv,
+static int vidioc_s_tuner(struct file *file, void *priv,
 			   struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int vidioc_g_audio (struct file *file, void *priv,
-			   struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "FM");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
-
 	return 0;
 }
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
-
-	return 0;
+	return i ? -EINVAL : 0;
 }
 
-
-static int vidioc_s_audio (struct file *file, void *priv,
+static int vidioc_g_audio(struct file *file, void *priv,
 			   struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
-
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
-static int vidioc_s_frequency (struct file *file, void *priv,
+
+static int vidioc_s_audio(struct file *file, void *priv,
+			   struct v4l2_audio *a)
+{
+	return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
 			       struct v4l2_frequency *f)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maxiradio *dev = video_drvdata(file);
 
 	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
-		dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
+		dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
 					f->frequency / 16000,
 					f->frequency % 16000 * 100 / 16000,
 					FREQ_LO / 16000, FREQ_HI / 16000);
@@ -308,75 +271,91 @@
 		return -EINVAL;
 	}
 
-	card->freq = f->frequency;
-	set_freq(card->io, card->freq);
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+	set_freq(dev, dev->freq);
 	msleep(125);
+	mutex_unlock(&dev->lock);
 
 	return 0;
 }
 
-static int vidioc_g_frequency (struct file *file, void *priv,
+static int vidioc_g_frequency(struct file *file, void *priv,
 			       struct v4l2_frequency *f)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maxiradio *dev = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
-	f->frequency = card->freq;
+	f->frequency = dev->freq;
 
-	dprintk(4, "radio freq is %d.%02d MHz",
+	dprintk(dev, 4, "radio freq is %d.%02d MHz",
 				f->frequency / 16000,
 				f->frequency % 16000 * 100 / 16000);
 
 	return 0;
 }
 
-static int vidioc_queryctrl (struct file *file, void *priv,
+static int vidioc_queryctrl(struct file *file, void *priv,
 			     struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
-			return (0);
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
 	}
-
 	return -EINVAL;
 }
 
-static int vidioc_g_ctrl (struct file *file, void *priv,
-			    struct v4l2_control *ctrl)
+static int vidioc_g_ctrl(struct file *file, void *priv,
+		struct v4l2_control *ctrl)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maxiradio *dev = video_drvdata(file);
 
 	switch (ctrl->id) {
-		case V4L2_CID_AUDIO_MUTE:
-			ctrl->value=card->muted;
-			return (0);
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value = dev->muted;
+		return 0;
 	}
 
 	return -EINVAL;
 }
 
-static int vidioc_s_ctrl (struct file *file, void *priv,
-			  struct v4l2_control *ctrl)
+static int vidioc_s_ctrl(struct file *file, void *priv,
+		struct v4l2_control *ctrl)
 {
-	struct radio_device *card = video_drvdata(file);
+	struct maxiradio *dev = video_drvdata(file);
 
 	switch (ctrl->id) {
-		case V4L2_CID_AUDIO_MUTE:
-			card->muted = ctrl->value;
-			if(card->muted)
-				turn_power(card->io, 0);
-			else
-				set_freq(card->io, card->freq);
-			return 0;
+	case V4L2_CID_AUDIO_MUTE:
+		mutex_lock(&dev->lock);
+		dev->muted = ctrl->value;
+		if (dev->muted)
+			turn_power(dev, 0);
+		else
+			set_freq(dev, dev->freq);
+		mutex_unlock(&dev->lock);
+		return 0;
 	}
 
 	return -EINVAL;
 }
 
+static int maxiradio_open(struct file *file)
+{
+	return 0;
+}
+
+static int maxiradio_release(struct file *file)
+{
+	return 0;
+}
+
+static const struct v4l2_file_operations maxiradio_fops = {
+	.owner		= THIS_MODULE,
+	.open           = maxiradio_open,
+	.release        = maxiradio_release,
+	.ioctl          = video_ioctl2,
+};
+
 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
 	.vidioc_querycap    = vidioc_querycap,
 	.vidioc_g_tuner     = vidioc_g_tuner,
@@ -392,60 +371,84 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device maxiradio_radio = {
-	.name		= "Maxi Radio FM2000 radio",
-	.fops           = &maxiradio_fops,
-	.ioctl_ops 	= &maxiradio_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	if(!request_region(pci_resource_start(pdev, 0),
+	struct maxiradio *dev;
+	struct v4l2_device *v4l2_dev;
+	int retval = -ENOMEM;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&pdev->dev, "not enough memory\n");
+		return -ENOMEM;
+	}
+
+	v4l2_dev = &dev->v4l2_dev;
+	mutex_init(&dev->lock);
+	dev->pdev = pdev;
+	dev->muted = 1;
+	dev->freq = FREQ_LO;
+
+	strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name));
+
+	retval = v4l2_device_register(&pdev->dev, v4l2_dev);
+	if (retval < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		goto errfr;
+	}
+
+	if (!request_region(pci_resource_start(pdev, 0),
 			   pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
-		printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
+		v4l2_err(v4l2_dev, "can't reserve I/O ports\n");
 		goto err_out;
 	}
 
 	if (pci_enable_device(pdev))
 		goto err_out_free_region;
 
-	radio_unit.io = pci_resource_start(pdev, 0);
-	mutex_init(&radio_unit.lock);
-	video_set_drvdata(&maxiradio_radio, &radio_unit);
+	dev->io = pci_resource_start(pdev, 0);
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.fops = &maxiradio_fops;
+	dev->vdev.ioctl_ops = &maxiradio_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	video_set_drvdata(&dev->vdev, dev);
 
-	if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		printk("radio-maxiradio: can't register device!");
+	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_err(v4l2_dev, "can't register device!");
 		goto err_out_free_region;
 	}
 
-	printk(KERN_INFO "radio-maxiradio: version "
-	       DRIVER_VERSION
-	       " time "
-	       __TIME__ "  "
-	       __DATE__
-	       "\n");
+	v4l2_info(v4l2_dev, "version " DRIVER_VERSION
+			" time " __TIME__ "  " __DATE__ "\n");
 
-	printk(KERN_INFO "radio-maxiradio: found Guillemot MAXI Radio device (io = 0x%x)\n",
-	       radio_unit.io);
+	v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n",
+	       dev->io);
 	return 0;
 
 err_out_free_region:
 	release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
 err_out:
+	v4l2_device_unregister(v4l2_dev);
+errfr:
+	kfree(dev);
 	return -ENODEV;
 }
 
 static void __devexit maxiradio_remove_one(struct pci_dev *pdev)
 {
-	video_unregister_device(&maxiradio_radio);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct maxiradio *dev = to_maxiradio(v4l2_dev);
+
+	video_unregister_device(&dev->vdev);
+	v4l2_device_unregister(&dev->v4l2_dev);
 	release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
 }
 
 static struct pci_device_id maxiradio_pci_tbl[] = {
 	{ PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO,
 		PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0,}
+	{ 0 }
 };
 
 MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl);
@@ -469,10 +472,3 @@
 
 module_init(maxiradio_radio_init);
 module_exit(maxiradio_radio_exit);
-
-MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
-MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio.");
-MODULE_LICENSE("GPL");
-
-module_param_named(debug,maxiradio_radio.debug, int, 0644);
-MODULE_PARM_DESC(debug,"activates debug info");
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index fdfc7bf..ded25bf 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -22,7 +22,7 @@
  */
 
 /*
- * Big thanks to authors of dsbr100.c and radio-si470x.c
+ * Big thanks to authors and contributors of dsbr100.c and radio-si470x.c
  *
  * When work was looked pretty good, i discover this:
  * http://av-usbradio.sourceforge.net/index.php
@@ -30,18 +30,23 @@
  * Latest release of theirs project was in 2005.
  * Probably, this driver could be improved trough using their
  * achievements (specifications given).
- * So, we have smth to begin with.
+ * Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
+ * in 2007. He allowed to use his driver to improve current mr800 radio driver.
+ * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
  *
- * History:
  * Version 0.01:	First working version.
  * 			It's required to blacklist AverMedia USB Radio
  * 			in usbhid/hid-quirks.c
+ * Version 0.10:	A lot of cleanups and fixes: unpluging the device,
+ * 			few mutex locks were added, codinstyle issues, etc.
+ * 			Added stereo support. Thanks to
+ * 			Douglas Schilling Landgraf <dougsland@gmail.com> and
+ * 			David Ellingsworth <david@identd.dyndns.org>
+ * 			for discussion, help and support.
  *
  * Many things to do:
  * 	- Correct power managment of device (suspend & resume)
- * 	- Make x86 independance (little-endian and big-endian stuff)
  * 	- Add code for scanning and smooth tuning
- * 	- Checked and add stereo&mono stuff
  * 	- Add code for sensitivity value
  * 	- Correct mistakes
  * 	- In Japan another FREQ_MIN and FREQ_MAX
@@ -62,8 +67,8 @@
 /* driver and module definitions */
 #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
 #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
-#define DRIVER_VERSION "0.01"
-#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+#define DRIVER_VERSION "0.10"
+#define RADIO_VERSION KERNEL_VERSION(0, 1, 0)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -87,6 +92,22 @@
 #define FREQ_MAX 108.0
 #define FREQ_MUL 16000
 
+/*
+ * Commands that device should understand
+ * List isnt full and will be updated with implementation of new functions
+ */
+#define AMRADIO_SET_FREQ	0xa4
+#define AMRADIO_SET_MUTE	0xab
+#define AMRADIO_SET_MONO	0xae
+
+/* Comfortable defines for amradio_set_mute */
+#define AMRADIO_START		0x00
+#define AMRADIO_STOP		0x01
+
+/* Comfortable defines for amradio_set_stereo */
+#define WANT_STEREO		0x00
+#define WANT_MONO		0x01
+
 /* module parameter */
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
@@ -169,40 +190,8 @@
 	.supports_autosuspend	= 0,
 };
 
-/* switch on radio. Send 8 bytes to device. */
-static int amradio_start(struct amradio_device *radio)
-{
-	int retval;
-	int size;
-
-	mutex_lock(&radio->lock);
-
-	radio->buffer[0] = 0x00;
-	radio->buffer[1] = 0x55;
-	radio->buffer[2] = 0xaa;
-	radio->buffer[3] = 0x00;
-	radio->buffer[4] = 0xab;
-	radio->buffer[5] = 0x00;
-	radio->buffer[6] = 0x00;
-	radio->buffer[7] = 0x00;
-
-	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
-		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
-
-	if (retval) {
-		mutex_unlock(&radio->lock);
-		return retval;
-	}
-
-	radio->muted = 0;
-
-	mutex_unlock(&radio->lock);
-
-	return retval;
-}
-
-/* switch off radio */
-static int amradio_stop(struct amradio_device *radio)
+/* switch on/off the radio. Send 8 bytes to device */
+static int amradio_set_mute(struct amradio_device *radio, char argument)
 {
 	int retval;
 	int size;
@@ -217,20 +206,20 @@
 	radio->buffer[1] = 0x55;
 	radio->buffer[2] = 0xaa;
 	radio->buffer[3] = 0x00;
-	radio->buffer[4] = 0xab;
-	radio->buffer[5] = 0x01;
+	radio->buffer[4] = AMRADIO_SET_MUTE;
+	radio->buffer[5] = argument;
 	radio->buffer[6] = 0x00;
 	radio->buffer[7] = 0x00;
 
 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 
-	if (retval) {
+	if (retval < 0 || size != BUFFER_LENGTH) {
 		mutex_unlock(&radio->lock);
 		return retval;
 	}
 
-	radio->muted = 1;
+	radio->muted = argument;
 
 	mutex_unlock(&radio->lock);
 
@@ -242,7 +231,7 @@
 {
 	int retval;
 	int size;
-	unsigned short freq_send = 0x13 + (freq >> 3) / 25;
+	unsigned short freq_send = 0x10 + (freq >> 3) / 25;
 
 	/* safety check */
 	if (radio->removed)
@@ -254,7 +243,7 @@
 	radio->buffer[1] = 0x55;
 	radio->buffer[2] = 0xaa;
 	radio->buffer[3] = 0x03;
-	radio->buffer[4] = 0xa4;
+	radio->buffer[4] = AMRADIO_SET_FREQ;
 	radio->buffer[5] = 0x00;
 	radio->buffer[6] = 0x00;
 	radio->buffer[7] = 0x08;
@@ -262,7 +251,7 @@
 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 
-	if (retval) {
+	if (retval < 0 || size != BUFFER_LENGTH) {
 		mutex_unlock(&radio->lock);
 		return retval;
 	}
@@ -279,24 +268,57 @@
 	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
 		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
 
-	if (retval) {
+	if (retval < 0 || size != BUFFER_LENGTH) {
 		mutex_unlock(&radio->lock);
 		return retval;
 	}
 
-	radio->stereo = 0;
-
 	mutex_unlock(&radio->lock);
 
 	return retval;
 }
 
-/* USB subsystem interface begins here */
+static int amradio_set_stereo(struct amradio_device *radio, char argument)
+{
+	int retval;
+	int size;
 
-/* handle unplugging of the device, release data structures
-if nothing keeps us from doing it.  If something is still
-keeping us busy, the release callback of v4l will take care
-of releasing it. */
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
+	mutex_lock(&radio->lock);
+
+	radio->buffer[0] = 0x00;
+	radio->buffer[1] = 0x55;
+	radio->buffer[2] = 0xaa;
+	radio->buffer[3] = 0x00;
+	radio->buffer[4] = AMRADIO_SET_MONO;
+	radio->buffer[5] = argument;
+	radio->buffer[6] = 0x00;
+	radio->buffer[7] = 0x00;
+
+	retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+		(void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+	if (retval < 0 || size != BUFFER_LENGTH) {
+		radio->stereo = -1;
+		mutex_unlock(&radio->lock);
+		return retval;
+	}
+
+	radio->stereo = 1;
+
+	mutex_unlock(&radio->lock);
+
+	return retval;
+}
+
+/* Handle unplugging the device.
+ * We call video_unregister_device in any case.
+ * The last function called in this procedure is
+ * usb_amradio_device_release.
+ */
 static void usb_amradio_disconnect(struct usb_interface *intf)
 {
 	struct amradio_device *radio = usb_get_intfdata(intf);
@@ -313,9 +335,11 @@
 static int vidioc_querycap(struct file *file, void *priv,
 					struct v4l2_capability *v)
 {
+	struct amradio_device *radio = video_drvdata(file);
+
 	strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
 	strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
-	sprintf(v->bus_info, "USB");
+	usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
 	v->capabilities = V4L2_CAP_TUNER;
 	return 0;
@@ -326,6 +350,7 @@
 				struct v4l2_tuner *v)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	/* safety check */
 	if (radio->removed)
@@ -337,7 +362,16 @@
 /* TODO: Add function which look is signal stereo or not
  * 	amradio_getstat(radio);
  */
-	radio->stereo = -1;
+
+/* we call amradio_set_stereo to set radio->stereo
+ * Honestly, amradio_getstat should cover this in future and
+ * amradio_set_stereo shouldn't be here
+ */
+	retval = amradio_set_stereo(radio, WANT_STEREO);
+	if (retval < 0)
+		amradio_dev_warn(&radio->videodev->dev,
+			"set stereo failed\n");
+
 	strcpy(v->name, "FM");
 	v->type = V4L2_TUNER_RADIO;
 	v->rangelow = FREQ_MIN * FREQ_MUL;
@@ -358,6 +392,7 @@
 				struct v4l2_tuner *v)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	/* safety check */
 	if (radio->removed)
@@ -365,6 +400,25 @@
 
 	if (v->index > 0)
 		return -EINVAL;
+
+	/* mono/stereo selector */
+	switch (v->audmode) {
+	case V4L2_TUNER_MODE_MONO:
+		retval = amradio_set_stereo(radio, WANT_MONO);
+		if (retval < 0)
+			amradio_dev_warn(&radio->videodev->dev,
+				"set mono failed\n");
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		retval = amradio_set_stereo(radio, WANT_STEREO);
+		if (retval < 0)
+			amradio_dev_warn(&radio->videodev->dev,
+				"set stereo failed\n");
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -373,13 +427,18 @@
 				struct v4l2_frequency *f)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	/* safety check */
 	if (radio->removed)
 		return -EIO;
 
+	mutex_lock(&radio->lock);
 	radio->curfreq = f->frequency;
-	if (amradio_setfreq(radio, radio->curfreq) < 0)
+	mutex_unlock(&radio->lock);
+
+	retval = amradio_setfreq(radio, radio->curfreq);
+	if (retval < 0)
 		amradio_dev_warn(&radio->videodev->dev,
 			"set frequency failed\n");
 	return 0;
@@ -438,6 +497,7 @@
 				struct v4l2_control *ctrl)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	/* safety check */
 	if (radio->removed)
@@ -446,13 +506,15 @@
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value) {
-			if (amradio_stop(radio) < 0) {
+			retval = amradio_set_mute(radio, AMRADIO_STOP);
+			if (retval < 0) {
 				amradio_dev_warn(&radio->videodev->dev,
 					"amradio_stop failed\n");
 				return -1;
 			}
 		} else {
-			if (amradio_start(radio) < 0) {
+			retval = amradio_set_mute(radio, AMRADIO_START);
+			if (retval < 0) {
 				amradio_dev_warn(&radio->videodev->dev,
 					"amradio_start failed\n");
 				return -1;
@@ -503,20 +565,29 @@
 static int usb_amradio_open(struct file *file)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	lock_kernel();
 
 	radio->users = 1;
 	radio->muted = 1;
 
-	if (amradio_start(radio) < 0) {
+	retval = amradio_set_mute(radio, AMRADIO_START);
+	if (retval < 0) {
 		amradio_dev_warn(&radio->videodev->dev,
 			"radio did not start up properly\n");
 		radio->users = 0;
 		unlock_kernel();
 		return -EIO;
 	}
-	if (amradio_setfreq(radio, radio->curfreq) < 0)
+
+	retval = amradio_set_stereo(radio, WANT_STEREO);
+	if (retval < 0)
+		amradio_dev_warn(&radio->videodev->dev,
+			"set stereo failed\n");
+
+	retval = amradio_setfreq(radio, radio->curfreq);
+	if (retval < 0)
 		amradio_dev_warn(&radio->videodev->dev,
 			"set frequency failed\n");
 
@@ -533,10 +604,12 @@
 	if (!radio)
 		return -ENODEV;
 
+	mutex_lock(&radio->lock);
 	radio->users = 0;
+	mutex_unlock(&radio->lock);
 
 	if (!radio->removed) {
-		retval = amradio_stop(radio);
+		retval = amradio_set_mute(radio, AMRADIO_STOP);
 		if (retval < 0)
 			amradio_dev_warn(&radio->videodev->dev,
 				"amradio_stop failed\n");
@@ -549,8 +622,10 @@
 static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct amradio_device *radio = usb_get_intfdata(intf);
+	int retval;
 
-	if (amradio_stop(radio) < 0)
+	retval = amradio_set_mute(radio, AMRADIO_STOP);
+	if (retval < 0)
 		dev_warn(&intf->dev, "amradio_stop failed\n");
 
 	dev_info(&intf->dev, "going into suspend..\n");
@@ -562,8 +637,10 @@
 static int usb_amradio_resume(struct usb_interface *intf)
 {
 	struct amradio_device *radio = usb_get_intfdata(intf);
+	int retval;
 
-	if (amradio_start(radio) < 0)
+	retval = amradio_set_mute(radio, AMRADIO_START);
+	if (retval < 0)
 		dev_warn(&intf->dev, "amradio_start failed\n");
 
 	dev_info(&intf->dev, "coming out of suspend..\n");
@@ -614,28 +691,32 @@
 	.release	= usb_amradio_device_release,
 };
 
-/* check if the device is present and register with v4l and
-usb if it is */
+/* check if the device is present and register with v4l and usb if it is */
 static int usb_amradio_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
 	struct amradio_device *radio;
+	int retval;
 
 	radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
 
-	if (!(radio))
+	if (!radio) {
+		dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
 		return -ENOMEM;
+	}
 
 	radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 
-	if (!(radio->buffer)) {
+	if (!radio->buffer) {
+		dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
 		kfree(radio);
 		return -ENOMEM;
 	}
 
 	radio->videodev = video_device_alloc();
 
-	if (!(radio->videodev)) {
+	if (!radio->videodev) {
+		dev_err(&intf->dev, "video_device_alloc failed\n");
 		kfree(radio->buffer);
 		kfree(radio);
 		return -ENOMEM;
@@ -648,12 +729,14 @@
 	radio->users = 0;
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->curfreq = 95.16 * FREQ_MUL;
+	radio->stereo = -1;
 
 	mutex_init(&radio->lock);
 
 	video_set_drvdata(radio->videodev, radio);
-	if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
-		dev_warn(&intf->dev, "could not register video device\n");
+	retval = video_register_device(radio->videodev,	VFL_TYPE_RADIO,	radio_nr);
+	if (retval < 0) {
+		dev_err(&intf->dev, "could not register video device\n");
 		video_device_release(radio->videodev);
 		kfree(radio->buffer);
 		kfree(radio);
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 2587227..d1e6b01d 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -13,34 +13,16 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/spinlock.h>
-
+#include <linux/mutex.h>
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
+MODULE_AUTHOR("Ben Pfaff");
+MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
+MODULE_LICENSE("GPL");
 
 #ifndef CONFIG_RADIO_RTRACK2_PORT
 #define CONFIG_RADIO_RTRACK2_PORT -1
@@ -48,79 +30,88 @@
 
 static int io = CONFIG_RADIO_RTRACK2_PORT;
 static int radio_nr = -1;
-static spinlock_t lock;
 
-struct rt_device
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct rtrack2
 {
-	unsigned long in_use;
-	int port;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
 	unsigned long curfreq;
 	int muted;
+	struct mutex lock;
 };
 
+static struct rtrack2 rtrack2_card;
+
 
 /* local things */
 
-static void rt_mute(struct rt_device *dev)
+static void rt_mute(struct rtrack2 *dev)
 {
-	if(dev->muted)
+	if (dev->muted)
 		return;
-	spin_lock(&lock);
-	outb(1, io);
-	spin_unlock(&lock);
+	mutex_lock(&dev->lock);
+	outb(1, dev->io);
+	mutex_unlock(&dev->lock);
 	dev->muted = 1;
 }
 
-static void rt_unmute(struct rt_device *dev)
+static void rt_unmute(struct rtrack2 *dev)
 {
 	if(dev->muted == 0)
 		return;
-	spin_lock(&lock);
-	outb(0, io);
-	spin_unlock(&lock);
+	mutex_lock(&dev->lock);
+	outb(0, dev->io);
+	mutex_unlock(&dev->lock);
 	dev->muted = 0;
 }
 
-static void zero(void)
+static void zero(struct rtrack2 *dev)
 {
-	outb_p(1, io);
-	outb_p(3, io);
-	outb_p(1, io);
+	outb_p(1, dev->io);
+	outb_p(3, dev->io);
+	outb_p(1, dev->io);
 }
 
-static void one(void)
+static void one(struct rtrack2 *dev)
 {
-	outb_p(5, io);
-	outb_p(7, io);
-	outb_p(5, io);
+	outb_p(5, dev->io);
+	outb_p(7, dev->io);
+	outb_p(5, dev->io);
 }
 
-static int rt_setfreq(struct rt_device *dev, unsigned long freq)
+static int rt_setfreq(struct rtrack2 *dev, unsigned long freq)
 {
 	int i;
 
+	mutex_lock(&dev->lock);
+	dev->curfreq = freq;
 	freq = freq / 200 + 856;
 
-	spin_lock(&lock);
-
-	outb_p(0xc8, io);
-	outb_p(0xc9, io);
-	outb_p(0xc9, io);
+	outb_p(0xc8, dev->io);
+	outb_p(0xc9, dev->io);
+	outb_p(0xc9, dev->io);
 
 	for (i = 0; i < 10; i++)
-		zero ();
+		zero(dev);
 
 	for (i = 14; i >= 0; i--)
 		if (freq & (1 << i))
-			one ();
+			one(dev);
 		else
-			zero ();
+			zero(dev);
 
-	outb_p(0xc8, io);
+	outb_p(0xc8, dev->io);
 	if (!dev->muted)
-		outb_p(0, io);
+		outb_p(0, dev->io);
 
-	spin_unlock(&lock);
+	mutex_unlock(&dev->lock);
 	return 0;
 }
 
@@ -129,61 +120,61 @@
 {
 	strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver));
 	strlcpy(v->card, "RadioTrack II", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
-static int rt_getsigstr(struct rt_device *dev)
+static int rt_getsigstr(struct rtrack2 *dev)
 {
-	if (inb(io) & 2)	/* bit set = no signal present	*/
-		return 0;
-	return 1;		/* signal present		*/
+	int sig = 1;
+
+	mutex_lock(&dev->lock);
+	if (inb(dev->io) & 2)	/* bit set = no signal present	*/
+		sig = 0;
+	mutex_unlock(&dev->lock);
+	return sig;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack2 *rt = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (88*16000);
-	v->rangehigh = (108*16000);
+	v->rangelow = 88 * 16000;
+	v->rangehigh = 108 * 16000;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	v->capability = V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = 0xFFFF*rt_getsigstr(rt);
+	v->signal = 0xFFFF * rt_getsigstr(rt);
 	return 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack2 *rt = video_drvdata(file);
 
-	rt->curfreq = f->frequency;
-	rt_setfreq(rt, rt->curfreq);
+	rt_setfreq(rt, f->frequency);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack2 *rt = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = rt->curfreq;
@@ -193,14 +184,11 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 				struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535);
 	}
 	return -EINVAL;
 }
@@ -208,7 +196,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack2 *rt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -227,7 +215,7 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
-	struct rt_device *rt = video_drvdata(file);
+	struct rtrack2 *rt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -246,17 +234,6 @@
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-				struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -265,36 +242,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 				struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int rtrack2_open(struct file *file)
+{
 	return 0;
 }
 
-static struct rt_device rtrack2_unit;
-
-static int rtrack2_exclusive_open(struct file *file)
+static int rtrack2_release(struct file *file)
 {
-	return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
-}
-
-static int rtrack2_exclusive_release(struct file *file)
-{
-	clear_bit(0, &rtrack2_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations rtrack2_fops = {
 	.owner		= THIS_MODULE,
-	.open           = rtrack2_exclusive_open,
-	.release        = rtrack2_exclusive_release,
+	.open           = rtrack2_open,
+	.release        = rtrack2_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -313,62 +292,61 @@
 	.vidioc_s_input     = vidioc_s_input,
 };
 
-static struct video_device rtrack2_radio = {
-	.name		= "RadioTrack II radio",
-	.fops           = &rtrack2_fops,
-	.ioctl_ops 	= &rtrack2_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init rtrack2_init(void)
 {
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
+	struct rtrack2 *dev = &rtrack2_card;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name));
+	dev->io = io;
+	if (dev->io == -1) {
+		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n");
 		return -EINVAL;
 	}
-	if (!request_region(io, 4, "rtrack2"))
-	{
-		printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
+	if (!request_region(dev->io, 4, "rtrack2")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io);
 		return -EBUSY;
 	}
 
-	video_set_drvdata(&rtrack2_radio, &rtrack2_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(dev->io, 4);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
 
-	spin_lock_init(&lock);
-	if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 4);
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.fops = &rtrack2_fops;
+	dev->vdev.ioctl_ops = &rtrack2_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	video_set_drvdata(&dev->vdev, dev);
+
+	mutex_init(&dev->lock);
+	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(dev->io, 4);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
+	v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
 
 	/* mute card - prevents noisy bootups */
-	outb(1, io);
-	rtrack2_unit.muted = 1;
+	outb(1, dev->io);
+	dev->muted = 1;
 
 	return 0;
 }
 
-MODULE_AUTHOR("Ben Pfaff");
-MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
-module_param(radio_nr, int, 0);
-
-static void __exit rtrack2_cleanup_module(void)
+static void __exit rtrack2_exit(void)
 {
-	video_unregister_device(&rtrack2_radio);
-	release_region(io,4);
+	struct rtrack2 *dev = &rtrack2_card;
+
+	video_unregister_device(&dev->vdev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	release_region(dev->io, 4);
 }
 
 module_init(rtrack2_init);
-module_exit(rtrack2_cleanup_module);
-
-/*
-  Local variables:
-  compile-command: "mmake"
-  End:
-*/
+module_exit(rtrack2_exit);
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index d358e48..f4784f0 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -22,113 +22,109 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/isapnp.h>
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/mutex.h>
+#include <linux/videodev2.h>	/* kernel radio structs		*/
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
 
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}
-};
-
-struct fmi_device
-{
-	unsigned long in_use;
-	int port;
-	int curvol; /* 1 or 0 */
-	unsigned long curfreq; /* freq in kHz */
-	__u32 flags;
-};
+MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
+MODULE_DESCRIPTION("A driver for the SF16MI radio.");
+MODULE_LICENSE("GPL");
 
 static int io = -1;
 static int radio_nr = -1;
-static struct pnp_dev *dev = NULL;
-static struct mutex lock;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct fmi
+{
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
+	int curvol; /* 1 or 0 */
+	unsigned long curfreq; /* freq in kHz */
+	__u32 flags;
+	struct mutex lock;
+};
+
+static struct fmi fmi_card;
+static struct pnp_dev *dev;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
 /* It is only useful to give freq in intervall of 800 (=0.05Mhz),
  * other bits will be truncated, e.g 92.7400016 -> 92.7, but
  * 92.7400017 -> 92.75
  */
-#define RSF16_ENCODE(x)	((x)/800+214)
-#define RSF16_MINFREQ 87*16000
-#define RSF16_MAXFREQ 108*16000
+#define RSF16_ENCODE(x)	((x) / 800 + 214)
+#define RSF16_MINFREQ (87 * 16000)
+#define RSF16_MAXFREQ (108 * 16000)
 
-static void outbits(int bits, unsigned int data, int port)
+static void outbits(int bits, unsigned int data, int io)
 {
-	while(bits--) {
-		if(data & 1) {
-			outb(5, port);
+	while (bits--) {
+		if (data & 1) {
+			outb(5, io);
 			udelay(6);
-			outb(7, port);
+			outb(7, io);
 			udelay(6);
 		} else {
-			outb(1, port);
+			outb(1, io);
 			udelay(6);
-			outb(3, port);
+			outb(3, io);
 			udelay(6);
 		}
-		data>>=1;
+		data >>= 1;
 	}
 }
 
-static inline void fmi_mute(int port)
+static inline void fmi_mute(struct fmi *fmi)
 {
-	mutex_lock(&lock);
-	outb(0x00, port);
-	mutex_unlock(&lock);
+	mutex_lock(&fmi->lock);
+	outb(0x00, fmi->io);
+	mutex_unlock(&fmi->lock);
 }
 
-static inline void fmi_unmute(int port)
+static inline void fmi_unmute(struct fmi *fmi)
 {
-	mutex_lock(&lock);
-	outb(0x08, port);
-	mutex_unlock(&lock);
+	mutex_lock(&fmi->lock);
+	outb(0x08, fmi->io);
+	mutex_unlock(&fmi->lock);
 }
 
-static inline int fmi_setfreq(struct fmi_device *dev)
+static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
 {
-	int myport = dev->port;
-	unsigned long freq = dev->curfreq;
+	mutex_lock(&fmi->lock);
+	fmi->curfreq = freq;
 
-	mutex_lock(&lock);
-
-	outbits(16, RSF16_ENCODE(freq), myport);
-	outbits(8, 0xC0, myport);
+	outbits(16, RSF16_ENCODE(freq), fmi->io);
+	outbits(8, 0xC0, fmi->io);
 	msleep(143);		/* was schedule_timeout(HZ/7) */
-	mutex_unlock(&lock);
-	if (dev->curvol) fmi_unmute(myport);
+	mutex_unlock(&fmi->lock);
+	if (fmi->curvol)
+		fmi_unmute(fmi);
 	return 0;
 }
 
-static inline int fmi_getsigstr(struct fmi_device *dev)
+static inline int fmi_getsigstr(struct fmi *fmi)
 {
 	int val;
 	int res;
-	int myport = dev->port;
 
-
-	mutex_lock(&lock);
-	val = dev->curvol ? 0x08 : 0x00;	/* unmute/mute */
-	outb(val, myport);
-	outb(val | 0x10, myport);
+	mutex_lock(&fmi->lock);
+	val = fmi->curvol ? 0x08 : 0x00;	/* unmute/mute */
+	outb(val, fmi->io);
+	outb(val | 0x10, fmi->io);
 	msleep(143); 		/* was schedule_timeout(HZ/7) */
-	res = (int)inb(myport+1);
-	outb(val, myport);
+	res = (int)inb(fmi->io + 1);
+	outb(val, fmi->io);
 
-	mutex_unlock(&lock);
+	mutex_unlock(&fmi->lock);
 	return (res & 2) ? 0 : 0xFFFF;
 }
 
@@ -137,9 +133,9 @@
 {
 	strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver));
 	strlcpy(v->card, "SF16-FMx radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
@@ -147,18 +143,18 @@
 					struct v4l2_tuner *v)
 {
 	int mult;
-	struct fmi_device *fmi = video_drvdata(file);
+	struct fmi *fmi = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 	mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
-	v->rangelow = RSF16_MINFREQ/mult;
-	v->rangehigh = RSF16_MAXFREQ/mult;
+	v->rangelow = RSF16_MINFREQ / mult;
+	v->rangehigh = RSF16_MAXFREQ / mult;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
-	v->capability = fmi->flags&V4L2_TUNER_CAP_LOW;
+	v->capability = fmi->flags & V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_STEREO;
 	v->signal = fmi_getsigstr(fmi);
 	return 0;
@@ -167,32 +163,29 @@
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct fmi_device *fmi = video_drvdata(file);
+	struct fmi *fmi = video_drvdata(file);
 
 	if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
 		f->frequency *= 1000;
 	if (f->frequency < RSF16_MINFREQ ||
-			f->frequency > RSF16_MAXFREQ )
+			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
-	/*rounding in steps of 800 to match th freq
-	that will be used */
-	fmi->curfreq = (f->frequency/800)*800;
-	fmi_setfreq(fmi);
+	/* rounding in steps of 800 to match the freq
+	   that will be used */
+	fmi_setfreq(fmi, (f->frequency / 800) * 800);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct fmi_device *fmi = video_drvdata(file);
+	struct fmi *fmi = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmi->curfreq;
@@ -204,14 +197,9 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
 	}
 	return -EINVAL;
 }
@@ -219,7 +207,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct fmi_device *fmi = video_drvdata(file);
+	struct fmi *fmi = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -232,31 +220,20 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct fmi_device *fmi = video_drvdata(file);
+	struct fmi *fmi = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value)
-			fmi_mute(fmi->port);
+			fmi_mute(fmi);
 		else
-			fmi_unmute(fmi->port);
+			fmi_unmute(fmi);
 		fmi->curvol = ctrl->value;
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -265,36 +242,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int fmi_open(struct file *file)
+{
 	return 0;
 }
 
-static struct fmi_device fmi_unit;
-
-static int fmi_exclusive_open(struct file *file)
+static int fmi_release(struct file *file)
 {
-	return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
-}
-
-static int fmi_exclusive_release(struct file *file)
-{
-	clear_bit(0, &fmi_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations fmi_fops = {
 	.owner		= THIS_MODULE,
-	.open           = fmi_exclusive_open,
-	.release        = fmi_exclusive_release,
+	.open           = fmi_open,
+	.release        = fmi_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -313,13 +292,6 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device fmi_radio = {
-	.name		= "SF16FMx radio",
-	.fops           = &fmi_fops,
-	.ioctl_ops 	= &fmi_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 /* ladis: this is my card. does any other types exist? */
 static struct isapnp_device_id id_table[] __devinitdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
@@ -344,7 +316,7 @@
 	if (pnp_device_attach(dev) < 0)
 		return -EAGAIN;
 	if (pnp_activate_dev(dev) < 0) {
-		printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n");
+		printk(KERN_ERR "radio-sf16fmi: PnP configure failed (out of resources?)\n");
 		pnp_device_detach(dev);
 		return -ENOMEM;
 	}
@@ -354,59 +326,72 @@
 	}
 
 	i = pnp_port_start(dev, 0);
-	printk ("radio-sf16fmi: PnP reports card at %#x\n", i);
+	printk(KERN_INFO "radio-sf16fmi: PnP reports card at %#x\n", i);
 
 	return i;
 }
 
 static int __init fmi_init(void)
 {
+	struct fmi *fmi = &fmi_card;
+	struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
+	int res;
+
 	if (io < 0)
 		io = isapnp_fmi_probe();
-	if (io < 0) {
-		printk(KERN_ERR "radio-sf16fmi: No PnP card found.\n");
-		return io;
+	strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
+	fmi->io = io;
+	if (fmi->io < 0) {
+		v4l2_err(v4l2_dev, "No PnP card found.\n");
+		return fmi->io;
 	}
 	if (!request_region(io, 2, "radio-sf16fmi")) {
-		printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io);
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io);
 		pnp_device_detach(dev);
 		return -EBUSY;
 	}
 
-	fmi_unit.port = io;
-	fmi_unit.curvol = 0;
-	fmi_unit.curfreq = 0;
-	fmi_unit.flags = V4L2_TUNER_CAP_LOW;
-	video_set_drvdata(&fmi_radio, &fmi_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(fmi->io, 2);
+		pnp_device_detach(dev);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
 
-	mutex_init(&lock);
+	fmi->flags = V4L2_TUNER_CAP_LOW;
+	strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
+	fmi->vdev.v4l2_dev = v4l2_dev;
+	fmi->vdev.fops = &fmi_fops;
+	fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
+	fmi->vdev.release = video_device_release_empty;
+	video_set_drvdata(&fmi->vdev, fmi);
 
-	if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 2);
+	mutex_init(&fmi->lock);
+
+	if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(fmi->io, 2);
+		pnp_device_detach(dev);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io);
+	v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
 	/* mute card - prevents noisy bootups */
-	fmi_mute(io);
+	fmi_mute(fmi);
 	return 0;
 }
 
-MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
-MODULE_DESCRIPTION("A driver for the SF16MI radio.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
-module_param(radio_nr, int, 0);
-
-static void __exit fmi_cleanup_module(void)
+static void __exit fmi_exit(void)
 {
-	video_unregister_device(&fmi_radio);
-	release_region(io, 2);
+	struct fmi *fmi = &fmi_card;
+
+	video_unregister_device(&fmi->vdev);
+	v4l2_device_unregister(&fmi->v4l2_dev);
+	release_region(fmi->io, 2);
 	if (dev)
 		pnp_device_detach(dev);
 }
 
 module_init(fmi_init);
-module_exit(fmi_cleanup_module);
+module_exit(fmi_exit);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 92f17a3..0ba9d88 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -18,40 +18,28 @@
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
-
-static struct mutex lock;
-
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com");
+MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
+MODULE_LICENSE("GPL");
+
+static int io = 0x384;
+static int radio_nr = -1;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
+module_param(radio_nr, int, 0);
+
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
 
 #define AUD_VOL_INDEX 1
 
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},
-	[AUD_VOL_INDEX] = {
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 15,
-		.step          = 1,
-		.default_value = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
-
 #undef DEBUG
 //#define DEBUG 1
 
@@ -62,156 +50,160 @@
 #endif
 
 /* this should be static vars for module size */
-struct fmr2_device
+struct fmr2
 {
-	unsigned long in_use;
-	int port;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct mutex lock;
+	int io;
 	int curvol; /* 0-15 */
 	int mute;
 	int stereo; /* card is producing stereo audio */
 	unsigned long curfreq; /* freq in kHz */
 	int card_type;
-	__u32 flags;
+	u32 flags;
 };
 
-static int io = 0x384;
-static int radio_nr = -1;
+static struct fmr2 fmr2_card;
 
 /* hw precision is 12.5 kHz
  * It is only useful to give freq in intervall of 200 (=0.0125Mhz),
  * other bits will be truncated
  */
-#define RSF16_ENCODE(x)	((x)/200+856)
-#define RSF16_MINFREQ 87*16000
-#define RSF16_MAXFREQ 108*16000
+#define RSF16_ENCODE(x)	((x) / 200 + 856)
+#define RSF16_MINFREQ (87 * 16000)
+#define RSF16_MAXFREQ (108 * 16000)
 
-static inline void wait(int n,int port)
+static inline void wait(int n, int io)
 {
-	for (;n;--n) inb(port);
+	for (; n; --n)
+		inb(io);
 }
 
-static void outbits(int bits, unsigned int data, int nWait, int port)
+static void outbits(int bits, unsigned int data, int nWait, int io)
 {
 	int bit;
-	for(;--bits>=0;) {
-		bit = (data>>bits) & 1;
-		outb(bit,port);
-		wait(nWait,port);
-		outb(bit|2,port);
-		wait(nWait,port);
-		outb(bit,port);
-		wait(nWait,port);
+
+	for (; --bits >= 0;) {
+		bit = (data >> bits) & 1;
+		outb(bit, io);
+		wait(nWait, io);
+		outb(bit | 2, io);
+		wait(nWait, io);
+		outb(bit, io);
+		wait(nWait, io);
 	}
 }
 
-static inline void fmr2_mute(int port)
+static inline void fmr2_mute(int io)
 {
-	outb(0x00, port);
-	wait(4,port);
+	outb(0x00, io);
+	wait(4, io);
 }
 
-static inline void fmr2_unmute(int port)
+static inline void fmr2_unmute(int io)
 {
-	outb(0x04, port);
-	wait(4,port);
+	outb(0x04, io);
+	wait(4, io);
 }
 
-static inline int fmr2_stereo_mode(int port)
+static inline int fmr2_stereo_mode(int io)
 {
-	int n = inb(port);
-	outb(6,port);
-	inb(port);
-	n = ((n>>3)&1)^1;
+	int n = inb(io);
+
+	outb(6, io);
+	inb(io);
+	n = ((n >> 3) & 1) ^ 1;
 	debug_print((KERN_DEBUG "stereo: %d\n", n));
 	return n;
 }
 
-static int fmr2_product_info(struct fmr2_device *dev)
+static int fmr2_product_info(struct fmr2 *dev)
 {
-	int n = inb(dev->port);
+	int n = inb(dev->io);
+
 	n &= 0xC1;
-	if (n == 0)
-	{
+	if (n == 0) {
 		/* this should support volume set */
 		dev->card_type = 12;
 		return 0;
 	}
 	/* not volume (mine is 11) */
-	dev->card_type = (n==128)?11:0;
+	dev->card_type = (n == 128) ? 11 : 0;
 	return n;
 }
 
-static inline int fmr2_getsigstr(struct fmr2_device *dev)
+static inline int fmr2_getsigstr(struct fmr2 *dev)
 {
-	/* !!! work only if scanning freq */
-	int port = dev->port, res = 0xffff;
-	outb(5,port);
-	wait(4,port);
-	if (!(inb(port)&1)) res = 0;
+	/* !!! works only if scanning freq */
+	int res = 0xffff;
+
+	outb(5, dev->io);
+	wait(4, dev->io);
+	if (!(inb(dev->io) & 1))
+		res = 0;
 	debug_print((KERN_DEBUG "signal: %d\n", res));
 	return res;
 }
 
 /* set frequency and unmute card */
-static int fmr2_setfreq(struct fmr2_device *dev)
+static int fmr2_setfreq(struct fmr2 *dev)
 {
-	int port = dev->port;
 	unsigned long freq = dev->curfreq;
 
-	fmr2_mute(port);
+	fmr2_mute(dev->io);
 
 	/* 0x42 for mono output
 	 * 0x102 forward scanning
 	 * 0x182 scansione avanti
 	 */
-	outbits(9,0x2,3,port);
-	outbits(16,RSF16_ENCODE(freq),2,port);
+	outbits(9, 0x2, 3, dev->io);
+	outbits(16, RSF16_ENCODE(freq), 2, dev->io);
 
-	fmr2_unmute(port);
+	fmr2_unmute(dev->io);
 
 	/* wait 0.11 sec */
 	msleep(110);
 
 	/* NOTE if mute this stop radio
 	   you must set freq on unmute */
-	dev->stereo = fmr2_stereo_mode(port);
+	dev->stereo = fmr2_stereo_mode(dev->io);
 	return 0;
 }
 
 /* !!! not tested, in my card this does't work !!! */
-static int fmr2_setvolume(struct fmr2_device *dev)
+static int fmr2_setvolume(struct fmr2 *dev)
 {
 	int vol[16] = { 0x021, 0x084, 0x090, 0x104,
 			0x110, 0x204, 0x210, 0x402,
 			0x404, 0x408, 0x410, 0x801,
 			0x802, 0x804, 0x808, 0x810 };
-	int i, a, port = dev->port;
+	int i, a;
 	int n = vol[dev->curvol & 0x0f];
 
 	if (dev->card_type != 11)
 		return 1;
 
 	for (i = 12; --i >= 0; ) {
-		a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
-		outb(a | 4, port);
-		wait(4, port);
-		outb(a | 0x24, port);
-		wait(4, port);
-		outb(a | 4, port);
-		wait(4, port);
+		a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */
+		outb(a | 4, dev->io);
+		wait(4, dev->io);
+		outb(a | 0x24, dev->io);
+		wait(4, dev->io);
+		outb(a | 4, dev->io);
+		wait(4, dev->io);
 	}
 	for (i = 6; --i >= 0; ) {
 		a = ((0x18 >> i) & 1) << 6;
-		outb(a | 4, port);
-		wait(4,port);
-		outb(a | 0x24, port);
-		wait(4,port);
-		outb(a|4, port);
-		wait(4,port);
+		outb(a | 4, dev->io);
+		wait(4, dev->io);
+		outb(a | 0x24, dev->io);
+		wait(4, dev->io);
+		outb(a | 4, dev->io);
+		wait(4, dev->io);
 	}
-	wait(4, port);
-	outb(0x14, port);
-
+	wait(4, dev->io);
+	outb(0x14, dev->io);
 	return 0;
 }
 
@@ -220,9 +212,9 @@
 {
 	strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver));
 	strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
@@ -230,54 +222,52 @@
 					struct v4l2_tuner *v)
 {
 	int mult;
-	struct fmr2_device *fmr2 = video_drvdata(file);
+	struct fmr2 *fmr2 = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
 
 	mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
-	v->rangelow = RSF16_MINFREQ/mult;
-	v->rangehigh = RSF16_MAXFREQ/mult;
+	v->rangelow = RSF16_MINFREQ / mult;
+	v->rangehigh = RSF16_MAXFREQ / mult;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
 	v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW;
 	v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
 				V4L2_TUNER_MODE_MONO;
-	mutex_lock(&lock);
+	mutex_lock(&fmr2->lock);
 	v->signal = fmr2_getsigstr(fmr2);
-	mutex_unlock(&lock);
+	mutex_unlock(&fmr2->lock);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct fmr2_device *fmr2 = video_drvdata(file);
+	struct fmr2 *fmr2 = video_drvdata(file);
 
 	if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
 		f->frequency *= 1000;
 	if (f->frequency < RSF16_MINFREQ ||
-			f->frequency > RSF16_MAXFREQ )
+			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
-	/*rounding in steps of 200 to match th freq
-	that will be used */
-	fmr2->curfreq = (f->frequency/200)*200;
+	/* rounding in steps of 200 to match the freq
+	   that will be used */
+	fmr2->curfreq = (f->frequency / 200) * 200;
 
 	/* set card freq (if not muted) */
 	if (fmr2->curvol && !fmr2->mute) {
-		mutex_lock(&lock);
+		mutex_lock(&fmr2->lock);
 		fmr2_setfreq(fmr2);
-		mutex_unlock(&lock);
+		mutex_unlock(&fmr2->lock);
 	}
 	return 0;
 }
@@ -285,7 +275,7 @@
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct fmr2_device *fmr2 = video_drvdata(file);
+	struct fmr2 *fmr2 = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmr2->curfreq;
@@ -297,13 +287,16 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
+	struct fmr2 *fmr2 = video_drvdata(file);
 
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &radio_qctrl[i], sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		/* Only card_type == 11 implements volume */
+		if (fmr2->card_type == 11)
+			return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0);
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
 	}
 	return -EINVAL;
 }
@@ -311,7 +304,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct fmr2_device *fmr2 = video_drvdata(file);
+	struct fmr2 *fmr2 = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -327,18 +320,14 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct fmr2_device *fmr2 = video_drvdata(file);
+	struct fmr2 *fmr2 = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		fmr2->mute = ctrl->value;
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
-		if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
-			fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
-		else
-			fmr2->curvol = ctrl->value;
-
+		fmr2->curvol = ctrl->value;
 		break;
 	default:
 		return -EINVAL;
@@ -351,25 +340,14 @@
 		printk(KERN_DEBUG "mute\n");
 #endif
 
-	mutex_lock(&lock);
+	mutex_lock(&fmr2->lock);
 	if (fmr2->curvol && !fmr2->mute) {
 		fmr2_setvolume(fmr2);
 		/* Set frequency and unmute card */
 		fmr2_setfreq(fmr2);
 	} else
-		fmr2_mute(fmr2->port);
-	mutex_unlock(&lock);
-	return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
+		fmr2_mute(fmr2->io);
+	mutex_unlock(&fmr2->lock);
 	return 0;
 }
 
@@ -381,36 +359,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int fmr2_open(struct file *file)
+{
 	return 0;
 }
 
-static struct fmr2_device fmr2_unit;
-
-static int fmr2_exclusive_open(struct file *file)
+static int fmr2_release(struct file *file)
 {
-	return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
-}
-
-static int fmr2_exclusive_release(struct file *file)
-{
-	clear_bit(0, &fmr2_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations fmr2_fops = {
 	.owner          = THIS_MODULE,
-	.open           = fmr2_exclusive_open,
-	.release        = fmr2_exclusive_release,
+	.open           = fmr2_open,
+	.release        = fmr2_release,
 	.ioctl          = video_ioctl2,
 };
 
@@ -429,67 +409,64 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device fmr2_radio = {
-	.name		= "SF16FMR2 radio",
-	.fops		= &fmr2_fops,
-	.ioctl_ops 	= &fmr2_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init fmr2_init(void)
 {
-	fmr2_unit.port = io;
-	fmr2_unit.curvol = 0;
-	fmr2_unit.mute = 0;
-	fmr2_unit.curfreq = 0;
-	fmr2_unit.stereo = 1;
-	fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
-	fmr2_unit.card_type = 0;
-	video_set_drvdata(&fmr2_radio, &fmr2_unit);
+	struct fmr2 *fmr2 = &fmr2_card;
+	struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev;
+	int res;
 
-	mutex_init(&lock);
+	strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name));
+	fmr2->io = io;
+	fmr2->stereo = 1;
+	fmr2->flags = V4L2_TUNER_CAP_LOW;
+	mutex_init(&fmr2->lock);
 
-	if (!request_region(io, 2, "sf16fmr2")) {
-		printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n");
+	if (!request_region(fmr2->io, 2, "sf16fmr2")) {
+		v4l2_err(v4l2_dev, "request_region failed!\n");
 		return -EBUSY;
 	}
 
-	if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 2);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(fmr2->io, 2);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
+
+	strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name));
+	fmr2->vdev.v4l2_dev = v4l2_dev;
+	fmr2->vdev.fops = &fmr2_fops;
+	fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops;
+	fmr2->vdev.release = video_device_release_empty;
+	video_set_drvdata(&fmr2->vdev, fmr2);
+
+	if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(fmr2->io, 2);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io);
+	v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
 	/* mute card - prevents noisy bootups */
-	mutex_lock(&lock);
-	fmr2_mute(io);
-	fmr2_product_info(&fmr2_unit);
-	mutex_unlock(&lock);
-	debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
-
-	/* Only card_type == 11 implements volume */
-	if (fmr2_unit.card_type != 11)
-		radio_qctrl[AUD_VOL_INDEX].maximum = 1;
-
+	mutex_lock(&fmr2->lock);
+	fmr2_mute(fmr2->io);
+	fmr2_product_info(fmr2);
+	mutex_unlock(&fmr2->lock);
+	debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
 	return 0;
 }
 
-MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com");
-MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
-module_param(radio_nr, int, 0);
-
-static void __exit fmr2_cleanup_module(void)
+static void __exit fmr2_exit(void)
 {
-	video_unregister_device(&fmr2_radio);
-	release_region(io,2);
+	struct fmr2 *fmr2 = &fmr2_card;
+
+	video_unregister_device(&fmr2->vdev);
+	v4l2_device_unregister(&fmr2->v4l2_dev);
+	release_region(fmr2->io, 2);
 }
 
 module_init(fmr2_init);
-module_exit(fmr2_cleanup_module);
+module_exit(fmr2_exit);
 
 #ifndef MODULE
 
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 4dfed6a..713e242 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -5,8 +5,9 @@
  *   - Silicon Labs USB FM Radio Reference Design
  *   - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
  *   - KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
+ *   - Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear)
  *
- *  Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net>
+ *  Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,7 +30,7 @@
  * 2008-01-12	Tobias Lorenz <tobias.lorenz@gmx.net>
  *		Version 1.0.0
  *		- First working version
- * 2008-01-13   Tobias Lorenz <tobias.lorenz@gmx.net>
+ * 2008-01-13	Tobias Lorenz <tobias.lorenz@gmx.net>
  *		Version 1.0.1
  *		- Improved error handling, every function now returns errno
  *		- Improved multi user access (start/mute/stop)
@@ -104,6 +105,7 @@
  * 2009-01-31	Rick Bronson <rick@efn.org>
  *		Tobias Lorenz <tobias.lorenz@gmx.net>
  *		- add LED status output
+ *		- get HW/SW version from scratchpad
  *
  * ToDo:
  * - add firmware download/update support
@@ -114,10 +116,10 @@
 /* driver definitions */
 #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
 #define DRIVER_NAME "radio-si470x"
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8)
+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 9)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.8"
+#define DRIVER_VERSION "1.0.9"
 
 
 /* kernel includes */
@@ -145,7 +147,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
 	/* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
-	/* DealExtreme USB Radio */
+	/* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },
 	/* Terminating entry */
 	{ }
@@ -345,7 +347,7 @@
 
 /* Report 19: stream */
 #define STREAM_REPORT_SIZE	3
-#define	STREAM_REPORT		19
+#define STREAM_REPORT		19
 
 /* Report 20: scratch */
 #define SCRATCH_PAGE_SIZE	63
@@ -353,9 +355,13 @@
 #define SCRATCH_REPORT		20
 
 /* Reports 19-22: flash upgrade of the C8051F321 */
+#define WRITE_REPORT_SIZE	4
 #define WRITE_REPORT		19
+#define FLASH_REPORT_SIZE	64
 #define FLASH_REPORT		20
+#define CRC_REPORT_SIZE		3
 #define CRC_REPORT		21
+#define RESPONSE_REPORT_SIZE	2
 #define RESPONSE_REPORT		22
 
 /* Report 23: currently unused, but can accept 60 byte reports on the HID */
@@ -414,7 +420,7 @@
 
 /* bootloader commands */
 #define GET_SW_VERSION_COMMAND	0x00
-#define	SET_PAGE_COMMAND	0x01
+#define SET_PAGE_COMMAND	0x01
 #define ERASE_PAGE_COMMAND	0x02
 #define WRITE_PAGE_COMMAND	0x03
 #define CRC_ON_PAGE_COMMAND	0x04
@@ -428,12 +434,6 @@
 #define COMMAND_FAILED		0x02
 #define COMMAND_PENDING		0x03
 
-/* buffer sizes */
-#define COMMAND_BUFFER_SIZE	4
-#define RESPONSE_BUFFER_SIZE	2
-#define FLASH_BUFFER_SIZE	64
-#define CRC_BUFFER_SIZE		3
-
 
 
 /**************************************************************************
@@ -465,6 +465,10 @@
 	unsigned int buf_size;
 	unsigned int rd_index;
 	unsigned int wr_index;
+
+	/* scratch page */
+	unsigned char software_version;
+	unsigned char hardware_version;
 };
 
 
@@ -480,7 +484,7 @@
 
 
 /**************************************************************************
- * General Driver Functions
+ * General Driver Functions - REGISTER_REPORTs
  **************************************************************************/
 
 /*
@@ -566,60 +570,6 @@
 
 
 /*
- * si470x_get_all_registers - read entire registers
- */
-static int si470x_get_all_registers(struct si470x_device *radio)
-{
-	unsigned char buf[ENTIRE_REPORT_SIZE];
-	int retval;
-	unsigned char regnr;
-
-	buf[0] = ENTIRE_REPORT;
-
-	retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
-
-	if (retval >= 0)
-		for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
-			radio->registers[regnr] = get_unaligned_be16(
-				&buf[regnr * RADIO_REGISTER_SIZE + 1]);
-
-	return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
- * si470x_get_rds_registers - read rds registers
- */
-static int si470x_get_rds_registers(struct si470x_device *radio)
-{
-	unsigned char buf[RDS_REPORT_SIZE];
-	int retval;
-	int size;
-	unsigned char regnr;
-
-	buf[0] = RDS_REPORT;
-
-	retval = usb_interrupt_msg(radio->usbdev,
-		usb_rcvintpipe(radio->usbdev, 1),
-		(void *) &buf, sizeof(buf), &size, usb_timeout);
-	if (size != sizeof(buf))
-		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
-			"return size differs: %d != %zu\n", size, sizeof(buf));
-	if (retval < 0)
-		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
-			"usb_interrupt_msg returned %d\n", retval);
-
-	if (retval >= 0)
-		for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
-			radio->registers[STATUSRSSI + regnr] =
-				get_unaligned_be16(
-				&buf[regnr * RADIO_REGISTER_SIZE + 1]);
-
-	return (retval < 0) ? -EINVAL : 0;
-}
-
-
-/*
  * si470x_set_chan - set the channel
  */
 static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
@@ -887,6 +837,70 @@
 
 
 /**************************************************************************
+ * General Driver Functions - ENTIRE_REPORT
+ **************************************************************************/
+
+/*
+ * si470x_get_all_registers - read entire registers
+ */
+static int si470x_get_all_registers(struct si470x_device *radio)
+{
+	unsigned char buf[ENTIRE_REPORT_SIZE];
+	int retval;
+	unsigned char regnr;
+
+	buf[0] = ENTIRE_REPORT;
+
+	retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
+
+	if (retval >= 0)
+		for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
+			radio->registers[regnr] = get_unaligned_be16(
+				&buf[regnr * RADIO_REGISTER_SIZE + 1]);
+
+	return (retval < 0) ? -EINVAL : 0;
+}
+
+
+
+/**************************************************************************
+ * General Driver Functions - RDS_REPORT
+ **************************************************************************/
+
+/*
+ * si470x_get_rds_registers - read rds registers
+ */
+static int si470x_get_rds_registers(struct si470x_device *radio)
+{
+	unsigned char buf[RDS_REPORT_SIZE];
+	int retval;
+	int size;
+	unsigned char regnr;
+
+	buf[0] = RDS_REPORT;
+
+	retval = usb_interrupt_msg(radio->usbdev,
+		usb_rcvintpipe(radio->usbdev, 1),
+		(void *) &buf, sizeof(buf), &size, usb_timeout);
+	if (size != sizeof(buf))
+		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+			"return size differs: %d != %zu\n", size, sizeof(buf));
+	if (retval < 0)
+		printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
+			"usb_interrupt_msg returned %d\n", retval);
+
+	if (retval >= 0)
+		for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
+			radio->registers[STATUSRSSI + regnr] =
+				get_unaligned_be16(
+				&buf[regnr * RADIO_REGISTER_SIZE + 1]);
+
+	return (retval < 0) ? -EINVAL : 0;
+}
+
+
+
+/**************************************************************************
  * General Driver Functions - LED_REPORT
  **************************************************************************/
 
@@ -911,6 +925,35 @@
 
 
 /**************************************************************************
+ * General Driver Functions - SCRATCH_REPORT
+ **************************************************************************/
+
+/*
+ * si470x_get_scratch_versions - gets the scratch page and version infos
+ */
+static int si470x_get_scratch_page_versions(struct si470x_device *radio)
+{
+	unsigned char buf[SCRATCH_REPORT_SIZE];
+	int retval;
+
+	buf[0] = SCRATCH_REPORT;
+
+	retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
+
+	if (retval < 0)
+		printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: "
+			"si470x_get_report returned %d\n", retval);
+	else {
+		radio->software_version = buf[1];
+		radio->hardware_version = buf[2];
+	}
+
+	return (retval < 0) ? -EINVAL : 0;
+}
+
+
+
+/**************************************************************************
  * RDS Driver Functions
  **************************************************************************/
 
@@ -1124,6 +1167,7 @@
 	}
 
 	if (radio->users == 1) {
+		/* start radio */
 		retval = si470x_start(radio);
 		if (retval < 0)
 			usb_autopm_put_interface(radio->intf);
@@ -1165,6 +1209,7 @@
 		/* cancel read processes */
 		wake_up_interruptible(&radio->read_queue);
 
+		/* stop radio */
 		retval = si470x_stop(radio);
 		usb_autopm_put_interface(radio->intf);
 	}
@@ -1226,9 +1271,11 @@
 static int si470x_vidioc_querycap(struct file *file, void *priv,
 		struct v4l2_capability *capability)
 {
+	struct si470x_device *radio = video_drvdata(file);
+
 	strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
 	strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
-	sprintf(capability->bus_info, "USB");
+	usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info));
 	capability->version = DRIVER_KERNEL_VERSION;
 	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
 		V4L2_CAP_TUNER | V4L2_CAP_RADIO;
@@ -1636,7 +1683,7 @@
 			sizeof(si470x_viddev_template));
 	video_set_drvdata(radio->videodev, radio);
 
-	/* show some infos about the specific device */
+	/* show some infos about the specific si470x device */
 	if (si470x_get_all_registers(radio) < 0) {
 		retval = -EIO;
 		goto err_all;
@@ -1644,7 +1691,16 @@
 	printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
 			radio->registers[DEVICEID], radio->registers[CHIPID]);
 
-	/* check if firmware is current */
+	/* get software and hardware versions */
+	if (si470x_get_scratch_page_versions(radio) < 0) {
+		retval = -EIO;
+		goto err_all;
+	}
+	printk(KERN_INFO DRIVER_NAME
+			": software version %d, hardware version %d\n",
+			radio->software_version, radio->hardware_version);
+
+	/* check if device and firmware is current */
 	if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
 			< RADIO_SW_VERSION_CURRENT) {
 		printk(KERN_WARNING DRIVER_NAME
@@ -1657,7 +1713,7 @@
 			": If you have some trouble using this driver,\n");
 		printk(KERN_WARNING DRIVER_NAME
 			": please report to V4L ML at "
-			"video4linux-list@redhat.com\n");
+			"linux-media@vger.kernel.org\n");
 	}
 
 	/* set initial frequency */
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 0798d71..5b007f5 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -27,16 +27,29 @@
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
-#include <linux/delay.h>	/* udelay			*/
-#include <asm/io.h>		/* outb, outb_p			*/
-#include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/spinlock.h>
-
+#include <linux/mutex.h>
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+#include <linux/io.h>		/* outb, outb_p			*/
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_AUTHOR("R.OFFERMANNS & others");
+MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
+MODULE_LICENSE("GPL");
+
+#ifndef CONFIG_RADIO_TERRATEC_PORT
+#define CONFIG_RADIO_TERRATEC_PORT 0x590
+#endif
+
+static int io = CONFIG_RADIO_TERRATEC_PORT;
+static int radio_nr = -1;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
 
 static struct v4l2_queryctrl radio_qctrl[] = {
 	{
@@ -57,13 +70,6 @@
 	}
 };
 
-#ifndef CONFIG_RADIO_TERRATEC_PORT
-#define CONFIG_RADIO_TERRATEC_PORT 0x590
-#endif
-
-/**************** this ones are for the terratec *******************/
-#define BASEPORT 	0x590
-#define VOLPORT 	0x591
 #define WRT_DIS 	0x00
 #define CLK_OFF		0x00
 #define IIC_DATA	0x01
@@ -71,138 +77,124 @@
 #define DATA		0x04
 #define CLK_ON 		0x08
 #define WRT_EN		0x10
-/*******************************************************************/
 
-static int io = CONFIG_RADIO_TERRATEC_PORT;
-static int radio_nr = -1;
-static spinlock_t lock;
-
-struct tt_device
+struct terratec
 {
-	unsigned long in_use;
-	int port;
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
 	int curvol;
 	unsigned long curfreq;
 	int muted;
+	struct mutex lock;
 };
 
+static struct terratec terratec_card;
 
 /* local things */
 
-static void cardWriteVol(int volume)
+static void tt_write_vol(struct terratec *tt, int volume)
 {
 	int i;
-	volume = volume+(volume * 32); // change both channels
-	spin_lock(&lock);
-	for (i=0;i<8;i++)
-	{
-		if (volume & (0x80>>i))
-			outb(0x80, VOLPORT);
-		else outb(0x00, VOLPORT);
+
+	volume = volume + (volume * 32); /* change both channels */
+	mutex_lock(&tt->lock);
+	for (i = 0; i < 8; i++) {
+		if (volume & (0x80 >> i))
+			outb(0x80, tt->io + 1);
+		else
+			outb(0x00, tt->io + 1);
 	}
-	spin_unlock(&lock);
+	mutex_unlock(&tt->lock);
 }
 
 
 
-static void tt_mute(struct tt_device *dev)
+static void tt_mute(struct terratec *tt)
 {
-	dev->muted = 1;
-	cardWriteVol(0);
+	tt->muted = 1;
+	tt_write_vol(tt, 0);
 }
 
-static int tt_setvol(struct tt_device *dev, int vol)
+static int tt_setvol(struct terratec *tt, int vol)
 {
-
-//	printk(KERN_ERR "setvol called, vol = %d\n", vol);
-
-	if(vol == dev->curvol) {	/* requested volume = current */
-		if (dev->muted) {	/* user is unmuting the card  */
-			dev->muted = 0;
-			cardWriteVol(vol);	/* enable card */
+	if (vol == tt->curvol) {	/* requested volume = current */
+		if (tt->muted) {	/* user is unmuting the card  */
+			tt->muted = 0;
+			tt_write_vol(tt, vol);	/* enable card */
 		}
-
 		return 0;
 	}
 
-	if(vol == 0) {			/* volume = 0 means mute the card */
-		cardWriteVol(0);	/* "turn off card" by setting vol to 0 */
-		dev->curvol = vol;	/* track the volume state!	*/
+	if (vol == 0) {			/* volume = 0 means mute the card */
+		tt_write_vol(tt, 0);	/* "turn off card" by setting vol to 0 */
+		tt->curvol = vol;	/* track the volume state!	*/
 		return 0;
 	}
 
-	dev->muted = 0;
-
-	cardWriteVol(vol);
-
-	dev->curvol = vol;
-
+	tt->muted = 0;
+	tt_write_vol(tt, vol);
+	tt->curvol = vol;
 	return 0;
-
 }
 
 
 /* this is the worst part in this driver */
 /* many more or less strange things are going on here, but hey, it works :) */
 
-static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
+static int tt_setfreq(struct terratec *tt, unsigned long freq1)
 {
 	int freq;
 	int i;
 	int p;
 	int  temp;
 	long rest;
-
 	unsigned char buffer[25];		/* we have to bit shift 25 registers */
-	freq = freq1/160;			/* convert the freq. to a nice to handle value */
-	for(i=24;i>-1;i--)
-		buffer[i]=0;
 
-	rest = freq*10+10700;		/* i once had understood what is going on here */
+	mutex_lock(&tt->lock);
+
+	tt->curfreq = freq1;
+
+	freq = freq1 / 160;			/* convert the freq. to a nice to handle value */
+	memset(buffer, 0, sizeof(buffer));
+
+	rest = freq * 10 + 10700;	/* I once had understood what is going on here */
 					/* maybe some wise guy (friedhelm?) can comment this stuff */
-	i=13;
-	p=10;
-	temp=102400;
-	while (rest!=0)
-	{
-		if (rest%temp  == rest)
+	i = 13;
+	p = 10;
+	temp = 102400;
+	while (rest != 0) {
+		if (rest % temp  == rest)
 			buffer[i] = 0;
-		else
-		{
+		else {
 			buffer[i] = 1;
-			rest = rest-temp;
+			rest = rest - temp;
 		}
 		i--;
 		p--;
-		temp = temp/2;
+		temp = temp / 2;
 	}
 
-	spin_lock(&lock);
-
-	for (i=24;i>-1;i--)			/* bit shift the values to the radiocard */
-	{
-		if (buffer[i]==1)
-		{
-			outb(WRT_EN|DATA, BASEPORT);
-			outb(WRT_EN|DATA|CLK_ON  , BASEPORT);
-			outb(WRT_EN|DATA, BASEPORT);
-		}
-		else
-		{
-			outb(WRT_EN|0x00, BASEPORT);
-			outb(WRT_EN|0x00|CLK_ON  , BASEPORT);
+	for (i = 24; i > -1; i--) {	/* bit shift the values to the radiocard */
+		if (buffer[i] == 1) {
+			outb(WRT_EN | DATA, tt->io);
+			outb(WRT_EN | DATA | CLK_ON, tt->io);
+			outb(WRT_EN | DATA, tt->io);
+		} else {
+			outb(WRT_EN | 0x00, tt->io);
+			outb(WRT_EN | 0x00 | CLK_ON, tt->io);
 		}
 	}
-	outb(0x00, BASEPORT);
+	outb(0x00, tt->io);
 
-	spin_unlock(&lock);
+	mutex_unlock(&tt->lock);
 
 	return 0;
 }
 
-static int tt_getsigstr(struct tt_device *dev)		/* TODO */
+static int tt_getsigstr(struct terratec *tt)
 {
-	if (inb(io) & 2)	/* bit set = no signal present	*/
+	if (inb(tt->io) & 2)	/* bit set = no signal present	*/
 		return 0;
 	return 1;		/* signal present		*/
 }
@@ -212,53 +204,50 @@
 {
 	strlcpy(v->driver, "radio-terratec", sizeof(v->driver));
 	strlcpy(v->card, "ActiveRadio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	struct tt_device *tt = video_drvdata(file);
+	struct terratec *tt = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (87*16000);
-	v->rangehigh = (108*16000);
+	v->rangelow = 87 * 16000;
+	v->rangehigh = 108 * 16000;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	v->capability = V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = 0xFFFF*tt_getsigstr(tt);
+	v->signal = 0xFFFF * tt_getsigstr(tt);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct tt_device *tt = video_drvdata(file);
+	struct terratec *tt = video_drvdata(file);
 
-	tt->curfreq = f->frequency;
-	tt_setfreq(tt, tt->curfreq);
+	tt_setfreq(tt, f->frequency);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct tt_device *tt = video_drvdata(file);
+	struct terratec *tt = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = tt->curfreq;
@@ -272,8 +261,7 @@
 
 	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
 		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
+			memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
 			return 0;
 		}
 	}
@@ -283,7 +271,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct tt_device *tt = video_drvdata(file);
+	struct terratec *tt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -302,7 +290,7 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct tt_device *tt = video_drvdata(file);
+	struct terratec *tt = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -318,17 +306,6 @@
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -337,36 +314,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int terratec_open(struct file *file)
+{
 	return 0;
 }
 
-static struct tt_device terratec_unit;
-
-static int terratec_exclusive_open(struct file *file)
+static int terratec_release(struct file *file)
 {
-	return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
-}
-
-static int terratec_exclusive_release(struct file *file)
-{
-	clear_bit(0, &terratec_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations terratec_fops = {
 	.owner		= THIS_MODULE,
-	.open           = terratec_exclusive_open,
-	.release        = terratec_exclusive_release,
+	.open           = terratec_open,
+	.release        = terratec_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -385,60 +364,63 @@
 	.vidioc_s_input     = vidioc_s_input,
 };
 
-static struct video_device terratec_radio = {
-	.name		= "TerraTec ActiveRadio",
-	.fops           = &terratec_fops,
-	.ioctl_ops 	= &terratec_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init terratec_init(void)
 {
-	if(io==-1)
-	{
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+	struct terratec *tt = &terratec_card;
+	struct v4l2_device *v4l2_dev = &tt->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name));
+	tt->io = io;
+	if (tt->io == -1) {
+		v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n");
 		return -EINVAL;
 	}
-	if (!request_region(io, 2, "terratec"))
-	{
-		printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
+	if (!request_region(tt->io, 2, "terratec")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
 
-	video_set_drvdata(&terratec_radio, &terratec_unit);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(tt->io, 2);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
 
-	spin_lock_init(&lock);
+	strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name));
+	tt->vdev.v4l2_dev = v4l2_dev;
+	tt->vdev.fops = &terratec_fops;
+	tt->vdev.ioctl_ops = &terratec_ioctl_ops;
+	tt->vdev.release = video_device_release_empty;
+	video_set_drvdata(&tt->vdev, tt);
 
-	if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io,2);
+	mutex_init(&tt->lock);
+
+	if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(&tt->v4l2_dev);
+		release_region(tt->io, 2);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n");
+	v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
 
 	/* mute card - prevents noisy bootups */
-
-	/* this ensures that the volume is all the way down  */
-	cardWriteVol(0);
-	terratec_unit.curvol = 0;
-
+	tt_write_vol(tt, 0);
 	return 0;
 }
 
-MODULE_AUTHOR("R.OFFERMANNS & others");
-MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
-MODULE_LICENSE("GPL");
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x591)");
-module_param(radio_nr, int, 0);
-
-static void __exit terratec_cleanup_module(void)
+static void __exit terratec_exit(void)
 {
-	video_unregister_device(&terratec_radio);
-	release_region(io,2);
-	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");
+	struct terratec *tt = &terratec_card;
+	struct v4l2_device *v4l2_dev = &tt->v4l2_dev;
+
+	video_unregister_device(&tt->vdev);
+	v4l2_device_unregister(&tt->v4l2_dev);
+	release_region(tt->io, 2);
+	v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver unloaded.\n");
 }
 
 module_init(terratec_init);
-module_exit(terratec_cleanup_module);
+module_exit(terratec_exit);
 
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index bdf9cb6..d1be649 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -19,49 +19,15 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <linux/io.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 2048,
-		.default_value = 65535,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BASS,
-		.name          = "Bass",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 4370,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_TREBLE,
-		.name          = "Treble",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 4370,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},
-};
+MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
+MODULE_LICENSE("GPL");
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
 
@@ -71,26 +37,41 @@
 
 static int io = CONFIG_RADIO_TRUST_PORT;
 static int radio_nr = -1;
-static int ioval = 0xf;
-static __u16 curvol;
-static __u16 curbass;
-static __u16 curtreble;
-static unsigned long curfreq;
-static int curstereo;
-static int curmute;
-static unsigned long in_use;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct trust {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
+	int ioval;
+	__u16 curvol;
+	__u16 curbass;
+	__u16 curtreble;
+	int muted;
+	unsigned long curfreq;
+	int curstereo;
+	int curmute;
+	struct mutex lock;
+};
+
+static struct trust trust_card;
 
 /* i2c addresses */
 #define TDA7318_ADDR 0x88
 #define TSA6060T_ADDR 0xc4
 
-#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0)
-#define TR_SET_SCL outb(ioval |= 2, io)
-#define TR_CLR_SCL outb(ioval &= 0xfd, io)
-#define TR_SET_SDA outb(ioval |= 1, io)
-#define TR_CLR_SDA outb(ioval &= 0xfe, io)
+#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0)
+#define TR_SET_SCL outb(tr->ioval |= 2, tr->io)
+#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io)
+#define TR_SET_SDA outb(tr->ioval |= 1, tr->io)
+#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io)
 
-static void write_i2c(int n, ...)
+static void write_i2c(struct trust *tr, int n, ...)
 {
 	unsigned char val, mask;
 	va_list args;
@@ -136,62 +117,77 @@
 	va_end(args);
 }
 
-static void tr_setvol(__u16 vol)
+static void tr_setvol(struct trust *tr, __u16 vol)
 {
-	curvol = vol / 2048;
-	write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f);
+	mutex_lock(&tr->lock);
+	tr->curvol = vol / 2048;
+	write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f);
+	mutex_unlock(&tr->lock);
 }
 
 static int basstreble2chip[15] = {
 	0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8
 };
 
-static void tr_setbass(__u16 bass)
+static void tr_setbass(struct trust *tr, __u16 bass)
 {
-	curbass = bass / 4370;
-	write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]);
+	mutex_lock(&tr->lock);
+	tr->curbass = bass / 4370;
+	write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]);
+	mutex_unlock(&tr->lock);
 }
 
-static void tr_settreble(__u16 treble)
+static void tr_settreble(struct trust *tr, __u16 treble)
 {
-	curtreble = treble / 4370;
-	write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]);
+	mutex_lock(&tr->lock);
+	tr->curtreble = treble / 4370;
+	write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]);
+	mutex_unlock(&tr->lock);
 }
 
-static void tr_setstereo(int stereo)
+static void tr_setstereo(struct trust *tr, int stereo)
 {
-	curstereo = !!stereo;
-	ioval = (ioval & 0xfb) | (!curstereo << 2);
-	outb(ioval, io);
+	mutex_lock(&tr->lock);
+	tr->curstereo = !!stereo;
+	tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2);
+	outb(tr->ioval, tr->io);
+	mutex_unlock(&tr->lock);
 }
 
-static void tr_setmute(int mute)
+static void tr_setmute(struct trust *tr, int mute)
 {
-	curmute = !!mute;
-	ioval = (ioval & 0xf7) | (curmute << 3);
-	outb(ioval, io);
+	mutex_lock(&tr->lock);
+	tr->curmute = !!mute;
+	tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3);
+	outb(tr->ioval, tr->io);
+	mutex_unlock(&tr->lock);
 }
 
-static int tr_getsigstr(void)
+static int tr_getsigstr(struct trust *tr)
 {
 	int i, v;
 
-	for(i = 0, v = 0; i < 100; i++) v |= inb(io);
-	return (v & 1)? 0 : 0xffff;
+	mutex_lock(&tr->lock);
+	for (i = 0, v = 0; i < 100; i++)
+		v |= inb(tr->io);
+	mutex_unlock(&tr->lock);
+	return (v & 1) ? 0 : 0xffff;
 }
 
-static int tr_getstereo(void)
+static int tr_getstereo(struct trust *tr)
 {
 	/* don't know how to determine it, just return the setting */
-	return curstereo;
+	return tr->curstereo;
 }
 
-static void tr_setfreq(unsigned long f)
+static void tr_setfreq(struct trust *tr, unsigned long f)
 {
+	mutex_lock(&tr->lock);
+	tr->curfreq = f;
 	f /= 160;	/* Convert to 10 kHz units	*/
-	f += 1070;	/* Add 10.7 MHz IF			*/
-
-	write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0);
+	f += 1070;	/* Add 10.7 MHz IF		*/
+	write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0);
+	mutex_unlock(&tr->lock);
 }
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -199,68 +195,75 @@
 {
 	strlcpy(v->driver, "radio-trust", sizeof(v->driver));
 	strlcpy(v->card, "Trust FM Radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
+	struct trust *tr = video_drvdata(file);
+
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (87.5*16000);
-	v->rangehigh = (108*16000);
-	v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->rangelow = 87.5 * 16000;
+	v->rangehigh = 108 * 16000;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 	v->capability = V4L2_TUNER_CAP_LOW;
-	if (tr_getstereo())
+	if (tr_getstereo(tr))
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 	else
 		v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = tr_getsigstr();
+	v->signal = tr_getsigstr(tr);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
+	struct trust *tr = video_drvdata(file);
 
+	if (v->index)
+		return -EINVAL;
+	tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO);
 	return 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
-	curfreq = f->frequency;
-	tr_setfreq(curfreq);
+	struct trust *tr = video_drvdata(file);
+
+	tr_setfreq(tr, f->frequency);
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
+	struct trust *tr = video_drvdata(file);
+
 	f->type = V4L2_TUNER_RADIO;
-	f->frequency = curfreq;
+	f->frequency = tr->curfreq;
 	return 0;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
 				struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 2048, 65535);
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768);
 	}
 	return -EINVAL;
 }
@@ -268,18 +271,20 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
+	struct trust *tr = video_drvdata(file);
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = curmute;
+		ctrl->value = tr->curmute;
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = curvol * 2048;
+		ctrl->value = tr->curvol * 2048;
 		return 0;
 	case V4L2_CID_AUDIO_BASS:
-		ctrl->value = curbass * 4370;
+		ctrl->value = tr->curbass * 4370;
 		return 0;
 	case V4L2_CID_AUDIO_TREBLE:
-		ctrl->value = curtreble * 4370;
+		ctrl->value = tr->curtreble * 4370;
 		return 0;
 	}
 	return -EINVAL;
@@ -288,34 +293,25 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
+	struct trust *tr = video_drvdata(file);
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		tr_setmute(ctrl->value);
+		tr_setmute(tr, ctrl->value);
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		tr_setvol(ctrl->value);
+		tr_setvol(tr, ctrl->value);
 		return 0;
 	case V4L2_CID_AUDIO_BASS:
-		tr_setbass(ctrl->value);
+		tr_setbass(tr, ctrl->value);
 		return 0;
 	case V4L2_CID_AUDIO_TREBLE:
-		tr_settreble(ctrl->value);
+		tr_settreble(tr, ctrl->value);
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-				struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -324,34 +320,38 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 				struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int trust_open(struct file *file)
+{
 	return 0;
 }
 
-static int trust_exclusive_open(struct file *file)
+static int trust_release(struct file *file)
 {
-	return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
-}
-
-static int trust_exclusive_release(struct file *file)
-{
-	clear_bit(0, &in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations trust_fops = {
 	.owner		= THIS_MODULE,
-	.open           = trust_exclusive_open,
-	.release        = trust_exclusive_release,
+	.open           = trust_open,
+	.release        = trust_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -370,59 +370,72 @@
 	.vidioc_s_input     = vidioc_s_input,
 };
 
-static struct video_device trust_radio = {
-	.name		= "Trust FM Radio",
-	.fops           = &trust_fops,
-	.ioctl_ops 	= &trust_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init trust_init(void)
 {
-	if(io == -1) {
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+	struct trust *tr = &trust_card;
+	struct v4l2_device *v4l2_dev = &tr->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name));
+	tr->io = io;
+	tr->ioval = 0xf;
+	mutex_init(&tr->lock);
+
+	if (tr->io == -1) {
+		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n");
 		return -EINVAL;
 	}
-	if(!request_region(io, 2, "Trust FM Radio")) {
-		printk(KERN_ERR "trust: port 0x%x already in use\n", io);
+	if (!request_region(tr->io, 2, "Trust FM Radio")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io);
 		return -EBUSY;
 	}
-	if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 2);
+
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(tr->io, 2);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
+
+	strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name));
+	tr->vdev.v4l2_dev = v4l2_dev;
+	tr->vdev.fops = &trust_fops;
+	tr->vdev.ioctl_ops = &trust_ioctl_ops;
+	tr->vdev.release = video_device_release_empty;
+	video_set_drvdata(&tr->vdev, tr);
+
+	if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(tr->io, 2);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "Trust FM Radio card driver v1.0.\n");
+	v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
 
-	write_i2c(2, TDA7318_ADDR, 0x80);	/* speaker att. LF = 0 dB */
-	write_i2c(2, TDA7318_ADDR, 0xa0);	/* speaker att. RF = 0 dB */
-	write_i2c(2, TDA7318_ADDR, 0xc0);	/* speaker att. LR = 0 dB */
-	write_i2c(2, TDA7318_ADDR, 0xe0);	/* speaker att. RR = 0 dB */
-	write_i2c(2, TDA7318_ADDR, 0x40);	/* stereo 1 input, gain = 18.75 dB */
+	write_i2c(tr, 2, TDA7318_ADDR, 0x80);	/* speaker att. LF = 0 dB */
+	write_i2c(tr, 2, TDA7318_ADDR, 0xa0);	/* speaker att. RF = 0 dB */
+	write_i2c(tr, 2, TDA7318_ADDR, 0xc0);	/* speaker att. LR = 0 dB */
+	write_i2c(tr, 2, TDA7318_ADDR, 0xe0);	/* speaker att. RR = 0 dB */
+	write_i2c(tr, 2, TDA7318_ADDR, 0x40);	/* stereo 1 input, gain = 18.75 dB */
 
-	tr_setvol(0x8000);
-	tr_setbass(0x8000);
-	tr_settreble(0x8000);
-	tr_setstereo(1);
+	tr_setvol(tr, 0xffff);
+	tr_setbass(tr, 0x8000);
+	tr_settreble(tr, 0x8000);
+	tr_setstereo(tr, 1);
 
 	/* mute card - prevents noisy bootups */
-	tr_setmute(1);
+	tr_setmute(tr, 1);
 
 	return 0;
 }
 
-MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
-MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
-module_param(radio_nr, int, 0);
-
 static void __exit cleanup_trust_module(void)
 {
-	video_unregister_device(&trust_radio);
-	release_region(io, 2);
+	struct trust *tr = &trust_card;
+
+	video_unregister_device(&tr->vdev);
+	v4l2_device_unregister(&tr->v4l2_dev);
+	release_region(tr->io, 2);
 }
 
 module_init(trust_init);
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 5c3b319..92d923c 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -34,37 +34,15 @@
 #include <linux/module.h>	/* Modules                        */
 #include <linux/init.h>		/* Initdata                       */
 #include <linux/ioport.h>	/* request_region		  */
-#include <linux/proc_fs.h>	/* radio card status report	  */
-#include <linux/seq_file.h>
-#include <asm/io.h>		/* outb, outb_p                   */
-#include <asm/uaccess.h>	/* copy to/from user              */
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #include <linux/videodev2.h>	/* kernel radio structs           */
-#include <media/v4l2-common.h>
+#include <linux/io.h>		/* outb, outb_p                   */
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,1,1)
-#define BANNER "Typhoon Radio Card driver v0.1.1\n"
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 1<<14,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
-
+MODULE_AUTHOR("Dr. Henrik Seidel");
+MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
+MODULE_LICENSE("GPL");
 
 #ifndef CONFIG_RADIO_TYPHOON_PORT
 #define CONFIG_RADIO_TYPHOON_PORT -1
@@ -74,13 +52,26 @@
 #define CONFIG_RADIO_TYPHOON_MUTEFREQ 0
 #endif
 
-#ifndef CONFIG_PROC_FS
-#undef CONFIG_RADIO_TYPHOON_PROC_FS
-#endif
+static int io = CONFIG_RADIO_TYPHOON_PORT;
+static int radio_nr = -1;
 
-struct typhoon_device {
-	unsigned long in_use;
-	int iobase;
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+
+module_param(radio_nr, int, 0);
+
+static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ;
+module_param(mutefreq, ulong, 0);
+MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+
+#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
+
+#define BANNER "Typhoon Radio Card driver v0.1.1\n"
+
+struct typhoon {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
 	int curvol;
 	int muted;
 	unsigned long curfreq;
@@ -88,25 +79,19 @@
 	struct mutex lock;
 };
 
-static void typhoon_setvol_generic(struct typhoon_device *dev, int vol);
-static int typhoon_setfreq_generic(struct typhoon_device *dev,
-				   unsigned long frequency);
-static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
-static void typhoon_mute(struct typhoon_device *dev);
-static void typhoon_unmute(struct typhoon_device *dev);
-static int typhoon_setvol(struct typhoon_device *dev, int vol);
+static struct typhoon typhoon_card;
 
-static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+static void typhoon_setvol_generic(struct typhoon *dev, int vol)
 {
 	mutex_lock(&dev->lock);
 	vol >>= 14;				/* Map 16 bit to 2 bit */
 	vol &= 3;
-	outb_p(vol / 2, dev->iobase);		/* Set the volume, high bit. */
-	outb_p(vol % 2, dev->iobase + 2);	/* Set the volume, low bit. */
+	outb_p(vol / 2, dev->io);		/* Set the volume, high bit. */
+	outb_p(vol % 2, dev->io + 2);	/* Set the volume, low bit. */
 	mutex_unlock(&dev->lock);
 }
 
-static int typhoon_setfreq_generic(struct typhoon_device *dev,
+static int typhoon_setfreq_generic(struct typhoon *dev,
 				   unsigned long frequency)
 {
 	unsigned long outval;
@@ -130,22 +115,22 @@
 	outval -= (10 * x * x + 10433) / 20866;
 	outval += 4 * x - 11505;
 
-	outb_p((outval >> 8) & 0x01, dev->iobase + 4);
-	outb_p(outval >> 9, dev->iobase + 6);
-	outb_p(outval & 0xff, dev->iobase + 8);
+	outb_p((outval >> 8) & 0x01, dev->io + 4);
+	outb_p(outval >> 9, dev->io + 6);
+	outb_p(outval & 0xff, dev->io + 8);
 	mutex_unlock(&dev->lock);
 
 	return 0;
 }
 
-static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency)
+static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency)
 {
 	typhoon_setfreq_generic(dev, frequency);
 	dev->curfreq = frequency;
 	return 0;
 }
 
-static void typhoon_mute(struct typhoon_device *dev)
+static void typhoon_mute(struct typhoon *dev)
 {
 	if (dev->muted == 1)
 		return;
@@ -154,7 +139,7 @@
 	dev->muted = 1;
 }
 
-static void typhoon_unmute(struct typhoon_device *dev)
+static void typhoon_unmute(struct typhoon *dev)
 {
 	if (dev->muted == 0)
 		return;
@@ -163,7 +148,7 @@
 	dev->muted = 0;
 }
 
-static int typhoon_setvol(struct typhoon_device *dev, int vol)
+static int typhoon_setvol(struct typhoon *dev, int vol)
 {
 	if (dev->muted && vol != 0) {	/* user is unmuting the card */
 		dev->curvol = vol;
@@ -188,9 +173,9 @@
 {
 	strlcpy(v->driver, "radio-typhoon", sizeof(v->driver));
 	strlcpy(v->card, "Typhoon Radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
@@ -200,10 +185,10 @@
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (87.5*16000);
-	v->rangehigh = (108*16000);
+	v->rangelow = 87.5 * 16000;
+	v->rangehigh = 108 * 16000;
 	v->rxsubchans = V4L2_TUNER_SUB_MONO;
 	v->capability = V4L2_TUNER_CAP_LOW;
 	v->audmode = V4L2_TUNER_MODE_MONO;
@@ -214,44 +199,37 @@
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
+	return v->index ? -EINVAL : 0;
+}
 
+static int vidioc_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct typhoon *dev = video_drvdata(file);
+
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = dev->curfreq;
 	return 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct typhoon_device *typhoon = video_drvdata(file);
+	struct typhoon *dev = video_drvdata(file);
 
-	typhoon->curfreq = f->frequency;
-	typhoon_setfreq(typhoon, typhoon->curfreq);
-	return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-					struct v4l2_frequency *f)
-{
-	struct typhoon_device *typhoon = video_drvdata(file);
-
-	f->type = V4L2_TUNER_RADIO;
-	f->frequency = typhoon->curfreq;
-
+	dev->curfreq = f->frequency;
+	typhoon_setfreq(dev, dev->curfreq);
 	return 0;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535);
 	}
 	return -EINVAL;
 }
@@ -259,14 +237,14 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct typhoon_device *typhoon = video_drvdata(file);
+	struct typhoon *dev = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = typhoon->muted;
+		ctrl->value = dev->muted;
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = typhoon->curvol;
+		ctrl->value = dev->curvol;
 		return 0;
 	}
 	return -EINVAL;
@@ -275,33 +253,22 @@
 static int vidioc_s_ctrl (struct file *file, void *priv,
 					struct v4l2_control *ctrl)
 {
-	struct typhoon_device *typhoon = video_drvdata(file);
+	struct typhoon *dev = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value)
-			typhoon_mute(typhoon);
+			typhoon_mute(dev);
 		else
-			typhoon_unmute(typhoon);
+			typhoon_unmute(dev);
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		typhoon_setvol(typhoon, ctrl->value);
+		typhoon_setvol(dev, ctrl->value);
 		return 0;
 	}
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -310,45 +277,62 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct typhoon *dev = video_drvdata(file);
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+
+	v4l2_info(v4l2_dev, BANNER);
+#ifdef MODULE
+	v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n");
+#else
+	v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n");
+#endif
+	v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4);
+	v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol);
+	v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ?  "on" : "off");
+	v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io);
+	v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4);
 	return 0;
 }
 
-static struct typhoon_device typhoon_unit =
+static int typhoon_open(struct file *file)
 {
-	.iobase		= CONFIG_RADIO_TYPHOON_PORT,
-	.curfreq	= CONFIG_RADIO_TYPHOON_MUTEFREQ,
-	.mutefreq	= CONFIG_RADIO_TYPHOON_MUTEFREQ,
-};
-
-static int typhoon_exclusive_open(struct file *file)
-{
-	return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
+	return 0;
 }
 
-static int typhoon_exclusive_release(struct file *file)
+static int typhoon_release(struct file *file)
 {
-	clear_bit(0, &typhoon_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations typhoon_fops = {
 	.owner		= THIS_MODULE,
-	.open           = typhoon_exclusive_open,
-	.release        = typhoon_exclusive_release,
+	.open           = typhoon_open,
+	.release        = typhoon_release,
 	.ioctl		= video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
+	.vidioc_log_status  = vidioc_log_status,
 	.vidioc_querycap    = vidioc_querycap,
 	.vidioc_g_tuner     = vidioc_g_tuner,
 	.vidioc_s_tuner     = vidioc_s_tuner,
@@ -363,125 +347,72 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device typhoon_radio = {
-	.name		= "Typhoon Radio",
-	.fops           = &typhoon_fops,
-	.ioctl_ops 	= &typhoon_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-
-static int typhoon_proc_show(struct seq_file *m, void *v)
-{
-	#ifdef MODULE
-	    #define MODULEPROCSTRING "Driver loaded as a module"
-	#else
-	    #define MODULEPROCSTRING "Driver compiled into kernel"
-	#endif
-
-	seq_puts(m, BANNER);
-	seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
-	seq_printf(m, "frequency = %lu kHz\n",
-		typhoon_unit.curfreq >> 4);
-	seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
-	seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
-		"on" : "off");
-	seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
-	seq_printf(m, "mute frequency = %lu kHz\n",
-		typhoon_unit.mutefreq >> 4);
-	return 0;
-}
-
-static int typhoon_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, typhoon_proc_show, NULL);
-}
-
-static const struct file_operations typhoon_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= typhoon_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
-
-MODULE_AUTHOR("Dr. Henrik Seidel");
-MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
-MODULE_LICENSE("GPL");
-
-static int io = -1;
-static int radio_nr = -1;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
-module_param(radio_nr, int, 0);
-
-#ifdef MODULE
-static unsigned long mutefreq;
-module_param(mutefreq, ulong, 0);
-MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
-#endif
-
 static int __init typhoon_init(void)
 {
-#ifdef MODULE
-	if (io == -1) {
-		printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n");
+	struct typhoon *dev = &typhoon_card;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
+	dev->io = io;
+	dev->curfreq = dev->mutefreq = mutefreq;
+
+	if (dev->io == -1) {
+		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");
 		return -EINVAL;
 	}
-	typhoon_unit.iobase = io;
 
-	if (mutefreq < 87000 || mutefreq > 108500) {
-		printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n");
-		printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
+	if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+		v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");
+		v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
 		return -EINVAL;
 	}
-	typhoon_unit.mutefreq = mutefreq;
-#endif /* MODULE */
 
-	printk(KERN_INFO BANNER);
-	mutex_init(&typhoon_unit.lock);
-	io = typhoon_unit.iobase;
-	if (!request_region(io, 8, "typhoon")) {
-		printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
-		       typhoon_unit.iobase);
+	mutex_init(&dev->lock);
+	if (!request_region(dev->io, 8, "typhoon")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n",
+		       dev->io);
 		return -EBUSY;
 	}
 
-	video_set_drvdata(&typhoon_radio, &typhoon_unit);
-	if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 8);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(dev->io, 8);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
+	v4l2_info(v4l2_dev, BANNER);
+
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.fops = &typhoon_fops;
+	dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	video_set_drvdata(&dev->vdev, dev);
+	if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(&dev->v4l2_dev);
+		release_region(dev->io, 8);
 		return -EINVAL;
 	}
-	printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
-	printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
-	       typhoon_unit.mutefreq);
-	typhoon_unit.mutefreq <<= 4;
+	v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
+	v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
+	dev->mutefreq <<= 4;
 
 	/* mute card - prevents noisy bootups */
-	typhoon_mute(&typhoon_unit);
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-	if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
-		printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
-#endif
+	typhoon_mute(dev);
 
 	return 0;
 }
 
-static void __exit typhoon_cleanup_module(void)
+static void __exit typhoon_exit(void)
 {
+	struct typhoon *dev = &typhoon_card;
 
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-	remove_proc_entry("driver/radio-typhoon", NULL);
-#endif
-
-	video_unregister_device(&typhoon_radio);
-	release_region(io, 8);
+	video_unregister_device(&dev->vdev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	release_region(dev->io, 8);
 }
 
 module_init(typhoon_init);
-module_exit(typhoon_cleanup_module);
+module_exit(typhoon_exit);
 
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index d2ac17e..1f85f20 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -33,33 +33,16 @@
 #include <linux/init.h>		/* Initdata                       */
 #include <linux/ioport.h>	/* request_region		  */
 #include <linux/delay.h>	/* udelay, msleep                 */
-#include <asm/io.h>		/* outb, outb_p                   */
-#include <asm/uaccess.h>	/* copy to/from user              */
 #include <linux/videodev2.h>	/* kernel radio structs           */
-#include <media/v4l2-common.h>
+#include <linux/mutex.h>
+#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
+#include <linux/io.h>		/* outb, outb_p                   */
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 
-#include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
-
-static struct v4l2_queryctrl radio_qctrl[] = {
-	{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.default_value = 1,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 4096,
-		.default_value = 0xff,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	}
-};
+MODULE_AUTHOR("C.van Schaik");
+MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
+MODULE_LICENSE("GPL");
 
 #ifndef CONFIG_RADIO_ZOLTRIX_PORT
 #define CONFIG_RADIO_ZOLTRIX_PORT -1
@@ -68,9 +51,16 @@
 static int io = CONFIG_RADIO_ZOLTRIX_PORT;
 static int radio_nr = -1;
 
-struct zol_device {
-	unsigned long in_use;
-	int port;
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+
+struct zoltrix {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	int io;
 	int curvol;
 	unsigned long curfreq;
 	int muted;
@@ -78,161 +68,158 @@
 	struct mutex lock;
 };
 
-static int zol_setvol(struct zol_device *dev, int vol)
+static struct zoltrix zoltrix_card;
+
+static int zol_setvol(struct zoltrix *zol, int vol)
 {
-	dev->curvol = vol;
-	if (dev->muted)
+	zol->curvol = vol;
+	if (zol->muted)
 		return 0;
 
-	mutex_lock(&dev->lock);
+	mutex_lock(&zol->lock);
 	if (vol == 0) {
-		outb(0, io);
-		outb(0, io);
-		inb(io + 3);    /* Zoltrix needs to be read to confirm */
-		mutex_unlock(&dev->lock);
+		outb(0, zol->io);
+		outb(0, zol->io);
+		inb(zol->io + 3);    /* Zoltrix needs to be read to confirm */
+		mutex_unlock(&zol->lock);
 		return 0;
 	}
 
-	outb(dev->curvol-1, io);
+	outb(zol->curvol-1, zol->io);
 	msleep(10);
-	inb(io + 2);
-	mutex_unlock(&dev->lock);
+	inb(zol->io + 2);
+	mutex_unlock(&zol->lock);
 	return 0;
 }
 
-static void zol_mute(struct zol_device *dev)
+static void zol_mute(struct zoltrix *zol)
 {
-	dev->muted = 1;
-	mutex_lock(&dev->lock);
-	outb(0, io);
-	outb(0, io);
-	inb(io + 3);            /* Zoltrix needs to be read to confirm */
-	mutex_unlock(&dev->lock);
+	zol->muted = 1;
+	mutex_lock(&zol->lock);
+	outb(0, zol->io);
+	outb(0, zol->io);
+	inb(zol->io + 3);            /* Zoltrix needs to be read to confirm */
+	mutex_unlock(&zol->lock);
 }
 
-static void zol_unmute(struct zol_device *dev)
+static void zol_unmute(struct zoltrix *zol)
 {
-	dev->muted = 0;
-	zol_setvol(dev, dev->curvol);
+	zol->muted = 0;
+	zol_setvol(zol, zol->curvol);
 }
 
-static int zol_setfreq(struct zol_device *dev, unsigned long freq)
+static int zol_setfreq(struct zoltrix *zol, unsigned long freq)
 {
 	/* tunes the radio to the desired frequency */
+	struct v4l2_device *v4l2_dev = &zol->v4l2_dev;
 	unsigned long long bitmask, f, m;
-	unsigned int stereo = dev->stereo;
+	unsigned int stereo = zol->stereo;
 	int i;
 
 	if (freq == 0) {
-		printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n");
+		v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n");
 		return -EINVAL;
 	}
 
 	m = (freq / 160 - 8800) * 2;
-	f = (unsigned long long) m + 0x4d1c;
+	f = (unsigned long long)m + 0x4d1c;
 
 	bitmask = 0xc480402c10080000ull;
 	i = 45;
 
-	mutex_lock(&dev->lock);
+	mutex_lock(&zol->lock);
 
-	outb(0, io);
-	outb(0, io);
-	inb(io + 3);            /* Zoltrix needs to be read to confirm */
+	zol->curfreq = freq;
 
-	outb(0x40, io);
-	outb(0xc0, io);
+	outb(0, zol->io);
+	outb(0, zol->io);
+	inb(zol->io + 3);            /* Zoltrix needs to be read to confirm */
 
-	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31));
+	outb(0x40, zol->io);
+	outb(0xc0, zol->io);
+
+	bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31));
 	while (i--) {
 		if ((bitmask & 0x8000000000000000ull) != 0) {
-			outb(0x80, io);
+			outb(0x80, zol->io);
 			udelay(50);
-			outb(0x00, io);
+			outb(0x00, zol->io);
 			udelay(50);
-			outb(0x80, io);
+			outb(0x80, zol->io);
 			udelay(50);
 		} else {
-			outb(0xc0, io);
+			outb(0xc0, zol->io);
 			udelay(50);
-			outb(0x40, io);
+			outb(0x40, zol->io);
 			udelay(50);
-			outb(0xc0, io);
+			outb(0xc0, zol->io);
 			udelay(50);
 		}
 		bitmask *= 2;
 	}
 	/* termination sequence */
-	outb(0x80, io);
-	outb(0xc0, io);
-	outb(0x40, io);
+	outb(0x80, zol->io);
+	outb(0xc0, zol->io);
+	outb(0x40, zol->io);
 	udelay(1000);
-	inb(io+2);
+	inb(zol->io + 2);
 
 	udelay(1000);
 
-	if (dev->muted)
-	{
-		outb(0, io);
-		outb(0, io);
-		inb(io + 3);
+	if (zol->muted) {
+		outb(0, zol->io);
+		outb(0, zol->io);
+		inb(zol->io + 3);
 		udelay(1000);
 	}
 
-	mutex_unlock(&dev->lock);
+	mutex_unlock(&zol->lock);
 
-	if(!dev->muted)
-	{
-		zol_setvol(dev, dev->curvol);
-	}
+	if (!zol->muted)
+		zol_setvol(zol, zol->curvol);
 	return 0;
 }
 
 /* Get signal strength */
-
-static int zol_getsigstr(struct zol_device *dev)
+static int zol_getsigstr(struct zoltrix *zol)
 {
 	int a, b;
 
-	mutex_lock(&dev->lock);
-	outb(0x00, io);         /* This stuff I found to do nothing */
-	outb(dev->curvol, io);
+	mutex_lock(&zol->lock);
+	outb(0x00, zol->io);         /* This stuff I found to do nothing */
+	outb(zol->curvol, zol->io);
 	msleep(20);
 
-	a = inb(io);
+	a = inb(zol->io);
 	msleep(10);
-	b = inb(io);
+	b = inb(zol->io);
 
-	mutex_unlock(&dev->lock);
+	mutex_unlock(&zol->lock);
 
 	if (a != b)
-		return (0);
+		return 0;
 
-	if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
-		|| (a == 0xef))       /* with a binary scanner on the card io */
-		return (1);
-	return (0);
+	/* I found this out by playing with a binary scanner on the card io */
+	return a == 0xcf || a == 0xdf || a == 0xef;
 }
 
-static int zol_is_stereo (struct zol_device *dev)
+static int zol_is_stereo(struct zoltrix *zol)
 {
 	int x1, x2;
 
-	mutex_lock(&dev->lock);
+	mutex_lock(&zol->lock);
 
-	outb(0x00, io);
-	outb(dev->curvol, io);
+	outb(0x00, zol->io);
+	outb(zol->curvol, zol->io);
 	msleep(20);
 
-	x1 = inb(io);
+	x1 = inb(zol->io);
 	msleep(10);
-	x2 = inb(io);
+	x2 = inb(zol->io);
 
-	mutex_unlock(&dev->lock);
+	mutex_unlock(&zol->lock);
 
-	if ((x1 == x2) && (x1 == 0xcf))
-		return 1;
-	return 0;
+	return x1 == x2 && x1 == 0xcf;
 }
 
 static int vidioc_querycap(struct file *file, void  *priv,
@@ -240,59 +227,54 @@
 {
 	strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver));
 	strlcpy(v->card, "Zoltrix Radio", sizeof(v->card));
-	sprintf(v->bus_info, "ISA");
+	strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
 	v->version = RADIO_VERSION;
-	v->capabilities = V4L2_CAP_TUNER;
+	v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
 	return 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	struct zol_device *zol = video_drvdata(file);
+	struct zoltrix *zol = video_drvdata(file);
 
 	if (v->index > 0)
 		return -EINVAL;
 
-	strcpy(v->name, "FM");
+	strlcpy(v->name, "FM", sizeof(v->name));
 	v->type = V4L2_TUNER_RADIO;
-	v->rangelow = (88*16000);
-	v->rangehigh = (108*16000);
-	v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->rangelow = 88 * 16000;
+	v->rangehigh = 108 * 16000;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 	v->capability = V4L2_TUNER_CAP_LOW;
 	if (zol_is_stereo(zol))
 		v->audmode = V4L2_TUNER_MODE_STEREO;
 	else
 		v->audmode = V4L2_TUNER_MODE_MONO;
-	v->signal = 0xFFFF*zol_getsigstr(zol);
+	v->signal = 0xFFFF * zol_getsigstr(zol);
 	return 0;
 }
 
 static int vidioc_s_tuner(struct file *file, void *priv,
 					struct v4l2_tuner *v)
 {
-	if (v->index > 0)
-		return -EINVAL;
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct zol_device *zol = video_drvdata(file);
+	struct zoltrix *zol = video_drvdata(file);
 
-	zol->curfreq = f->frequency;
-	if (zol_setfreq(zol, zol->curfreq) != 0) {
-		printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+	if (zol_setfreq(zol, f->frequency) != 0)
 		return -EINVAL;
-	}
 	return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
 					struct v4l2_frequency *f)
 {
-	struct zol_device *zol = video_drvdata(file);
+	struct zoltrix *zol = video_drvdata(file);
 
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = zol->curfreq;
@@ -302,14 +284,11 @@
 static int vidioc_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *qc)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
-			return 0;
-		}
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 4096, 65535);
 	}
 	return -EINVAL;
 }
@@ -317,7 +296,7 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
-	struct zol_device *zol = video_drvdata(file);
+	struct zoltrix *zol = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -333,7 +312,7 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
-	struct zol_device *zol = video_drvdata(file);
+	struct zoltrix *zol = video_drvdata(file);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
@@ -341,43 +320,30 @@
 			zol_mute(zol);
 		else {
 			zol_unmute(zol);
-			zol_setvol(zol,zol->curvol);
+			zol_setvol(zol, zol->curvol);
 		}
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
-		zol_setvol(zol,ctrl->value/4096);
+		zol_setvol(zol, ctrl->value / 4096);
 		return 0;
 	}
 	zol->stereo = 1;
-	if (zol_setfreq(zol, zol->curfreq) != 0) {
-		printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+	if (zol_setfreq(zol, zol->curfreq) != 0)
 		return -EINVAL;
-	}
 #if 0
 /* FIXME: Implement stereo/mono switch on V4L2 */
-			if (v->mode & VIDEO_SOUND_STEREO) {
-				zol->stereo = 1;
-				zol_setfreq(zol, zol->curfreq);
-			}
-			if (v->mode & VIDEO_SOUND_MONO) {
-				zol->stereo = 0;
-				zol_setfreq(zol, zol->curfreq);
-			}
+	if (v->mode & VIDEO_SOUND_STEREO) {
+		zol->stereo = 1;
+		zol_setfreq(zol, zol->curfreq);
+	}
+	if (v->mode & VIDEO_SOUND_MONO) {
+		zol->stereo = 0;
+		zol_setfreq(zol, zol->curfreq);
+	}
 #endif
 	return -EINVAL;
 }
 
-static int vidioc_g_audio(struct file *file, void *priv,
-					struct v4l2_audio *a)
-{
-	if (a->index > 1)
-		return -EINVAL;
-
-	strcpy(a->name, "Radio");
-	a->capability = V4L2_AUDCAP_STEREO;
-	return 0;
-}
-
 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
 {
 	*i = 0;
@@ -386,37 +352,39 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
+	return i ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	a->index = 0;
+	strlcpy(a->name, "Radio", sizeof(a->name));
+	a->capability = V4L2_AUDCAP_STEREO;
 	return 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
+	return a->index ? -EINVAL : 0;
+}
+
+static int zoltrix_open(struct file *file)
+{
 	return 0;
 }
 
-static struct zol_device zoltrix_unit;
-
-static int zoltrix_exclusive_open(struct file *file)
+static int zoltrix_release(struct file *file)
 {
-	return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
-}
-
-static int zoltrix_exclusive_release(struct file *file)
-{
-	clear_bit(0, &zoltrix_unit.in_use);
 	return 0;
 }
 
 static const struct v4l2_file_operations zoltrix_fops =
 {
 	.owner		= THIS_MODULE,
-	.open           = zoltrix_exclusive_open,
-	.release        = zoltrix_exclusive_release,
+	.open           = zoltrix_open,
+	.release        = zoltrix_release,
 	.ioctl		= video_ioctl2,
 };
 
@@ -435,67 +403,75 @@
 	.vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
-static struct video_device zoltrix_radio = {
-	.name		= "Zoltrix Radio Plus",
-	.fops           = &zoltrix_fops,
-	.ioctl_ops 	= &zoltrix_ioctl_ops,
-	.release	= video_device_release_empty,
-};
-
 static int __init zoltrix_init(void)
 {
-	if (io == -1) {
-		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+	struct zoltrix *zol = &zoltrix_card;
+	struct v4l2_device *v4l2_dev = &zol->v4l2_dev;
+	int res;
+
+	strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name));
+	zol->io = io;
+	if (zol->io == -1) {
+		v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n");
 		return -EINVAL;
 	}
-	if ((io != 0x20c) && (io != 0x30c)) {
-		printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n");
+	if (zol->io != 0x20c && zol->io != 0x30c) {
+		v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n");
 		return -ENXIO;
 	}
 
-	video_set_drvdata(&zoltrix_radio, &zoltrix_unit);
-	if (!request_region(io, 2, "zoltrix")) {
-		printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
+	if (!request_region(zol->io, 2, "zoltrix")) {
+		v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io);
 		return -EBUSY;
 	}
 
-	if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
-		release_region(io, 2);
+	res = v4l2_device_register(NULL, v4l2_dev);
+	if (res < 0) {
+		release_region(zol->io, 2);
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return res;
+	}
+
+	strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
+	zol->vdev.v4l2_dev = v4l2_dev;
+	zol->vdev.fops = &zoltrix_fops;
+	zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
+	zol->vdev.release = video_device_release_empty;
+	video_set_drvdata(&zol->vdev, zol);
+
+	if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+		v4l2_device_unregister(v4l2_dev);
+		release_region(zol->io, 2);
 		return -EINVAL;
 	}
-	printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
+	v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
 
-	mutex_init(&zoltrix_unit.lock);
+	mutex_init(&zol->lock);
 
 	/* mute card - prevents noisy bootups */
 
 	/* this ensures that the volume is all the way down  */
 
-	outb(0, io);
-	outb(0, io);
+	outb(0, zol->io);
+	outb(0, zol->io);
 	msleep(20);
-	inb(io + 3);
+	inb(zol->io + 3);
 
-	zoltrix_unit.curvol = 0;
-	zoltrix_unit.stereo = 1;
+	zol->curvol = 0;
+	zol->stereo = 1;
 
 	return 0;
 }
 
-MODULE_AUTHOR("C.van Schaik");
-MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
-module_param(radio_nr, int, 0);
-
-static void __exit zoltrix_cleanup_module(void)
+static void __exit zoltrix_exit(void)
 {
-	video_unregister_device(&zoltrix_radio);
-	release_region(io, 2);
+	struct zoltrix *zol = &zoltrix_card;
+
+	video_unregister_device(&zol->vdev);
+	v4l2_device_unregister(&zol->v4l2_dev);
+	release_region(zol->io, 2);
 }
 
 module_init(zoltrix_init);
-module_exit(zoltrix_cleanup_module);
+module_exit(zoltrix_exit);
 
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 19cf3b8..76bad58 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -249,11 +249,25 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called vp27smpx.
 
+comment "RDS decoders"
+
+config VIDEO_SAA6588
+	tristate "SAA6588 Radio Chip RDS decoder support"
+	depends on VIDEO_V4L2 && I2C
+
+	help
+	  Support for this Radio Data System (RDS) decoder. This allows
+	  seeing radio station identification transmitted using this
+	  standard.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa6588.
+
 comment "Video decoders"
 
 config VIDEO_BT819
 	tristate "BT819A VideoStream decoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for BT819A video decoder.
 
@@ -262,7 +276,7 @@
 
 config VIDEO_BT856
 	tristate "BT856 VideoStream decoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for BT856 video decoder.
 
@@ -271,7 +285,7 @@
 
 config VIDEO_BT866
 	tristate "BT866 VideoStream decoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for BT866 video decoder.
 
@@ -280,7 +294,7 @@
 
 config VIDEO_KS0127
 	tristate "KS0127 video decoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for KS0127 video decoder.
 
@@ -307,38 +321,18 @@
 
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the Philips SAA7110 video decoders.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called saa7110.
 
-config VIDEO_SAA7111
-	tristate "Philips SAA7111 video decoder"
-	depends on VIDEO_V4L1 && I2C
-	---help---
-	  Support for the Philips SAA711 video decoder.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa7111.
-
-config VIDEO_SAA7114
-	tristate "Philips SAA7114 video decoder"
-	depends on VIDEO_V4L1 && I2C
-	---help---
-	  Support for the Philips SAA7114 video decoder. This driver
-	  is used only on Zoran driver and should be moved soon to
-	  SAA711x module.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa7114.
-
 config VIDEO_SAA711X
-	tristate "Philips SAA7113/4/5 video decoders"
+	tristate "Philips SAA7111/3/4/5 video decoders"
 	depends on VIDEO_V4L2 && I2C
 	---help---
-	  Support for the Philips SAA7113/4/5 video decoders.
+	  Support for the Philips SAA7111/3/4/5 video decoders.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called saa7115.
@@ -383,7 +377,7 @@
 
 config VIDEO_VPX3220
 	tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for VPX322x video decoders.
 
@@ -421,7 +415,7 @@
 
 config VIDEO_SAA7185
 	tristate "Philips SAA7185 video encoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the Philips SAA7185 video encoder.
 
@@ -430,7 +424,7 @@
 
 config VIDEO_ADV7170
 	tristate "Analog Devices ADV7170 video encoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the Analog Devices ADV7170 video encoder driver
 
@@ -439,7 +433,7 @@
 
 config VIDEO_ADV7175
 	tristate "Analog Devices ADV7175 video encoder"
-	depends on VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the Analog Devices ADV7175 video encoder driver
 
@@ -487,18 +481,6 @@
 
 source "drivers/media/video/bt8xx/Kconfig"
 
-config VIDEO_SAA6588
-	tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
-	depends on I2C && VIDEO_BT848
-
-	help
-	  Support for  Radio Data System (RDS) decoder. This allows seeing
-	  radio station identification transmitted using this standard.
-	  Currently, it works only with bt8x8 chips.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa6588.
-
 config VIDEO_PMS
 	tristate "Mediavision Pro Movie Studio Video For Linux"
 	depends on ISA && VIDEO_V4L1
@@ -602,7 +584,6 @@
 config VIDEO_VINO
 	tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
 	depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
-	select I2C_ALGO_SGI
 	select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
 	help
 	  Say Y here to build in support for the Vino video input system found
@@ -639,7 +620,7 @@
 	depends on PCI && VIDEO_V4L1 && I2C
 	select VIDEO_SAA7146_VV
 	select VIDEO_TUNER
-	select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
@@ -728,13 +709,6 @@
 	  This driver supports MT9M001 cameras from Micron, monochrome
 	  and colour models.
 
-config MT9M001_PCA9536_SWITCH
-	bool "pca9536 datawidth switch for mt9m001"
-	depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
-	help
-	  Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
-	  extender to switch between 8 and 10 bit datawidth modes
-
 config SOC_CAMERA_MT9M111
 	tristate "mt9m111 and mt9m112 support"
 	depends on SOC_CAMERA && I2C
@@ -754,13 +728,6 @@
 	help
 	  This driver supports MT9V022 cameras from Micron
 
-config MT9V022_PCA9536_SWITCH
-	bool "pca9536 datawidth switch for mt9v022"
-	depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
-	help
-	  Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
-	  extender to switch between 8 and 10 bit datawidth modes
-
 config SOC_CAMERA_TW9910
 	tristate "tw9910 support"
 	depends on SOC_CAMERA && I2C
@@ -779,6 +746,13 @@
 	help
 	  This is a ov772x camera driver
 
+config VIDEO_MX3
+	tristate "i.MX3x Camera Sensor Interface driver"
+	depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
+	select VIDEOBUF_DMA_CONTIG
+	---help---
+	  This is a v4l2 driver for the i.MX3x Camera Sensor Interface
+
 config VIDEO_PXA27x
 	tristate "PXA27x Quick Capture Interface driver"
 	depends on VIDEO_DEV && PXA27x && SOC_CAMERA
@@ -817,6 +791,8 @@
 
 source "drivers/media/video/pvrusb2/Kconfig"
 
+source "drivers/media/video/hdpvr/Kconfig"
+
 source "drivers/media/video/em28xx/Kconfig"
 
 source "drivers/media/video/usbvision/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 72f6d03..b904674 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -30,7 +30,6 @@
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
-obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
@@ -43,8 +42,6 @@
 obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
 obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
 obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
-obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
-obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
 obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
 obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
@@ -122,6 +119,8 @@
 obj-$(CONFIG_USB_ZC0301)        += zc0301/
 obj-$(CONFIG_USB_GSPCA)         += gspca/
 
+obj-$(CONFIG_VIDEO_HDPVR)	+= hdpvr/
+
 obj-$(CONFIG_USB_IBMCAM)        += usbvideo/
 obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
 obj-$(CONFIG_USB_VICAM)         += usbvideo/
@@ -134,10 +133,11 @@
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
-obj-$(CONFIG_VIDEO_PXA27x)	+= pxa_camera.o
+obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o
+obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
 obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
-obj-$(CONFIG_SOC_CAMERA)	+= soc_camera.o
+obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
 obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index e0eb4f3..873c30a 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -34,15 +34,16 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_encoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
 MODULE_AUTHOR("Maxim Yevtyushkin");
 MODULE_LICENSE("GPL");
 
+
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -50,38 +51,43 @@
 /* ----------------------------------------------------------------------- */
 
 struct adv7170 {
+	struct v4l2_subdev sd;
 	unsigned char reg[128];
 
-	int norm;
+	v4l2_std_id norm;
 	int input;
-	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
+static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7170, sd);
+}
+
 static char *inputs[] = { "pass_through", "play_back" };
-static char *norms[] = { "PAL", "NTSC" };
 
 /* ----------------------------------------------------------------------- */
 
-static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
-	struct adv7170 *encoder = i2c_get_clientdata(client);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct adv7170 *encoder = to_adv7170(sd);
 
 	encoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int adv7170_read(struct i2c_client *client, u8 reg)
+static inline int adv7170_read(struct v4l2_subdev *sd, u8 reg)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int adv7170_write_block(struct i2c_client *client,
+static int adv7170_write_block(struct v4l2_subdev *sd,
 		     const u8 *data, unsigned int len)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct adv7170 *encoder = to_adv7170(sd);
 	int ret = -1;
 	u8 reg;
 
@@ -89,7 +95,6 @@
 	 * the adapter understands raw I2C */
 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		/* do raw I2C, not smbus compatible */
-		struct adv7170 *encoder = i2c_get_clientdata(client);
 		u8 block_data[32];
 		int block_len;
 
@@ -110,7 +115,7 @@
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			ret = adv7170_write(client, reg, *data++);
+			ret = adv7170_write(sd, reg, *data++);
 			if (ret < 0)
 				break;
 			len -= 2;
@@ -128,203 +133,161 @@
 #define TR1PLAY	    0x00
 
 static const unsigned char init_NTSC[] = {
-	0x00, 0x10,		// MR0
-	0x01, 0x20,		// MR1
-	0x02, 0x0e,		// MR2 RTC control: bits 2 and 1
-	0x03, 0x80,		// MR3
-	0x04, 0x30,		// MR4
-	0x05, 0x00,		// Reserved
-	0x06, 0x00,		// Reserved
-	0x07, TR0MODE,		// TM0
-	0x08, TR1CAPT,		// TM1
-	0x09, 0x16,		// Fsc0
-	0x0a, 0x7c,		// Fsc1
-	0x0b, 0xf0,		// Fsc2
-	0x0c, 0x21,		// Fsc3
-	0x0d, 0x00,		// Subcarrier Phase
-	0x0e, 0x00,		// Closed Capt. Ext 0
-	0x0f, 0x00,		// Closed Capt. Ext 1
-	0x10, 0x00,		// Closed Capt. 0
-	0x11, 0x00,		// Closed Capt. 1
-	0x12, 0x00,		// Pedestal Ctl 0
-	0x13, 0x00,		// Pedestal Ctl 1
-	0x14, 0x00,		// Pedestal Ctl 2
-	0x15, 0x00,		// Pedestal Ctl 3
-	0x16, 0x00,		// CGMS_WSS_0
-	0x17, 0x00,		// CGMS_WSS_1
-	0x18, 0x00,		// CGMS_WSS_2
-	0x19, 0x00,		// Teletext Ctl
+	0x00, 0x10,		/* MR0 */
+	0x01, 0x20,		/* MR1 */
+	0x02, 0x0e,		/* MR2 RTC control: bits 2 and 1 */
+	0x03, 0x80,		/* MR3 */
+	0x04, 0x30,		/* MR4 */
+	0x05, 0x00,		/* Reserved */
+	0x06, 0x00,		/* Reserved */
+	0x07, TR0MODE,		/* TM0 */
+	0x08, TR1CAPT,		/* TM1 */
+	0x09, 0x16,		/* Fsc0 */
+	0x0a, 0x7c,		/* Fsc1 */
+	0x0b, 0xf0,		/* Fsc2 */
+	0x0c, 0x21,		/* Fsc3 */
+	0x0d, 0x00,		/* Subcarrier Phase */
+	0x0e, 0x00,		/* Closed Capt. Ext 0 */
+	0x0f, 0x00,		/* Closed Capt. Ext 1 */
+	0x10, 0x00,		/* Closed Capt. 0 */
+	0x11, 0x00,		/* Closed Capt. 1 */
+	0x12, 0x00,		/* Pedestal Ctl 0 */
+	0x13, 0x00,		/* Pedestal Ctl 1 */
+	0x14, 0x00,		/* Pedestal Ctl 2 */
+	0x15, 0x00,		/* Pedestal Ctl 3 */
+	0x16, 0x00,		/* CGMS_WSS_0 */
+	0x17, 0x00,		/* CGMS_WSS_1 */
+	0x18, 0x00,		/* CGMS_WSS_2 */
+	0x19, 0x00,		/* Teletext Ctl */
 };
 
 static const unsigned char init_PAL[] = {
-	0x00, 0x71,		// MR0
-	0x01, 0x20,		// MR1
-	0x02, 0x0e,		// MR2 RTC control: bits 2 and 1
-	0x03, 0x80,		// MR3
-	0x04, 0x30,		// MR4
-	0x05, 0x00,		// Reserved
-	0x06, 0x00,		// Reserved
-	0x07, TR0MODE,		// TM0
-	0x08, TR1CAPT,		// TM1
-	0x09, 0xcb,		// Fsc0
-	0x0a, 0x8a,		// Fsc1
-	0x0b, 0x09,		// Fsc2
-	0x0c, 0x2a,		// Fsc3
-	0x0d, 0x00,		// Subcarrier Phase
-	0x0e, 0x00,		// Closed Capt. Ext 0
-	0x0f, 0x00,		// Closed Capt. Ext 1
-	0x10, 0x00,		// Closed Capt. 0
-	0x11, 0x00,		// Closed Capt. 1
-	0x12, 0x00,		// Pedestal Ctl 0
-	0x13, 0x00,		// Pedestal Ctl 1
-	0x14, 0x00,		// Pedestal Ctl 2
-	0x15, 0x00,		// Pedestal Ctl 3
-	0x16, 0x00,		// CGMS_WSS_0
-	0x17, 0x00,		// CGMS_WSS_1
-	0x18, 0x00,		// CGMS_WSS_2
-	0x19, 0x00,		// Teletext Ctl
+	0x00, 0x71,		/* MR0 */
+	0x01, 0x20,		/* MR1 */
+	0x02, 0x0e,		/* MR2 RTC control: bits 2 and 1 */
+	0x03, 0x80,		/* MR3 */
+	0x04, 0x30,		/* MR4 */
+	0x05, 0x00,		/* Reserved */
+	0x06, 0x00,		/* Reserved */
+	0x07, TR0MODE,		/* TM0 */
+	0x08, TR1CAPT,		/* TM1 */
+	0x09, 0xcb,		/* Fsc0 */
+	0x0a, 0x8a,		/* Fsc1 */
+	0x0b, 0x09,		/* Fsc2 */
+	0x0c, 0x2a,		/* Fsc3 */
+	0x0d, 0x00,		/* Subcarrier Phase */
+	0x0e, 0x00,		/* Closed Capt. Ext 0 */
+	0x0f, 0x00,		/* Closed Capt. Ext 1 */
+	0x10, 0x00,		/* Closed Capt. 0 */
+	0x11, 0x00,		/* Closed Capt. 1 */
+	0x12, 0x00,		/* Pedestal Ctl 0 */
+	0x13, 0x00,		/* Pedestal Ctl 1 */
+	0x14, 0x00,		/* Pedestal Ctl 2 */
+	0x15, 0x00,		/* Pedestal Ctl 3 */
+	0x16, 0x00,		/* CGMS_WSS_0 */
+	0x17, 0x00,		/* CGMS_WSS_1 */
+	0x18, 0x00,		/* CGMS_WSS_2 */
+	0x19, 0x00,		/* Teletext Ctl */
 };
 
 
-static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 {
-	struct adv7170 *encoder = i2c_get_clientdata(client);
+	struct adv7170 *encoder = to_adv7170(sd);
 
-	switch (cmd) {
-	case 0:
-#if 0
-		/* This is just for testing!!! */
-		adv7170_write_block(client, init_common,
-				    sizeof(init_common));
-		adv7170_write(client, 0x07, TR0MODE | TR0RST);
-		adv7170_write(client, 0x07, TR0MODE);
-#endif
-		break;
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
 
-	case ENCODER_GET_CAPABILITIES:
-	{
-		struct video_encoder_capability *cap = arg;
-
-		cap->flags = VIDEO_ENCODER_PAL |
-			     VIDEO_ENCODER_NTSC;
-		cap->inputs = 2;
-		cap->outputs = 1;
-		break;
-	}
-
-	case ENCODER_SET_NORM:
-	{
-		int iarg = *(int *) arg;
-
-		v4l_dbg(1, debug, client, "set norm %d\n", iarg);
-
-		switch (iarg) {
-		case VIDEO_MODE_NTSC:
-			adv7170_write_block(client, init_NTSC,
-					    sizeof(init_NTSC));
-			if (encoder->input == 0)
-				adv7170_write(client, 0x02, 0x0e);	// Enable genlock
-			adv7170_write(client, 0x07, TR0MODE | TR0RST);
-			adv7170_write(client, 0x07, TR0MODE);
-			break;
-
-		case VIDEO_MODE_PAL:
-			adv7170_write_block(client, init_PAL,
-					    sizeof(init_PAL));
-			if (encoder->input == 0)
-				adv7170_write(client, 0x02, 0x0e);	// Enable genlock
-			adv7170_write(client, 0x07, TR0MODE | TR0RST);
-			adv7170_write(client, 0x07, TR0MODE);
-			break;
-
-		default:
-			v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
-			return -EINVAL;
-		}
-		v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
-		encoder->norm = iarg;
-		break;
-	}
-
-	case ENCODER_SET_INPUT:
-	{
-		int iarg = *(int *) arg;
-
-		/* RJ: *iarg = 0: input is from decoder
-		 *iarg = 1: input is from ZR36060
-		 *iarg = 2: color bar */
-
-		v4l_dbg(1, debug, client, "set input from %s\n",
-			iarg == 0 ? "decoder" : "ZR36060");
-
-		switch (iarg) {
-		case 0:
-			adv7170_write(client, 0x01, 0x20);
-			adv7170_write(client, 0x08, TR1CAPT);	/* TR1 */
-			adv7170_write(client, 0x02, 0x0e);	// Enable genlock
-			adv7170_write(client, 0x07, TR0MODE | TR0RST);
-			adv7170_write(client, 0x07, TR0MODE);
-			/* udelay(10); */
-			break;
-
-		case 1:
-			adv7170_write(client, 0x01, 0x00);
-			adv7170_write(client, 0x08, TR1PLAY);	/* TR1 */
-			adv7170_write(client, 0x02, 0x08);
-			adv7170_write(client, 0x07, TR0MODE | TR0RST);
-			adv7170_write(client, 0x07, TR0MODE);
-			/* udelay(10); */
-			break;
-
-		default:
-			v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
-			return -EINVAL;
-		}
-		v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
-		encoder->input = iarg;
-		break;
-	}
-
-	case ENCODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0) {
-			return -EINVAL;
-		}
-		break;
-	}
-
-	case ENCODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-
-		encoder->enable = !!*iarg;
-		break;
-	}
-
-	default:
+	if (std & V4L2_STD_NTSC) {
+		adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC));
+		if (encoder->input == 0)
+			adv7170_write(sd, 0x02, 0x0e);	/* Enable genlock */
+		adv7170_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7170_write(sd, 0x07, TR0MODE);
+	} else if (std & V4L2_STD_PAL) {
+		adv7170_write_block(sd, init_PAL, sizeof(init_PAL));
+		if (encoder->input == 0)
+			adv7170_write(sd, 0x02, 0x0e);	/* Enable genlock */
+		adv7170_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7170_write(sd, 0x07, TR0MODE);
+	} else {
+		v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
+				(unsigned long long)std);
 		return -EINVAL;
 	}
-
+	v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
+	encoder->norm = std;
 	return 0;
 }
 
+static int adv7170_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct adv7170 *encoder = to_adv7170(sd);
+
+	/* RJ: route->input = 0: input is from decoder
+	   route->input = 1: input is from ZR36060
+	   route->input = 2: color bar */
+
+	v4l2_dbg(1, debug, sd, "set input from %s\n",
+			route->input == 0 ? "decoder" : "ZR36060");
+
+	switch (route->input) {
+	case 0:
+		adv7170_write(sd, 0x01, 0x20);
+		adv7170_write(sd, 0x08, TR1CAPT);	/* TR1 */
+		adv7170_write(sd, 0x02, 0x0e);	/* Enable genlock */
+		adv7170_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7170_write(sd, 0x07, TR0MODE);
+		/* udelay(10); */
+		break;
+
+	case 1:
+		adv7170_write(sd, 0x01, 0x00);
+		adv7170_write(sd, 0x08, TR1PLAY);	/* TR1 */
+		adv7170_write(sd, 0x02, 0x08);
+		adv7170_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7170_write(sd, 0x07, TR0MODE);
+		/* udelay(10); */
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input);
+		return -EINVAL;
+	}
+	v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]);
+	encoder->input = route->input;
+	return 0;
+}
+
+static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static unsigned short normal_i2c[] = {
-	0xd4 >> 1, 0xd6 >> 1,	/* adv7170 IDs */
-	0x54 >> 1, 0x56 >> 1,	/* adv7171 IDs */
-	I2C_CLIENT_END
+static const struct v4l2_subdev_core_ops adv7170_core_ops = {
+	.g_chip_ident = adv7170_g_chip_ident,
 };
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_video_ops adv7170_video_ops = {
+	.s_std_output = adv7170_s_std_output,
+	.s_routing = adv7170_s_routing,
+};
+
+static const struct v4l2_subdev_ops adv7170_ops = {
+	.core = &adv7170_core_ops,
+	.video = &adv7170_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
 
 static int adv7170_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct adv7170 *encoder;
+	struct v4l2_subdev *sd;
 	int i;
 
 	/* Check if the adapter supports the needed features */
@@ -337,26 +300,29 @@
 	encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
 	if (encoder == NULL)
 		return -ENOMEM;
-	encoder->norm = VIDEO_MODE_NTSC;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7170_ops);
+	encoder->norm = V4L2_STD_NTSC;
 	encoder->input = 0;
-	encoder->enable = 1;
-	i2c_set_clientdata(client, encoder);
 
-	i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC));
+	i = adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC));
 	if (i >= 0) {
-		i = adv7170_write(client, 0x07, TR0MODE | TR0RST);
-		i = adv7170_write(client, 0x07, TR0MODE);
-		i = adv7170_read(client, 0x12);
-		v4l_dbg(1, debug, client, "revision %d\n", i & 1);
+		i = adv7170_write(sd, 0x07, TR0MODE | TR0RST);
+		i = adv7170_write(sd, 0x07, TR0MODE);
+		i = adv7170_read(sd, 0x12);
+		v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
 	}
 	if (i < 0)
-		v4l_dbg(1, debug, client, "init error 0x%x\n", i);
+		v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
 	return 0;
 }
 
 static int adv7170_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_adv7170(sd));
 	return 0;
 }
 
@@ -371,8 +337,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "adv7170",
-	.driverid = I2C_DRIVERID_ADV7170,
-	.command = adv7170_command,
 	.probe = adv7170_probe,
 	.remove = adv7170_remove,
 	.id_table = adv7170_id,
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 6008e84..ff12103 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -30,15 +30,19 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_encoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
 MODULE_AUTHOR("Dave Perks");
 MODULE_LICENSE("GPL");
 
+#define   I2C_ADV7175        0xd4
+#define   I2C_ADV7176        0x54
+
+
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -46,36 +50,38 @@
 /* ----------------------------------------------------------------------- */
 
 struct adv7175 {
-	int norm;
+	struct v4l2_subdev sd;
+	v4l2_std_id norm;
 	int input;
-	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
-#define   I2C_ADV7175        0xd4
-#define   I2C_ADV7176        0x54
+static inline struct adv7175 *to_adv7175(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7175, sd);
+}
 
 static char *inputs[] = { "pass_through", "play_back", "color_bar" };
-static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
 
 /* ----------------------------------------------------------------------- */
 
-static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int adv7175_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int adv7175_read(struct i2c_client *client, u8 reg)
+static inline int adv7175_read(struct v4l2_subdev *sd, u8 reg)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int adv7175_write_block(struct i2c_client *client,
+static int adv7175_write_block(struct v4l2_subdev *sd,
 		     const u8 *data, unsigned int len)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret = -1;
 	u8 reg;
 
@@ -103,7 +109,7 @@
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			ret = adv7175_write(client, reg, *data++);
+			ret = adv7175_write(sd, reg, *data++);
 			if (ret < 0)
 				break;
 			len -= 2;
@@ -113,18 +119,18 @@
 	return ret;
 }
 
-static void set_subcarrier_freq(struct i2c_client *client, int pass_through)
+static void set_subcarrier_freq(struct v4l2_subdev *sd, int pass_through)
 {
 	/* for some reason pass_through NTSC needs
 	 * a different sub-carrier freq to remain stable. */
 	if (pass_through)
-		adv7175_write(client, 0x02, 0x00);
+		adv7175_write(sd, 0x02, 0x00);
 	else
-		adv7175_write(client, 0x02, 0x55);
+		adv7175_write(sd, 0x02, 0x55);
 
-	adv7175_write(client, 0x03, 0x55);
-	adv7175_write(client, 0x04, 0x55);
-	adv7175_write(client, 0x05, 0x25);
+	adv7175_write(sd, 0x03, 0x55);
+	adv7175_write(sd, 0x04, 0x55);
+	adv7175_write(sd, 0x05, 0x25);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -184,180 +190,144 @@
 	0x06, 0x1a,		/* subc. phase */
 };
 
-static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int adv7175_init(struct v4l2_subdev *sd, u32 val)
 {
-	struct adv7175 *encoder = i2c_get_clientdata(client);
+	/* This is just for testing!!! */
+	adv7175_write_block(sd, init_common, sizeof(init_common));
+	adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+	adv7175_write(sd, 0x07, TR0MODE);
+	return 0;
+}
 
-	switch (cmd) {
-	case 0:
-		/* This is just for testing!!! */
-		adv7175_write_block(client, init_common,
-				    sizeof(init_common));
-		adv7175_write(client, 0x07, TR0MODE | TR0RST);
-		adv7175_write(client, 0x07, TR0MODE);
-		break;
+static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7175 *encoder = to_adv7175(sd);
 
-	case ENCODER_GET_CAPABILITIES:
-	{
-		struct video_encoder_capability *cap = arg;
-
-		cap->flags = VIDEO_ENCODER_PAL |
-			     VIDEO_ENCODER_NTSC |
-			     VIDEO_ENCODER_SECAM; /* well, hacky */
-		cap->inputs = 2;
-		cap->outputs = 1;
-		break;
-	}
-
-	case ENCODER_SET_NORM:
-	{
-		int iarg = *(int *) arg;
-
-		switch (iarg) {
-		case VIDEO_MODE_NTSC:
-			adv7175_write_block(client, init_ntsc,
-					    sizeof(init_ntsc));
-			if (encoder->input == 0)
-				adv7175_write(client, 0x0d, 0x4f);	// Enable genlock
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			break;
-
-		case VIDEO_MODE_PAL:
-			adv7175_write_block(client, init_pal,
-					    sizeof(init_pal));
-			if (encoder->input == 0)
-				adv7175_write(client, 0x0d, 0x4f);	// Enable genlock
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			break;
-
-		case VIDEO_MODE_SECAM:	// WARNING! ADV7176 does not support SECAM.
-			/* This is an attempt to convert
-			 * SECAM->PAL (typically it does not work
-			 * due to genlock: when decoder is in SECAM
-			 * and encoder in in PAL the subcarrier can
-			 * not be syncronized with horizontal
-			 * quency) */
-			adv7175_write_block(client, init_pal,
-					    sizeof(init_pal));
-			if (encoder->input == 0)
-				adv7175_write(client, 0x0d, 0x49);	// Disable genlock
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			break;
-		default:
-			v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
-			return -EINVAL;
-		}
-		v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
-		encoder->norm = iarg;
-		break;
-	}
-
-	case ENCODER_SET_INPUT:
-	{
-		int iarg = *(int *) arg;
-
-		/* RJ: *iarg = 0: input is from SAA7110
-		 *iarg = 1: input is from ZR36060
-		 *iarg = 2: color bar */
-
-		switch (iarg) {
-		case 0:
-			adv7175_write(client, 0x01, 0x00);
-
-			if (encoder->norm == VIDEO_MODE_NTSC)
-				set_subcarrier_freq(client, 1);
-
-			adv7175_write(client, 0x0c, TR1CAPT);	/* TR1 */
-			if (encoder->norm == VIDEO_MODE_SECAM)
-				adv7175_write(client, 0x0d, 0x49);	// Disable genlock
-			else
-				adv7175_write(client, 0x0d, 0x4f);	// Enable genlock
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			//udelay(10);
-			break;
-
-		case 1:
-			adv7175_write(client, 0x01, 0x00);
-
-			if (encoder->norm == VIDEO_MODE_NTSC)
-				set_subcarrier_freq(client, 0);
-
-			adv7175_write(client, 0x0c, TR1PLAY);	/* TR1 */
-			adv7175_write(client, 0x0d, 0x49);
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			/* udelay(10); */
-			break;
-
-		case 2:
-			adv7175_write(client, 0x01, 0x80);
-
-			if (encoder->norm == VIDEO_MODE_NTSC)
-				set_subcarrier_freq(client, 0);
-
-			adv7175_write(client, 0x0d, 0x49);
-			adv7175_write(client, 0x07, TR0MODE | TR0RST);
-			adv7175_write(client, 0x07, TR0MODE);
-			/* udelay(10); */
-			break;
-
-		default:
-			v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
-			return -EINVAL;
-		}
-		v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
-		encoder->input = iarg;
-		break;
-	}
-
-	case ENCODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-
-	case ENCODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-
-		encoder->enable = !!*iarg;
-		break;
-	}
-
-	default:
+	if (std & V4L2_STD_NTSC) {
+		adv7175_write_block(sd, init_ntsc, sizeof(init_ntsc));
+		if (encoder->input == 0)
+			adv7175_write(sd, 0x0d, 0x4f);	/* Enable genlock */
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+	} else if (std & V4L2_STD_PAL) {
+		adv7175_write_block(sd, init_pal, sizeof(init_pal));
+		if (encoder->input == 0)
+			adv7175_write(sd, 0x0d, 0x4f);	/* Enable genlock */
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+	} else if (std & V4L2_STD_SECAM) {
+		/* This is an attempt to convert
+		 * SECAM->PAL (typically it does not work
+		 * due to genlock: when decoder is in SECAM
+		 * and encoder in in PAL the subcarrier can
+		 * not be syncronized with horizontal
+		 * quency) */
+		adv7175_write_block(sd, init_pal, sizeof(init_pal));
+		if (encoder->input == 0)
+			adv7175_write(sd, 0x0d, 0x49);	/* Disable genlock */
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+	} else {
+		v4l2_dbg(1, debug, sd, "illegal norm: %llx\n",
+				(unsigned long long)std);
 		return -EINVAL;
 	}
-
+	v4l2_dbg(1, debug, sd, "switched to %llx\n", (unsigned long long)std);
+	encoder->norm = std;
 	return 0;
 }
 
+static int adv7175_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct adv7175 *encoder = to_adv7175(sd);
+
+	/* RJ: route->input = 0: input is from decoder
+	   route->input = 1: input is from ZR36060
+	   route->input = 2: color bar */
+
+	switch (route->input) {
+	case 0:
+		adv7175_write(sd, 0x01, 0x00);
+
+		if (encoder->norm & V4L2_STD_NTSC)
+			set_subcarrier_freq(sd, 1);
+
+		adv7175_write(sd, 0x0c, TR1CAPT);	/* TR1 */
+		if (encoder->norm & V4L2_STD_SECAM)
+			adv7175_write(sd, 0x0d, 0x49);	/* Disable genlock */
+		else
+			adv7175_write(sd, 0x0d, 0x4f);	/* Enable genlock */
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+		/*udelay(10);*/
+		break;
+
+	case 1:
+		adv7175_write(sd, 0x01, 0x00);
+
+		if (encoder->norm & V4L2_STD_NTSC)
+			set_subcarrier_freq(sd, 0);
+
+		adv7175_write(sd, 0x0c, TR1PLAY);	/* TR1 */
+		adv7175_write(sd, 0x0d, 0x49);
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+		/* udelay(10); */
+		break;
+
+	case 2:
+		adv7175_write(sd, 0x01, 0x80);
+
+		if (encoder->norm & V4L2_STD_NTSC)
+			set_subcarrier_freq(sd, 0);
+
+		adv7175_write(sd, 0x0d, 0x49);
+		adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		adv7175_write(sd, 0x07, TR0MODE);
+		/* udelay(10); */
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd, "illegal input: %d\n", route->input);
+		return -EINVAL;
+	}
+	v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[route->input]);
+	encoder->input = route->input;
+	return 0;
+}
+
+static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
-static unsigned short normal_i2c[] = {
-	I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1,
-	I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
-	I2C_CLIENT_END
+static const struct v4l2_subdev_core_ops adv7175_core_ops = {
+	.g_chip_ident = adv7175_g_chip_ident,
+	.init = adv7175_init,
 };
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_video_ops adv7175_video_ops = {
+	.s_std_output = adv7175_s_std_output,
+	.s_routing = adv7175_s_routing,
+};
+
+static const struct v4l2_subdev_ops adv7175_ops = {
+	.core = &adv7175_core_ops,
+	.video = &adv7175_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
 
 static int adv7175_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	int i;
 	struct adv7175 *encoder;
+	struct v4l2_subdev *sd;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -369,26 +339,29 @@
 	encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
 	if (encoder == NULL)
 		return -ENOMEM;
-	encoder->norm = VIDEO_MODE_PAL;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
+	encoder->norm = V4L2_STD_NTSC;
 	encoder->input = 0;
-	encoder->enable = 1;
-	i2c_set_clientdata(client, encoder);
 
-	i = adv7175_write_block(client, init_common, sizeof(init_common));
+	i = adv7175_write_block(sd, init_common, sizeof(init_common));
 	if (i >= 0) {
-		i = adv7175_write(client, 0x07, TR0MODE | TR0RST);
-		i = adv7175_write(client, 0x07, TR0MODE);
-		i = adv7175_read(client, 0x12);
-		v4l_dbg(1, debug, client, "revision %d\n", i & 1);
+		i = adv7175_write(sd, 0x07, TR0MODE | TR0RST);
+		i = adv7175_write(sd, 0x07, TR0MODE);
+		i = adv7175_read(sd, 0x12);
+		v4l2_dbg(1, debug, sd, "revision %d\n", i & 1);
 	}
 	if (i < 0)
-		v4l_dbg(1, debug, client, "init error 0x%x\n", i);
+		v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
 	return 0;
 }
 
 static int adv7175_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_adv7175(sd));
 	return 0;
 }
 
@@ -403,8 +376,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "adv7175",
-	.driverid = I2C_DRIVERID_ADV7175,
-	.command = adv7175_command,
 	.probe = adv7175_probe,
 	.remove = adv7175_remove,
 	.id_table = adv7175_id,
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
index 018f72b..05cdf49 100644
--- a/drivers/media/video/au0828/Kconfig
+++ b/drivers/media/video/au0828/Kconfig
@@ -1,13 +1,13 @@
 
 config VIDEO_AU0828
 	tristate "Auvitek AU0828 support"
-	depends on I2C && INPUT && DVB_CORE && USB
+	depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
 	select I2C_ALGOBIT
 	select VIDEO_TVEEPROM
-	select DVB_AU8522 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
+	select DVB_AU8522 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This is a video4linux driver for Auvitek's USB device.
 
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
index cd2c582..4d26231 100644
--- a/drivers/media/video/au0828/Makefile
+++ b/drivers/media/video/au0828/Makefile
@@ -1,4 +1,4 @@
-au0828-objs	:= au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
+au0828-objs	:= au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
index d60123b..1aabaa7 100644
--- a/drivers/media/video/au0828/au0828-cards.c
+++ b/drivers/media/video/au0828/au0828-cards.c
@@ -21,25 +21,89 @@
 
 #include "au0828.h"
 #include "au0828-cards.h"
+#include "au8522.h"
+#include "media/tuner.h"
+#include "media/v4l2-common.h"
+
+void hvr950q_cs5340_audio(void *priv, int enable)
+{
+	/* Because the HVR-950q shares an i2s bus between the cs5340 and the
+	   au8522, we need to hold cs5340 in reset when using the au8522 */
+	struct au0828_dev *dev = priv;
+	if (enable == 1)
+		au0828_set(dev, REG_000, 0x10);
+	else
+		au0828_clear(dev, REG_000, 0x10);
+}
 
 struct au0828_board au0828_boards[] = {
 	[AU0828_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
+		.tuner_type = UNSET,
+		.tuner_addr = ADDR_UNSET,
 	},
 	[AU0828_BOARD_HAUPPAUGE_HVR850] = {
 		.name	= "Hauppauge HVR850",
+		.tuner_type = TUNER_XC5000,
+		.tuner_addr = 0x61,
+		.input = {
+			{
+				.type = AU0828_VMUX_TELEVISION,
+				.vmux = AU8522_COMPOSITE_CH4_SIF,
+				.amux = AU8522_AUDIO_SIF,
+			},
+			{
+				.type = AU0828_VMUX_COMPOSITE,
+				.vmux = AU8522_COMPOSITE_CH1,
+				.amux = AU8522_AUDIO_NONE,
+				.audio_setup = hvr950q_cs5340_audio,
+			},
+			{
+				.type = AU0828_VMUX_SVIDEO,
+				.vmux = AU8522_SVIDEO_CH13,
+				.amux = AU8522_AUDIO_NONE,
+				.audio_setup = hvr950q_cs5340_audio,
+			},
+		},
 	},
 	[AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
 		.name	= "Hauppauge HVR950Q",
+		.tuner_type = TUNER_XC5000,
+		.tuner_addr = 0x61,
+		.input = {
+			{
+				.type = AU0828_VMUX_TELEVISION,
+				.vmux = AU8522_COMPOSITE_CH4_SIF,
+				.amux = AU8522_AUDIO_SIF,
+			},
+			{
+				.type = AU0828_VMUX_COMPOSITE,
+				.vmux = AU8522_COMPOSITE_CH1,
+				.amux = AU8522_AUDIO_NONE,
+				.audio_setup = hvr950q_cs5340_audio,
+			},
+			{
+				.type = AU0828_VMUX_SVIDEO,
+				.vmux = AU8522_SVIDEO_CH13,
+				.amux = AU8522_AUDIO_NONE,
+				.audio_setup = hvr950q_cs5340_audio,
+			},
+		},
 	},
 	[AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
 		.name	= "Hauppauge HVR950Q rev xxF8",
+		.tuner_type = UNSET,
+		.tuner_addr = ADDR_UNSET,
 	},
 	[AU0828_BOARD_DVICO_FUSIONHDTV7] = {
 		.name	= "DViCO FusionHDTV USB",
+		.tuner_type = UNSET,
+		.tuner_addr = ADDR_UNSET,
 	},
 	[AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
 		.name = "Hauppauge Woodbury",
+		.tuner_type = UNSET,
+		.tuner_addr = ADDR_UNSET,
 	},
 };
 
@@ -52,7 +116,7 @@
 
 	dprintk(1, "%s()\n", __func__);
 
-	switch (dev->board) {
+	switch (dev->boardnr) {
 	case AU0828_BOARD_HAUPPAUGE_HVR850:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -81,17 +145,18 @@
 	struct tveeprom tv;
 
 	tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+	dev->board.tuner_type = tv.tuner_type;
 
 	/* Make sure we support the board model */
 	switch (tv.model) {
 	case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
-	case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
-	case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
-	case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
-	case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
-	case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */
-	case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
-	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
+	case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+	case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+	case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+	case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
+	case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+	case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
 	case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
 		break;
 	default:
@@ -107,15 +172,21 @@
 void au0828_card_setup(struct au0828_dev *dev)
 {
 	static u8 eeprom[256];
+	struct tuner_setup tun_setup;
+	struct v4l2_subdev *sd;
+	unsigned int mode_mask = T_ANALOG_TV |
+				 T_DIGITAL_TV;
 
 	dprintk(1, "%s()\n", __func__);
 
+	memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
+
 	if (dev->i2c_rc == 0) {
 		dev->i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
 	}
 
-	switch (dev->board) {
+	switch (dev->boardnr) {
 	case AU0828_BOARD_HAUPPAUGE_HVR850:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -124,6 +195,32 @@
 			hauppauge_eeprom(dev, eeprom+0xa0);
 		break;
 	}
+
+	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
+		/* Load the analog demodulator driver (note this would need to
+		   be abstracted out if we ever need to support a different
+		   demod) */
+		sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "au8522", "au8522",
+					 0x8e >> 1);
+		if (sd == NULL)
+			printk(KERN_ERR "analog subdev registration failed\n");
+	}
+
+	/* Setup tuners */
+	if (dev->board.tuner_type != TUNER_ABSENT) {
+		/* Load the tuner module, which does the attach */
+		sd = v4l2_i2c_new_subdev(&dev->i2c_adap, "tuner", "tuner",
+					 dev->board.tuner_addr);
+		if (sd == NULL)
+			printk(KERN_ERR "tuner subdev registration fail\n");
+
+		tun_setup.mode_mask      = mode_mask;
+		tun_setup.type           = dev->board.tuner_type;
+		tun_setup.addr           = dev->board.tuner_addr;
+		tun_setup.tuner_callback = au0828_tuner_callback;
+		v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr,
+				     &tun_setup);
+	}
 }
 
 /*
@@ -135,7 +232,7 @@
 {
 	dprintk(1, "%s()\n", __func__);
 
-	switch (dev->board) {
+	switch (dev->boardnr) {
 	case AU0828_BOARD_HAUPPAUGE_HVR850:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
@@ -144,21 +241,23 @@
 		 * 4 - CS5340
 		 * 5 - AU8522 Demodulator
 		 * 6 - eeprom W/P
+		 * 7 - power supply
 		 * 9 - XC5000 Tuner
 		 */
 
 		/* Into reset */
 		au0828_write(dev, REG_003, 0x02);
-		au0828_write(dev, REG_002, 0x88 | 0x20);
+		au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
 		au0828_write(dev, REG_001, 0x0);
 		au0828_write(dev, REG_000, 0x0);
 		msleep(100);
 
-		/* Out of reset */
+		/* Out of reset (leave the cs5340 in reset until needed) */
 		au0828_write(dev, REG_003, 0x02);
 		au0828_write(dev, REG_001, 0x02);
-		au0828_write(dev, REG_002, 0x88 | 0x20);
-		au0828_write(dev, REG_000, 0x88 | 0x20 | 0x40);
+		au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
+		au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20);
+
 		msleep(250);
 		break;
 	case AU0828_BOARD_DVICO_FUSIONHDTV7:
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
index 5765e86..8c761d164 100644
--- a/drivers/media/video/au0828/au0828-core.c
+++ b/drivers/media/video/au0828/au0828-core.c
@@ -36,6 +36,8 @@
 module_param_named(debug, au0828_debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
 
+static atomic_t au0828_instance = ATOMIC_INIT(0);
+
 #define _AU0828_BULKPIPE 0x03
 #define _BULKPIPESIZE 0xffff
 
@@ -51,13 +53,13 @@
 u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
 {
 	recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
-	dprintk(8, "%s(0x%x) = 0x%x\n", __func__, reg, dev->ctrlmsg[0]);
+	dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]);
 	return dev->ctrlmsg[0];
 }
 
 u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
 {
-	dprintk(8, "%s(0x%x, 0x%x)\n", __func__, reg, val);
+	dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
 	return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
 				dev->ctrlmsg, 0);
 }
@@ -146,9 +148,14 @@
 	/* Digital TV */
 	au0828_dvb_unregister(dev);
 
+	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
+		au0828_analog_unregister(dev);
+
 	/* I2C */
 	au0828_i2c_unregister(dev);
 
+	v4l2_device_unregister(&dev->v4l2_dev);
+
 	usb_set_intfdata(interface, NULL);
 
 	mutex_lock(&dev->mutex);
@@ -162,7 +169,7 @@
 static int au0828_usb_probe(struct usb_interface *interface,
 	const struct usb_device_id *id)
 {
-	int ifnum;
+	int ifnum, retval, i;
 	struct au0828_dev *dev;
 	struct usb_device *usbdev = interface_to_usbdev(interface);
 
@@ -185,10 +192,22 @@
 	mutex_init(&dev->mutex);
 	mutex_init(&dev->dvb.lock);
 	dev->usbdev = usbdev;
-	dev->board = id->driver_info;
+	dev->boardnr = id->driver_info;
 
 	usb_set_intfdata(interface, dev);
 
+	/* Create the v4l2_device */
+	i = atomic_inc_return(&au0828_instance) - 1;
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s-%03d",
+		 "au0828", i);
+	retval = v4l2_device_register(&dev->usbdev->dev, &dev->v4l2_dev);
+	if (retval) {
+		printk(KERN_ERR "%s() v4l2_device_register failed\n",
+		       __func__);
+		kfree(dev);
+		return -EIO;
+	}
+
 	/* Power Up the bridge */
 	au0828_write(dev, REG_600, 1 << 4);
 
@@ -201,12 +220,15 @@
 	/* Setup */
 	au0828_card_setup(dev);
 
+	/* Analog TV */
+	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
+		au0828_analog_register(dev, interface);
+
 	/* Digital TV */
 	au0828_dvb_register(dev);
 
 	printk(KERN_INFO "Registered device AU0828 [%s]\n",
-		au0828_boards[dev->board].name == NULL ? "Unset" :
-		au0828_boards[dev->board].name);
+		dev->board.name == NULL ? "Unset" : dev->board.name);
 
 	return 0;
 }
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
index a882cf5..14baffc 100644
--- a/drivers/media/video/au0828/au0828-dvb.c
+++ b/drivers/media/video/au0828/au0828-dvb.c
@@ -378,7 +378,7 @@
 	dprintk(1, "%s()\n", __func__);
 
 	/* init frontend */
-	switch (dev->board) {
+	switch (dev->boardnr) {
 	case AU0828_BOARD_HAUPPAUGE_HVR850:
 	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
 		dvb->frontend = dvb_attach(au8522_attach,
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
index d618fba..f9a958d 100644
--- a/drivers/media/video/au0828/au0828-i2c.c
+++ b/drivers/media/video/au0828/au0828-i2c.c
@@ -140,13 +140,39 @@
 	dprintk(4, "%s()\n", __func__);
 
 	au0828_write(dev, REG_2FF, 0x01);
-	au0828_write(dev, REG_202, 0x07);
+
+	/* FIXME: There is a problem with i2c communications with xc5000 that
+	   requires us to slow down the i2c clock until we have a better
+	   strategy (such as using the secondary i2c bus to do firmware
+	   loading */
+	if ((msg->addr << 1) == 0xc2)
+		au0828_write(dev, REG_202, 0x40);
+	else
+		au0828_write(dev, REG_202, 0x07);
 
 	/* Hardware needs 8 bit addresses */
 	au0828_write(dev, REG_203, msg->addr << 1);
 
 	dprintk(4, "SEND: %02x\n", msg->addr);
 
+	/* Deal with i2c_scan */
+	if (msg->len == 0) {
+		/* The analog tuner detection code makes use of the SMBUS_QUICK
+		   message (which involves a zero length i2c write).  To avoid
+		   checking the status register when we didn't strobe out any
+		   actual bytes to the bus, just do a read check.  This is
+		   consistent with how I saw i2c device checking done in the
+		   USB trace of the Windows driver */
+		au0828_write(dev, REG_200, 0x20);
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+
+		if (i2c_wait_read_ack(i2c_adap))
+			return -EIO;
+
+		return 0;
+	}
+
 	for (i = 0; i < msg->len;) {
 
 		dprintk(4, " %02x\n", msg->buf[i]);
@@ -191,7 +217,15 @@
 	dprintk(4, "%s()\n", __func__);
 
 	au0828_write(dev, REG_2FF, 0x01);
-	au0828_write(dev, REG_202, 0x07);
+
+	/* FIXME: There is a problem with i2c communications with xc5000 that
+	   requires us to slow down the i2c clock until we have a better
+	   strategy (such as using the secondary i2c bus to do firmware
+	   loading */
+	if ((msg->addr << 1) == 0xc2)
+		au0828_write(dev, REG_202, 0x40);
+	else
+		au0828_write(dev, REG_202, 0x07);
 
 	/* Hardware needs 8 bit addresses */
 	au0828_write(dev, REG_203, msg->addr << 1);
@@ -265,33 +299,6 @@
 	return retval;
 }
 
-static int attach_inform(struct i2c_client *client)
-{
-	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->driver.name, client->addr, client->name);
-
-	if (!client->driver->command)
-		return 0;
-
-	return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
-	dprintk(1, "i2c detach [client=%s]\n", client->name);
-
-	return 0;
-}
-
-void au0828_call_i2c_clients(struct au0828_dev *dev,
-			      unsigned int cmd, void *arg)
-{
-	if (dev->i2c_rc != 0)
-		return;
-
-	i2c_clients_command(&dev->i2c_adap, cmd, arg);
-}
-
 static u32 au0828_functionality(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
@@ -309,9 +316,6 @@
 	.owner             = THIS_MODULE,
 	.id                = I2C_HW_B_AU0828,
 	.algo              = &au0828_i2c_algo_template,
-	.class             = I2C_CLASS_TV_ANALOG,
-	.client_register   = attach_inform,
-	.client_unregister = detach_inform,
 };
 
 static struct i2c_client au0828_i2c_client_template = {
@@ -356,9 +360,9 @@
 	strlcpy(dev->i2c_adap.name, DRIVER_NAME,
 		sizeof(dev->i2c_adap.name));
 
-	dev->i2c_algo.data = dev;
+	dev->i2c_adap.algo = &dev->i2c_algo;
 	dev->i2c_adap.algo_data = dev;
-	i2c_set_adapdata(&dev->i2c_adap, dev);
+	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 	i2c_add_adapter(&dev->i2c_adap);
 
 	dev->i2c_client.adapter = &dev->i2c_adap;
diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
index 1e87fa0c6..b15e4a3 100644
--- a/drivers/media/video/au0828/au0828-reg.h
+++ b/drivers/media/video/au0828/au0828-reg.h
@@ -27,6 +27,9 @@
 #define REG_002 0x002
 #define REG_003 0x003
 
+#define AU0828_SENSORCTRL_100 0x100
+#define AU0828_SENSORCTRL_VBI_103 0x103
+
 #define REG_200 0x200
 #define REG_201 0x201
 #define REG_202 0x202
@@ -35,4 +38,7 @@
 #define REG_209 0x209
 #define REG_2FF 0x2ff
 
+/* Audio registers */
+#define AU0828_AUDIOCTRL_50C 0x50C
+
 #define REG_600 0x600
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
new file mode 100644
index 0000000..f7ad495
--- /dev/null
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -0,0 +1,1712 @@
+/*
+ * Auvitek AU0828 USB Bridge (Analog video support)
+ *
+ * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
+ * Copyright (C) 2005-2008 Auvitek International, 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Developer Notes:
+ *
+ * VBI support is not yet working
+ * The hardware scaler supported is unimplemented
+ * AC97 audio support is unimplemented (only i2s audio mode)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/version.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/tuner.h>
+#include "au0828.h"
+#include "au0828-reg.h"
+
+static LIST_HEAD(au0828_devlist);
+static DEFINE_MUTEX(au0828_sysfs_lock);
+
+#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
+
+/* ------------------------------------------------------------------
+	Videobuf operations
+   ------------------------------------------------------------------*/
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define au0828_isocdbg(fmt, arg...) \
+do {\
+	if (isoc_debug) { \
+		printk(KERN_INFO "au0828 %s :"fmt, \
+		       __func__ , ##arg);	   \
+	} \
+  } while (0)
+
+static inline void print_err_status(struct au0828_dev *dev,
+				    int packet, int status)
+{
+	char *errmsg = "Unknown";
+
+	switch (status) {
+	case -ENOENT:
+		errmsg = "unlinked synchronuously";
+		break;
+	case -ECONNRESET:
+		errmsg = "unlinked asynchronuously";
+		break;
+	case -ENOSR:
+		errmsg = "Buffer error (overrun)";
+		break;
+	case -EPIPE:
+		errmsg = "Stalled (device not responding)";
+		break;
+	case -EOVERFLOW:
+		errmsg = "Babble (bad cable?)";
+		break;
+	case -EPROTO:
+		errmsg = "Bit-stuff error (bad cable?)";
+		break;
+	case -EILSEQ:
+		errmsg = "CRC/Timeout (could be anything)";
+		break;
+	case -ETIME:
+		errmsg = "Device does not respond";
+		break;
+	}
+	if (packet < 0) {
+		au0828_isocdbg("URB status %d [%s].\n",	status, errmsg);
+	} else {
+		au0828_isocdbg("URB packet %d, status %d [%s].\n",
+			       packet, status, errmsg);
+	}
+}
+
+static int check_dev(struct au0828_dev *dev)
+{
+	if (dev->dev_state & DEV_DISCONNECTED) {
+		printk(KERN_INFO "v4l2 ioctl: device not present\n");
+		return -ENODEV;
+	}
+
+	if (dev->dev_state & DEV_MISCONFIGURED) {
+		printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
+		       "close and open it again\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void au0828_irq_callback(struct urb *urb)
+{
+	struct au0828_dmaqueue  *dma_q = urb->context;
+	struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+	int rc, i;
+
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		au0828_isocdbg("au0828_irq_callback called: status kill\n");
+		return;
+	default:            /* unknown error */
+		au0828_isocdbg("urb completition error %d.\n", urb->status);
+		break;
+	}
+
+	/* Copy data from URB */
+	spin_lock(&dev->slock);
+	rc = dev->isoc_ctl.isoc_copy(dev, urb);
+	spin_unlock(&dev->slock);
+
+	/* Reset urb buffers */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		urb->iso_frame_desc[i].status = 0;
+		urb->iso_frame_desc[i].actual_length = 0;
+	}
+	urb->status = 0;
+
+	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (urb->status) {
+		au0828_isocdbg("urb resubmit failed (error=%i)\n",
+			       urb->status);
+	}
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void au0828_uninit_isoc(struct au0828_dev *dev)
+{
+	struct urb *urb;
+	int i;
+
+	au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
+
+	dev->isoc_ctl.nfields = -1;
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		urb = dev->isoc_ctl.urb[i];
+		if (urb) {
+			if (!irqs_disabled())
+				usb_kill_urb(urb);
+			else
+				usb_unlink_urb(urb);
+
+			if (dev->isoc_ctl.transfer_buffer[i]) {
+				usb_buffer_free(dev->usbdev,
+					urb->transfer_buffer_length,
+					dev->isoc_ctl.transfer_buffer[i],
+					urb->transfer_dma);
+			}
+			usb_free_urb(urb);
+			dev->isoc_ctl.urb[i] = NULL;
+		}
+		dev->isoc_ctl.transfer_buffer[i] = NULL;
+	}
+
+	kfree(dev->isoc_ctl.urb);
+	kfree(dev->isoc_ctl.transfer_buffer);
+
+	dev->isoc_ctl.urb = NULL;
+	dev->isoc_ctl.transfer_buffer = NULL;
+	dev->isoc_ctl.num_bufs = 0;
+}
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
+		     int num_bufs, int max_pkt_size,
+		     int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
+{
+	struct au0828_dmaqueue *dma_q = &dev->vidq;
+	int i;
+	int sb_size, pipe;
+	struct urb *urb;
+	int j, k;
+	int rc;
+
+	au0828_isocdbg("au0828: called au0828_prepare_isoc\n");
+
+	/* De-allocates all pending stuff */
+	au0828_uninit_isoc(dev);
+
+	dev->isoc_ctl.isoc_copy = isoc_copy;
+	dev->isoc_ctl.num_bufs = num_bufs;
+
+	dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+	if (!dev->isoc_ctl.urb) {
+		au0828_isocdbg("cannot alloc memory for usb buffers\n");
+		return -ENOMEM;
+	}
+
+	dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+					      GFP_KERNEL);
+	if (!dev->isoc_ctl.transfer_buffer) {
+		au0828_isocdbg("cannot allocate memory for usb transfer\n");
+		kfree(dev->isoc_ctl.urb);
+		return -ENOMEM;
+	}
+
+	dev->isoc_ctl.max_pkt_size = max_pkt_size;
+	dev->isoc_ctl.buf = NULL;
+
+	sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
+
+	/* allocate urbs and transfer buffers */
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+		if (!urb) {
+			au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
+			au0828_uninit_isoc(dev);
+			return -ENOMEM;
+		}
+		dev->isoc_ctl.urb[i] = urb;
+
+		dev->isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->usbdev,
+			sb_size, GFP_KERNEL, &urb->transfer_dma);
+		if (!dev->isoc_ctl.transfer_buffer[i]) {
+			printk("unable to allocate %i bytes for transfer"
+					" buffer %i%s\n",
+					sb_size, i,
+					in_interrupt() ? " while in int" : "");
+			au0828_uninit_isoc(dev);
+			return -ENOMEM;
+		}
+		memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+		pipe = usb_rcvisocpipe(dev->usbdev,
+				       dev->isoc_in_endpointaddr),
+
+		usb_fill_int_urb(urb, dev->usbdev, pipe,
+				 dev->isoc_ctl.transfer_buffer[i], sb_size,
+				 au0828_irq_callback, dma_q, 1);
+
+		urb->number_of_packets = max_packets;
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+		k = 0;
+		for (j = 0; j < max_packets; j++) {
+			urb->iso_frame_desc[j].offset = k;
+			urb->iso_frame_desc[j].length =
+						dev->isoc_ctl.max_pkt_size;
+			k += dev->isoc_ctl.max_pkt_size;
+		}
+	}
+
+	init_waitqueue_head(&dma_q->wq);
+
+	/* submit urbs and enables IRQ */
+	for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+		rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+		if (rc) {
+			au0828_isocdbg("submit of urb %i failed (error=%i)\n",
+				       i, rc);
+			au0828_uninit_isoc(dev);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct au0828_dev *dev,
+				  struct au0828_dmaqueue *dma_q,
+				  struct au0828_buffer *buf)
+{
+	/* Advice that buffer was filled */
+	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+
+	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.field_count++;
+	do_gettimeofday(&buf->vb.ts);
+
+	dev->isoc_ctl.buf = NULL;
+
+	list_del(&buf->vb.queue);
+	wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void au0828_copy_video(struct au0828_dev *dev,
+			      struct au0828_dmaqueue  *dma_q,
+			      struct au0828_buffer *buf,
+			      unsigned char *p,
+			      unsigned char *outp, unsigned long len)
+{
+	void *fieldstart, *startwrite, *startread;
+	int  linesdone, currlinedone, offset, lencopy, remain;
+	int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
+
+	if (dma_q->pos + len > buf->vb.size)
+		len = buf->vb.size - dma_q->pos;
+
+	startread = p;
+	remain = len;
+
+	/* Interlaces frame */
+	if (buf->top_field)
+		fieldstart = outp;
+	else
+		fieldstart = outp + bytesperline;
+
+	linesdone = dma_q->pos / bytesperline;
+	currlinedone = dma_q->pos % bytesperline;
+	offset = linesdone * bytesperline * 2 + currlinedone;
+	startwrite = fieldstart + offset;
+	lencopy = bytesperline - currlinedone;
+	lencopy = lencopy > remain ? remain : lencopy;
+
+	if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+		au0828_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
+			       ((char *)startwrite + lencopy) -
+			       ((char *)outp + buf->vb.size));
+		remain = (char *)outp + buf->vb.size - (char *)startwrite;
+		lencopy = remain;
+	}
+	if (lencopy <= 0)
+		return;
+	memcpy(startwrite, startread, lencopy);
+
+	remain -= lencopy;
+
+	while (remain > 0) {
+		startwrite += lencopy + bytesperline;
+		startread += lencopy;
+		if (bytesperline > remain)
+			lencopy = remain;
+		else
+			lencopy = bytesperline;
+
+		if ((char *)startwrite + lencopy > (char *)outp +
+		    buf->vb.size) {
+			au0828_isocdbg("Overflow %zi bytes past buf end (2)\n",
+				       ((char *)startwrite + lencopy) -
+				       ((char *)outp + buf->vb.size));
+			lencopy = remain = (char *)outp + buf->vb.size -
+					   (char *)startwrite;
+		}
+		if (lencopy <= 0)
+			break;
+
+		memcpy(startwrite, startread, lencopy);
+
+		remain -= lencopy;
+	}
+
+	if (offset > 1440) {
+		/* We have enough data to check for greenscreen */
+		if (outp[0] < 0x60 && outp[1440] < 0x60)
+			dev->greenscreen_detected = 1;
+	}
+
+	dma_q->pos += len;
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
+				struct au0828_buffer **buf)
+{
+	struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+
+	if (list_empty(&dma_q->active)) {
+		au0828_isocdbg("No active queue to serve\n");
+		dev->isoc_ctl.buf = NULL;
+		*buf = NULL;
+		return;
+	}
+
+	/* Get the next buffer */
+	*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
+	dev->isoc_ctl.buf = *buf;
+
+	return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
+{
+	struct au0828_buffer    *buf;
+	struct au0828_dmaqueue  *dma_q = urb->context;
+	unsigned char *outp = NULL;
+	int i, len = 0, rc = 1;
+	unsigned char *p;
+	unsigned char fbyte;
+
+	if (!dev)
+		return 0;
+
+	if ((dev->dev_state & DEV_DISCONNECTED) ||
+	    (dev->dev_state & DEV_MISCONFIGURED))
+		return 0;
+
+	if (urb->status < 0) {
+		print_err_status(dev, -1, urb->status);
+		if (urb->status == -ENOENT)
+			return 0;
+	}
+
+	buf = dev->isoc_ctl.buf;
+	if (buf != NULL)
+		outp = videobuf_to_vmalloc(&buf->vb);
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		int status = urb->iso_frame_desc[i].status;
+
+		if (status < 0) {
+			print_err_status(dev, i, status);
+			if (urb->iso_frame_desc[i].status != -EPROTO)
+				continue;
+		}
+
+		if (urb->iso_frame_desc[i].actual_length <= 0)
+			continue;
+
+		if (urb->iso_frame_desc[i].actual_length >
+						dev->max_pkt_size) {
+			au0828_isocdbg("packet bigger than packet size");
+			continue;
+		}
+
+		p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		fbyte = p[0];
+		len = urb->iso_frame_desc[i].actual_length - 4;
+		p += 4;
+
+		if (fbyte & 0x80) {
+			len -= 4;
+			p += 4;
+			au0828_isocdbg("Video frame %s\n",
+				       (fbyte & 0x40) ? "odd" : "even");
+			if (!(fbyte & 0x40)) {
+				if (buf != NULL)
+					buffer_filled(dev, dma_q, buf);
+				get_next_buf(dma_q, &buf);
+				if (buf == NULL)
+					outp = NULL;
+				else
+					outp = videobuf_to_vmalloc(&buf->vb);
+			}
+
+			if (buf != NULL) {
+				if (fbyte & 0x40)
+					buf->top_field = 1;
+				else
+					buf->top_field = 0;
+			}
+
+			dma_q->pos = 0;
+		}
+		if (buf != NULL)
+			au0828_copy_video(dev, dma_q, buf, p, outp, len);
+	}
+	return rc;
+}
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+	     unsigned int *size)
+{
+	struct au0828_fh *fh = vq->priv_data;
+	*size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+
+	if (0 == *count)
+		*count = AU0828_DEF_BUF;
+
+	if (*count < AU0828_MIN_BUF)
+		*count = AU0828_MIN_BUF;
+	return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
+{
+	struct au0828_fh     *fh  = vq->priv_data;
+	struct au0828_dev    *dev = fh->dev;
+	unsigned long flags = 0;
+	if (in_interrupt())
+		BUG();
+
+	/* We used to wait for the buffer to finish here, but this didn't work
+	   because, as we were keeping the state as VIDEOBUF_QUEUED,
+	   videobuf_queue_cancel marked it as finished for us.
+	   (Also, it could wedge forever if the hardware was misconfigured.)
+
+	   This should be safe; by the time we get here, the buffer isn't
+	   queued anymore. If we ever start marking the buffers as
+	   VIDEOBUF_ACTIVE, it won't be, though.
+	*/
+	spin_lock_irqsave(&dev->slock, flags);
+	if (dev->isoc_ctl.buf == buf)
+		dev->isoc_ctl.buf = NULL;
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	videobuf_vmalloc_free(&buf->vb);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+						enum v4l2_field field)
+{
+	struct au0828_fh     *fh  = vq->priv_data;
+	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+	struct au0828_dev    *dev = fh->dev;
+	int                  rc = 0, urb_init = 0;
+
+	buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	buf->vb.width  = dev->width;
+	buf->vb.height = dev->height;
+	buf->vb.field  = field;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		rc = videobuf_iolock(vq, &buf->vb, NULL);
+		if (rc < 0) {
+			printk(KERN_INFO "videobuf_iolock failed\n");
+			goto fail;
+		}
+	}
+
+	if (!dev->isoc_ctl.num_bufs)
+		urb_init = 1;
+
+	if (urb_init) {
+		rc = au0828_init_isoc(dev, AU0828_ISO_PACKETS_PER_URB,
+				      AU0828_MAX_ISO_BUFS, dev->max_pkt_size,
+				      au0828_isoc_copy);
+		if (rc < 0) {
+			printk(KERN_INFO "au0828_init_isoc failed\n");
+			goto fail;
+		}
+	}
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+fail:
+	free_buffer(vq, buf);
+	return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct au0828_buffer    *buf     = container_of(vb,
+							struct au0828_buffer,
+							vb);
+	struct au0828_fh        *fh      = vq->priv_data;
+	struct au0828_dev       *dev     = fh->dev;
+	struct au0828_dmaqueue  *vidq    = &dev->vidq;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue, &vidq->active);
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+				struct videobuf_buffer *vb)
+{
+	struct au0828_buffer   *buf  = container_of(vb,
+						    struct au0828_buffer,
+						    vb);
+
+	free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops au0828_video_qops = {
+	.buf_setup      = buffer_setup,
+	.buf_prepare    = buffer_prepare,
+	.buf_queue      = buffer_queue,
+	.buf_release    = buffer_release,
+};
+
+/* ------------------------------------------------------------------
+   V4L2 interface
+   ------------------------------------------------------------------*/
+
+static int au0828_i2s_init(struct au0828_dev *dev)
+{
+	/* Enable i2s mode */
+	au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
+	return 0;
+}
+
+/*
+ * Auvitek au0828 analog stream enable
+ * Please set interface0 to AS5 before enable the stream
+ */
+int au0828_analog_stream_enable(struct au0828_dev *d)
+{
+	dprintk(1, "au0828_analog_stream_enable called\n");
+	au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
+	au0828_writereg(d, 0x106, 0x00);
+	/* set x position */
+	au0828_writereg(d, 0x110, 0x00);
+	au0828_writereg(d, 0x111, 0x00);
+	au0828_writereg(d, 0x114, 0xa0);
+	au0828_writereg(d, 0x115, 0x05);
+	/* set y position */
+	au0828_writereg(d, 0x112, 0x02);
+	au0828_writereg(d, 0x113, 0x00);
+	au0828_writereg(d, 0x116, 0xf2);
+	au0828_writereg(d, 0x117, 0x00);
+	au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
+
+	return 0;
+}
+
+int au0828_analog_stream_disable(struct au0828_dev *d)
+{
+	dprintk(1, "au0828_analog_stream_disable called\n");
+	au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
+	return 0;
+}
+
+void au0828_analog_stream_reset(struct au0828_dev *dev)
+{
+	dprintk(1, "au0828_analog_stream_reset called\n");
+	au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
+	mdelay(30);
+	au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
+}
+
+/*
+ * Some operations needs to stop current streaming
+ */
+static int au0828_stream_interrupt(struct au0828_dev *dev)
+{
+	int ret = 0;
+
+	dev->stream_state = STREAM_INTERRUPT;
+	if (dev->dev_state == DEV_DISCONNECTED)
+		return -ENODEV;
+	else if (ret) {
+		dev->dev_state = DEV_MISCONFIGURED;
+		dprintk(1, "%s device is misconfigured!\n", __func__);
+		return ret;
+	}
+	return 0;
+}
+
+/*
+ * au0828_release_resources
+ * unregister v4l2 devices
+ */
+void au0828_analog_unregister(struct au0828_dev *dev)
+{
+	dprintk(1, "au0828_release_resources called\n");
+	mutex_lock(&au0828_sysfs_lock);
+
+	if (dev->vdev) {
+		list_del(&dev->au0828list);
+		video_unregister_device(dev->vdev);
+	}
+	if (dev->vbi_dev)
+		video_unregister_device(dev->vbi_dev);
+
+	mutex_unlock(&au0828_sysfs_lock);
+}
+
+
+/* Usage lock check functions */
+static int res_get(struct au0828_fh *fh)
+{
+	struct au0828_dev *dev = fh->dev;
+	int		 rc   = 0;
+
+	/* This instance already has stream_on */
+	if (fh->stream_on)
+		return rc;
+
+	if (dev->stream_on)
+		return -EBUSY;
+
+	dev->stream_on = 1;
+	fh->stream_on  = 1;
+	return rc;
+}
+
+static int res_check(struct au0828_fh *fh)
+{
+	return fh->stream_on;
+}
+
+static void res_free(struct au0828_fh *fh)
+{
+	struct au0828_dev *dev = fh->dev;
+
+	fh->stream_on = 0;
+	dev->stream_on = 0;
+}
+
+static int au0828_v4l2_open(struct file *filp)
+{
+	int minor = video_devdata(filp)->minor;
+	int ret = 0;
+	struct au0828_dev *h, *dev = NULL;
+	struct au0828_fh *fh;
+	int type = 0;
+	struct list_head *list;
+
+	list_for_each(list, &au0828_devlist) {
+		h = list_entry(list, struct au0828_dev, au0828list);
+		if (h->vdev->minor == minor) {
+			dev = h;
+			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		}
+#ifdef VBI_IS_WORKING
+		if (h->vbi_dev->minor == minor) {
+			dev = h;
+			type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		}
+#endif
+	}
+
+	if (NULL == dev)
+		return -ENODEV;
+
+	fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
+	if (NULL == fh) {
+		dprintk(1, "Failed allocate au0828_fh struct!\n");
+		return -ENOMEM;
+	}
+
+	fh->type = type;
+	fh->dev = dev;
+	filp->private_data = fh;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+		/* set au0828 interface0 to AS5 here again */
+		ret = usb_set_interface(dev->usbdev, 0, 5);
+		if (ret < 0) {
+			printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
+			return -EBUSY;
+		}
+		dev->width = NTSC_STD_W;
+		dev->height = NTSC_STD_H;
+		dev->frame_size = dev->width * dev->height * 2;
+		dev->field_size = dev->width * dev->height;
+		dev->bytesperline = dev->width * 2;
+
+		au0828_analog_stream_enable(dev);
+		au0828_analog_stream_reset(dev);
+
+		/* If we were doing ac97 instead of i2s, it would go here...*/
+		au0828_i2s_init(dev);
+
+		dev->stream_state = STREAM_OFF;
+		dev->dev_state |= DEV_INITIALIZED;
+	}
+
+	dev->users++;
+
+	videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
+				    NULL, &dev->slock, fh->type,
+				    V4L2_FIELD_INTERLACED,
+				    sizeof(struct au0828_buffer), fh);
+
+	return ret;
+}
+
+static int au0828_v4l2_close(struct file *filp)
+{
+	int ret;
+	struct au0828_fh *fh = filp->private_data;
+	struct au0828_dev *dev = fh->dev;
+
+	mutex_lock(&dev->lock);
+	if (res_check(fh))
+		res_free(fh);
+
+	if (dev->users == 1) {
+		videobuf_stop(&fh->vb_vidq);
+		videobuf_mmap_free(&fh->vb_vidq);
+
+		if (dev->dev_state & DEV_DISCONNECTED) {
+			au0828_analog_unregister(dev);
+			mutex_unlock(&dev->lock);
+			kfree(dev);
+			return 0;
+		}
+
+		au0828_analog_stream_disable(dev);
+
+		au0828_uninit_isoc(dev);
+
+		/* When close the device, set the usb intf0 into alt0 to free
+		   USB bandwidth */
+		ret = usb_set_interface(dev->usbdev, 0, 0);
+		if (ret < 0)
+			printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
+	}
+
+	kfree(fh);
+	dev->users--;
+	wake_up_interruptible_nr(&dev->open, 1);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
+				size_t count, loff_t *pos)
+{
+	struct au0828_fh *fh = filp->private_data;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		mutex_lock(&dev->lock);
+		rc = res_get(fh);
+		mutex_unlock(&dev->lock);
+
+		if (unlikely(rc < 0))
+			return rc;
+
+		return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+					filp->f_flags & O_NONBLOCK);
+	}
+	return 0;
+}
+
+static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
+{
+	struct au0828_fh *fh = filp->private_data;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+	mutex_unlock(&dev->lock);
+
+	if (unlikely(rc < 0))
+		return POLLERR;
+
+	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+		return POLLERR;
+
+	return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+}
+
+static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct au0828_fh *fh    = filp->private_data;
+	struct au0828_dev *dev   = fh->dev;
+	int		 rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+	mutex_unlock(&dev->lock);
+
+	if (unlikely(rc < 0))
+		return rc;
+
+	rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+
+	dprintk(2, "vma start=0x%08lx, size=%ld, ret=%d\n",
+		(unsigned long)vma->vm_start,
+		(unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+		rc);
+
+	return rc;
+}
+
+static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
+			     struct v4l2_format *format)
+{
+	int ret;
+	int width = format->fmt.pix.width;
+	int height = format->fmt.pix.height;
+	unsigned int maxwidth, maxheight;
+
+	maxwidth = 720;
+	maxheight = 480;
+
+#ifdef VBI_IS_WORKING
+	if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+		dprintk(1, "VBI format set: to be supported!\n");
+		return 0;
+	}
+	if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		return 0;
+#endif
+	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	/* If they are demanding a format other than the one we support,
+	   bail out (tvtime asks for UYVY and then retries with YUYV) */
+	if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
+		return -EINVAL;
+
+	/* format->fmt.pix.width only support 720 and height 480 */
+	if (width != 720)
+		width = 720;
+	if (height != 480)
+		height = 480;
+
+	format->fmt.pix.width = width;
+	format->fmt.pix.height = height;
+	format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+	format->fmt.pix.bytesperline = width * 2;
+	format->fmt.pix.sizeimage = width * height * 2;
+	format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	format->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+	if (cmd == VIDIOC_TRY_FMT)
+		return 0;
+
+	/* maybe set new image format, driver current only support 720*480 */
+	dev->width = width;
+	dev->height = height;
+	dev->frame_size = width * height * 2;
+	dev->field_size = width * height;
+	dev->bytesperline = width * 2;
+
+	if (dev->stream_state == STREAM_ON) {
+		dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
+		ret = au0828_stream_interrupt(dev);
+		if (ret != 0) {
+			dprintk(1, "error interrupting video stream!\n");
+			return ret;
+		}
+	}
+
+	/* set au0828 interface0 to AS5 here again */
+	ret = usb_set_interface(dev->usbdev, 0, 5);
+	if (ret < 0) {
+		printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
+		return -EBUSY;
+	}
+
+	au0828_analog_stream_enable(dev);
+
+	return 0;
+}
+
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+			    struct v4l2_queryctrl *qc)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
+	if (qc->type)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+			   struct v4l2_capability *cap)
+{
+	struct au0828_fh *fh  = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	strlcpy(cap->driver, "au0828", sizeof(cap->driver));
+	strlcpy(cap->card, dev->board.name, sizeof(cap->card));
+	strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+
+	cap->version = AU0828_VERSION_CODE;
+
+	/*set the device capabilities */
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+#ifdef VBI_IS_WORKING
+		V4L2_CAP_VBI_CAPTURE |
+#endif
+		V4L2_CAP_AUDIO |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING |
+		V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (f->index)
+		return -EINVAL;
+
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	strcpy(f->description, "Packed YUV2");
+
+	f->flags = 0;
+	f->pixelformat = V4L2_PIX_FMT_UYVY;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct au0828_fh *fh  = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	f->fmt.pix.width = dev->width;
+	f->fmt.pix.height = dev->height;
+	f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+	f->fmt.pix.bytesperline = dev->bytesperline;
+	f->fmt.pix.sizeimage = dev->frame_size;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
+	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct au0828_fh *fh  = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct au0828_fh *fh  = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+		printk(KERN_INFO "%s queue busy\n", __func__);
+		rc = -EBUSY;
+		goto out;
+	}
+
+	if (dev->stream_on && !fh->stream_on) {
+		printk(KERN_INFO "%s device in use by another fh\n", __func__);
+		rc = -EBUSY;
+		goto out;
+	}
+
+	return au0828_set_format(dev, VIDIOC_S_FMT, f);
+out:
+	return rc;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	/* FIXME: when we support something other than NTSC, we are going to
+	   have to make the au0828 bridge adjust the size of its capture
+	   buffer, which is currently hardcoded at 720x480 */
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_std, *norm);
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *input)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	unsigned int tmp;
+
+	static const char *inames[] = {
+		[AU0828_VMUX_UNDEFINED] = "Undefined",
+		[AU0828_VMUX_COMPOSITE] = "Composite",
+		[AU0828_VMUX_SVIDEO] = "S-Video",
+		[AU0828_VMUX_CABLE] = "Cable TV",
+		[AU0828_VMUX_TELEVISION] = "Television",
+		[AU0828_VMUX_DVB] = "DVB",
+		[AU0828_VMUX_DEBUG] = "tv debug"
+	};
+
+	tmp = input->index;
+
+	if (tmp > AU0828_MAX_INPUT)
+		return -EINVAL;
+	if (AUVI_INPUT(tmp).type == 0)
+		return -EINVAL;
+
+	input->index = tmp;
+	strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
+	if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
+	    (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
+		input->type |= V4L2_INPUT_TYPE_TUNER;
+	else
+		input->type |= V4L2_INPUT_TYPE_CAMERA;
+
+	input->std = dev->vdev->tvnorms;
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	*i = dev->ctrl_input;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int i;
+	struct v4l2_routing route;
+
+	dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
+		index);
+	if (index >= AU0828_MAX_INPUT)
+		return -EINVAL;
+	if (AUVI_INPUT(index).type == 0)
+		return -EINVAL;
+	dev->ctrl_input = index;
+
+	switch (AUVI_INPUT(index).type) {
+	case AU0828_VMUX_SVIDEO:
+		dev->input_type = AU0828_VMUX_SVIDEO;
+		break;
+	case AU0828_VMUX_COMPOSITE:
+		dev->input_type = AU0828_VMUX_COMPOSITE;
+		break;
+	case AU0828_VMUX_TELEVISION:
+		dev->input_type = AU0828_VMUX_TELEVISION;
+		break;
+	default:
+		dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
+			AUVI_INPUT(index).type);
+		break;
+	}
+
+	route.input = AUVI_INPUT(index).vmux;
+	route.output = 0;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing, &route);
+
+	for (i = 0; i < AU0828_MAX_INPUT; i++) {
+		int enable = 0;
+		if (AUVI_INPUT(i).audio_setup == NULL)
+			continue;
+
+		if (i == index)
+			enable = 1;
+		else
+			enable = 0;
+		if (enable) {
+			(AUVI_INPUT(i).audio_setup)(dev, enable);
+		} else {
+			/* Make sure we leave it turned on if some
+			   other input is routed to this callback */
+			if ((AUVI_INPUT(i).audio_setup) !=
+			    ((AUVI_INPUT(index).audio_setup))) {
+				(AUVI_INPUT(i).audio_setup)(dev, enable);
+			}
+		}
+	}
+
+	route.input = AUVI_INPUT(index).amux;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing, &route);
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	unsigned int index = a->index;
+
+	if (a->index > 1)
+		return -EINVAL;
+
+	index = dev->ctrl_ainput;
+	if (index == 0)
+		strcpy(a->name, "Television");
+	else
+		strcpy(a->name, "Line in");
+
+	a->capability = V4L2_AUDCAP_STEREO;
+	a->index = index;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	if (a->index != dev->ctrl_ainput)
+		return -EINVAL;
+	return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+			 struct v4l2_control *ctrl)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
+	return 0;
+
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
+	return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	if (t->index != 0)
+		return -EINVAL;
+
+	strcpy(t->name, "Auvitek tuner");
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	if (t->index != 0)
+		return -EINVAL;
+
+	t->type = V4L2_TUNER_ANALOG_TV;
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+	dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
+		t->afc);
+	return 0;
+
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *freq)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	freq->type = V4L2_TUNER_ANALOG_TV;
+	freq->frequency = dev->ctrl_freq;
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *freq)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	if (freq->tuner != 0)
+		return -EINVAL;
+	if (freq->type != V4L2_TUNER_ANALOG_TV)
+		return -EINVAL;
+
+	dev->ctrl_freq = freq->frequency;
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
+
+	au0828_analog_stream_reset(dev);
+
+	return 0;
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+	       struct v4l2_dbg_chip_ident *chip)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+
+	if (v4l2_chip_match_host(&chip->match)) {
+		chip->ident = V4L2_IDENT_AU0828;
+		return 0;
+	}
+
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
+	if (chip->ident == V4L2_IDENT_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+			  struct v4l2_cropcap *cc)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	cc->bounds.left = 0;
+	cc->bounds.top = 0;
+	cc->bounds.width = dev->width;
+	cc->bounds.height = dev->height;
+
+	cc->defrect = cc->bounds;
+
+	cc->pixelaspect.numerator = 54;
+	cc->pixelaspect.denominator = 59;
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+			   enum v4l2_buf_type type)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		au0828_analog_stream_enable(dev);
+		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
+	}
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+
+	if (likely(rc >= 0))
+		rc = videobuf_streamon(&fh->vb_vidq);
+	mutex_unlock(&dev->lock);
+
+	return rc;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+			    enum v4l2_buf_type type)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int i;
+	int ret;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (type != fh->type)
+		return -EINVAL;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+		ret = au0828_stream_interrupt(dev);
+		if (ret != 0)
+			return ret;
+	}
+
+	for (i = 0; i < AU0828_MAX_INPUT; i++) {
+		if (AUVI_INPUT(i).audio_setup == NULL)
+			continue;
+		(AUVI_INPUT(i).audio_setup)(dev, 0);
+	}
+
+	mutex_lock(&dev->lock);
+	videobuf_streamoff(&fh->vb_vidq);
+	res_free(fh);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+			     struct v4l2_dbg_register *reg)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_I2C_DRIVER:
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+			     struct v4l2_dbg_register *reg)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_I2C_DRIVER:
+		v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+#endif
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *rb)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_reqbufs(&fh->vb_vidq, rb);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+			   struct v4l2_buffer *b)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_querybuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_qbuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct au0828_fh *fh = priv;
+	struct au0828_dev *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	/* Workaround for a bug in the au0828 hardware design that sometimes
+	   results in the colorspace being inverted */
+	if (dev->greenscreen_detected == 1) {
+		dprintk(1, "Detected green frame.  Resetting stream...\n");
+		au0828_analog_stream_reset(dev);
+		dev->greenscreen_detected = 0;
+	}
+
+	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
+}
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+	struct au0828_fh *fh = priv;
+
+	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
+}
+#endif
+
+static struct v4l2_file_operations au0828_v4l_fops = {
+	.owner      = THIS_MODULE,
+	.open       = au0828_v4l2_open,
+	.release    = au0828_v4l2_close,
+	.read       = au0828_v4l2_read,
+	.poll       = au0828_v4l2_poll,
+	.mmap       = au0828_v4l2_mmap,
+	.ioctl      = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap            = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+#ifdef VBI_IS_WORKING
+	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+	.vidioc_try_fmt_vbi_cap     = vidioc_s_fmt_vbi_cap,
+	.vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
+#endif
+	.vidioc_g_audio             = vidioc_g_audio,
+	.vidioc_s_audio             = vidioc_s_audio,
+	.vidioc_cropcap             = vidioc_cropcap,
+#ifdef VBI_IS_WORKING
+	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
+	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
+	.vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,
+#endif
+	.vidioc_reqbufs             = vidioc_reqbufs,
+	.vidioc_querybuf            = vidioc_querybuf,
+	.vidioc_qbuf                = vidioc_qbuf,
+	.vidioc_dqbuf               = vidioc_dqbuf,
+	.vidioc_s_std               = vidioc_s_std,
+	.vidioc_enum_input          = vidioc_enum_input,
+	.vidioc_g_input             = vidioc_g_input,
+	.vidioc_s_input             = vidioc_s_input,
+	.vidioc_queryctrl           = vidioc_queryctrl,
+	.vidioc_g_ctrl              = vidioc_g_ctrl,
+	.vidioc_s_ctrl              = vidioc_s_ctrl,
+	.vidioc_streamon            = vidioc_streamon,
+	.vidioc_streamoff           = vidioc_streamoff,
+	.vidioc_g_tuner             = vidioc_g_tuner,
+	.vidioc_s_tuner             = vidioc_s_tuner,
+	.vidioc_g_frequency         = vidioc_g_frequency,
+	.vidioc_s_frequency         = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register          = vidioc_g_register,
+	.vidioc_s_register          = vidioc_s_register,
+#endif
+	.vidioc_g_chip_ident        = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidiocgmbuf                = vidiocgmbuf,
+#endif
+};
+
+static const struct video_device au0828_video_template = {
+	.fops                       = &au0828_v4l_fops,
+	.release                    = video_device_release,
+	.ioctl_ops 		    = &video_ioctl_ops,
+	.minor                      = -1,
+	.tvnorms                    = V4L2_STD_NTSC_M,
+	.current_norm               = V4L2_STD_NTSC_M,
+};
+
+/**************************************************************************/
+
+int au0828_analog_register(struct au0828_dev *dev,
+			   struct usb_interface *interface)
+{
+	int retval = -ENOMEM;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int i;
+
+	dprintk(1, "au0828_analog_register called!\n");
+
+	/* set au0828 usb interface0 to as5 */
+	retval = usb_set_interface(dev->usbdev,
+			interface->cur_altsetting->desc.bInterfaceNumber, 5);
+	if (retval != 0) {
+		printk(KERN_INFO "Failure setting usb interface0 to as5\n");
+		return retval;
+	}
+
+	/* Figure out which endpoint has the isoc interface */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		     == USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+		     == USB_ENDPOINT_XFER_ISOC)) {
+
+			/* we find our isoc in endpoint */
+			u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
+			dev->max_pkt_size = (tmp & 0x07ff) *
+				(((tmp & 0x1800) >> 11) + 1);
+			dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
+		}
+	}
+	if (!(dev->isoc_in_endpointaddr)) {
+		printk(KERN_INFO "Could not locate isoc endpoint\n");
+		kfree(dev);
+		return -ENODEV;
+	}
+
+	init_waitqueue_head(&dev->open);
+	spin_lock_init(&dev->slock);
+	mutex_init(&dev->lock);
+
+	INIT_LIST_HEAD(&dev->vidq.active);
+	INIT_LIST_HEAD(&dev->vidq.queued);
+
+	dev->width = NTSC_STD_W;
+	dev->height = NTSC_STD_H;
+	dev->field_size = dev->width * dev->height;
+	dev->frame_size = dev->field_size << 1;
+	dev->bytesperline = dev->width << 1;
+	dev->ctrl_ainput = 0;
+
+	/* allocate and fill v4l2 video struct */
+	dev->vdev = video_device_alloc();
+	if (NULL == dev->vdev) {
+		dprintk(1, "Can't allocate video_device.\n");
+		return -ENOMEM;
+	}
+
+#ifdef VBI_IS_WORKING
+	dev->vbi_dev = video_device_alloc();
+	if (NULL == dev->vbi_dev) {
+		dprintk(1, "Can't allocate vbi_device.\n");
+		kfree(dev->vdev);
+		return -ENOMEM;
+	}
+#endif
+
+	/* Fill the video capture device struct */
+	*dev->vdev = au0828_video_template;
+	dev->vdev->parent = &dev->usbdev->dev;
+	strcpy(dev->vdev->name, "au0828a video");
+
+#ifdef VBI_IS_WORKING
+	/* Setup the VBI device */
+	*dev->vbi_dev = au0828_video_template;
+	dev->vbi_dev->parent = &dev->usbdev->dev;
+	strcpy(dev->vbi_dev->name, "au0828a vbi");
+#endif
+
+	list_add_tail(&dev->au0828list, &au0828_devlist);
+
+	/* Register the v4l2 device */
+	retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
+	if (retval != 0) {
+		dprintk(1, "unable to register video device (error = %d).\n",
+			retval);
+		list_del(&dev->au0828list);
+		video_device_release(dev->vdev);
+		return -ENODEV;
+	}
+
+#ifdef VBI_IS_WORKING
+	/* Register the vbi device */
+	retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
+	if (retval != 0) {
+		dprintk(1, "unable to register vbi device (error = %d).\n",
+			retval);
+		list_del(&dev->au0828list);
+		video_device_release(dev->vbi_dev);
+		video_device_release(dev->vdev);
+		return -ENODEV;
+	}
+#endif
+
+	dprintk(1, "%s completed!\n", __func__);
+
+	return 0;
+}
+
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 9d6a116..6ed1a61 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -24,6 +24,11 @@
 #include <linux/i2c-algo-bit.h>
 #include <media/tveeprom.h>
 
+/* Analog */
+#include <linux/videodev2.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+
 /* DVB */
 #include "demux.h"
 #include "dmxdev.h"
@@ -39,8 +44,45 @@
 #define URB_COUNT   16
 #define URB_BUFSIZE (0xe522)
 
+/* Analog constants */
+#define NTSC_STD_W      720
+#define NTSC_STD_H      480
+
+#define AU0828_INTERLACED_DEFAULT       1
+#define V4L2_CID_PRIVATE_SHARPNESS  (V4L2_CID_PRIVATE_BASE + 0)
+
+/* Defination for AU0828 USB transfer */
+#define AU0828_MAX_ISO_BUFS    12  /* maybe resize this value in the future */
+#define AU0828_ISO_PACKETS_PER_URB      10
+
+#define AU0828_MIN_BUF 4
+#define AU0828_DEF_BUF 8
+
+#define AU0828_MAX_INPUT        4
+
+enum au0828_itype {
+	AU0828_VMUX_UNDEFINED = 0,
+	AU0828_VMUX_COMPOSITE,
+	AU0828_VMUX_SVIDEO,
+	AU0828_VMUX_CABLE,
+	AU0828_VMUX_TELEVISION,
+	AU0828_VMUX_DVB,
+	AU0828_VMUX_DEBUG
+};
+
+struct au0828_input {
+	enum au0828_itype type;
+	unsigned int vmux;
+	unsigned int amux;
+	void (*audio_setup) (void *priv, int enable);
+};
+
 struct au0828_board {
 	char *name;
+	unsigned int tuner_type;
+	unsigned char tuner_addr;
+	struct au0828_input input[AU0828_MAX_INPUT];
+
 };
 
 struct au0828_dvb {
@@ -55,31 +97,143 @@
 	int feeding;
 };
 
+enum au0828_stream_state {
+	STREAM_OFF,
+	STREAM_INTERRUPT,
+	STREAM_ON
+};
+
+#define AUVI_INPUT(nr) (dev->board.input[nr])
+
+/* device state */
+enum au0828_dev_state {
+	DEV_INITIALIZED = 0x01,
+	DEV_DISCONNECTED = 0x02,
+	DEV_MISCONFIGURED = 0x04
+};
+
+struct au0828_fh {
+	struct au0828_dev *dev;
+	unsigned int  stream_on:1;	/* Locks streams */
+	struct videobuf_queue        vb_vidq;
+	enum v4l2_buf_type           type;
+};
+
+struct au0828_usb_isoc_ctl {
+		/* max packet size of isoc transaction */
+	int				max_pkt_size;
+
+		/* number of allocated urbs */
+	int				num_bufs;
+
+		/* urb for isoc transfers */
+	struct urb			**urb;
+
+		/* transfer buffers for isoc transfer */
+	char				**transfer_buffer;
+
+		/* Last buffer command and region */
+	u8				cmd;
+	int				pos, size, pktsize;
+
+		/* Last field: ODD or EVEN? */
+	int				field;
+
+		/* Stores incomplete commands */
+	u32				tmp_buf;
+	int				tmp_buf_len;
+
+		/* Stores already requested buffers */
+	struct au0828_buffer    	*buf;
+
+		/* Stores the number of received fields */
+	int				nfields;
+
+		/* isoc urb callback */
+	int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb);
+
+};
+
+/* buffer for one video frame */
+struct au0828_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	struct list_head frame;
+	int top_field;
+	int receiving;
+};
+
+struct au0828_dmaqueue {
+	struct list_head       active;
+	struct list_head       queued;
+
+	wait_queue_head_t          wq;
+
+	/* Counters to control buffer fill */
+	int                        pos;
+};
+
 struct au0828_dev {
 	struct mutex mutex;
 	struct usb_device	*usbdev;
-	int			board;
+	int			boardnr;
+	struct au0828_board	board;
 	u8			ctrlmsg[64];
 
 	/* I2C */
 	struct i2c_adapter		i2c_adap;
-	struct i2c_algo_bit_data	i2c_algo;
+	struct i2c_algorithm		i2c_algo;
 	struct i2c_client		i2c_client;
 	u32 				i2c_rc;
 
 	/* Digital */
 	struct au0828_dvb		dvb;
 
+	/* Analog */
+	struct list_head au0828list;
+	struct v4l2_device v4l2_dev;
+	int users;
+	unsigned int stream_on:1;	/* Locks streams */
+	struct video_device *vdev;
+	struct video_device *vbi_dev;
+	int width;
+	int height;
+	u32 field_size;
+	u32 frame_size;
+	u32 bytesperline;
+	int type;
+	u8 ctrl_ainput;
+	__u8 isoc_in_endpointaddr;
+	u8 isoc_init_ok;
+	int greenscreen_detected;
+	unsigned int frame_count;
+	int ctrl_freq;
+	int input_type;
+	unsigned int ctrl_input;
+	enum au0828_dev_state dev_state;
+	enum au0828_stream_state stream_state;
+	wait_queue_head_t open;
+
+	struct mutex lock;
+
+	/* Isoc control struct */
+	struct au0828_dmaqueue vidq;
+	struct au0828_usb_isoc_ctl isoc_ctl;
+	spinlock_t slock;
+
+	/* usb transfer */
+	int alt;		/* alternate */
+	int max_pkt_size;	/* max packet size of isoc transaction */
+	int num_alt;		/* Number of alternative settings */
+	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
+	struct urb *urb[AU0828_MAX_ISO_BUFS];	/* urb for isoc transfers */
+	char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc
+						   transfer */
+
 	/* USB / URB Related */
 	int		urb_streaming;
 	struct urb	*urbs[URB_COUNT];
-
-};
-
-struct au0828_buff {
-	struct au0828_dev	*dev;
-	struct urb		*purb;
-	struct list_head	buff_list;
 };
 
 /* ----------------------------------------------------------- */
@@ -111,8 +265,13 @@
 /* au0828-i2c.c */
 extern int au0828_i2c_register(struct au0828_dev *dev);
 extern int au0828_i2c_unregister(struct au0828_dev *dev);
-extern void au0828_call_i2c_clients(struct au0828_dev *dev,
-	unsigned int cmd, void *arg);
+
+/* ----------------------------------------------------------- */
+/* au0828-video.c */
+int au0828_analog_register(struct au0828_dev *dev,
+			   struct usb_interface *interface);
+int au0828_analog_stream_disable(struct au0828_dev *d);
+void au0828_analog_unregister(struct au0828_dev *dev);
 
 /* ----------------------------------------------------------- */
 /* au0828-dvb.c */
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index a07b7b8..df4516d 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -29,16 +29,16 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
+#include <media/bt819.h>
 
 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
 MODULE_AUTHOR("Mike Bernson & Dave Perks");
@@ -48,13 +48,15 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+
 /* ----------------------------------------------------------------------- */
 
 struct bt819 {
+	struct v4l2_subdev sd;
 	unsigned char reg[32];
 
-	int initialized;
-	int norm;
+	v4l2_std_id norm;
+	int ident;
 	int input;
 	int enable;
 	int bright;
@@ -63,6 +65,11 @@
 	int sat;
 };
 
+static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct bt819, sd);
+}
+
 struct timing {
 	int hactive;
 	int hdelay;
@@ -80,24 +87,23 @@
 
 /* ----------------------------------------------------------------------- */
 
-static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
 {
-	struct bt819 *decoder = i2c_get_clientdata(client);
+	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
 
 	decoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
+static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
 {
-	struct bt819 *decoder = i2c_get_clientdata(client);
-
-	return bt819_write(client, reg,
+	return bt819_write(decoder, reg,
 		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
 }
 
-static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
+static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
 	int ret = -1;
 	u8 reg;
 
@@ -105,7 +111,6 @@
 	 * the adapter understands raw I2C */
 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		/* do raw I2C, not smbus compatible */
-		struct bt819 *decoder = i2c_get_clientdata(client);
 		u8 block_data[32];
 		int block_len;
 
@@ -126,7 +131,8 @@
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			if ((ret = bt819_write(client, reg, *data++)) < 0)
+			ret = bt819_write(decoder, reg, *data++);
+			if (ret < 0)
 				break;
 			len -= 2;
 		}
@@ -135,15 +141,15 @@
 	return ret;
 }
 
-static inline int bt819_read(struct i2c_client *client, u8 reg)
+static inline int bt819_read(struct bt819 *decoder, u8 reg)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
+
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int bt819_init(struct i2c_client *client)
+static int bt819_init(struct v4l2_subdev *sd)
 {
-	struct bt819 *decoder = i2c_get_clientdata(client);
-
 	static unsigned char init[] = {
 		/*0x1f, 0x00,*/     /* Reset */
 		0x01, 0x59,	/* 0x01 input format */
@@ -178,7 +184,8 @@
 		0x1a, 0x80,	/* 0x1a ADC Interface */
 	};
 
-	struct timing *timing = &timing_data[decoder->norm];
+	struct bt819 *decoder = to_bt819(sd);
+	struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
 
 	init[0x03 * 2 - 1] =
 	    (((timing->vdelay >> 8) & 0x03) << 6) |
@@ -192,266 +199,306 @@
 	init[0x08 * 2 - 1] = timing->hscale >> 8;
 	init[0x09 * 2 - 1] = timing->hscale & 0xff;
 	/* 0x15 in array is address 0x19 */
-	init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93;	/* Chroma burst delay */
+	init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
 	/* reset */
-	bt819_write(client, 0x1f, 0x00);
+	bt819_write(decoder, 0x1f, 0x00);
 	mdelay(1);
 
 	/* init */
-	return bt819_write_block(client, init, sizeof(init));
+	return bt819_write_block(decoder, init, sizeof(init));
 }
 
 /* ----------------------------------------------------------------------- */
 
-static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
 {
-	int temp;
+	struct bt819 *decoder = to_bt819(sd);
+	int status = bt819_read(decoder, 0x00);
+	int res = V4L2_IN_ST_NO_SIGNAL;
+	v4l2_std_id std;
 
-	struct bt819 *decoder = i2c_get_clientdata(client);
-
-	if (!decoder->initialized) {	/* First call to bt819_init could be */
-		bt819_init(client);	/* without #FRST = 0 */
-		decoder->initialized = 1;
-	}
-
-	switch (cmd) {
-	case 0:
-		/* This is just for testing!!! */
-		bt819_init(client);
-		break;
-
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *cap = arg;
-
-		cap->flags = VIDEO_DECODER_PAL |
-			     VIDEO_DECODER_NTSC |
-			     VIDEO_DECODER_AUTO |
-			     VIDEO_DECODER_CCIR;
-		cap->inputs = 8;
-		cap->outputs = 1;
-		break;
-	}
-
-	case DECODER_GET_STATUS:
-	{
-		int *iarg = arg;
-		int status;
-		int res;
-
-		status = bt819_read(client, 0x00);
+	if ((status & 0x80))
 		res = 0;
-		if ((status & 0x80))
-			res |= DECODER_STATUS_GOOD;
 
-		switch (decoder->norm) {
-		case VIDEO_MODE_NTSC:
-			res |= DECODER_STATUS_NTSC;
-			break;
-		case VIDEO_MODE_PAL:
-			res |= DECODER_STATUS_PAL;
-			break;
-		default:
-		case VIDEO_MODE_AUTO:
-			if ((status & 0x10))
-				res |= DECODER_STATUS_PAL;
-			else
-				res |= DECODER_STATUS_NTSC;
-			break;
-		}
-		res |= DECODER_STATUS_COLOR;
-		*iarg = res;
+	if ((status & 0x10))
+		std = V4L2_STD_PAL;
+	else
+		std = V4L2_STD_NTSC;
+	if (pstd)
+		*pstd = std;
+	if (pstatus)
+		*pstatus = status;
 
-		v4l_dbg(1, debug, client, "get status %x\n", *iarg);
-		break;
+	v4l2_dbg(1, debug, sd, "get status %x\n", status);
+	return 0;
+}
+
+static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	return bt819_status(sd, NULL, std);
+}
+
+static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	return bt819_status(sd, status, NULL);
+}
+
+static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct bt819 *decoder = to_bt819(sd);
+	struct timing *timing = NULL;
+
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
+
+	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
+		v4l2_err(sd, "no notify found!\n");
+
+	if (std & V4L2_STD_NTSC) {
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
+		bt819_setbit(decoder, 0x01, 0, 1);
+		bt819_setbit(decoder, 0x01, 1, 0);
+		bt819_setbit(decoder, 0x01, 5, 0);
+		bt819_write(decoder, 0x18, 0x68);
+		bt819_write(decoder, 0x19, 0x5d);
+		/* bt819_setbit(decoder, 0x1a,  5, 1); */
+		timing = &timing_data[1];
+	} else if (std & V4L2_STD_PAL) {
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
+		bt819_setbit(decoder, 0x01, 0, 1);
+		bt819_setbit(decoder, 0x01, 1, 1);
+		bt819_setbit(decoder, 0x01, 5, 1);
+		bt819_write(decoder, 0x18, 0x7f);
+		bt819_write(decoder, 0x19, 0x72);
+		/* bt819_setbit(decoder, 0x1a,  5, 0); */
+		timing = &timing_data[0];
+	} else {
+		v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
+				(unsigned long long)std);
+		return -EINVAL;
 	}
+	bt819_write(decoder, 0x03,
+			(((timing->vdelay >> 8) & 0x03) << 6) |
+			(((timing->vactive >> 8) & 0x03) << 4) |
+			(((timing->hdelay >> 8) & 0x03) << 2) |
+			((timing->hactive >> 8) & 0x03));
+	bt819_write(decoder, 0x04, timing->vdelay & 0xff);
+	bt819_write(decoder, 0x05, timing->vactive & 0xff);
+	bt819_write(decoder, 0x06, timing->hdelay & 0xff);
+	bt819_write(decoder, 0x07, timing->hactive & 0xff);
+	bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
+	bt819_write(decoder, 0x09, timing->hscale & 0xff);
+	decoder->norm = std;
+	v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0);
+	return 0;
+}
 
-	case DECODER_SET_NORM:
-	{
-		int *iarg = arg;
-		struct timing *timing = NULL;
+static int bt819_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct bt819 *decoder = to_bt819(sd);
 
-		v4l_dbg(1, debug, client, "set norm %x\n", *iarg);
+	v4l2_dbg(1, debug, sd, "set input %x\n", route->input);
 
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			bt819_setbit(client, 0x01, 0, 1);
-			bt819_setbit(client, 0x01, 1, 0);
-			bt819_setbit(client, 0x01, 5, 0);
-			bt819_write(client, 0x18, 0x68);
-			bt819_write(client, 0x19, 0x5d);
-			/* bt819_setbit(client, 0x1a,  5, 1); */
-			timing = &timing_data[VIDEO_MODE_NTSC];
-			break;
-		case VIDEO_MODE_PAL:
-			bt819_setbit(client, 0x01, 0, 1);
-			bt819_setbit(client, 0x01, 1, 1);
-			bt819_setbit(client, 0x01, 5, 1);
-			bt819_write(client, 0x18, 0x7f);
-			bt819_write(client, 0x19, 0x72);
-			/* bt819_setbit(client, 0x1a,  5, 0); */
-			timing = &timing_data[VIDEO_MODE_PAL];
-			break;
-		case VIDEO_MODE_AUTO:
-			bt819_setbit(client, 0x01, 0, 0);
-			bt819_setbit(client, 0x01, 1, 0);
-			break;
-		default:
-			v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg);
-			return -EINVAL;
+	if (route->input < 0 || route->input > 7)
+		return -EINVAL;
+
+	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
+		v4l2_err(sd, "no notify found!\n");
+
+	if (decoder->input != route->input) {
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
+		decoder->input = route->input;
+		/* select mode */
+		if (decoder->input == 0) {
+			bt819_setbit(decoder, 0x0b, 6, 0);
+			bt819_setbit(decoder, 0x1a, 1, 1);
+		} else {
+			bt819_setbit(decoder, 0x0b, 6, 1);
+			bt819_setbit(decoder, 0x1a, 1, 0);
 		}
-
-		if (timing) {
-			bt819_write(client, 0x03,
-				    (((timing->vdelay >> 8) & 0x03) << 6) |
-				    (((timing->vactive >> 8) & 0x03) << 4) |
-				    (((timing->hdelay >> 8) & 0x03) << 2) |
-				     ((timing->hactive >> 8) & 0x03) );
-			bt819_write(client, 0x04, timing->vdelay & 0xff);
-			bt819_write(client, 0x05, timing->vactive & 0xff);
-			bt819_write(client, 0x06, timing->hdelay & 0xff);
-			bt819_write(client, 0x07, timing->hactive & 0xff);
-			bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
-			bt819_write(client, 0x09, timing->hscale & 0xff);
-		}
-
-		decoder->norm = *iarg;
-		break;
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0);
 	}
+	return 0;
+}
 
-	case DECODER_SET_INPUT:
-	{
-		int *iarg = arg;
+static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct bt819 *decoder = to_bt819(sd);
 
-		v4l_dbg(1, debug, client, "set input %x\n", *iarg);
+	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
 
-		if (*iarg < 0 || *iarg > 7)
-			return -EINVAL;
-
-		if (decoder->input != *iarg) {
-			decoder->input = *iarg;
-			/* select mode */
-			if (decoder->input == 0) {
-				bt819_setbit(client, 0x0b, 6, 0);
-				bt819_setbit(client, 0x1a, 1, 1);
-			} else {
-				bt819_setbit(client, 0x0b, 6, 1);
-				bt819_setbit(client, 0x1a, 1, 0);
-			}
-		}
-		break;
+	if (decoder->enable != enable) {
+		decoder->enable = enable;
+		bt819_setbit(decoder, 0x16, 7, !enable);
 	}
+	return 0;
+}
 
-	case DECODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set output %x\n", *iarg);
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
+static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 		break;
-	}
 
-	case DECODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-		int enable = (*iarg != 0);
-
-		v4l_dbg(1, debug, client, "enable output %x\n", *iarg);
-
-		if (decoder->enable != enable) {
-			decoder->enable = enable;
-			bt819_setbit(client, 0x16, 7, !enable);
-		}
+	case V4L2_CID_CONTRAST:
+		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
 		break;
-	}
 
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *pic = arg;
-
-		v4l_dbg(1, debug, client,
-			"set picture brightness %d contrast %d colour %d\n",
-			pic->brightness, pic->contrast, pic->colour);
-
-
-		if (decoder->bright != pic->brightness) {
-			/* We want -128 to 127 we get 0-65535 */
-			decoder->bright = pic->brightness;
-			bt819_write(client, 0x0a,
-				    (decoder->bright >> 8) - 128);
-		}
-
-		if (decoder->contrast != pic->contrast) {
-			/* We want 0 to 511 we get 0-65535 */
-			decoder->contrast = pic->contrast;
-			bt819_write(client, 0x0c,
-				    (decoder->contrast >> 7) & 0xff);
-			bt819_setbit(client, 0x0b, 2,
-				     ((decoder->contrast >> 15) & 0x01));
-		}
-
-		if (decoder->sat != pic->colour) {
-			/* We want 0 to 511 we get 0-65535 */
-			decoder->sat = pic->colour;
-			bt819_write(client, 0x0d,
-				    (decoder->sat >> 7) & 0xff);
-			bt819_setbit(client, 0x0b, 1,
-				     ((decoder->sat >> 15) & 0x01));
-
-			temp = (decoder->sat * 201) / 237;
-			bt819_write(client, 0x0e, (temp >> 7) & 0xff);
-			bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
-		}
-
-		if (decoder->hue != pic->hue) {
-			/* We want -128 to 127 we get 0-65535 */
-			decoder->hue = pic->hue;
-			bt819_write(client, 0x0f,
-				    128 - (decoder->hue >> 8));
-		}
+	case V4L2_CID_SATURATION:
+		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
 		break;
-	}
+
+	case V4L2_CID_HUE:
+		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
+		break;
 
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
+static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct bt819 *decoder = to_bt819(sd);
+	int temp;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (decoder->bright == ctrl->value)
+			break;
+		decoder->bright = ctrl->value;
+		bt819_write(decoder, 0x0a, decoder->bright);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		if (decoder->contrast == ctrl->value)
+			break;
+		decoder->contrast = ctrl->value;
+		bt819_write(decoder, 0x0c, decoder->contrast & 0xff);
+		bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01));
+		break;
+
+	case V4L2_CID_SATURATION:
+		if (decoder->sat == ctrl->value)
+			break;
+		decoder->sat = ctrl->value;
+		bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff);
+		bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01));
+
+		/* Ratio between U gain and V gain must stay the same as
+		   the ratio between the default U and V gain values. */
+		temp = (decoder->sat * 180) / 254;
+		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
+		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
+		break;
+
+	case V4L2_CID_HUE:
+		if (decoder->hue == ctrl->value)
+			break;
+		decoder->hue = ctrl->value;
+		bt819_write(decoder, 0x0f, decoder->hue);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct bt819 *decoder = to_bt819(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = decoder->bright;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctrl->value = decoder->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctrl->value = decoder->sat;
+		break;
+	case V4L2_CID_HUE:
+		ctrl->value = decoder->hue;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct bt819 *decoder = to_bt819(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END };
+static const struct v4l2_subdev_core_ops bt819_core_ops = {
+	.g_chip_ident = bt819_g_chip_ident,
+	.g_ctrl = bt819_g_ctrl,
+	.s_ctrl = bt819_s_ctrl,
+	.queryctrl = bt819_queryctrl,
+};
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_tuner_ops bt819_tuner_ops = {
+	.s_std = bt819_s_std,
+};
+
+static const struct v4l2_subdev_video_ops bt819_video_ops = {
+	.s_routing = bt819_s_routing,
+	.s_stream = bt819_s_stream,
+	.querystd = bt819_querystd,
+	.g_input_status = bt819_g_input_status,
+};
+
+static const struct v4l2_subdev_ops bt819_ops = {
+	.core = &bt819_core_ops,
+	.tuner = &bt819_tuner_ops,
+	.video = &bt819_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
 
 static int bt819_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	int i, ver;
 	struct bt819 *decoder;
+	struct v4l2_subdev *sd;
 	const char *name;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	ver = bt819_read(client, 0x17);
+	decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
+	if (decoder == NULL)
+		return -ENOMEM;
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &bt819_ops);
+
+	ver = bt819_read(decoder, 0x17);
 	switch (ver & 0xf0) {
 	case 0x70:
 		name = "bt819a";
+		decoder->ident = V4L2_IDENT_BT819A;
 		break;
 	case 0x60:
 		name = "bt817a";
+		decoder->ident = V4L2_IDENT_BT817A;
 		break;
 	case 0x20:
 		name = "bt815a";
+		decoder->ident = V4L2_IDENT_BT815A;
 		break;
 	default:
-		v4l_dbg(1, debug, client,
+		v4l2_dbg(1, debug, sd,
 			"unknown chip version 0x%02x\n", ver);
 		return -ENODEV;
 	}
@@ -459,28 +506,26 @@
 	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
 			client->addr << 1, client->adapter->name);
 
-	decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
-	if (decoder == NULL)
-		return -ENOMEM;
-	decoder->norm = VIDEO_MODE_NTSC;
+	decoder->norm = V4L2_STD_NTSC;
 	decoder->input = 0;
 	decoder->enable = 1;
-	decoder->bright = 32768;
-	decoder->contrast = 32768;
-	decoder->hue = 32768;
-	decoder->sat = 32768;
-	decoder->initialized = 0;
-	i2c_set_clientdata(client, decoder);
+	decoder->bright = 0;
+	decoder->contrast = 0xd8;	/* 100% of original signal */
+	decoder->hue = 0;
+	decoder->sat = 0xfe;		/* 100% of original signal */
 
-	i = bt819_init(client);
+	i = bt819_init(sd);
 	if (i < 0)
-		v4l_dbg(1, debug, client, "init status %d\n", i);
+		v4l2_dbg(1, debug, sd, "init status %d\n", i);
 	return 0;
 }
 
 static int bt819_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_bt819(sd));
 	return 0;
 }
 
@@ -496,8 +541,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "bt819",
-	.driverid = I2C_DRIVERID_BT819,
-	.command = bt819_command,
 	.probe = bt819_probe,
 	.remove = bt819_remove,
 	.id_table = bt819_id,
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 4213867..78db395 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -34,10 +34,10 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_encoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
 MODULE_AUTHOR("Mike Bernson & Dave Perks");
@@ -47,43 +47,46 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+
 /* ----------------------------------------------------------------------- */
 
 #define BT856_REG_OFFSET	0xDA
 #define BT856_NR_REG		6
 
 struct bt856 {
+	struct v4l2_subdev sd;
 	unsigned char reg[BT856_NR_REG];
 
-	int norm;
-	int enable;
+	v4l2_std_id norm;
 };
 
+static inline struct bt856 *to_bt856(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct bt856, sd);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int bt856_write(struct bt856 *encoder, u8 reg, u8 value)
 {
-	struct bt856 *encoder = i2c_get_clientdata(client);
+	struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
 
 	encoder->reg[reg - BT856_REG_OFFSET] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
+static inline int bt856_setbit(struct bt856 *encoder, u8 reg, u8 bit, u8 value)
 {
-	struct bt856 *encoder = i2c_get_clientdata(client);
-
-	return bt856_write(client, reg,
+	return bt856_write(encoder, reg,
 		(encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
 				(value ? (1 << bit) : 0));
 }
 
-static void bt856_dump(struct i2c_client *client)
+static void bt856_dump(struct bt856 *encoder)
 {
 	int i;
-	struct bt856 *encoder = i2c_get_clientdata(client);
 
-	v4l_info(client, "register dump:\n");
+	v4l2_info(&encoder->sd, "register dump:\n");
 	for (i = 0; i < BT856_NR_REG; i += 2)
 		printk(KERN_CONT " %02x", encoder->reg[i]);
 	printk(KERN_CONT "\n");
@@ -91,153 +94,120 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int bt856_init(struct v4l2_subdev *sd, u32 arg)
 {
-	struct bt856 *encoder = i2c_get_clientdata(client);
+	struct bt856 *encoder = to_bt856(sd);
 
-	switch (cmd) {
+	/* This is just for testing!!! */
+	v4l2_dbg(1, debug, sd, "init\n");
+	bt856_write(encoder, 0xdc, 0x18);
+	bt856_write(encoder, 0xda, 0);
+	bt856_write(encoder, 0xde, 0);
+
+	bt856_setbit(encoder, 0xdc, 3, 1);
+	/*bt856_setbit(encoder, 0xdc, 6, 0);*/
+	bt856_setbit(encoder, 0xdc, 4, 1);
+
+	if (encoder->norm & V4L2_STD_NTSC)
+		bt856_setbit(encoder, 0xdc, 2, 0);
+	else
+		bt856_setbit(encoder, 0xdc, 2, 1);
+
+	bt856_setbit(encoder, 0xdc, 1, 1);
+	bt856_setbit(encoder, 0xde, 4, 0);
+	bt856_setbit(encoder, 0xde, 3, 1);
+	if (debug != 0)
+		bt856_dump(encoder);
+	return 0;
+}
+
+static int bt856_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct bt856 *encoder = to_bt856(sd);
+
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
+
+	if (std & V4L2_STD_NTSC) {
+		bt856_setbit(encoder, 0xdc, 2, 0);
+	} else if (std & V4L2_STD_PAL) {
+		bt856_setbit(encoder, 0xdc, 2, 1);
+		bt856_setbit(encoder, 0xda, 0, 0);
+		/*bt856_setbit(encoder, 0xda, 0, 1);*/
+	} else {
+		return -EINVAL;
+	}
+	encoder->norm = std;
+	if (debug != 0)
+		bt856_dump(encoder);
+	return 0;
+}
+
+static int bt856_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct bt856 *encoder = to_bt856(sd);
+
+	v4l2_dbg(1, debug, sd, "set input %d\n", route->input);
+
+	/* We only have video bus.
+	 * route->input= 0: input is from bt819
+	 * route->input= 1: input is from ZR36060 */
+	switch (route->input) {
 	case 0:
-		/* This is just for testing!!! */
-		v4l_dbg(1, debug, client, "init\n");
-		bt856_write(client, 0xdc, 0x18);
-		bt856_write(client, 0xda, 0);
-		bt856_write(client, 0xde, 0);
-
-		bt856_setbit(client, 0xdc, 3, 1);
-		//bt856_setbit(client, 0xdc, 6, 0);
-		bt856_setbit(client, 0xdc, 4, 1);
-
-		switch (encoder->norm) {
-		case VIDEO_MODE_NTSC:
-			bt856_setbit(client, 0xdc, 2, 0);
-			break;
-
-		case VIDEO_MODE_PAL:
-			bt856_setbit(client, 0xdc, 2, 1);
-			break;
-		}
-
-		bt856_setbit(client, 0xdc, 1, 1);
-		bt856_setbit(client, 0xde, 4, 0);
-		bt856_setbit(client, 0xde, 3, 1);
-		if (debug != 0)
-			bt856_dump(client);
+		bt856_setbit(encoder, 0xde, 4, 0);
+		bt856_setbit(encoder, 0xde, 3, 1);
+		bt856_setbit(encoder, 0xdc, 3, 1);
+		bt856_setbit(encoder, 0xdc, 6, 0);
 		break;
-
-	case ENCODER_GET_CAPABILITIES:
-	{
-		struct video_encoder_capability *cap = arg;
-
-		v4l_dbg(1, debug, client, "get capabilities\n");
-
-		cap->flags = VIDEO_ENCODER_PAL |
-			     VIDEO_ENCODER_NTSC |
-			     VIDEO_ENCODER_CCIR;
-		cap->inputs = 2;
-		cap->outputs = 1;
+	case 1:
+		bt856_setbit(encoder, 0xde, 4, 0);
+		bt856_setbit(encoder, 0xde, 3, 1);
+		bt856_setbit(encoder, 0xdc, 3, 1);
+		bt856_setbit(encoder, 0xdc, 6, 1);
 		break;
-	}
-
-	case ENCODER_SET_NORM:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
-
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			bt856_setbit(client, 0xdc, 2, 0);
-			break;
-
-		case VIDEO_MODE_PAL:
-			bt856_setbit(client, 0xdc, 2, 1);
-			bt856_setbit(client, 0xda, 0, 0);
-			//bt856_setbit(client, 0xda, 0, 1);
-			break;
-
-		default:
-			return -EINVAL;
-		}
-		encoder->norm = *iarg;
-		if (debug != 0)
-			bt856_dump(client);
+	case 2:	/* Color bar */
+		bt856_setbit(encoder, 0xdc, 3, 0);
+		bt856_setbit(encoder, 0xde, 4, 1);
 		break;
-	}
-
-	case ENCODER_SET_INPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set input %d\n", *iarg);
-
-		/* We only have video bus.
-		 * iarg = 0: input is from bt819
-		 * iarg = 1: input is from ZR36060 */
-		switch (*iarg) {
-		case 0:
-			bt856_setbit(client, 0xde, 4, 0);
-			bt856_setbit(client, 0xde, 3, 1);
-			bt856_setbit(client, 0xdc, 3, 1);
-			bt856_setbit(client, 0xdc, 6, 0);
-			break;
-		case 1:
-			bt856_setbit(client, 0xde, 4, 0);
-			bt856_setbit(client, 0xde, 3, 1);
-			bt856_setbit(client, 0xdc, 3, 1);
-			bt856_setbit(client, 0xdc, 6, 1);
-			break;
-		case 2:	// Color bar
-			bt856_setbit(client, 0xdc, 3, 0);
-			bt856_setbit(client, 0xde, 4, 1);
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		if (debug != 0)
-			bt856_dump(client);
-		break;
-	}
-
-	case ENCODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set output %d\n", *iarg);
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-
-	case ENCODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-
-		encoder->enable = !!*iarg;
-
-		v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
-		break;
-	}
-
 	default:
 		return -EINVAL;
 	}
 
+	if (debug != 0)
+		bt856_dump(encoder);
 	return 0;
 }
 
+static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
+static const struct v4l2_subdev_core_ops bt856_core_ops = {
+	.g_chip_ident = bt856_g_chip_ident,
+	.init = bt856_init,
+};
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_video_ops bt856_video_ops = {
+	.s_std_output = bt856_s_std_output,
+	.s_routing = bt856_s_routing,
+};
+
+static const struct v4l2_subdev_ops bt856_ops = {
+	.core = &bt856_core_ops,
+	.video = &bt856_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
 
 static int bt856_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct bt856 *encoder;
+	struct v4l2_subdev *sd;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -249,41 +219,38 @@
 	encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
 	if (encoder == NULL)
 		return -ENOMEM;
-	encoder->norm = VIDEO_MODE_NTSC;
-	encoder->enable = 1;
-	i2c_set_clientdata(client, encoder);
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &bt856_ops);
+	encoder->norm = V4L2_STD_NTSC;
 
-	bt856_write(client, 0xdc, 0x18);
-	bt856_write(client, 0xda, 0);
-	bt856_write(client, 0xde, 0);
+	bt856_write(encoder, 0xdc, 0x18);
+	bt856_write(encoder, 0xda, 0);
+	bt856_write(encoder, 0xde, 0);
 
-	bt856_setbit(client, 0xdc, 3, 1);
-	//bt856_setbit(client, 0xdc, 6, 0);
-	bt856_setbit(client, 0xdc, 4, 1);
+	bt856_setbit(encoder, 0xdc, 3, 1);
+	/*bt856_setbit(encoder, 0xdc, 6, 0);*/
+	bt856_setbit(encoder, 0xdc, 4, 1);
 
-	switch (encoder->norm) {
+	if (encoder->norm & V4L2_STD_NTSC)
+		bt856_setbit(encoder, 0xdc, 2, 0);
+	else
+		bt856_setbit(encoder, 0xdc, 2, 1);
 
-	case VIDEO_MODE_NTSC:
-		bt856_setbit(client, 0xdc, 2, 0);
-		break;
-
-	case VIDEO_MODE_PAL:
-		bt856_setbit(client, 0xdc, 2, 1);
-		break;
-	}
-
-	bt856_setbit(client, 0xdc, 1, 1);
-	bt856_setbit(client, 0xde, 4, 0);
-	bt856_setbit(client, 0xde, 3, 1);
+	bt856_setbit(encoder, 0xdc, 1, 1);
+	bt856_setbit(encoder, 0xde, 4, 0);
+	bt856_setbit(encoder, 0xde, 3, 1);
 
 	if (debug != 0)
-		bt856_dump(client);
+		bt856_dump(encoder);
 	return 0;
 }
 
 static int bt856_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_bt856(sd));
 	return 0;
 }
 
@@ -295,8 +262,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "bt856",
-	.driverid = I2C_DRIVERID_BT856,
-	.command = bt856_command,
 	.probe = bt856_probe,
 	.remove = bt856_remove,
 	.id_table = bt856_id,
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
index 596f9e2..350cae4 100644
--- a/drivers/media/video/bt866.c
+++ b/drivers/media/video/bt866.c
@@ -34,10 +34,10 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_encoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
 MODULE_AUTHOR("Mike Bernson & Dave Perks");
@@ -47,22 +47,22 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+
 /* ----------------------------------------------------------------------- */
 
 struct bt866 {
+	struct v4l2_subdev sd;
 	u8 reg[256];
-
-	int norm;
-	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
-static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data)
+static inline struct bt866 *to_bt866(struct v4l2_subdev *sd)
 {
-	struct bt866 *encoder = i2c_get_clientdata(client);
+	return container_of(sd, struct bt866, sd);
+}
+
+static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
 	u8 buffer[2];
 	int err;
 
@@ -89,163 +89,120 @@
 	return 0;
 }
 
-static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 {
-	struct bt866 *encoder = i2c_get_clientdata(client);
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
 
-	switch (cmd) {
-	case ENCODER_GET_CAPABILITIES:
-	{
-		struct video_encoder_capability *cap = arg;
-
-		v4l_dbg(1, debug, client, "get capabilities\n");
-
-		cap->flags
-			= VIDEO_ENCODER_PAL
-			| VIDEO_ENCODER_NTSC
-			| VIDEO_ENCODER_CCIR;
-		cap->inputs = 2;
-		cap->outputs = 1;
-		break;
-	}
-
-	case ENCODER_SET_NORM:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
-
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			break;
-
-		case VIDEO_MODE_PAL:
-			break;
-
-		default:
-			return -EINVAL;
-		}
-		encoder->norm = *iarg;
-		break;
-	}
-
-	case ENCODER_SET_INPUT:
-	{
-		int *iarg = arg;
-		static const __u8 init[] = {
-			0xc8, 0xcc, /* CRSCALE */
-			0xca, 0x91, /* CBSCALE */
-			0xcc, 0x24, /* YC16 | OSDNUM */
-			0xda, 0x00, /*  */
-			0xdc, 0x24, /* SETMODE | PAL */
-			0xde, 0x02, /* EACTIVE */
-
-			/* overlay colors */
-			0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
-			0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
-			0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
-			0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
-			0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
-			0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
-			0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
-			0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
-
-			0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
-			0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
-			0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
-			0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
-			0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
-			0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
-			0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
-			0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
-		};
-		int i;
-		u8 val;
-
-		for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
-			bt866_write(client, init[i], init[i+1]);
-
-		val = encoder->reg[0xdc];
-
-		if (*iarg == 0)
-			val |= 0x40; /* CBSWAP */
-		else
-			val &= ~0x40; /* !CBSWAP */
-
-		bt866_write(client, 0xdc, val);
-
-		val = encoder->reg[0xcc];
-		if (*iarg == 2)
-			val |= 0x01; /* OSDBAR */
-		else
-			val &= ~0x01; /* !OSDBAR */
-		bt866_write(client, 0xcc, val);
-
-		v4l_dbg(1, debug, client, "set input %d\n", *iarg);
-
-		switch (*iarg) {
-		case 0:
-			break;
-		case 1:
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	}
-
-	case ENCODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set output %d\n", *iarg);
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-
-	case ENCODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-		encoder->enable = !!*iarg;
-
-		v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
-		break;
-	}
-
-	case 4711:
-	{
-		int *iarg = arg;
-		__u8 val;
-
-		v4l_dbg(1, debug, client, "square %d\n", *iarg);
-
-		val = encoder->reg[0xdc];
-		if (*iarg)
-			val |= 1; /* SQUARE */
-		else
-			val &= ~1; /* !SQUARE */
-		bt866_write(client, 0xdc, val);
-		break;
-	}
-
-	default:
+	/* Only PAL supported by this driver at the moment! */
+	if (!(std & V4L2_STD_NTSC))
 		return -EINVAL;
-	}
-
 	return 0;
 }
 
-static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
+static int bt866_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	static const __u8 init[] = {
+		0xc8, 0xcc, /* CRSCALE */
+		0xca, 0x91, /* CBSCALE */
+		0xcc, 0x24, /* YC16 | OSDNUM */
+		0xda, 0x00, /*  */
+		0xdc, 0x24, /* SETMODE | PAL */
+		0xde, 0x02, /* EACTIVE */
 
-I2C_CLIENT_INSMOD;
+		/* overlay colors */
+		0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
+		0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
+		0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
+		0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
+		0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
+		0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
+		0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
+		0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
+
+		0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
+		0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
+		0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
+		0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
+		0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
+		0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
+		0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
+		0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
+	};
+	struct bt866 *encoder = to_bt866(sd);
+	u8 val;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
+		bt866_write(encoder, init[i], init[i+1]);
+
+	val = encoder->reg[0xdc];
+
+	if (route->input == 0)
+		val |= 0x40; /* CBSWAP */
+	else
+		val &= ~0x40; /* !CBSWAP */
+
+	bt866_write(encoder, 0xdc, val);
+
+	val = encoder->reg[0xcc];
+	if (route->input == 2)
+		val |= 0x01; /* OSDBAR */
+	else
+		val &= ~0x01; /* !OSDBAR */
+	bt866_write(encoder, 0xcc, val);
+
+	v4l2_dbg(1, debug, sd, "set input %d\n", route->input);
+
+	switch (route->input) {
+	case 0:
+	case 1:
+	case 2:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#if 0
+/* Code to setup square pixels, might be of some use in the future,
+   but is currently unused. */
+	val = encoder->reg[0xdc];
+	if (*iarg)
+		val |= 1; /* SQUARE */
+	else
+		val &= ~1; /* !SQUARE */
+	bt866_write(client, 0xdc, val);
+#endif
+
+static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops bt866_core_ops = {
+	.g_chip_ident = bt866_g_chip_ident,
+};
+
+static const struct v4l2_subdev_video_ops bt866_video_ops = {
+	.s_std_output = bt866_s_std_output,
+	.s_routing = bt866_s_routing,
+};
+
+static const struct v4l2_subdev_ops bt866_ops = {
+	.core = &bt866_core_ops,
+	.video = &bt866_video_ops,
+};
 
 static int bt866_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct bt866 *encoder;
+	struct v4l2_subdev *sd;
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
@@ -253,20 +210,18 @@
 	encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
 	if (encoder == NULL)
 		return -ENOMEM;
-
-	i2c_set_clientdata(client, encoder);
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &bt866_ops);
 	return 0;
 }
 
 static int bt866_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
-	return 0;
-}
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
-static int bt866_legacy_probe(struct i2c_adapter *adapter)
-{
-	return adapter->id == I2C_HW_B_ZR36067;
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_bt866(sd));
+	return 0;
 }
 
 static const struct i2c_device_id bt866_id[] = {
@@ -277,10 +232,7 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "bt866",
-	.driverid = I2C_DRIVERID_BT866,
-	.command = bt866_command,
 	.probe = bt866_probe,
 	.remove = bt866_remove,
-	.legacy_probe = bt866_legacy_probe,
 	.id_table = bt866_id,
 };
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index ce71e8e..3077c450 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -10,7 +10,7 @@
 	select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO
-	select VIDEO_TDA9875 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
 	---help---
 	  Support for BT848 based frame grabber/overlay boards. This includes
 	  the Miro, Hauppauge and STB boards. Please read the material in
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index d24dcc0..b9c3ba5 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -73,6 +73,11 @@
 
 static void geovision_muxsel(struct bttv *btv, unsigned int input);
 
+static void phytec_muxsel(struct bttv *btv, unsigned int input);
+
+static void gv800s_muxsel(struct bttv *btv, unsigned int input);
+static void gv800s_init(struct bttv *btv);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -91,12 +96,10 @@
 static unsigned int tuner[BTTV_MAX]  = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
 static unsigned int svhs[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
 static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int audiodev[BTTV_MAX];
+static unsigned int saa6588[BTTV_MAX];
 static struct bttv  *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
-#ifdef MODULE
-static unsigned int autoload = 1;
-#else
-static unsigned int autoload;
-#endif
+static unsigned int autoload = UNSET;
 static unsigned int gpiomask = UNSET;
 static unsigned int audioall = UNSET;
 static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
@@ -115,6 +118,7 @@
 module_param_array(tuner,    int, NULL, 0444);
 module_param_array(svhs,     int, NULL, 0444);
 module_param_array(remote,   int, NULL, 0444);
+module_param_array(audiodev, int, NULL, 0444);
 module_param_array(audiomux, int, NULL, 0444);
 
 MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
@@ -125,7 +129,14 @@
 MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
 MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)");
 MODULE_PARM_DESC(tuner,"specify installed tuner type");
-MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)");
+MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore");
+MODULE_PARM_DESC(audiodev, "specify audio device:\n"
+		"\t\t-1 = no audio\n"
+		"\t\t 0 = autodetect (default)\n"
+		"\t\t 1 = msp3400\n"
+		"\t\t 2 = tda7432\n"
+		"\t\t 3 = tvaudio");
+MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition.");
 MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
 		" [some VIA/SIS chipsets are known to have problem with overlay]");
 
@@ -246,6 +257,10 @@
 	{ 0xa182ff0d, BTTV_BOARD_IVC120,        "IVC-120G" },
 	{ 0xa182ff0e, BTTV_BOARD_IVC120,        "IVC-120G" },
 	{ 0xa182ff0f, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xf0500000, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+	{ 0xf0500001, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+	{ 0xf0500002, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
+	{ 0xf0500003, BTTV_BOARD_IVCE8784,      "IVCE-8784" },
 
 	{ 0x41424344, BTTV_BOARD_GRANDTEC,      "GrandTec Multi Capture" },
 	{ 0x01020304, BTTV_BOARD_XGUARD,        "Grandtec Grand X-Guard" },
@@ -289,6 +304,8 @@
 	/* Duplicate PCI ID, reconfigure for this board during the eeprom read.
 	* { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB,  "Hauppauge ImpactVCB" }, */
 
+	{ 0x109e036e, BTTV_BOARD_CONCEPTRONIC_CTVFMI2,	"Conceptronic CTVFMi v2"},
+
 	/* DVB cards (using pci function .1 for mpeg data xfer) */
 	{ 0x001c11bd, BTTV_BOARD_PINNACLESAT,   "Pinnacle PCTV Sat" },
 	{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
@@ -305,6 +322,20 @@
 	{ 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,	"DViCO FusionHDTV 2" },
 	{ 0x763c008a, BTTV_BOARD_GEOVISION_GV600,	"GeoVision GV-600" },
 	{ 0x18011000, BTTV_BOARD_ENLTV_FM_2,	"Encore ENL TV-FM-2" },
+	{ 0x763d800a, BTTV_BOARD_GEOVISION_GV800S, "GeoVision GV-800(S) (master)" },
+	{ 0x763d800b, BTTV_BOARD_GEOVISION_GV800S_SL,	"GeoVision GV-800(S) (slave)" },
+	{ 0x763d800c, BTTV_BOARD_GEOVISION_GV800S_SL,	"GeoVision GV-800(S) (slave)" },
+	{ 0x763d800d, BTTV_BOARD_GEOVISION_GV800S_SL,	"GeoVision GV-800(S) (slave)" },
+
+	{ 0x15401830, BTTV_BOARD_PV183,         "Provideo PV183-1" },
+	{ 0x15401831, BTTV_BOARD_PV183,         "Provideo PV183-2" },
+	{ 0x15401832, BTTV_BOARD_PV183,         "Provideo PV183-3" },
+	{ 0x15401833, BTTV_BOARD_PV183,         "Provideo PV183-4" },
+	{ 0x15401834, BTTV_BOARD_PV183,         "Provideo PV183-5" },
+	{ 0x15401835, BTTV_BOARD_PV183,         "Provideo PV183-6" },
+	{ 0x15401836, BTTV_BOARD_PV183,         "Provideo PV183-7" },
+	{ 0x15401837, BTTV_BOARD_PV183,         "Provideo PV183-8" },
+
 	{ 0, -1, NULL }
 };
 
@@ -316,59 +347,50 @@
 	[BTTV_BOARD_UNKNOWN] = {
 		.name		= " *** UNKNOWN/GENERIC *** ",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
 		.svhs		= 2,
-		.muxsel		= { 2, 3, 1, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0),
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MIRO] = {
 		.name		= "MIRO PCTV",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 2, 0, 0, 0 },
 		.gpiomute 	= 10,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_HAUPPAUGE] = {
 		.name		= "Hauppauge (bt848)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_STB] = {
 		.name		= "STB, Gateway P/N 6000699 (bt848)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 4, 0, 2, 3 },
 		.gpiomute 	= 1,
 		.no_msp34xx	= 1,
 		.needs_tvaudio	= 1,
 		.tuner_type     = TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 		.has_radio      = 1,
 	},
@@ -377,202 +399,177 @@
 	[BTTV_BOARD_INTEL] = {
 		.name		= "Intel Create and Share PCI/ Smart Video Recorder III",
 		.video_inputs	= 4,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
+		/* .audio_inputs= 0, */
 		.svhs		= 2,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0 },
 		.needs_tvaudio	= 0,
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_DIAMOND] = {
 		.name		= "Diamond DTV2000",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 3,
-		.muxsel		= { 2, 3, 1, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0),
 		.gpiomux 	= { 0, 1, 0, 1 },
 		.gpiomute 	= 3,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_AVERMEDIA] = {
 		.name		= "AVerMedia TVPhone",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomask	= 0x0f,
 		.gpiomux 	= { 0x0c, 0x04, 0x08, 0x04 },
 		/*                0x04 for some cards ?? */
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= avermedia_tvphone_audio,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_MATRIX_VISION] = {
 		.name		= "MATRIX-Vision MV-Delta",
 		.video_inputs	= 5,
-		.audio_inputs	= 1,
-		.tuner		= UNSET,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 0, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
 		.gpiomux 	= { 0 },
 		.needs_tvaudio	= 1,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x08 ---------------------------------- */
 	[BTTV_BOARD_FLYVIDEO] = {
 		.name		= "Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xc00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0xc00, 0x800, 0x400 },
 		.gpiomute 	= 0xc00,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TURBOTV] = {
 		.name		= "IMS/IXmicro TurboTV",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 3,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 1, 1, 2, 3 },
 		.needs_tvaudio	= 0,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_HAUPPAUGE878] = {
 		.name		= "Hauppauge (bt878)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x0f, /* old: 7 */
-		.muxsel		= { 2, 0, 1, 1 },
+		.muxsel		= MUXSEL(2, 0, 1, 1),
 		.gpiomux 	= { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MIROPRO] = {
 		.name		= "MIRO PCTV pro",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x3014f,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x20001,0x10001, 0, 0 },
 		.gpiomute 	= 10,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x0c ---------------------------------- */
 	[BTTV_BOARD_ADSTECH_TV] = {
 		.name		= "ADS Technologies Channel Surfer TV (bt848)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 13, 14, 11, 7 },
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_AVERMEDIA98] = {
 		.name		= "AVerMedia TVCapture 98",
 		.video_inputs	= 3,
-		.audio_inputs	= 4,
-		.tuner		= 0,
+		/* .audio_inputs= 4, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 13, 14, 11, 7 },
 		.needs_tvaudio	= 1,
 		.msp34xx_alt    = 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= avermedia_tv_stereo_audio,
 		.no_gpioirq     = 1,
 	},
 	[BTTV_BOARD_VHX] = {
 		.name		= "Aimslab Video Highway Xtreme (VHX)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */
 		.gpiomute 	= 4,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ZOLTRIX] = {
 		.name		= "Zoltrix TV-Max",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0, 1, 0 },
 		.gpiomute 	= 10,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x10 ---------------------------------- */
 	[BTTV_BOARD_PIXVIEWPLAYTV] = {
 		.name		= "Prolink Pixelview PlayTV (bt878)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x01fe00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		/* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
 		.gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
 		.gpiomute 	= 0x002000,
@@ -580,194 +577,170 @@
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_WINVIEW_601] = {
 		.name		= "Leadtek WinView 601",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x8300f8,
-		.muxsel		= { 2, 3, 1, 1,0 },
+		.muxsel		= MUXSEL(2, 3, 1, 1, 0),
 		.gpiomux 	= { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
 		.gpiomute 	= 0xcfa007,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.volume_gpio	= winview_volume,
 		.has_radio	= 1,
 	},
 	[BTTV_BOARD_AVEC_INTERCAP] = {
 		.name		= "AVEC Intercapture",
 		.video_inputs	= 3,
-		.audio_inputs	= 2,
-		.tuner		= 0,
+		/* .audio_inputs= 2, */
 		.svhs		= 2,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 1, 0, 0, 0 },
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_LIFE_FLYKIT] = {
 		.name		= "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= UNSET,
-		.svhs		= UNSET,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
 		.gpiomask	= 0x8dff00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0 },
 		.no_msp34xx	= 1,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x14 ---------------------------------- */
 	[BTTV_BOARD_CEI_RAFFLES] = {
 		.name		= "CEI Raffles Card",
 		.video_inputs	= 3,
-		.audio_inputs	= 3,
-		.tuner		= 0,
+		/* .audio_inputs= 3, */
 		.svhs		= 2,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_CONFERENCETV] = {
 		.name		= "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
 		.video_inputs	= 4,
-		.audio_inputs	= 2,  /* tuner, line in */
-		.tuner		= 0,
+		/* .audio_inputs= 2,  tuner, line in */
 		.svhs		= 2,
 		.gpiomask	= 0x1800,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_PHOEBE_TVMAS] = {
 		.name		= "Askey CPH050/ Phoebe Tv Master + FM",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xc00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 1, 0x800, 0x400 },
 		.gpiomute 	= 0xc00,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MODTEC_205] = {
 		.name		= "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
-		.svhs		= UNSET,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
+		.has_dig_in	= 1,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 3, -1 },
-		.digital_mode   = DIGITAL_MODE_CAMERA,
+		.muxsel		= MUXSEL(2, 3, 0), /* input 2 is digital */
+		/* .digital_mode= DIGITAL_MODE_CAMERA, */
 		.gpiomux 	= { 0, 0, 0, 0 },
 		.no_msp34xx	= 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_ALPS_TSBB5_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x18 ---------------------------------- */
 	[BTTV_BOARD_MAGICTVIEW061] = {
 		.name		= "Askey CPH05X/06X (bt878) [many vendors]",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xe00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= {0x400, 0x400, 0x400, 0x400 },
 		.gpiomute 	= 0xc00,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_VOBIS_BOOSTAR] = {
 		.name           = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask       = 0x1f0fff,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
 		.gpiomute 	= 0x40000,
 		.needs_tvaudio	= 0,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= terratv_audio,
 	},
 	[BTTV_BOARD_HAUPPAUG_WCAM] = {
 		.name		= "Hauppauge WinCam newer (bt878)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 0, 1, 1 },
+		.muxsel		= MUXSEL(2, 0, 1, 1),
 		.gpiomux 	= { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.needs_tvaudio	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MAXI] = {
 		.name		= "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
 		.video_inputs	= 4,
-		.audio_inputs	= 2,
-		.tuner		= 0,
+		/* .audio_inputs= 2, */
 		.svhs		= 2,
 		.gpiomask	= 0x1800,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll            = PLL_28,
 		.tuner_type	= TUNER_PHILIPS_SECAM,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x1c ---------------------------------- */
 	[BTTV_BOARD_TERRATV] = {
 		.name           = "Terratec TerraTV+ Version 1.1 (bt878)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x1f0fff,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x20000, 0x30000, 0x10000, 0x00000 },
 		.gpiomute 	= 0x40000,
 		.needs_tvaudio	= 0,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= terratv_audio,
 		/* GPIO wiring:
 		External 20 pin connector (for Active Radio Upgrade board)
@@ -805,87 +778,77 @@
 		/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
 		.name		= "Imagenation PXC200",
 		.video_inputs	= 5,
-		.audio_inputs	= 1,
-		.tuner		= UNSET,
+		/* .audio_inputs= 1, */
 		.svhs		= 1, /* was: 4 */
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 0, 0},
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
 		.gpiomux 	= { 0 },
 		.needs_tvaudio	= 1,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.muxsel_hook    = PXC200_muxsel,
 
 	},
 	[BTTV_BOARD_FLYVIDEO_98] = {
 		.name		= "Lifeview FlyVideo 98 LR50",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x1800,  /* 0x8dfe00 */
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0x0800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll            = PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_IPROTV] = {
 		.name		= "Formac iProTV, Formac ProTV I (bt848)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
 		.gpiomask	= 1,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 1, 0, 0, 0 },
 		.pll            = PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x20 ---------------------------------- */
 	[BTTV_BOARD_INTEL_C_S_PCI] = {
 		.name		= "Intel Create and Share PCI/ Smart Video Recorder III",
 		.video_inputs	= 4,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
+		/* .audio_inputs= 0, */
 		.svhs		= 2,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0 },
 		.needs_tvaudio	= 0,
 		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TERRATVALUE] = {
 		.name           = "Terratec TerraTValue Version Bt878",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xffff00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x500, 0, 0x300, 0x900 },
 		.gpiomute 	= 0x900,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_WINFAST2000] = {
 		.name		= "Leadtek WinFast 2000/ WinFast 2000 XP",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
-		.muxsel		= { 2, 3, 1, 1, 0 }, /* TV, CVid, SVid, CVid over SVid connector */
+		/* TV, CVid, SVid, CVid over SVid connector */
+		.muxsel		= MUXSEL(2, 3, 1, 1, 0),
 		/* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
 		.gpiomask	= 0xb33000,
 		.gpiomux 	= { 0x122000,0x1000,0x0000,0x620000 },
@@ -906,217 +869,191 @@
 		.has_radio	= 1,
 		.tuner_type	= TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= winfast2000_audio,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_CHRONOS_VS2] = {
 		.name		= "Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II",
 		.video_inputs	= 4,
-		.audio_inputs	= 3,
-		.tuner		= 0,
+		/* .audio_inputs= 3, */
 		.svhs		= 2,
 		.gpiomask	= 0x1800,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x24 ---------------------------------- */
 	[BTTV_BOARD_TYPHOON_TVIEW] = {
 		.name		= "Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner",
 		.video_inputs	= 4,
-		.audio_inputs	= 3,
-		.tuner		= 0,
+		/* .audio_inputs= 3, */
 		.svhs		= 2,
 		.gpiomask	= 0x1800,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio	= 1,
 	},
 	[BTTV_BOARD_PXELVWPLTVPRO] = {
 		.name		= "Prolink PixelView PlayTV pro",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xff,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x21, 0x20, 0x24, 0x2c },
 		.gpiomute 	= 0x29,
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MAGICTVIEW063] = {
 		.name		= "Askey CPH06X TView99",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x551e00,
-		.muxsel		= { 2, 3, 1, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0),
 		.gpiomux 	= { 0x551400, 0x551200, 0, 0 },
 		.gpiomute 	= 0x551c00,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_PINNACLE] = {
 		.name		= "Pinnacle PCTV Studio/Rave",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x03000F,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 2, 0xd0001, 0, 0 },
 		.gpiomute 	= 1,
 		.needs_tvaudio	= 0,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x28 ---------------------------------- */
 	[BTTV_BOARD_STB2] = {
 		.name		= "STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 7,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 4, 0, 2, 3 },
 		.gpiomute 	= 1,
 		.no_msp34xx	= 1,
 		.needs_tvaudio	= 1,
 		.tuner_type     = TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 		.has_radio      = 1,
 	},
 	[BTTV_BOARD_AVPHONE98] = {
 		.name		= "AVerMedia TVPhone 98",
 		.video_inputs	= 3,
-		.audio_inputs	= 4,
-		.tuner		= 0,
+		/* .audio_inputs= 4, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 13, 4, 11, 7 },
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio	= 1,
 		.audio_mode_gpio= avermedia_tvphone_audio,
 	},
 	[BTTV_BOARD_PV951] = {
 		.name		= "ProVideo PV951", /* pic16c54 */
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 1},
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0, 0, 0},
 		.needs_tvaudio	= 1,
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ONAIR_TV] = {
 		.name		= "Little OnAir TV",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xe00b,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
 		.gpiomute 	= 0xff3ffc,
 		.no_msp34xx	= 1,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x2c ---------------------------------- */
 	[BTTV_BOARD_SIGMA_TVII_FM] = {
 		.name		= "Sigma TVII-FM",
 		.video_inputs	= 2,
-		.audio_inputs	= 1,
-		.tuner		= 0,
-		.svhs		= UNSET,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
 		.gpiomask	= 3,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 1, 1, 0, 2 },
 		.gpiomute 	= 3,
 		.no_msp34xx	= 1,
 		.pll		= PLL_NONE,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MATRIX_VISION2] = {
 		.name		= "MATRIX-Vision MV-Delta 2",
 		.video_inputs	= 5,
-		.audio_inputs	= 1,
-		.tuner		= UNSET,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
 		.gpiomask	= 0,
-		.muxsel		= { 2, 3, 1, 0, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
 		.gpiomux 	= { 0 },
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ZOLTRIX_GENIE] = {
 		.name		= "Zoltrix Genie TV/FM",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xbcf03f,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0xbc803f, 0xbc903f, 0xbcb03f, 0 },
 		.gpiomute 	= 0xbcb03f,
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TEMIC_4039FR5_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TERRATVRADIO] = {
 		.name		= "Terratec TV/Radio+",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x70000,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x20000, 0x30000, 0x10000, 0 },
 		.gpiomute 	= 0x40000,
 		.needs_tvaudio	= 1,
@@ -1124,7 +1061,6 @@
 		.pll		= PLL_35,
 		.tuner_type	= TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio	= 1,
 	},
 
@@ -1132,51 +1068,46 @@
 	[BTTV_BOARD_DYNALINK] = {
 		.name		= "Askey CPH03x/ Dynalink Magic TView",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= {2,0,0,0 },
 		.gpiomute 	= 1,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_GVBCTV3PCI] = {
 		.name		= "IODATA GV-BCTV3/PCI",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x010f00,
-		.muxsel		= {2, 3, 0, 0 },
+		.muxsel		= MUXSEL(2, 3, 0, 0),
 		.gpiomux 	= {0x10000, 0, 0x10000, 0 },
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_ALPS_TSHC6_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= gvbctv3pci_audio,
 	},
 	[BTTV_BOARD_PXELVWPLTVPAK] = {
 		.name		= "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
 		.video_inputs	= 5,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 3,
+		.has_dig_in	= 1,
 		.gpiomask	= 0xAA0000,
-		.muxsel		= { 2,3,1,1,-1 },
-		.digital_mode   = DIGITAL_MODE_CAMERA,
+		.muxsel		= MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
+		/* .digital_mode= DIGITAL_MODE_CAMERA, */
 		.gpiomux 	= { 0x20000, 0, 0x80000, 0x80000 },
 		.gpiomute 	= 0xa8000,
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote	= 1,
 		/* GPIO wiring: (different from Rev.4C !)
 			GPIO17: U4.A0 (first hef4052bt)
@@ -1191,17 +1122,15 @@
 	[BTTV_BOARD_EAGLE] = {
 		.name           = "Eagle Wireless Capricorn2 (bt878A)",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 7,
-		.muxsel         = { 2, 0, 1, 1 },
+		.muxsel         = MUXSEL(2, 0, 1, 1),
 		.gpiomux        = { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.pll            = PLL_28,
 		.tuner_type     = UNSET /* TUNER_ALPS_TMDH2_NTSC */,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x34 ---------------------------------- */
@@ -1209,11 +1138,10 @@
 		/* David Härdeman <david@2gen.com> */
 		.name           = "Pinnacle PCTV Studio Pro",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 3,
 		.gpiomask       = 0x03000F,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 1, 0xd0001, 0, 0 },
 		.gpiomute 	= 10,
 				/* sound path (5 sources):
@@ -1229,25 +1157,22 @@
 		.pll            = PLL_28,
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TVIEW_RDS_FM] = {
 		/* Claas Langbehn <claas@bigfoot.com>,
 		Sven Grothklags <sven@upb.de> */
 		.name		= "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
 		.video_inputs	= 4,
-		.audio_inputs	= 3,
-		.tuner		= 0,
+		/* .audio_inputs= 3, */
 		.svhs		= 2,
 		.gpiomask	= 0x1c,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0, 0, 0x10, 8 },
 		.gpiomute 	= 4,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio	= 1,
 	},
 	[BTTV_BOARD_LIFETEC_9415] = {
@@ -1258,11 +1183,10 @@
 			options tuner type=5 */
 		.name		= "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x18e0,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x0000,0x0800,0x1000,0x1000 },
 		.gpiomute 	= 0x18e0,
 			/* For cards with tda9820/tda9821:
@@ -1272,25 +1196,22 @@
 		.pll		= PLL_28,
 		.tuner_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_BESTBUY_EASYTV] = {
 		/* Miguel Angel Alvarez <maacruz@navegalia.com>
 		old Easy TV BT848 version (model CPH031) */
 		.name           = "Askey CPH031/ BESTBUY Easy TV",
 		.video_inputs	= 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0xF,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 2, 0, 0, 0 },
 		.gpiomute 	= 10,
 		.needs_tvaudio  = 0,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x38 ---------------------------------- */
@@ -1298,17 +1219,15 @@
 		/* Gordon Heydon <gjheydon@bigfoot.com ('98) */
 		.name           = "Lifeview FlyVideo 98FM LR50",
 		.video_inputs   = 4,
-		.audio_inputs   = 3,
-		.tuner          = 0,
+		/* .audio_inputs= 3, */
 		.svhs           = 2,
 		.gpiomask       = 0x1800,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 0x800, 0x1000, 0x1000 },
 		.gpiomute 	= 0x1800,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 		/* This is the ultimate cheapo capture card
 		* just a BT848A on a small PCB!
@@ -1316,51 +1235,45 @@
 	[BTTV_BOARD_GRANDTEC] = {
 		.name           = "GrandTec 'Grand Video Capture' (Bt848)",
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 1,
 		.gpiomask       = 0,
-		.muxsel         = { 3, 1 },
+		.muxsel         = MUXSEL(3, 1),
 		.gpiomux        = { 0 },
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
 		.pll            = PLL_35,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ASKEY_CPH060] = {
 		/* Daniel Herrington <daniel.herrington@home.com> */
 		.name           = "Askey CPH060/ Phoebe TV Master Only (No FM)",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0xe00,
-		.muxsel         = { 2, 3, 1, 1},
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0x400, 0x400, 0x400, 0x400 },
 		.gpiomute 	= 0x800,
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ASKEY_CPH03X] = {
 		/* Matti Mottus <mottus@physic.ut.ee> */
 		.name		= "Askey CPH03x TV Capturer",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask       = 0x03000F,
-		.muxsel		= { 2, 3, 1, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 2, 0, 0, 0 },
 		.gpiomute 	= 1,
 		.pll            = PLL_28,
 		.tuner_type	= TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x3c ---------------------------------- */
@@ -1368,34 +1281,30 @@
 		/* Philip Blundell <philb@gnu.org> */
 		.name           = "Modular Technology MM100PCTV",
 		.video_inputs   = 2,
-		.audio_inputs   = 2,
-		.tuner		= 0,
-		.svhs		= UNSET,
+		/* .audio_inputs= 2, */
+		.svhs		= NO_SVHS,
 		.gpiomask       = 11,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 2, 0, 0, 1 },
 		.gpiomute 	= 8,
 		.pll            = PLL_35,
 		.tuner_type     = TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_GMV1] = {
 		/* Adrian Cox <adrian@humboldt.co.uk */
 		.name		= "AG Electronics GMV1",
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
-		.tuner		= UNSET,
+		/* .audio_inputs= 0, */
 		.svhs		= 1,
 		.gpiomask       = 0xF,
-		.muxsel		= { 2, 2 },
+		.muxsel		= MUXSEL(2, 2),
 		.gpiomux        = { },
 		.no_msp34xx     = 1,
 		.needs_tvaudio  = 0,
 		.pll		= PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_BESTBUY_EASYTV2] = {
 		/* Miguel Angel Alvarez <maacruz@navegalia.com>
@@ -1403,34 +1312,30 @@
 		special thanks to Informatica Mieres for providing the card */
 		.name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
 		.video_inputs	= 3,
-		.audio_inputs   = 2,
-		.tuner          = 0,
+		/* .audio_inputs= 2, */
 		.svhs           = 2,
 		.gpiomask       = 0xFF,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 1, 0, 4, 4 },
 		.gpiomute 	= 9,
 		.needs_tvaudio  = 0,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_ATI_TVWONDER] = {
 		/* Lukas Gebauer <geby@volny.cz> */
 		.name		= "ATI TV-Wonder",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xf03f,
-		.muxsel		= { 2, 3, 1, 0 },
+		.muxsel		= MUXSEL(2, 3, 1, 0),
 		.gpiomux 	= { 0xbffe, 0, 0xbfff, 0 },
 		.gpiomute 	= 0xbffe,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TEMIC_4006FN5_MULTI_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x40 ---------------------------------- */
@@ -1438,27 +1343,24 @@
 		/* Lukas Gebauer <geby@volny.cz> */
 		.name		= "ATI TV-Wonder VE",
 		.video_inputs	= 2,
-		.audio_inputs	= 1,
-		.tuner		= 0,
-		.svhs		= UNSET,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
 		.gpiomask	= 1,
-		.muxsel		= { 2, 3, 0, 1 },
+		.muxsel		= MUXSEL(2, 3, 0, 1),
 		.gpiomux 	= { 0, 0, 1, 0 },
 		.no_msp34xx	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_TEMIC_4006FN5_MULTI_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_FLYVIDEO2000] = {
 		/* DeeJay <deejay@westel900.net (2000S) */
 		.name           = "Lifeview FlyVideo 2000S LR90",
 		.video_inputs   = 3,
-		.audio_inputs   = 3,
-		.tuner          = 0,
+		/* .audio_inputs= 3, */
 		.svhs           = 2,
 		.gpiomask	= 0x18e0,
-		.muxsel		= { 2, 3, 0, 1 },
+		.muxsel		= MUXSEL(2, 3, 0, 1),
 				/* Radio changed from 1e80 to 0x800 to make
 				FlyVideo2000S in .hu happy (gm)*/
 				/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
@@ -1471,40 +1373,35 @@
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TERRATVALUER] = {
 		.name		= "Terratec TValueRadio",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0xffff00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x500, 0x500, 0x300, 0x900 },
 		.gpiomute 	= 0x900,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio	= 1,
 	},
 	[BTTV_BOARD_GVBCTV4PCI] = {
 		/* TANAKA Kei <peg00625@nifty.com> */
 		.name           = "IODATA GV-BCTV4/PCI",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x010f00,
-		.muxsel         = {2, 3, 0, 0 },
+		.muxsel         = MUXSEL(2, 3, 0, 0),
 		.gpiomux        = {0x10000, 0, 0x10000, 0 },
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_SHARP_2U5JF5540_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= gvbctv3pci_audio,
 	},
 
@@ -1514,9 +1411,8 @@
 		/* try "insmod msp3400 simple=0" if you have
 		* sound problems with this card. */
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
-		.svhs           = UNSET,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0x4f8a00,
 		/* 0x100000: 1=MSP enabled (0=disable again)
 		* 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
@@ -1524,10 +1420,9 @@
 		.gpiomute 	= 0x947fff,
 		/* tvtuner, radio,   external,internal, mute,  stereo
 		* tuner, Composit, SVid, Composit-on-Svid-adapter */
-		.muxsel         = { 2, 3 ,0 ,1 },
+		.muxsel         = MUXSEL(2, 3, 0, 1),
 		.tuner_type     = TUNER_MT2032,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll		= PLL_28,
 		.has_radio	= 1,
 	},
@@ -1536,9 +1431,8 @@
 		/* try "insmod msp3400 simple=0" if you have
 		* sound problems with this card. */
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
-		.svhs           = UNSET,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0x4f8a00,
 		/* 0x100000: 1=MSP enabled (0=disable again)
 		* 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
@@ -1546,10 +1440,9 @@
 		.gpiomute 	= 0x947fff,
 		/* tvtuner, radio,   external,internal, mute,  stereo
 		* tuner, Composit, SVid, Composit-on-Svid-adapter */
-		.muxsel         = { 2, 3 ,0 ,1 },
+		.muxsel         = MUXSEL(2, 3, 0, 1),
 		.tuner_type     = TUNER_MT2032,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll		= PLL_28,
 		.has_radio	= 1,
 	},
@@ -1557,31 +1450,27 @@
 		/* Philip Blundell <pb@nexus.co.uk> */
 		.name           = "Active Imaging AIMMS",
 		.video_inputs   = 1,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
-		.muxsel         = { 2 },
+		.muxsel         = MUXSEL(2),
 		.gpiomask       = 0
 	},
 	[BTTV_BOARD_PV_BT878P_PLUS] = {
 		/* Tomasz Pyra <hellfire@sedez.iq.pl> */
 		.name           = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
 		.video_inputs   = 3,
-		.audio_inputs   = 4,
-		.tuner          = 0,
+		/* .audio_inputs= 4, */
 		.svhs           = 2,
 		.gpiomask       = 15,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */
 		.gpiomute 	= 13,
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_LG_PAL_I_FM,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 		/* GPIO wiring:
 			GPIO0: U4.A0 (hef4052bt)
@@ -1594,15 +1483,14 @@
 	[BTTV_BOARD_FLYVIDEO98EZ] = {
 		.name		= "Lifeview FlyVideo 98EZ (capture only) LR51",
 		.video_inputs	= 4,
-		.audio_inputs   = 0,
-		.tuner		= UNSET,
+		/* .audio_inputs= 0, */
 		.svhs		= 2,
-		.muxsel		= { 2, 3, 1, 1 }, /* AV1, AV2, SVHS, CVid adapter on SVHS */
+		/* AV1, AV2, SVHS, CVid adapter on SVHS */
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 	/* ---- card 0x48 ---------------------------------- */
@@ -1610,11 +1498,10 @@
 		/* Dariusz Kowalewski <darekk@automex.pl> */
 		.name		= "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
 		.video_inputs	= 4,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x3f,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 0x01, 0x00, 0x03, 0x03 },
 		.gpiomute 	= 0x09,
 		.needs_tvaudio  = 1,
@@ -1623,7 +1510,6 @@
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */
 		.has_radio	= 1,  /* Note: not all cards have radio */
 		.has_remote     = 1,
@@ -1640,49 +1526,42 @@
 		/* you must jumper JP5 for the card to work */
 		.name           = "Sensoray 311",
 		.video_inputs   = 5,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 4,
 		.gpiomask       = 0,
-		.muxsel         = { 2, 3, 1, 0, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0, 0),
 		.gpiomux        = { 0 },
 		.needs_tvaudio  = 0,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_RV605] = {
 		/* Miguel Freitas <miguel@cetuc.puc-rio.br> */
 		.name           = "RemoteVision MX (RV605)",
 		.video_inputs   = 16,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0x00,
 		.gpiomask2      = 0x07ff,
-		.muxsel         = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
-				0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
+		.muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.muxsel_hook    = rv605_muxsel,
 	},
 	[BTTV_BOARD_POWERCLR_MTV878] = {
 		.name           = "Powercolor MTV878/ MTV878R/ MTV878F",
 		.video_inputs   = 3,
-		.audio_inputs   = 2,
-		.tuner		= 0,
+		/* .audio_inputs= 2, */
 		.svhs           = 2,
 		.gpiomask       = 0x1C800F,  /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
-		.muxsel         = { 2, 1, 1, },
+		.muxsel         = MUXSEL(2, 1, 1),
 		.gpiomux        = { 0, 1, 2, 2 },
 		.gpiomute 	= 4,
 		.needs_tvaudio  = 0,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll		= PLL_28,
 		.has_radio	= 1,
 	},
@@ -1692,42 +1571,38 @@
 		/* Masaki Suzuki <masaki@btree.org> */
 		.name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x140007,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.tuner_type     = TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= windvr_audio,
 	},
 	[BTTV_BOARD_GRANDTEC_MULTI] = {
 		.name           = "GrandTec Multi Capture Card (Bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 0 },
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_KWORLD] = {
 		.name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
 		.video_inputs   = 4,
-		.audio_inputs   = 3,
-		.tuner          = 0,
+		/* .audio_inputs= 3, */
 		.svhs           = 2,
 		.gpiomask       = 7,
-		.muxsel         = { 2, 3, 1, 1 },   /* Tuner, SVid, SVHS, SVid to SVHS connector */
+		/* Tuner, SVid, SVHS, SVid to SVHS connector */
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 0, 4, 4 },/* Yes, this tuner uses the same audio output for TV and FM radio!
 						* This card lacks external Audio In, so we mute it on Ext. & Int.
 						* The PCB can take a sbx1637/sbx1673, wiring unknown.
@@ -1741,7 +1616,6 @@
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		/* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
 		radio signal strength indicators work fine. */
 		.has_radio	= 1,
@@ -1759,27 +1633,24 @@
 		/* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
 		.name           = "DSP Design TCVIDEO",
 		.video_inputs   = 4,
-		.svhs           = UNSET,
-		.muxsel         = { 2, 3, 1, 0 },
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.pll            = PLL_28,
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 		/* ---- card 0x50 ---------------------------------- */
 	[BTTV_BOARD_HAUPPAUGEPVR] = {
 		.name           = "Hauppauge WinTV PVR",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel         = { 2, 0, 1, 1 },
+		.muxsel         = MUXSEL(2, 0, 1, 1),
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 
 		.gpiomask       = 7,
 		.gpiomux        = {7},
@@ -1787,32 +1658,28 @@
 	[BTTV_BOARD_GVBCTV5PCI] = {
 		.name           = "IODATA GV-BCTV5/PCI",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x0f0f80,
-		.muxsel         = {2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = {0x030000, 0x010000, 0, 0 },
 		.gpiomute 	= 0x020000,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_NTSC_M,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= gvbctv5pci_audio,
 		.has_radio      = 1,
 	},
 	[BTTV_BOARD_OSPREY1x0] = {
 		.name           = "Osprey 100/150 (878)", /* 0x1(2|3)-45C6-C1 */
 		.video_inputs   = 4,                  /* id-inputs-clock */
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 3,
-		.muxsel         = { 3, 2, 0, 1 },
+		.muxsel         = MUXSEL(3, 2, 0, 1),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1820,14 +1687,12 @@
 	[BTTV_BOARD_OSPREY1x0_848] = {
 		.name           = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
 		.video_inputs   = 3,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 2,
-		.muxsel         = { 2, 3, 1 },
+		.muxsel         = MUXSEL(2, 3, 1),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1837,14 +1702,12 @@
 	[BTTV_BOARD_OSPREY101_848] = {
 		.name           = "Osprey 101 (848)", /* 0x05-40C0-C1 */
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 1,
-		.muxsel         = { 3, 1 },
+		.muxsel         = MUXSEL(3, 1),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1852,14 +1715,12 @@
 	[BTTV_BOARD_OSPREY1x1] = {
 		.name           = "Osprey 101/151",       /* 0x1(4|5)-0004-C4 */
 		.video_inputs   = 1,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 0 },
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(0),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1867,14 +1728,12 @@
 	[BTTV_BOARD_OSPREY1x1_SVID] = {
 		.name           = "Osprey 101/151 w/ svid",  /* 0x(16|17|20)-00C4-C1 */
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 1,
-		.muxsel         = { 0, 1 },
+		.muxsel         = MUXSEL(0, 1),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1882,14 +1741,12 @@
 	[BTTV_BOARD_OSPREY2xx] = {
 		.name           = "Osprey 200/201/250/251",  /* 0x1(8|9|E|F)-0004-C4 */
 		.video_inputs   = 1,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 0 },
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(0),
 		.pll            = PLL_28,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1899,14 +1756,12 @@
 	[BTTV_BOARD_OSPREY2x0_SVID] = {
 		.name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
 		.video_inputs   = 2,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
+		/* .audio_inputs= 1, */
 		.svhs           = 1,
-		.muxsel         = { 0, 1 },
+		.muxsel         = MUXSEL(0, 1),
 		.pll            = PLL_28,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1914,14 +1769,12 @@
 	[BTTV_BOARD_OSPREY2x0] = {
 		.name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
 		.video_inputs   = 2,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
+		/* .audio_inputs= 1, */
 		.svhs           = 1,
-		.muxsel         = { 2, 3 },
+		.muxsel         = MUXSEL(2, 3),
 		.pll            = PLL_28,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1929,14 +1782,12 @@
 	[BTTV_BOARD_OSPREY500] = {
 		.name           = "Osprey 500",   /* 500 */
 		.video_inputs   = 2,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
+		/* .audio_inputs= 1, */
 		.svhs           = 1,
-		.muxsel         = { 2, 3 },
+		.muxsel         = MUXSEL(2, 3),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1944,12 +1795,10 @@
 	[BTTV_BOARD_OSPREY540] = {
 		.name           = "Osprey 540",   /* 540 */
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
+		/* .audio_inputs= 1, */
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -1959,14 +1808,12 @@
 	[BTTV_BOARD_OSPREY2000] = {
 		.name           = "Osprey 2000",  /* 2000 */
 		.video_inputs   = 2,
-		.audio_inputs   = 1,
-		.tuner          = UNSET,
+		/* .audio_inputs= 1, */
 		.svhs           = 1,
-		.muxsel         = { 2, 3 },
+		.muxsel         = MUXSEL(2, 3),
 		.pll            = PLL_28,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
@@ -1975,14 +1822,12 @@
 		/* M G Berberich <berberic@forwiss.uni-passau.de> */
 		.name           = "IDS Eagle",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs           = UNSET,
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0,
-		.muxsel         = { 0, 1, 2, 3 },
+		.muxsel         = MUXSEL(2, 2, 2, 2),
 		.muxsel_hook    = eagle_muxsel,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
@@ -1991,16 +1836,14 @@
 	[BTTV_BOARD_PINNACLESAT] = {
 		.name           = "Pinnacle PCTV Sat",
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
+		/* .audio_inputs= 0, */
 		.svhs           = 1,
-		.tuner          = UNSET,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-		.muxsel         = { 3, 1 },
+		.muxsel         = MUXSEL(3, 1),
 		.pll            = PLL_28,
 		.no_gpioirq     = 1,
 		.has_dvb        = 1,
@@ -2008,18 +1851,16 @@
 	[BTTV_BOARD_FORMAC_PROTV] = {
 		.name           = "Formac ProTV II (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 3,
 		.gpiomask       = 2,
 		/* TV, Comp1, Composite over SVID con, SVID */
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 2, 2, 0, 0 },
 		.pll            = PLL_28,
 		.has_radio      = 1,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	/* sound routing:
 		GPIO=0x00,0x01,0x03: mute (?)
 		0x02: both TV and radio (tuner: FM1216/I)
@@ -2033,62 +1874,55 @@
 	[BTTV_BOARD_MACHTV] = {
 		.name           = "MachTV",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
-		.svhs           = UNSET,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 7,
-		.muxsel         = { 2, 3, 1, 1},
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 3},
 		.gpiomute 	= 4,
 		.needs_tvaudio  = 1,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 	},
 	[BTTV_BOARD_EURESYS_PICOLO] = {
 		.name           = "Euresys Picolo",
 		.video_inputs   = 3,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
+		/* .audio_inputs= 0, */
 		.svhs           = 2,
 		.gpiomask       = 0,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-		.muxsel         = { 2, 0, 1},
+		.muxsel         = MUXSEL(2, 0, 1),
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_PV150] = {
 		/* Luc Van Hoeylandt <luc@e-magic.be> */
 		.name           = "ProVideo PV150", /* 0x4f */
 		.video_inputs   = 2,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0,
-		.muxsel         = { 2, 3 },
+		.muxsel         = MUXSEL(2, 3),
 		.gpiomux        = { 0 },
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_AD_TVK503] = {
 		/* Hiroshi Takekawa <sian@big.or.jp> */
 		/* This card lacks subsystem ID */
 		.name           = "AD-TVK503", /* 0x63 */
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x001e8007,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		/*                  Tuner, Radio, external, internal, off,  on */
 		.gpiomux        = { 0x08,  0x0f,  0x0a,     0x08 },
 		.gpiomute 	= 0x0f,
@@ -2097,7 +1931,6 @@
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.audio_mode_gpio= adtvk503_audio,
 	},
 
@@ -2105,17 +1938,15 @@
 	[BTTV_BOARD_HERCULES_SM_TV] = {
 		.name           = "Hercules Smart TV Stereo",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x00,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.needs_tvaudio  = 1,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		/* Notes:
 		- card lacks subsystem ID
 		- stereo variant w/ daughter board with tda9874a @0xb0
@@ -2129,16 +1960,15 @@
 	[BTTV_BOARD_PACETV] = {
 		.name           = "Pace TV & Radio Card",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel         = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */
+		/* Tuner, CVid, SVid, CVid over SVid connector */
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomask       = 0,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_PHILIPS_PAL_I,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio      = 1,
 		.pll            = PLL_28,
 		/* Bt878, Bt832, FI1246 tuner; no pci subsystem id
@@ -2152,27 +1982,34 @@
 		/* Chris Willing <chris@vislab.usyd.edu.au> */
 		.name           = "IVC-200",
 		.video_inputs   = 1,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs           = UNSET,
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0xdf,
-		.muxsel         = { 2 },
+		.muxsel         = MUXSEL(2),
+		.pll            = PLL_28,
+	},
+	[BTTV_BOARD_IVCE8784] = {
+		.name           = "IVCE-8784",
+		.video_inputs   = 1,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr     = ADDR_UNSET,
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0xdf,
+		.muxsel         = MUXSEL(2),
 		.pll            = PLL_28,
 	},
 	[BTTV_BOARD_XGUARD] = {
 		.name           = "Grand X-Guard / Trust 814PCI",
 		.video_inputs   = 16,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.gpiomask2      = 0xff,
-		.muxsel         = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 },
+		.muxsel         = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0),
 		.muxsel_hook    = xguard_muxsel,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
@@ -2184,16 +2021,14 @@
 	[BTTV_BOARD_NEBULA_DIGITV] = {
 		.name           = "Nebula Electronics DigiTV",
 		.video_inputs   = 1,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 2, 3, 1, 0 },
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_dvb        = 1,
 		.has_remote	= 1,
 		.gpiomask	= 0x1b,
@@ -2203,118 +2038,101 @@
 		/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
 		.name           = "ProVideo PV143",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 0 },
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_VD009X1_VD011_MINIDIN] = {
 		/* M.Klahr@phytec.de */
 		.name           = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 3,
 		.gpiomask       = 0x00,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_VD009X1_VD011_COMBI] = {
 		.name           = "PHYTEC VD-009-X1 VD-011 Combi (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 3,
 		.gpiomask       = 0x00,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 
 		/* ---- card 0x6c ---------------------------------- */
 	[BTTV_BOARD_VD009_MINIDIN] = {
 		.name           = "PHYTEC VD-009 MiniDIN (bt878)",
 		.video_inputs   = 10,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 9,
 		.gpiomask       = 0x00,
-		.gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
-					via the upper nibble of muxsel. here: used for
-					xternal video-mux */
-		.muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
+		.gpiomask2      = 0x03, /* used for external vodeo mux */
+		.muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 0),
+		.muxsel_hook	= phytec_muxsel,
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_VD009_COMBI] = {
 		.name           = "PHYTEC VD-009 Combi (bt878)",
 		.video_inputs   = 10,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 9,
 		.gpiomask       = 0x00,
-		.gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
-					via the upper nibble of muxsel. here: used for
-					xternal video-mux */
-		.muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
+		.gpiomask2      = 0x03, /* used for external vodeo mux */
+		.muxsel         = MUXSEL(2, 2, 2, 2, 3, 3, 3, 3, 1, 1),
+		.muxsel_hook	= phytec_muxsel,
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_IVC100] = {
 		.name           = "IVC-100",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs           = UNSET,
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0xdf,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.pll            = PLL_28,
 	},
 	[BTTV_BOARD_IVC120] = {
 		/* IVC-120G - Alan Garfield <alan@fromorbit.com> */
 		.name           = "IVC-120G",
 		.video_inputs   = 16,
-		.audio_inputs   = 0,    /* card has no audio */
-		.tuner          = UNSET,   /* card has no tuner */
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs           = UNSET,   /* card has no svhs */
+		.svhs           = NO_SVHS,   /* card has no svhs */
 		.needs_tvaudio  = 0,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.gpiomask       = 0x00,
-		.muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-				0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
+		.muxsel         = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
 		.muxsel_hook    = ivc120_muxsel,
 		.pll            = PLL_28,
 	},
@@ -2323,13 +2141,11 @@
 	[BTTV_BOARD_PC_HDTV] = {
 		.name           = "pcHDTV HD-2000 TV",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.tuner_type     = TUNER_PHILIPS_FCV1236D,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_dvb        = 1,
 	},
 	[BTTV_BOARD_TWINHAN_DST] = {
@@ -2339,38 +2155,34 @@
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_video       = 1,
 		.has_dvb        = 1,
 	},
 	[BTTV_BOARD_WINFASTVC100] = {
 		.name           = "Winfast VC100",
 		.video_inputs   = 3,
-		.audio_inputs   = 0,
+		/* .audio_inputs= 0, */
 		.svhs           = 1,
-		.tuner          = UNSET,
-		.muxsel         = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */
+		/* Vid In, SVid In, Vid over SVid in connector */
+		.muxsel		= MUXSEL(3, 1, 1, 3),
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 	},
 	[BTTV_BOARD_TEV560] = {
 		.name           = "Teppro TEV-560/InterVision IV-560",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 3,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 1, 1, 1, 1 },
 		.needs_tvaudio  = 1,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_35,
 	},
 
@@ -2378,14 +2190,12 @@
 	[BTTV_BOARD_SIMUS_GVC1100] = {
 		.name           = "SIMUS GVC1100",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.tuner_type     = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
-		.muxsel         = { 2, 2, 2, 2 },
+		.muxsel         = MUXSEL(2, 2, 2, 2),
 		.gpiomask       = 0x3F,
 		.muxsel_hook    = gvc1100_muxsel,
 	},
@@ -2393,47 +2203,41 @@
 		/* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
 		.name           = "NGS NGSTV+",
 		.video_inputs   = 3,
-		.tuner          = 0,
 		.svhs           = 2,
 		.gpiomask       = 0x008007,
-		.muxsel         = { 2, 3, 0, 0 },
+		.muxsel         = MUXSEL(2, 3, 0, 0),
 		.gpiomux        = { 0, 0, 0, 0 },
 		.gpiomute 	= 0x000003,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_LMLBT4] = {
 		/* http://linuxmedialabs.com */
 		.name           = "LMLBT4",
 		.video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 2, 3, 1, 0 },
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.needs_tvaudio  = 0,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_TEKRAM_M205] = {
 		/* Helmroos Harri <harri.helmroos@pp.inet.fi> */
 		.name           = "Tekram M205 PRO",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.svhs           = 2,
 		.needs_tvaudio  = 0,
 		.gpiomask       = 0x68,
-		.muxsel         = { 2, 3, 1 },
+		.muxsel         = MUXSEL(2, 3, 1),
 		.gpiomux        = { 0x68, 0x68, 0x61, 0x61 },
 		.pll            = PLL_28,
 	},
@@ -2444,18 +2248,16 @@
 		/* bt878 TV + FM without subsystem ID */
 		.name           = "Conceptronic CONTVFMi",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x008007,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 2 },
 		.gpiomute 	= 3,
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 		.has_radio      = 1,
 	},
@@ -2466,37 +2268,34 @@
 		/*0x79 in bttv.h*/
 		.name           = "Euresys Picolo Tetra",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0,
 		.gpiomask2      = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-		.muxsel         = {2,2,2,2},/*878A input is always MUX0, see above.*/
+		/*878A input is always MUX0, see above.*/
+		.muxsel         = MUXSEL(2, 2, 2, 2),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.pll            = PLL_28,
 		.needs_tvaudio  = 0,
 		.muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_SPIRIT_TV] = {
 		/* Spirit TV Tuner from http://spiritmodems.com.au */
 		/* Stafford Goodsell <surge@goliath.homeunix.org> */
 		.name           = "Spirit TV Tuner",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x0000000f,
-		.muxsel         = { 2, 1, 1 },
+		.muxsel         = MUXSEL(2, 1, 1),
 		.gpiomux        = { 0x02, 0x00, 0x00, 0x00 },
 		.tuner_type     = TUNER_TEMIC_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 	},
@@ -2505,11 +2304,9 @@
 		.name           = "AVerMedia AVerTV DVB-T 771",
 		.video_inputs   = 2,
 		.svhs           = 1,
-		.tuner          = UNSET,
 		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.muxsel         = { 3 , 3 },
+		.muxsel         = MUXSEL(3, 3),
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -2524,54 +2321,47 @@
 		/* Based on the Nebula card data - added remote and new card number - BTTV_BOARD_AVDVBT_761, see also ir-kbd-gpio.c */
 		.name           = "AverMedia AverTV DVB-T 761",
 		.video_inputs   = 2,
-		.tuner          = UNSET,
 		.svhs           = 1,
-		.muxsel         = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */
+		.muxsel         = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_dvb        = 1,
 		.no_gpioirq     = 1,
 		.has_remote     = 1,
 	},
 	[BTTV_BOARD_MATRIX_VISIONSQ] = {
 		/* andre.schwarz@matrix-vision.de */
-		.name             = "MATRIX Vision Sigma-SQ",
-		.video_inputs     = 16,
-		.audio_inputs     = 0,
-		.tuner            = UNSET,
-		.svhs             = UNSET,
-		.gpiomask         = 0x0,
-		.muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
-				3, 3, 3, 3, 3, 3, 3, 3 },
-		.muxsel_hook      = sigmaSQ_muxsel,
-		.gpiomux          = { 0 },
-		.no_msp34xx       = 1,
-		.pll              = PLL_28,
-		.tuner_type       = UNSET,
-		.tuner_addr	  = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
+		.name		= "MATRIX Vision Sigma-SQ",
+		.video_inputs	= 16,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x0,
+		.muxsel		= MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3),
+		.muxsel_hook	= sigmaSQ_muxsel,
+		.gpiomux	= { 0 },
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
 	},
 	[BTTV_BOARD_MATRIX_VISIONSLC] = {
 		/* andre.schwarz@matrix-vision.de */
-		.name             = "MATRIX Vision Sigma-SLC",
-		.video_inputs     = 4,
-		.audio_inputs     = 0,
-		.tuner            = UNSET,
-		.svhs             = UNSET,
-		.gpiomask         = 0x0,
-		.muxsel           = { 2, 2, 2, 2 },
-		.muxsel_hook      = sigmaSLC_muxsel,
-		.gpiomux          = { 0 },
-		.no_msp34xx       = 1,
-		.pll              = PLL_28,
-		.tuner_type       = UNSET,
-		.tuner_addr	  = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
+		.name		= "MATRIX Vision Sigma-SLC",
+		.video_inputs	= 4,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x0,
+		.muxsel		= MUXSEL(2, 2, 2, 2),
+		.muxsel_hook	= sigmaSLC_muxsel,
+		.gpiomux	= { 0 },
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
 	},
 		/* BTTV_BOARD_APAC_VIEWCOMP */
 	[BTTV_BOARD_APAC_VIEWCOMP] = {
@@ -2579,18 +2369,16 @@
 		/* bt878 TV + FM 0x00000000 subsystem ID */
 		.name           = "APAC Viewcomp 878(AMAX)",
 		.video_inputs   = 2,
-		.audio_inputs   = 1,
-		.tuner          = 0,
-		.svhs           = UNSET,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0xFF,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 2, 0, 0, 0 },
 		.gpiomute 	= 10,
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
 		.has_radio      = 1,   /* not every card has radio */
 	},
@@ -2599,46 +2387,40 @@
 	[BTTV_BOARD_DVICO_DVBT_LITE] = {
 		/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
 		.name           = "DViCO FusionHDTV DVB-T Lite",
-		.tuner          = UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
 		.pll            = PLL_28,
 		.no_video       = 1,
 		.has_dvb        = 1,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_VGEAR_MYVCD] = {
 		/* Steven <photon38@pchome.com.tw> */
 		.name           = "V-Gear MyVCD",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x3f,
-		.muxsel         = {2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.gpiomux        = {0x31, 0x31, 0x31, 0x31 },
 		.gpiomute 	= 0x31,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_NTSC_M,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio      = 0,
 	},
 	[BTTV_BOARD_SUPER_TV] = {
 		/* Rick C <cryptdragoon@gmail.com> */
 		.name           = "Super TV Tuner",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.tuner_type     = TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.gpiomask       = 0x008007,
 		.gpiomux        = { 0, 0x000001,0,0 },
 		.needs_tvaudio  = 1,
@@ -2648,17 +2430,15 @@
 		/* Chris Fanning <video4linux@haydon.net> */
 		.name           = "Tibet Systems 'Progress DVR' CS16",
 		.video_inputs   = 16,
-		.audio_inputs   = 0,
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
 		.pll		= PLL_28,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432	= 1,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.muxsel_hook    = tibetCS16_muxsel,
 	},
 	[BTTV_BOARD_KODICOM_4400R] = {
@@ -2675,12 +2455,10 @@
 		*/
 		.name           = "Kodicom 4400R (master)",
 		.video_inputs	= 16,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
-		.tuner_type	= UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs		= UNSET,
+		.svhs		= NO_SVHS,
 		/* GPIO bits 0-9 used for analog switch:
 		*   00 - 03:	camera selector
 		*   04 - 06:	channel (controller) selector
@@ -2691,7 +2469,7 @@
 		*/
 		.gpiomask	= 0x0003ff,
 		.no_gpioirq     = 1,
-		.muxsel		= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+		.muxsel		= MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
@@ -2707,15 +2485,13 @@
 		*/
 		.name		= "Kodicom 4400R (slave)",
 		.video_inputs	= 16,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
-		.tuner_type	= UNSET,
+		/* .audio_inputs= 0, */
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.svhs		= UNSET,
+		.svhs		= NO_SVHS,
 		.gpiomask	= 0x010000,
 		.no_gpioirq     = 1,
-		.muxsel		= { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+		.muxsel		= MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
 		.pll		= PLL_28,
 		.no_msp34xx	= 1,
 		.no_tda7432	= 1,
@@ -2728,27 +2504,23 @@
 		/* Adlink RTV24 with special unlock codes */
 		.name           = "Adlink RTV24",
 		.video_inputs   = 4,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel         = { 2, 3, 1, 0 },
+		.muxsel         = MUXSEL(2, 3, 1, 0),
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 	},
 		/* ---- card 0x87---------------------------------- */
 	[BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
 		/* Michael Krufky <mkrufky@m1k.net> */
 		.name           = "DViCO FusionHDTV 5 Lite",
-		.tuner          = 0,
 		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel		= { 2, 3, 1 },
+		.muxsel		= MUXSEL(2, 3, 1),
 		.gpiomask       = 0x00e00007,
 		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
 		.gpiomute 	= 0x00c00007,
@@ -2762,75 +2534,68 @@
 		/* Mauro Carvalho Chehab <mchehab@infradead.org> */
 		.name		= "Acorp Y878F",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x01fe00,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
 		.gpiomute 	= 0x002000,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_YMEC_TVF66T5_B_DFF,
 		.tuner_addr	= 0xc1 >>1,
-		.radio_addr     = 0xc1 >>1,
 		.has_radio	= 1,
 	},
 		/* ---- card 0x89 ---------------------------------- */
 	[BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = {
 		.name           = "Conceptronic CTVFMi v2",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x001c0007,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 2 },
 		.gpiomute 	= 3,
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_TENA_9533_DI,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_remote     = 1,
 		.has_radio      = 1,
 	},
 		/* ---- card 0x8a ---------------------------------- */
 	[BTTV_BOARD_PV_BT878P_2E] = {
-		.name          = "Prolink Pixelview PV-BT878P+ (Rev.2E)",
-		.video_inputs  = 5,
-		.audio_inputs  = 1,
-		.tuner         = 0,
-		.svhs          = 3,
-		.gpiomask      = 0x01fe00,
-		.muxsel        = { 2,3,1,1,-1 },
-		.digital_mode  = DIGITAL_MODE_CAMERA,
-		.gpiomux       = { 0x00400, 0x10400, 0x04400, 0x80000 },
-		.gpiomute      = 0x12400,
-		.no_msp34xx    = 1,
-		.pll           = PLL_28,
-		.tuner_type    = TUNER_LG_PAL_FM,
+		.name		= "Prolink Pixelview PV-BT878P+ (Rev.2E)",
+		.video_inputs	= 5,
+		/* .audio_inputs= 1, */
+		.svhs		= 3,
+		.has_dig_in	= 1,
+		.gpiomask	= 0x01fe00,
+		.muxsel		= MUXSEL(2, 3, 1, 1, 0), /* in 4 is digital */
+		/* .digital_mode= DIGITAL_MODE_CAMERA, */
+		.gpiomux	= { 0x00400, 0x10400, 0x04400, 0x80000 },
+		.gpiomute	= 0x12400,
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_LG_PAL_FM,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-		.has_remote    = 1,
+		.has_remote	= 1,
 	},
 		/* ---- card 0x8b ---------------------------------- */
 	[BTTV_BOARD_PV_M4900] = {
 		/* Sérgio Fortier <sergiofortier@yahoo.com.br> */
 		.name           = "Prolink PixelView PlayTV MPEG2 PV-M4900",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x3f,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0x21, 0x20, 0x24, 0x2c },
 		.gpiomute 	= 0x29,
 		.no_msp34xx     = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_YMEC_TVF_5533MF,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.has_radio      = 1,
 		.has_remote     = 1,
 	},
@@ -2850,17 +2615,15 @@
 	[BTTV_BOARD_OSPREY440]  = {
 		.name           = "Osprey 440",
 		.video_inputs   = 4,
-		.audio_inputs   = 2, /* this is meaningless */
-		.tuner          = UNSET,
-		.svhs           = UNSET,
-		.muxsel         = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */
+		/* .audio_inputs= 2, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 0, 1), /* 3,0,1 are guesses */
 		.gpiomask	= 0x303,
 		.gpiomute	= 0x000, /* int + 32kHz */
 		.gpiomux	= { 0, 0, 0x000, 0x100},
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
@@ -2869,28 +2632,25 @@
 	[BTTV_BOARD_ASOUND_SKYEYE] = {
 		.name		= "Asound Skyeye PCTV",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 15,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 2, 0, 0, 0 },
 		.gpiomute 	= 1,
 		.needs_tvaudio	= 1,
 		.pll		= PLL_28,
 		.tuner_type	= TUNER_PHILIPS_NTSC,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 		/* ---- card 0x8e ---------------------------------- */
 	[BTTV_BOARD_SABRENT_TVFM] = {
 		.name		= "Sabrent TV-FM (bttv version)",
 		.video_inputs	= 3,
-		.audio_inputs	= 1,
-		.tuner		= 0,
+		/* .audio_inputs= 1, */
 		.svhs		= 2,
 		.gpiomask	= 0x108007,
-		.muxsel		= { 2, 3, 1, 1 },
+		.muxsel		= MUXSEL(2, 3, 1, 1),
 		.gpiomux 	= { 100000, 100002, 100002, 100000 },
 		.no_msp34xx	= 1,
 		.no_tda9875     = 1,
@@ -2904,17 +2664,15 @@
 	[BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
 		.name		= "Hauppauge ImpactVCB (bt878)",
 		.video_inputs	= 4,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
-		.svhs		= UNSET,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
 		.gpiomask	= 0x0f, /* old: 7 */
-		.muxsel		= { 0, 1, 3, 2 }, /* Composite 0-3 */
+		.muxsel		= MUXSEL(0, 1, 3, 2), /* Composite 0-3 */
 		.no_msp34xx	= 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-		.tuner_type	= UNSET,
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_MACHTV_MAGICTV] = {
 		/* Julian Calaby <julian.calaby@gmail.com>
@@ -2926,16 +2684,14 @@
 
 		.name           = "MagicTV", /* rebranded MachTV */
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 7,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 3 },
 		.gpiomute 	= 4,
 		.tuner_type     = TUNER_TEMIC_4009FR5_PAL,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 		.has_radio      = 1,
 		.has_remote     = 1,
@@ -2943,36 +2699,30 @@
 	[BTTV_BOARD_SSAI_SECURITY] = {
 		.name		= "SSAI Security Video Interface",
 		.video_inputs	= 4,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
-		.svhs		= UNSET,
-		.muxsel		= { 0, 1, 2, 3 },
-		.tuner_type	= UNSET,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.muxsel		= MUXSEL(0, 1, 2, 3),
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_SSAI_ULTRASOUND] = {
 		.name		= "SSAI Ultrasound Video Interface",
 		.video_inputs	= 2,
-		.audio_inputs	= 0,
-		.tuner		= UNSET,
+		/* .audio_inputs= 0, */
 		.svhs		= 1,
-		.muxsel		= { 2, 0, 1, 3 },
-		.tuner_type	= UNSET,
+		.muxsel		= MUXSEL(2, 0, 1, 3),
+		.tuner_type	= TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	/* ---- card 0x94---------------------------------- */
 	[BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
 		.name           = "DViCO FusionHDTV 2",
-		.tuner          = 0,
 		.tuner_type     = TUNER_PHILIPS_FCV1236D,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
-		.muxsel		= { 2, 3, 1 },
+		.muxsel		= MUXSEL(2, 3, 1),
 		.gpiomask       = 0x00e00007,
 		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
 		.gpiomute 	= 0x00c00007,
@@ -2984,36 +2734,31 @@
 	[BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
 		.name           = "Typhoon TV-Tuner PCI (50684)",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x3014f,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0x20001,0x10001, 0, 0 },
 		.gpiomute       = 10,
 		.needs_tvaudio  = 1,
 		.pll            = PLL_28,
 		.tuner_type     = TUNER_PHILIPS_PAL_I,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 	[BTTV_BOARD_GEOVISION_GV600] = {
 		/* emhn@usb.ve */
-		.name             = "Geovision GV-600",
-		.video_inputs     = 16,
-		.audio_inputs     = 0,
-		.tuner            = UNSET,
-		.svhs             = UNSET,
-		.gpiomask         = 0x0,
-		.muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
-				      2, 2, 2, 2, 2, 2, 2, 2 },
-		.muxsel_hook      = geovision_muxsel,
-		.gpiomux          = { 0 },
-		.no_msp34xx       = 1,
-		.pll              = PLL_28,
-		.tuner_type       = UNSET,
-		.tuner_addr	  = ADDR_UNSET,
-		.radio_addr       = ADDR_UNSET,
+		.name		= "Geovision GV-600",
+		.video_inputs	= 16,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x0,
+		.muxsel		= MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+		.muxsel_hook	= geovision_muxsel,
+		.gpiomux	= { 0 },
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
 	},
 	[BTTV_BOARD_KOZUMI_KTV_01C] = {
 		/* Mauro Lacy <mauro@lacy.com.ar>
@@ -3021,17 +2766,15 @@
 
 		.name           = "Kozumi KTV-01C",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		.gpiomask       = 0x008007,
-		.muxsel         = { 2, 3, 1, 1 },
+		.muxsel         = MUXSEL(2, 3, 1, 1),
 		.gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
 		.gpiomute 	= 3, /* CONTVFMi */
 		.needs_tvaudio  = 0,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 		.has_radio      = 1,
 		.has_remote     = 1,
@@ -3041,8 +2784,7 @@
 		   Mauro Carvalho Chehab <mchehab@infradead.org */
 		.name           = "Encore ENL TV-FM-2",
 		.video_inputs   = 3,
-		.audio_inputs   = 1,
-		.tuner          = 0,
+		/* .audio_inputs= 1, */
 		.svhs           = 2,
 		/* bit 6          -> IR disabled
 		   bit 18/17 = 00 -> mute
@@ -3051,12 +2793,11 @@
 			       11 -> internal audio input
 		 */
 		.gpiomask       = 0x060040,
-		.muxsel         = { 2, 3, 3 },
+		.muxsel         = MUXSEL(2, 3, 3),
 		.gpiomux        = { 0x60000, 0x60000, 0x20000, 0x20000 },
 		.gpiomute 	= 0,
 		.tuner_type	= TUNER_TCL_MF02GIP_5N,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 		.pll            = PLL_28,
 		.has_radio      = 1,
 		.has_remote     = 1,
@@ -3065,50 +2806,111 @@
 		/* D.Heer@Phytec.de */
 		.name           = "PHYTEC VD-012 (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
-		.svhs           = UNSET, /* card has no s-video */
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
 		.gpiomask       = 0x00,
-		.muxsel         = { 0, 2, 3, 1 },
+		.muxsel         = MUXSEL(0, 2, 3, 1),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 		[BTTV_BOARD_VD012_X1] = {
 		/* D.Heer@Phytec.de */
 		.name           = "PHYTEC VD-012-X1 (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 3,
 		.gpiomask       = 0x00,
-		.muxsel         = { 2, 3, 1 },
+		.muxsel         = MUXSEL(2, 3, 1),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
 	},
 		[BTTV_BOARD_VD012_X2] = {
 		/* D.Heer@Phytec.de */
 		.name           = "PHYTEC VD-012-X2 (bt878)",
 		.video_inputs   = 4,
-		.audio_inputs   = 0,
-		.tuner          = UNSET, /* card has no tuner */
+		/* .audio_inputs= 0, */
 		.svhs           = 3,
 		.gpiomask       = 0x00,
-		.muxsel         = { 3, 2, 1 },
+		.muxsel         = MUXSEL(3, 2, 1),
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
 		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
-		.tuner_type     = UNSET,
+		.tuner_type     = TUNER_ABSENT,
 		.tuner_addr	= ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
-	}
+	},
+		[BTTV_BOARD_GEOVISION_GV800S] = {
+		/* Bruno Christo <bchristo@inf.ufsm.br>
+		 *
+		 * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
+		 * 	1 audio input  per BT878A = 4 audio inputs
+		 * 	4 video inputs per BT878A = 16 video inputs
+		 * This is the first BT878A chip of the GV-800(S). It's the
+		 * "master" chip and it controls the video inputs through an
+		 * analog multiplexer (a CD22M3494) via some GPIO pins. The
+		 * slaves should use card type 0x9e (following this one).
+		 * There is a EEPROM on the card which is currently not handled.
+		 * The audio input is not working yet.
+		 */
+		.name           = "Geovision GV-800(S) (master)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = NO_SVHS,
+		.gpiomask	= 0xf107f,
+		.no_gpioirq     = 1,
+		.muxsel		= MUXSEL(2, 2, 2, 2),
+		.pll		= PLL_28,
+		.no_msp34xx	= 1,
+		.no_tda7432	= 1,
+		.no_tda9875	= 1,
+		.muxsel_hook    = gv800s_muxsel,
+	},
+		[BTTV_BOARD_GEOVISION_GV800S_SL] = {
+		/* Bruno Christo <bchristo@inf.ufsm.br>
+		 *
+		 * GeoVision GV-800(S) has 4 Conexant Fusion 878A:
+		 * 	1 audio input  per BT878A = 4 audio inputs
+		 * 	4 video inputs per BT878A = 16 video inputs
+		 * The 3 other BT878A chips are "slave" chips of the GV-800(S)
+		 * and should use this card type.
+		 * The audio input is not working yet.
+		 */
+		.name           = "Geovision GV-800(S) (slave)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = NO_SVHS,
+		.gpiomask	= 0x00,
+		.no_gpioirq     = 1,
+		.muxsel		= MUXSEL(2, 2, 2, 2),
+		.pll		= PLL_28,
+		.no_msp34xx	= 1,
+		.no_tda7432	= 1,
+		.no_tda9875	= 1,
+		.muxsel_hook    = gv800s_muxsel,
+	},
+	[BTTV_BOARD_PV183] = {
+		.name           = "ProVideo PV183", /* 0x9f */
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 3),
+		.gpiomux        = { 0 },
+		.needs_tvaudio  = 0,
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
 };
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3152,7 +2954,7 @@
 			       btv->c.nr, btv->cardid & 0xffff,
 			       (btv->cardid >> 16) & 0xffff);
 			printk(KERN_DEBUG "please mail id, board name and "
-			       "the correct card= insmod option to video4linux-list@redhat.com\n");
+			       "the correct card= insmod option to linux-media@vger.kernel.org\n");
 		}
 	}
 
@@ -3403,8 +3205,7 @@
  * has its own multiplexer */
 static void eagle_muxsel(struct bttv *btv, unsigned int input)
 {
-	btaor((2)<<5, ~(3<<5), BT848_IFORM);
-	gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]);
+	gpio_bits(3, input & 3);
 
 	/* composite */
 	/* set chroma ADC to sleep */
@@ -3523,6 +3324,17 @@
 /* initialization part two -- after registering i2c bus */
 void __devinit bttv_init_card2(struct bttv *btv)
 {
+	static const unsigned short tvaudio_addrs[] = {
+		I2C_ADDR_TDA8425   >> 1,
+		I2C_ADDR_TEA6300   >> 1,
+		I2C_ADDR_TEA6420   >> 1,
+		I2C_ADDR_TDA9840   >> 1,
+		I2C_ADDR_TDA985x_L >> 1,
+		I2C_ADDR_TDA985x_H >> 1,
+		I2C_ADDR_TDA9874   >> 1,
+		I2C_ADDR_PIC16C54  >> 1,
+		I2C_CLIENT_END
+	};
 	int addr=ADDR_UNSET;
 
 	btv->tuner_type = UNSET;
@@ -3629,6 +3441,9 @@
 	case BTTV_BOARD_KODICOM_4400R:
 		kodicom4400r_init(btv);
 		break;
+	case BTTV_BOARD_GEOVISION_GV800S:
+		gv800s_init(btv);
+		break;
 	}
 
 	/* pll configuration */
@@ -3670,13 +3485,12 @@
 		addr = bttv_tvcards[btv->c.type].tuner_addr;
 
 	if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
-		if(UNSET == btv->tuner_type)
+		if (UNSET == btv->tuner_type)
 			btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
 	if (UNSET != tuner[btv->c.nr])
 		btv->tuner_type = tuner[btv->c.nr];
 
-	if (btv->tuner_type == TUNER_ABSENT ||
-	    bttv_tvcards[btv->c.type].tuner == UNSET)
+	if (btv->tuner_type == TUNER_ABSENT)
 		printk(KERN_INFO "bttv%d: tuner absent\n", btv->c.nr);
 	else if(btv->tuner_type == UNSET)
 		printk(KERN_WARNING "bttv%d: tuner type unset\n", btv->c.nr);
@@ -3684,14 +3498,35 @@
 		printk(KERN_INFO "bttv%d: tuner type=%d\n", btv->c.nr,
 		       btv->tuner_type);
 
-	if (btv->tuner_type != UNSET) {
+	if (autoload != UNSET) {
+		printk(KERN_WARNING "bttv%d: the autoload option is obsolete.\n", btv->c.nr);
+		printk(KERN_WARNING "bttv%d: use option msp3400, tda7432 or tvaudio to\n", btv->c.nr);
+		printk(KERN_WARNING "bttv%d: override which audio module should be used.\n", btv->c.nr);
+	}
+
+	if (UNSET == btv->tuner_type)
+		btv->tuner_type = TUNER_ABSENT;
+
+	if (btv->tuner_type != TUNER_ABSENT) {
 		struct tuner_setup tun_setup;
 
+		/* Load tuner module before issuing tuner config call! */
+		if (bttv_tvcards[btv->c.type].has_radio)
+			v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+		v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
+
 		tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
 		tun_setup.type = btv->tuner_type;
 		tun_setup.addr = addr;
 
-		bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
+		if (bttv_tvcards[btv->c.type].has_radio)
+			tun_setup.mode_mask |= T_RADIO;
+
+		bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
 	}
 
 	if (btv->tda9887_conf) {
@@ -3700,10 +3535,13 @@
 		tda9887_cfg.tuner = TUNER_TDA9887;
 		tda9887_cfg.priv = &btv->tda9887_conf;
 
-		bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg);
+		bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
 	}
 
-	btv->svhs = bttv_tvcards[btv->c.type].svhs;
+	btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
+		   bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
+	btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
+		    UNSET : bttv_tvcards[btv->c.type].svhs;
 	if (svhs[btv->c.nr] != UNSET)
 		btv->svhs = svhs[btv->c.nr];
 	if (remote[btv->c.nr] != UNSET)
@@ -3720,34 +3558,127 @@
 	if (bttv_tvcards[btv->c.type].audio_mode_gpio)
 		btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
 
-	if (!autoload)
-		return;
-
-	if (bttv_tvcards[btv->c.type].tuner == UNSET)
+	if (btv->tuner_type == TUNER_ABSENT)
 		return;  /* no tuner or related drivers to load */
 
+	if (btv->has_saa6588 || saa6588[btv->c.nr]) {
+		/* Probe for RDS receiver chip */
+		static const unsigned short addrs[] = {
+			0x20 >> 1,
+			0x22 >> 1,
+			I2C_CLIENT_END
+		};
+		struct v4l2_subdev *sd;
+
+		sd = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"saa6588", "saa6588", addrs);
+		btv->has_saa6588 = (sd != NULL);
+	}
+
 	/* try to detect audio/fader chips */
-	if (!bttv_tvcards[btv->c.type].no_msp34xx &&
-	    bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx") >=0)
-		request_module("msp3400");
 
-	if (bttv_tvcards[btv->c.type].msp34xx_alt &&
-	    bttv_I2CRead(btv, I2C_ADDR_MSP3400_ALT, "MSP34xx (alternate address)") >=0)
-		request_module("msp3400");
+	/* First check if the user specified the audio chip via a module
+	   option. */
 
-	if (!bttv_tvcards[btv->c.type].no_tda9875 &&
-	    bttv_I2CRead(btv, I2C_ADDR_TDA9875, "TDA9875") >=0)
-		request_module("tda9875");
+	switch (audiodev[btv->c.nr]) {
+	case -1:
+		return;	/* do not load any audio module */
 
-	if (!bttv_tvcards[btv->c.type].no_tda7432 &&
-	    bttv_I2CRead(btv, I2C_ADDR_TDA7432, "TDA7432") >=0)
-		request_module("tda7432");
+	case 0: /* autodetect */
+		break;
 
-	if (bttv_tvcards[btv->c.type].needs_tvaudio)
-		request_module("tvaudio");
+	case 1: {
+		/* The user specified that we should probe for msp3400 */
+		static const unsigned short addrs[] = {
+			I2C_ADDR_MSP3400 >> 1,
+			I2C_ADDR_MSP3400_ALT >> 1,
+			I2C_CLIENT_END
+		};
 
-	if (btv->tuner_type != UNSET && btv->tuner_type != TUNER_ABSENT)
-		request_module("tuner");
+		btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"msp3400", "msp3400", addrs);
+		if (btv->sd_msp34xx)
+			return;
+		goto no_audio;
+	}
+
+	case 2: {
+		/* The user specified that we should probe for tda7432 */
+		static const unsigned short addrs[] = {
+			I2C_ADDR_TDA7432 >> 1,
+			I2C_CLIENT_END
+		};
+
+		if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"tda7432", "tda7432", addrs))
+			return;
+		goto no_audio;
+	}
+
+	case 3: {
+		/* The user specified that we should probe for tvaudio */
+		btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"tvaudio", "tvaudio", tvaudio_addrs);
+		if (btv->sd_tvaudio)
+			return;
+		goto no_audio;
+	}
+
+	default:
+		printk(KERN_WARNING "bttv%d: unknown audiodev value!\n",
+			btv->c.nr);
+		return;
+	}
+
+	/* There were no overrides, so now we try to discover this through the
+	   card definition */
+
+	/* probe for msp3400 first: this driver can detect whether or not
+	   it really is a msp3400, so it will return NULL when the device
+	   found is really something else (e.g. a tea6300). */
+	if (!bttv_tvcards[btv->c.type].no_msp34xx) {
+		static const unsigned short addrs[] = {
+			I2C_ADDR_MSP3400 >> 1,
+			I2C_CLIENT_END
+		};
+
+		btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"msp3400", "msp3400", addrs);
+	} else if (bttv_tvcards[btv->c.type].msp34xx_alt) {
+		static const unsigned short addrs[] = {
+			I2C_ADDR_MSP3400_ALT >> 1,
+			I2C_CLIENT_END
+		};
+
+		btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"msp3400", "msp3400", addrs);
+	}
+
+	/* If we found a msp34xx, then we're done. */
+	if (btv->sd_msp34xx)
+		return;
+
+	/* it might also be a tda7432. */
+	if (!bttv_tvcards[btv->c.type].no_tda7432) {
+		static const unsigned short addrs[] = {
+			I2C_ADDR_TDA7432 >> 1,
+			I2C_CLIENT_END
+		};
+
+		if (v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+				"tda7432", "tda7432", addrs))
+			return;
+	}
+
+	/* Now see if we can find one of the tvaudio devices. */
+	btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.i2c_adap,
+			"tvaudio", "tvaudio", tvaudio_addrs);
+	if (btv->sd_tvaudio)
+		return;
+
+no_audio:
+	printk(KERN_WARNING "bttv%d: audio absent, no audio device found!\n",
+			btv->c.nr);
 }
 
 
@@ -3819,6 +3750,7 @@
 		printk("bttv%d: Terratec Active Radio Upgrade found.\n",
 		       btv->c.nr);
 		btv->has_radio    = 1;
+		btv->has_saa6588  = 1;
 		btv->has_matchbox = 1;
 	} else {
 		btv->has_radio    = 0;
@@ -4067,27 +3999,26 @@
 	       btv->has_remote ? "yes" : "no");
 }
 
-/* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
-void bttv_tda9880_setnorm(struct bttv *btv, int norm)
+/*
+ * For Voodoo TV/FM and Voodoo 200.  These cards' tuners use a TDA9880
+ * analog demod, which is not I2C controlled like the newer and more common
+ * TDA9887 series.  Instead is has two tri-state input pins, S0 and S1,
+ * that control the IF for the video and audio.  Apparently, bttv GPIO
+ * 0x10000 is connected to S0.  S0 low selects a 38.9 MHz VIF for B/G/D/K/I
+ * (i.e., PAL) while high selects 45.75 MHz for M/N (i.e., NTSC).
+ */
+u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits)
 {
-	/* fix up our card entry */
-	if(norm==V4L2_STD_NTSC) {
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x957fff;
-		dprintk("bttv_tda9880_setnorm to NTSC\n");
+
+	if (btv->audio == TVAUDIO_INPUT_TUNER) {
+		if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
+			gpiobits |= 0x10000;
+		else
+			gpiobits &= ~0x10000;
 	}
-	else {
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x947fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x947fff;
-		bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomute=0x947fff;
-		dprintk("bttv_tda9880_setnorm to PAL\n");
-	}
-	/* set GPIO according */
-	gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
-		  bttv_tvcards[btv->c.type].gpiomux[btv->audio]);
+
+	gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits);
+	return gpiobits;
 }
 
 
@@ -4463,6 +4394,11 @@
  */
 static void rv605_muxsel(struct bttv *btv, unsigned int input)
 {
+	static const u8 muxgpio[] = { 0x3, 0x1, 0x2, 0x4, 0xf, 0x7, 0xe, 0x0,
+				      0xd, 0xb, 0xc, 0x6, 0x9, 0x5, 0x8, 0xa };
+
+	gpio_bits(0x07f, muxgpio[input]);
+
 	/* reset all conections */
 	gpio_bits(0x200,0x200);
 	mdelay(1);
@@ -4470,7 +4406,6 @@
 	mdelay(1);
 
 	/* create a new connection */
-	gpio_bits(0x480,0x080);
 	gpio_bits(0x480,0x480);
 	mdelay(1);
 	gpio_bits(0x480,0x080);
@@ -4729,8 +4664,7 @@
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
 		      ((matrix == 2) ? 0x03 : 0x00), 1);  /* 9-12 */
 
-	/* Selects MUX0 for input on the 878 */
-	btaor((0)<<5, ~(3<<5), BT848_IFORM);
+	/* 878's MUX0 is already selected for input via muxsel values */
 }
 
 
@@ -4814,6 +4748,132 @@
 	printk(KERN_DEBUG "bttv%d: setting input channel to:%d\n", btv->c.nr,(int)mux);
 }
 
+static void phytec_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int mux = input % 4;
+
+	if (input == btv->svhs)
+		mux = 0;
+
+	gpio_bits(0x3, mux);
+}
+
+/*
+ * GeoVision GV-800(S) functions
+ * Bruno Christo <bchristo@inf.ufsm.br>
+*/
+
+/* This is a function to control the analog switch, which determines which
+ * camera is routed to which controller.  The switch comprises an X-address
+ * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
+ * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
+ * A data value (gpio bit 18) of '1' enables the switch, and '0' disables
+ * the switch.  A STROBE bit (gpio bit 17) latches the data value into the
+ * specified address. There is also a chip select (gpio bit 16).
+ * The idea is to set the address and chip select together, bring
+ * STROBE high, write the data, and finally bring STROBE back to low.
+ */
+static void gv800s_write(struct bttv *btv,
+			 unsigned char xaddr,
+			 unsigned char yaddr,
+			 unsigned char data) {
+	/* On the "master" 878A:
+	* GPIO bits 0-9 are used for the analog switch:
+	*   00 - 03:	camera selector
+	*   04 - 06:	878A (controller) selector
+	*   16: 	cselect
+	*   17:		strobe
+	*   18: 	data (1->on, 0->off)
+	*   19:		reset
+	*/
+	const u32 ADDRESS = ((xaddr&0xf) | (yaddr&3)<<4);
+	const u32 CSELECT = 1<<16;
+	const u32 STROBE = 1<<17;
+	const u32 DATA = data<<18;
+
+	gpio_bits(0x1007f, ADDRESS | CSELECT);	/* write ADDRESS and CSELECT */
+	gpio_bits(0x20000, STROBE);		/* STROBE high */
+	gpio_bits(0x40000, DATA);		/* write DATA */
+	gpio_bits(0x20000, ~STROBE);		/* STROBE low */
+}
+
+/*
+ * GeoVision GV-800(S) muxsel
+ *
+ * Each of the 4 cards (controllers) use this function.
+ * The controller using this function selects the input through the GPIO pins
+ * of the "master" card. A pointer to this card is stored in master[btv->c.nr].
+ *
+ * The parameter 'input' is the requested camera number (0-4) on the controller.
+ * The map array has the address of each input. Note that the addresses in the
+ * array are in the sequence the original GeoVision driver uses, that is, set
+ * every controller to input 0, then to input 1, 2, 3, repeat. This means that
+ * the physical "camera 1" connector corresponds to controller 0 input 0,
+ * "camera 2" corresponds to controller 1 input 0, and so on.
+ *
+ * After getting the input address, the function then writes the appropriate
+ * data to the analog switch, and housekeeps the local copy of the switch
+ * information.
+ */
+static void gv800s_muxsel(struct bttv *btv, unsigned int input)
+{
+	struct bttv *mctlr;
+	char *sw_status;
+	int xaddr, yaddr;
+	static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
+					  { 0x1, 0x5, 0xb, 0x7 },
+					  { 0x2, 0x8, 0xc, 0xe },
+					  { 0x3, 0x9, 0xd, 0xf } };
+	input = input%4;
+	mctlr = master[btv->c.nr];
+	if (mctlr == NULL) {
+		/* do nothing until the "master" is detected */
+		return;
+	}
+	yaddr = (btv->c.nr - mctlr->c.nr) & 3;
+	sw_status = (char *)(&mctlr->mbox_we);
+	xaddr = map[yaddr][input] & 0xf;
+
+	/* Check if the controller/camera pair has changed, ignore otherwise */
+	if (sw_status[yaddr] != xaddr) {
+		/* disable the old switch, enable the new one and save status */
+		gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
+		sw_status[yaddr] = xaddr;
+		gv800s_write(mctlr, xaddr, yaddr, 1);
+	}
+}
+
+/* GeoVision GV-800(S) "master" chip init */
+static void gv800s_init(struct bttv *btv)
+{
+	char *sw_status = (char *)(&btv->mbox_we);
+	int ix;
+
+	gpio_inout(0xf107f, 0xf107f);
+	gpio_write(1<<19); /* reset the analog MUX */
+	gpio_write(0);
+
+	/* Preset camera 0 to the 4 controllers */
+	for (ix = 0; ix < 4; ix++) {
+		sw_status[ix] = ix;
+		gv800s_write(btv, ix, ix, 1);
+	}
+
+	/* Inputs on the "master" controller need this brightness fix */
+	bttv_I2CWrite(btv, 0x18, 0x5, 0x90, 1);
+
+	if (btv->c.nr > BTTV_MAX-4)
+		return;
+	/*
+	 * Store the "master" controller pointer in the master
+	 * array for later use in the muxsel function.
+	 */
+	master[btv->c.nr]   = btv;
+	master[btv->c.nr+1] = btv;
+	master[btv->c.nr+2] = btv;
+	master[btv->c.nr+3] = btv;
+}
+
 /* ----------------------------------------------------------------------- */
 /* motherboard chipset specific stuff                                      */
 
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index c71f394..7a8ca0d 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -58,7 +58,7 @@
 
 
 unsigned int bttv_num;			/* number of Bt848s in use */
-struct bttv bttvs[BTTV_MAX];
+struct bttv *bttvs[BTTV_MAX];
 
 unsigned int bttv_debug;
 unsigned int bttv_verbose = 1;
@@ -167,7 +167,7 @@
 			 struct device_attribute *attr, char *buf)
 {
 	struct video_device *vfd = container_of(cd, struct video_device, dev);
-	struct bttv *btv = dev_get_drvdata(vfd->parent);
+	struct bttv *btv = video_get_drvdata(vfd);
 	return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
 }
 static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
@@ -1040,7 +1040,7 @@
 	int table_idx = bttv_tvnorms[btv->tvnorm].sram;
 	int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
 
-	if (UNSET == bttv_tvcards[btv->c.type].muxsel[btv->input]) {
+	if (btv->input == btv->dig) {
 		dprintk("bttv%d: load digital timing table (table_idx=%d)\n",
 			btv->c.nr,table_idx);
 
@@ -1142,7 +1142,7 @@
 		btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
 		btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
 	}
-	mux = bttv_tvcards[btv->c.type].muxsel[input] & 3;
+	mux = bttv_muxsel(btv, input);
 	btaor(mux<<5, ~(3<<5), BT848_IFORM);
 	dprintk(KERN_DEBUG "bttv%d: video mux: input=%d mux=%d\n",
 		btv->c.nr,input,mux);
@@ -1163,7 +1163,6 @@
 {
 	int gpio_val, signal;
 	struct v4l2_control ctrl;
-	struct i2c_client *c;
 
 	gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
 		   bttv_tvcards[btv->c.type].gpiomask);
@@ -1180,7 +1179,16 @@
 	else
 		gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
 
-	gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
+	switch (btv->c.type) {
+	case BTTV_BOARD_VOODOOTV_FM:
+	case BTTV_BOARD_VOODOOTV_200:
+		gpio_val = bttv_tda9880_setnorm(btv, gpio_val);
+		break;
+
+	default:
+		gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpio_val);
+	}
+
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv, audio_modes[mute ? 4 : input]);
 	if (in_interrupt())
@@ -1188,9 +1196,8 @@
 
 	ctrl.id = V4L2_CID_AUDIO_MUTE;
 	ctrl.value = btv->mute;
-	bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl);
-	c = btv->i2c_msp34xx_client;
-	if (c) {
+	bttv_call_all(btv, core, s_ctrl, &ctrl);
+	if (btv->sd_msp34xx) {
 		struct v4l2_routing route;
 
 		/* Note: the inputs tuner/radio/extern/intern are translated
@@ -1229,15 +1236,14 @@
 			break;
 		}
 		route.output = MSP_OUTPUT_DEFAULT;
-		c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+		v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, &route);
 	}
-	c = btv->i2c_tvaudio_client;
-	if (c) {
+	if (btv->sd_tvaudio) {
 		struct v4l2_routing route;
 
 		route.input = input;
 		route.output = 0;
-		c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+		v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, &route);
 	}
 	return 0;
 }
@@ -1277,7 +1283,7 @@
 }
 
 static void
-bttv_crop_reset(struct bttv_crop *c, int norm)
+bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
 {
 	c->rect = bttv_tvnorms[norm].cropcap.defrect;
 	bttv_crop_calc_limits(c);
@@ -1290,16 +1296,13 @@
 	const struct bttv_tvnorm *tvnorm;
 	v4l2_std_id id;
 
-	if (norm < 0 || norm >= BTTV_TVNORMS)
-		return -EINVAL;
+	BUG_ON(norm >= BTTV_TVNORMS);
+	BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
 
 	tvnorm = &bttv_tvnorms[norm];
 
-	if (btv->tvnorm < 0 ||
-	    btv->tvnorm >= BTTV_TVNORMS ||
-	    0 != memcmp(&bttv_tvnorms[btv->tvnorm].cropcap,
-			&tvnorm->cropcap,
-			sizeof (tvnorm->cropcap))) {
+	if (!memcmp(&bttv_tvnorms[btv->tvnorm].cropcap, &tvnorm->cropcap,
+		    sizeof (tvnorm->cropcap))) {
 		bttv_crop_reset(&btv->crop[0], norm);
 		btv->crop[1] = btv->crop[0]; /* current = default */
 
@@ -1322,11 +1325,11 @@
 	switch (btv->c.type) {
 	case BTTV_BOARD_VOODOOTV_FM:
 	case BTTV_BOARD_VOODOOTV_200:
-		bttv_tda9880_setnorm(btv,norm);
+		bttv_tda9880_setnorm(btv, gpio_read());
 		break;
 	}
 	id = tvnorm->v4l2_id;
-	bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id);
+	bttv_call_all(btv, tuner, s_std, id);
 
 	return 0;
 }
@@ -1350,8 +1353,8 @@
 	} else {
 		video_mux(btv,input);
 	}
-	audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
-		       TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
+	audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
+			 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
 	set_tvnorm(btv, norm);
 }
 
@@ -1470,7 +1473,7 @@
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c);
+		bttv_call_all(btv, core, g_ctrl, c);
 		break;
 
 	case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1544,12 +1547,12 @@
 		if (btv->volume_gpio)
 			btv->volume_gpio(btv, c->value);
 
-		bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
+		bttv_call_all(btv, core, s_ctrl, c);
 		break;
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
+		bttv_call_all(btv, core, s_ctrl, c);
 		break;
 
 	case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1888,20 +1891,15 @@
 {
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
-	unsigned int n;
+	int n;
 
-	n = i->index;
-
-	if (n >= bttv_tvcards[btv->c.type].video_inputs)
+	if (i->index >= bttv_tvcards[btv->c.type].video_inputs)
 		return -EINVAL;
 
-	memset(i, 0, sizeof(*i));
-
-	i->index    = n;
 	i->type     = V4L2_INPUT_TYPE_CAMERA;
 	i->audioset = 1;
 
-	if (i->index == bttv_tvcards[btv->c.type].tuner) {
+	if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
 		sprintf(i->name, "Television");
 		i->type  = V4L2_INPUT_TYPE_TUNER;
 		i->tuner = 0;
@@ -1965,14 +1963,14 @@
 	if (0 != err)
 		return err;
 
-	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+	if (btv->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 
 	if (0 != t->index)
 		return -EINVAL;
 
 	mutex_lock(&btv->lock);
-	bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+	bttv_call_all(btv, tuner, s_tuner, t);
 
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 1);
@@ -2017,7 +2015,7 @@
 		return -EINVAL;
 	mutex_lock(&btv->lock);
 	btv->freq = f->frequency;
-	bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f);
+	bttv_call_all(btv, tuner, s_frequency, f);
 	if (btv->has_matchbox && btv->radio_user)
 		tea5757_set_freq(btv, btv->freq);
 	mutex_unlock(&btv->lock);
@@ -2031,7 +2029,7 @@
 
 	printk(KERN_INFO "bttv%d: ========  START STATUS CARD #%d  ========\n",
 			btv->c.nr, btv->c.nr);
-	bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+	bttv_call_all(btv, core, log_status);
 	printk(KERN_INFO "bttv%d: ========  END STATUS CARD   #%d  ========\n",
 			btv->c.nr, btv->c.nr);
 	return 0;
@@ -2659,8 +2657,7 @@
 	if (no_overlay <= 0)
 		cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
 
-	if (bttv_tvcards[btv->c.type].tuner != UNSET &&
-	    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
+	if (btv->tuner_type != TUNER_ABSENT)
 		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
 }
@@ -2927,13 +2924,9 @@
 {
 	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
-	struct v4l2_standard s;
 
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
-				 bttv_tvnorms[btv->tvnorm].name);
-	parm->parm.capture.timeperframe = s.frameperiod;
+	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
+				    &parm->parm.capture.timeperframe);
 	return 0;
 }
 
@@ -2943,15 +2936,14 @@
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+	if (btv->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 
 	mutex_lock(&btv->lock);
-	memset(t, 0, sizeof(*t));
 	t->rxsubchans = V4L2_TUNER_SUB_MONO;
-	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+	bttv_call_all(btv, tuner, g_tuner, t);
 	strcpy(t->name, "Television");
 	t->capability = V4L2_TUNER_CAP_NORM;
 	t->type       = V4L2_TUNER_ANALOG_TV;
@@ -3212,29 +3204,19 @@
 static int bttv_open(struct file *file)
 {
 	int minor = video_devdata(file)->minor;
-	struct bttv *btv = NULL;
+	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
 	enum v4l2_buf_type type = 0;
-	unsigned int i;
 
 	dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
 
 	lock_kernel();
-	for (i = 0; i < bttv_num; i++) {
-		if (bttvs[i].video_dev &&
-		    bttvs[i].video_dev->minor == minor) {
-			btv = &bttvs[i];
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-			break;
-		}
-		if (bttvs[i].vbi_dev &&
-		    bttvs[i].vbi_dev->minor == minor) {
-			btv = &bttvs[i];
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-			break;
-		}
-	}
-	if (NULL == btv) {
+	if (btv->video_dev->minor == minor) {
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	} else if (btv->vbi_dev->minor == minor) {
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	} else {
+		WARN_ON(1);
 		unlock_kernel();
 		return -ENODEV;
 	}
@@ -3424,20 +3406,14 @@
 static int radio_open(struct file *file)
 {
 	int minor = video_devdata(file)->minor;
-	struct bttv *btv = NULL;
+	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
-	unsigned int i;
 
 	dprintk("bttv: open minor=%d\n",minor);
 
 	lock_kernel();
-	for (i = 0; i < bttv_num; i++) {
-		if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {
-			btv = &bttvs[i];
-			break;
-		}
-	}
-	if (NULL == btv) {
+	WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor);
+	if (!btv->radio_dev || btv->radio_dev->minor != minor) {
 		unlock_kernel();
 		return -ENODEV;
 	}
@@ -3458,7 +3434,7 @@
 
 	btv->radio_user++;
 
-	bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL);
+	bttv_call_all(btv, tuner, s_radio);
 	audio_input(btv,TVAUDIO_INPUT_RADIO);
 
 	mutex_unlock(&btv->lock);
@@ -3478,7 +3454,7 @@
 
 	btv->radio_user--;
 
-	bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+	bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
 
 	return 0;
 }
@@ -3503,16 +3479,15 @@
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 
-	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+	if (btv->tuner_type == TUNER_ABSENT)
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
 	mutex_lock(&btv->lock);
-	memset(t, 0, sizeof(*t));
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
 
-	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+	bttv_call_all(btv, tuner, g_tuner, t);
 
 	if (btv->audio_mode_gpio)
 		btv->audio_mode_gpio(btv, t, 0);
@@ -3554,7 +3529,7 @@
 	if (0 != t->index)
 		return -EINVAL;
 
-	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+	bttv_call_all(btv, tuner, g_tuner, t);
 	return 0;
 }
 
@@ -3615,7 +3590,7 @@
 	cmd.instance = file;
 	cmd.result = -ENODEV;
 
-	bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
+	bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd);
 
 	return cmd.result;
 }
@@ -3628,7 +3603,7 @@
 	cmd.instance = file;
 	cmd.event_list = wait;
 	cmd.result = -ENODEV;
-	bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
+	bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd);
 
 	return cmd.result;
 }
@@ -3712,14 +3687,14 @@
 	unsigned int i,j,n;
 
 	printk("%s: risc disasm: %p [dma=0x%08lx]\n",
-	       btv->c.name, risc->cpu, (unsigned long)risc->dma);
+	       btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
 	for (i = 0; i < (risc->size >> 2); i += n) {
-		printk("%s:   0x%lx: ", btv->c.name,
+		printk("%s:   0x%lx: ", btv->c.v4l2_dev.name,
 		       (unsigned long)(risc->dma + (i<<2)));
 		n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
 		for (j = 1; j < n; j++)
 			printk("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
-			       btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
+			       btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)),
 			       risc->cpu[i+j], j);
 		if (0 == risc->cpu[i])
 			break;
@@ -4195,9 +4170,10 @@
 		return NULL;
 	*vfd = *template;
 	vfd->minor   = -1;
-	vfd->parent  = &btv->c.pci->dev;
+	vfd->v4l2_dev = &btv->c.v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = bttv_debug;
+	video_set_drvdata(vfd, btv);
 	snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
 		 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
 		 type_name, bttv_tvcards[btv->c.type].name);
@@ -4307,10 +4283,14 @@
 	if (bttv_num == BTTV_MAX)
 		return -ENOMEM;
 	printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
-	btv=&bttvs[bttv_num];
-	memset(btv,0,sizeof(*btv));
+	bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
+	if (btv == NULL) {
+		printk(KERN_ERR "bttv: out of memory.\n");
+		return -ENOMEM;
+	}
 	btv->c.nr  = bttv_num;
-	sprintf(btv->c.name,"bttv%d",btv->c.nr);
+	snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name),
+			"bttv%d", btv->c.nr);
 
 	/* initialize structs / fill in defaults */
 	mutex_init(&btv->lock);
@@ -4347,7 +4327,7 @@
 	}
 	if (!request_mem_region(pci_resource_start(dev,0),
 				pci_resource_len(dev,0),
-				btv->c.name)) {
+				btv->c.v4l2_dev.name)) {
 		printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n",
 		       btv->c.nr,
 		       (unsigned long long)pci_resource_start(dev,0));
@@ -4355,7 +4335,12 @@
 	}
 	pci_set_master(dev);
 	pci_set_command(dev);
-	pci_set_drvdata(dev,btv);
+
+	result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
+	if (result < 0) {
+		printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr);
+		goto fail0;
+	}
 
 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
@@ -4379,7 +4364,7 @@
 	/* disable irqs, register irq handler */
 	btwrite(0, BT848_INT_MASK);
 	result = request_irq(btv->c.pci->irq, bttv_irq,
-			     IRQF_SHARED | IRQF_DISABLED,btv->c.name,(void *)btv);
+	    IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv);
 	if (result < 0) {
 		printk(KERN_ERR "bttv%d: can't get IRQ %d\n",
 		       bttv_num,btv->c.pci->irq);
@@ -4463,21 +4448,24 @@
 	bttv_num++;
 	return 0;
 
- fail2:
+fail2:
 	free_irq(btv->c.pci->irq,btv);
 
- fail1:
+fail1:
+	v4l2_device_unregister(&btv->c.v4l2_dev);
+
+fail0:
 	if (btv->bt848_mmio)
 		iounmap(btv->bt848_mmio);
 	release_mem_region(pci_resource_start(btv->c.pci,0),
 			   pci_resource_len(btv->c.pci,0));
-	pci_set_drvdata(dev,NULL);
 	return result;
 }
 
 static void __devexit bttv_remove(struct pci_dev *pci_dev)
 {
-	struct bttv *btv = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
 
 	if (bttv_verbose)
 		printk("bttv%d: unloading\n",btv->c.nr);
@@ -4511,14 +4499,18 @@
 	release_mem_region(pci_resource_start(btv->c.pci,0),
 			   pci_resource_len(btv->c.pci,0));
 
-	pci_set_drvdata(pci_dev, NULL);
+	v4l2_device_unregister(&btv->c.v4l2_dev);
+	bttvs[btv->c.nr] = NULL;
+	kfree(btv);
+
 	return;
 }
 
 #ifdef CONFIG_PM
 static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
-	struct bttv *btv = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
 	struct bttv_buffer_set idle;
 	unsigned long flags;
 
@@ -4553,7 +4545,8 @@
 
 static int bttv_resume(struct pci_dev *pci_dev)
 {
-	struct bttv *btv = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
 	unsigned long flags;
 	int err;
 
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index bcd2cd2..a99d92f 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -36,8 +36,6 @@
 #include <linux/jiffies.h>
 #include <asm/io.h>
 
-static int attach_inform(struct i2c_client *client);
-
 static int i2c_debug;
 static int i2c_hw;
 static int i2c_scan;
@@ -231,7 +229,8 @@
 
 static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
-	struct bttv *btv = i2c_get_adapdata(i2c_adap);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+	struct bttv *btv = to_bttv(v4l2_dev);
 	int retval = 0;
 	int i;
 
@@ -265,52 +264,6 @@
 /* ----------------------------------------------------------------------- */
 /* I2C functions - common stuff                                            */
 
-static int attach_inform(struct i2c_client *client)
-{
-	struct bttv *btv = i2c_get_adapdata(client->adapter);
-	int addr=ADDR_UNSET;
-
-
-	if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
-		addr = bttv_tvcards[btv->c.type].tuner_addr;
-
-
-	if (bttv_debug)
-		printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
-			btv->c.nr, client->driver->driver.name, client->addr,
-			client->name);
-	if (!client->driver->command)
-		return 0;
-
-	if (client->driver->id == I2C_DRIVERID_MSP3400)
-		btv->i2c_msp34xx_client = client;
-	if (client->driver->id == I2C_DRIVERID_TVAUDIO)
-		btv->i2c_tvaudio_client = client;
-	if (btv->tuner_type != UNSET) {
-		struct tuner_setup tun_setup;
-
-		if ((addr==ADDR_UNSET) ||
-				(addr==client->addr)) {
-
-			tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV | T_RADIO;
-			tun_setup.type = btv->tuner_type;
-			tun_setup.addr = addr;
-			bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
-		}
-
-	}
-
-	return 0;
-}
-
-void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
-{
-	if (0 != btv->i2c_rc)
-		return;
-	i2c_clients_command(&btv->c.i2c_adap, cmd, arg);
-}
-
-
 /* read I2C */
 int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
 {
@@ -417,21 +370,15 @@
 		btv->c.i2c_adap.algo_data = &btv->i2c_algo;
 	}
 	btv->c.i2c_adap.owner = THIS_MODULE;
-	btv->c.i2c_adap.class = I2C_CLASS_TV_ANALOG;
-	btv->c.i2c_adap.client_register = attach_inform;
 
 	btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
 	snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
 		 "bt%d #%d [%s]", btv->id, btv->c.nr,
 		 btv->use_i2c_hw ? "hw" : "sw");
 
-	i2c_set_adapdata(&btv->c.i2c_adap, btv);
+	i2c_set_adapdata(&btv->c.i2c_adap, &btv->c.v4l2_dev);
 	btv->i2c_client.adapter = &btv->c.i2c_adap;
 
-	if (bttv_tvcards[btv->c.type].no_video)
-		btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG;
-	if (bttv_tvcards[btv->c.type].has_dvb)
-		btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
 
 	if (btv->use_i2c_hw) {
 		btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
@@ -441,7 +388,7 @@
 		btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
 	}
 	if (0 == btv->i2c_rc && i2c_scan)
-		do_i2c_scan(btv->c.name,&btv->i2c_client);
+		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
 	return btv->i2c_rc;
 }
 
diff --git a/drivers/media/video/bt8xx/bttv-if.c b/drivers/media/video/bt8xx/bttv-if.c
index ecf0798..a6a540d 100644
--- a/drivers/media/video/bt8xx/bttv-if.c
+++ b/drivers/media/video/bt8xx/bttv-if.c
@@ -47,7 +47,10 @@
 {
 	if (card >= bttv_num)
 		return NULL;
-	return bttvs[card].c.pci;
+	if (!bttvs[card])
+		return NULL;
+
+	return bttvs[card]->c.pci;
 }
 
 
@@ -59,7 +62,10 @@
 		return -EINVAL;
 	}
 
-	btv = &bttvs[card];
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
+
 	gpio_inout(mask,data);
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"extern enable");
@@ -74,7 +80,9 @@
 		return -EINVAL;
 	}
 
-	btv = &bttvs[card];
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
 
 	if(btv->shutdown) {
 		return -ENODEV;
@@ -94,7 +102,9 @@
 		return -EINVAL;
 	}
 
-	btv = &bttvs[card];
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
 
 /* prior setting BT848_GPIO_REG_INP is (probably) not needed
    because direct input is set on init */
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c
index 5b1b8e4..d16af28 100644
--- a/drivers/media/video/bt8xx/bttv-risc.c
+++ b/drivers/media/video/bt8xx/bttv-risc.c
@@ -341,7 +341,7 @@
 	int totalwidth   = tvnorm->totalwidth;
 	int scaledtwidth = tvnorm->scaledtwidth;
 
-	if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
+	if (btv->input == btv->dig) {
 		swidth       = 720;
 		totalwidth   = 858;
 		scaledtwidth = 858;
@@ -391,7 +391,7 @@
 	     && crop->width == tvnorm->cropcap.defrect.width
 	     && crop->height == tvnorm->cropcap.defrect.height
 	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
-	    || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
+	    || btv->input == btv->dig) {
 		bttv_calc_geo_old(btv, geo, width, height,
 				  both_fields, tvnorm);
 		return;
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 6819e21..e79a402 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -411,7 +411,7 @@
 	return 0;
 }
 
-void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm)
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
 {
 	const struct bttv_tvnorm *tvnorm;
 	unsigned int real_samples_per_line;
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 529bf6c..3d36daf 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -14,8 +14,9 @@
 #ifndef _BTTV_H_
 #define _BTTV_H_
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
+#include <media/v4l2-device.h>
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
 #include <media/i2c-addr.h>
@@ -180,6 +181,10 @@
 #define BTTV_BOARD_VD012		   0x99
 #define BTTV_BOARD_VD012_X1		   0x9a
 #define BTTV_BOARD_VD012_X2		   0x9b
+#define BTTV_BOARD_IVCE8784		   0x9c
+#define BTTV_BOARD_GEOVISION_GV800S	   0x9d
+#define BTTV_BOARD_GEOVISION_GV800S_SL	   0x9e
+#define BTTV_BOARD_PV183                   0x9f
 
 
 /* more card-specific defines */
@@ -191,12 +196,9 @@
 #define WINVIEW_PT2254_DATA 0x20
 #define WINVIEW_PT2254_STROBE 0x80
 
-/* digital_mode */
-#define DIGITAL_MODE_VIDEO 1
-#define DIGITAL_MODE_CAMERA 2
-
 struct bttv_core {
 	/* device structs */
+	struct v4l2_device   v4l2_dev;
 	struct pci_dev       *pci;
 	struct i2c_adapter   i2c_adap;
 	struct list_head     subs;     /* struct bttv_sub_device */
@@ -204,59 +206,79 @@
 	/* device config */
 	unsigned int         nr;       /* dev nr (for printk("bttv%d: ...");  */
 	unsigned int         type;     /* card type (pointer into tvcards[])  */
-	char                 name[8];  /* dev name */
 };
 
 struct bttv;
 
-
-struct tvcard
-{
+struct tvcard {
 	char *name;
-	unsigned int video_inputs;
-	unsigned int audio_inputs;
-	unsigned int tuner;
-	unsigned int svhs;
-	unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO
+	void (*volume_gpio)(struct bttv *btv, __u16 volume);
+	void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+	void (*muxsel_hook)(struct bttv *btv, unsigned int input);
+
+	/* MUX bits for each input, two bits per input starting with the LSB */
+	u32 muxsel; /* Use MUXSEL() to set */
+
 	u32 gpiomask;
-	u32 muxsel[16];
 	u32 gpiomux[4];  /* Tuner, Radio, external, internal */
 	u32 gpiomute;    /* GPIO mute setting */
 	u32 gpiomask2;   /* GPIO MUX mask */
 
+	unsigned int tuner_type;
+	u8 tuner_addr;
+	u8 video_inputs;	/* Number of inputs */
+	unsigned int svhs:4;	/* Which input is s-video */
+#define NO_SVHS	15
+	unsigned int pll:2;
+#define PLL_NONE 0
+#define PLL_28   1
+#define PLL_35   2
+
 	/* i2c audio flags */
 	unsigned int no_msp34xx:1;
 	unsigned int no_tda9875:1;
 	unsigned int no_tda7432:1;
 	unsigned int needs_tvaudio:1;
 	unsigned int msp34xx_alt:1;
+	/* Note: currently no card definition needs to mark the presence
+	   of a RDS saa6588 chip. If this is ever needed, then add a new
+	   'has_saa6588' bit here. */
 
-	/* flag: video pci function is unused */
-	unsigned int no_video:1;
+	unsigned int no_video:1; /* video pci function is unused */
 	unsigned int has_dvb:1;
 	unsigned int has_remote:1;
+	unsigned int has_radio:1;
+	unsigned int has_dig_in:1; /* Has digital input (always last input) */
 	unsigned int no_gpioirq:1;
-
-	/* other settings */
-	unsigned int pll;
-#define PLL_NONE 0
-#define PLL_28   1
-#define PLL_35   2
-
-	unsigned int tuner_type;
-	unsigned int tuner_addr;
-	unsigned int radio_addr;
-
-	unsigned int has_radio;
-
-	void (*volume_gpio)(struct bttv *btv, __u16 volume);
-	void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
-
-	void (*muxsel_hook)(struct bttv *btv, unsigned int input);
 };
 
 extern struct tvcard bttv_tvcards[];
 
+/*
+ * This bit of cpp voodoo is used to create a macro with a variable number of
+ * arguments (1 to 16).  It will pack each argument into a word two bits at a
+ * time.  It can't be a function because it needs to be compile time constant to
+ * initialize structures.  Since each argument must fit in two bits, it's ok
+ * that they are changed to octal.  One should not use hex number, macros, or
+ * anything else with this macro.  Just use plain integers from 0 to 3.
+ */
+#define _MUXSELf(a)      	0##a << 30
+#define _MUXSELe(a, b...)	0##a << 28 | _MUXSELf(b)
+#define _MUXSELd(a, b...)	0##a << 26 | _MUXSELe(b)
+#define _MUXSELc(a, b...)	0##a << 24 | _MUXSELd(b)
+#define _MUXSELb(a, b...)	0##a << 22 | _MUXSELc(b)
+#define _MUXSELa(a, b...)	0##a << 20 | _MUXSELb(b)
+#define _MUXSEL9(a, b...)	0##a << 18 | _MUXSELa(b)
+#define _MUXSEL8(a, b...)	0##a << 16 | _MUXSEL9(b)
+#define _MUXSEL7(a, b...)	0##a << 14 | _MUXSEL8(b)
+#define _MUXSEL6(a, b...)	0##a << 12 | _MUXSEL7(b)
+#define _MUXSEL5(a, b...)	0##a << 10 | _MUXSEL6(b)
+#define _MUXSEL4(a, b...)	0##a << 8  | _MUXSEL5(b)
+#define _MUXSEL3(a, b...)	0##a << 6  | _MUXSEL4(b)
+#define _MUXSEL2(a, b...)	0##a << 4  | _MUXSEL3(b)
+#define _MUXSEL1(a, b...)	0##a << 2  | _MUXSEL2(b)
+#define MUXSEL(a, b...)		(a | _MUXSEL1(b))
+
 /* identification / initialization of the card */
 extern void bttv_idcard(struct bttv *btv);
 extern void bttv_init_card1(struct bttv *btv);
@@ -264,7 +286,7 @@
 
 /* card-specific funtions */
 extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
-extern void bttv_tda9880_setnorm(struct bttv *btv, int norm);
+extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits);
 
 /* extra tweaks for some chipsets */
 extern void bttv_check_chipset(void);
@@ -336,7 +358,9 @@
 /* ---------------------------------------------------------- */
 /* i2c                                                        */
 
-extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
+#define bttv_call_all(btv, o, f, args...) \
+	v4l2_device_call_all(&btv->c.v4l2_dev, 0, o, f, ##args)
+
 extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
 extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
 			 unsigned char b2, int both);
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 199a4d2..9649848 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -32,7 +32,6 @@
 #include <linux/wait.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
 #include <linux/pci.h>
 #include <linux/input.h>
 #include <linux/mutex.h>
@@ -135,7 +134,7 @@
 
 	/* bttv specific */
 	const struct bttv_format   *fmt;
-	int                        tvnorm;
+	unsigned int               tvnorm;
 	int                        btformat;
 	int                        btswap;
 	struct bttv_geometry       geo;
@@ -154,7 +153,7 @@
 };
 
 struct bttv_overlay {
-	int                    tvnorm;
+	unsigned int           tvnorm;
 	struct v4l2_rect       w;
 	enum v4l2_field        field;
 	struct v4l2_clip       *clips;
@@ -174,7 +173,7 @@
 };
 
 /* bttv-vbi.c */
-void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm);
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
 
 struct bttv_crop {
 	/* A cropping rectangle in struct bttv_tvnorm.cropcap units. */
@@ -329,7 +328,8 @@
 	unsigned int cardid;   /* pci subsystem id (bt878 based ones) */
 	unsigned int tuner_type;  /* tuner chip type */
 	unsigned int tda9887_conf;
-	unsigned int svhs;
+	unsigned int svhs, dig;
+	unsigned int has_saa6588:1;
 	struct bttv_pll_info pll;
 	int triton1;
 	int gpioirq;
@@ -353,8 +353,8 @@
 	int                        i2c_state, i2c_rc;
 	int                        i2c_done;
 	wait_queue_head_t          i2c_queue;
-	struct i2c_client 	  *i2c_msp34xx_client;
-	struct i2c_client 	  *i2c_tvaudio_client;
+	struct v4l2_subdev 	  *sd_msp34xx;
+	struct v4l2_subdev 	  *sd_tvaudio;
 
 	/* video4linux (1) */
 	struct video_device *video_dev;
@@ -378,7 +378,8 @@
 	unsigned int audio;
 	unsigned int mute;
 	unsigned long freq;
-	int tvnorm,hue,contrast,bright,saturation;
+	unsigned int tvnorm;
+	int hue, contrast, bright, saturation;
 	struct v4l2_framebuffer fbuf;
 	unsigned int field_count;
 
@@ -458,10 +459,21 @@
 	__s32			crop_start;
 };
 
+static inline struct bttv *to_bttv(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct bttv, c.v4l2_dev);
+}
+
 /* our devices */
 #define BTTV_MAX 32
 extern unsigned int bttv_num;
-extern struct bttv bttvs[BTTV_MAX];
+extern struct bttv *bttvs[BTTV_MAX];
+
+static inline unsigned int bttv_muxsel(const struct bttv *btv,
+				       unsigned int input)
+{
+	return (bttv_tvcards[btv->c.type].muxsel >> (input * 2)) & 3;
+}
 
 #endif
 
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 46fd573..7abe94d 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -11,6 +11,12 @@
  *
  * Written by Jonathan Corbet, corbet@lwn.net.
  *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this conversion is untested! Please contact the linux-media
+ * mailinglist if you can test this, together with the test results.
+ *
  * This file may be distributed under the terms of the GNU General
  * Public License, version 2.
  */
@@ -25,7 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-chip-ident.h>
 #include <linux/device.h>
@@ -33,7 +39,6 @@
 #include <linux/list.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <linux/debugfs.h>
 #include <linux/jiffies.h>
 #include <linux/vmalloc.h>
 
@@ -136,6 +141,7 @@
  */
 struct cafe_camera
 {
+	struct v4l2_device v4l2_dev;
 	enum cafe_state state;
 	unsigned long flags;   		/* Buffer status, mainly (dev_lock) */
 	int users;			/* How many open FDs */
@@ -145,9 +151,10 @@
 	 * Subsystem structures.
 	 */
 	struct pci_dev *pdev;
-	struct video_device v4ldev;
+	struct video_device vdev;
 	struct i2c_adapter i2c_adapter;
-	struct i2c_client *sensor;
+	struct v4l2_subdev *sensor;
+	unsigned short sensor_addr;
 
 	unsigned char __iomem *regs;
 	struct list_head dev_list;	/* link to other devices */
@@ -180,10 +187,6 @@
 	/* Misc */
 	wait_queue_head_t smbus_wait;	/* Waiting on i2c events */
 	wait_queue_head_t iowait;	/* Waiting on frame data */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	struct dentry *dfs_regs;
-	struct dentry *dfs_cam_regs;
-#endif
 };
 
 /*
@@ -195,6 +198,13 @@
 #define CF_DMA_ACTIVE	 3	/* A frame is incoming */
 #define CF_CONFIG_NEEDED 4	/* Must configure hardware */
 
+#define sensor_call(cam, o, f, args...) \
+	v4l2_subdev_call(cam->sensor, o, f, ##args)
+
+static inline struct cafe_camera *to_cam(struct v4l2_device *dev)
+{
+	return container_of(dev, struct cafe_camera, v4l2_dev);
+}
 
 
 /*
@@ -238,59 +248,7 @@
 
 
 /* ---------------------------------------------------------------------*/
-/*
- * We keep a simple list of known devices to search at open time.
- */
-static LIST_HEAD(cafe_dev_list);
-static DEFINE_MUTEX(cafe_dev_list_lock);
 
-static void cafe_add_dev(struct cafe_camera *cam)
-{
-	mutex_lock(&cafe_dev_list_lock);
-	list_add_tail(&cam->dev_list, &cafe_dev_list);
-	mutex_unlock(&cafe_dev_list_lock);
-}
-
-static void cafe_remove_dev(struct cafe_camera *cam)
-{
-	mutex_lock(&cafe_dev_list_lock);
-	list_del(&cam->dev_list);
-	mutex_unlock(&cafe_dev_list_lock);
-}
-
-static struct cafe_camera *cafe_find_dev(int minor)
-{
-	struct cafe_camera *cam;
-
-	mutex_lock(&cafe_dev_list_lock);
-	list_for_each_entry(cam, &cafe_dev_list, dev_list) {
-		if (cam->v4ldev.minor == minor)
-			goto done;
-	}
-	cam = NULL;
-  done:
-	mutex_unlock(&cafe_dev_list_lock);
-	return cam;
-}
-
-
-static struct cafe_camera *cafe_find_by_pdev(struct pci_dev *pdev)
-{
-	struct cafe_camera *cam;
-
-	mutex_lock(&cafe_dev_list_lock);
-	list_for_each_entry(cam, &cafe_dev_list, dev_list) {
-		if (cam->pdev == pdev)
-			goto done;
-	}
-	cam = NULL;
-  done:
-	mutex_unlock(&cafe_dev_list_lock);
-	return cam;
-}
-
-
-/* ------------------------------------------------------------------------ */
 /*
  * Device register I/O
  */
@@ -481,18 +439,11 @@
 		unsigned short flags, char rw, u8 command,
 		int size, union i2c_smbus_data *data)
 {
-	struct cafe_camera *cam = i2c_get_adapdata(adapter);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
+	struct cafe_camera *cam = to_cam(v4l2_dev);
 	int ret = -EINVAL;
 
 	/*
-	 * Refuse to talk to anything but OV cam chips.  We should
-	 * never even see an attempt to do so, but one never knows.
-	 */
-	if (cam->sensor && addr != cam->sensor->addr) {
-		cam_err(cam, "funky smbus addr %d\n", addr);
-		return -EINVAL;
-	}
-	/*
 	 * This interface would appear to only do byte data ops.  OK
 	 * it can do word too, but the cam chip has no use for that.
 	 */
@@ -530,38 +481,9 @@
 };
 
 /* Somebody is on the bus */
-static int cafe_cam_init(struct cafe_camera *cam);
 static void cafe_ctlr_stop_dma(struct cafe_camera *cam);
 static void cafe_ctlr_power_down(struct cafe_camera *cam);
 
-static int cafe_smbus_attach(struct i2c_client *client)
-{
-	struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
-
-	/*
-	 * Don't talk to chips we don't recognize.
-	 */
-	if (client->driver->id == I2C_DRIVERID_OV7670) {
-		cam->sensor = client;
-		return cafe_cam_init(cam);
-	}
-	return -EINVAL;
-}
-
-static int cafe_smbus_detach(struct i2c_client *client)
-{
-	struct cafe_camera *cam = i2c_get_adapdata(client->adapter);
-
-	if (cam->sensor == client) {
-		cafe_ctlr_stop_dma(cam);
-		cafe_ctlr_power_down(cam);
-		cam_err(cam, "lost the sensor!\n");
-		cam->sensor = NULL;  /* Bummer, no camera */
-		cam->state = S_NOTREADY;
-	}
-	return 0;
-}
-
 static int cafe_smbus_setup(struct cafe_camera *cam)
 {
 	struct i2c_adapter *adap = &cam->i2c_adapter;
@@ -570,12 +492,10 @@
 	cafe_smbus_enable_irq(cam);
 	adap->id = I2C_HW_SMBUS_CAFE;
 	adap->owner = THIS_MODULE;
-	adap->client_register = cafe_smbus_attach;
-	adap->client_unregister = cafe_smbus_detach;
 	adap->algo = &cafe_smbus_algo;
 	strcpy(adap->name, "cafe_ccic");
 	adap->dev.parent = &cam->pdev->dev;
-	i2c_set_adapdata(adap, cam);
+	i2c_set_adapdata(adap, &cam->v4l2_dev);
 	ret = i2c_add_adapter(adap);
 	if (ret)
 		printk(KERN_ERR "Unable to register cafe i2c adapter\n");
@@ -809,9 +729,9 @@
 	 * Control 1 is power down, set to 0 to operate.
 	 */
 	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
-//	mdelay(1); /* Marvell says 1ms will do it */
+/*	mdelay(1); */ /* Marvell says 1ms will do it */
 	cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
-//	mdelay(1); /* Enough? */
+/*	mdelay(1); */ /* Enough? */
 	spin_unlock_irqrestore(&cam->dev_lock, flags);
 	msleep(5); /* Just to be sure */
 }
@@ -833,23 +753,9 @@
  * Communications with the sensor.
  */
 
-static int __cafe_cam_cmd(struct cafe_camera *cam, int cmd, void *arg)
-{
-	struct i2c_client *sc = cam->sensor;
-	int ret;
-
-	if (sc == NULL || sc->driver == NULL || sc->driver->command == NULL)
-		return -EINVAL;
-	ret = sc->driver->command(sc, cmd, arg);
-	if (ret == -EPERM) /* Unsupported command */
-		return 0;
-	return ret;
-}
-
 static int __cafe_cam_reset(struct cafe_camera *cam)
 {
-	int zero = 0;
-	return __cafe_cam_cmd(cam, VIDIOC_INT_RESET, &zero);
+	return sensor_call(cam, core, reset, 0);
 }
 
 /*
@@ -869,14 +775,13 @@
 	if (ret)
 		goto out;
 	chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
-	chip.match.addr = cam->sensor->addr;
-	ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip);
+	chip.match.addr = cam->sensor_addr;
+	ret = sensor_call(cam, core, g_chip_ident, &chip);
 	if (ret)
 		goto out;
 	cam->sensor_type = chip.ident;
-//	if (cam->sensor->addr != OV7xx0_SID) {
 	if (cam->sensor_type != V4L2_IDENT_OV7670) {
-		cam_err(cam, "Unsupported sensor type %d", cam->sensor->addr);
+		cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type);
 		ret = -EINVAL;
 		goto out;
 	}
@@ -900,21 +805,21 @@
 	memset(&ctrl, 0, sizeof(ctrl));
 	ctrl.id = V4L2_CID_VFLIP;
 	ctrl.value = flip;
-	return __cafe_cam_cmd(cam, VIDIOC_S_CTRL, &ctrl);
+	return sensor_call(cam, core, s_ctrl, &ctrl);
 }
 
 
 static int cafe_cam_configure(struct cafe_camera *cam)
 {
 	struct v4l2_format fmt;
-	int ret, zero = 0;
+	int ret;
 
 	if (cam->state != S_IDLE)
 		return -EINVAL;
 	fmt.fmt.pix = cam->pix_format;
-	ret = __cafe_cam_cmd(cam, VIDIOC_INT_INIT, &zero);
+	ret = sensor_call(cam, core, init, 0);
 	if (ret == 0)
-		ret = __cafe_cam_cmd(cam, VIDIOC_S_FMT, &fmt);
+		ret = sensor_call(cam, video, s_fmt, &fmt);
 	/*
 	 * OV7670 does weird things if flip is set *before* format...
 	 */
@@ -1246,8 +1151,6 @@
 	 * Make sure it's something we can do.  User pointers could be
 	 * implemented without great pain, but that's not been done yet.
 	 */
-	if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 	if (req->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 	/*
@@ -1311,9 +1214,7 @@
 	int ret = -EINVAL;
 
 	mutex_lock(&cam->s_mutex);
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		goto out;
-	if (buf->index < 0 || buf->index >= cam->n_sbufs)
+	if (buf->index >= cam->n_sbufs)
 		goto out;
 	*buf = cam->sb_bufs[buf->index].v4lbuf;
 	ret = 0;
@@ -1331,9 +1232,7 @@
 	unsigned long flags;
 
 	mutex_lock(&cam->s_mutex);
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		goto out;
-	if (buf->index < 0 || buf->index >= cam->n_sbufs)
+	if (buf->index >= cam->n_sbufs)
 		goto out;
 	sbuf = cam->sb_bufs + buf->index;
 	if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED) {
@@ -1364,8 +1263,6 @@
 	unsigned long flags;
 
 	mutex_lock(&cam->s_mutex);
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		goto out_unlock;
 	if (cam->state != S_STREAMING)
 		goto out_unlock;
 	if (list_empty(&cam->sb_full) && filp->f_flags & O_NONBLOCK) {
@@ -1474,11 +1371,8 @@
 
 static int cafe_v4l_open(struct file *filp)
 {
-	struct cafe_camera *cam;
+	struct cafe_camera *cam = video_drvdata(filp);
 
-	cam = cafe_find_dev(video_devdata(filp)->minor);
-	if (cam == NULL)
-		return -ENODEV;
 	filp->private_data = cam;
 
 	mutex_lock(&cam->s_mutex);
@@ -1532,11 +1426,11 @@
 static int cafe_vidioc_queryctrl(struct file *filp, void *priv,
 		struct v4l2_queryctrl *qc)
 {
-	struct cafe_camera *cam = filp->private_data;
+	struct cafe_camera *cam = priv;
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_QUERYCTRL, qc);
+	ret = sensor_call(cam, core, queryctrl, qc);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -1545,11 +1439,11 @@
 static int cafe_vidioc_g_ctrl(struct file *filp, void *priv,
 		struct v4l2_control *ctrl)
 {
-	struct cafe_camera *cam = filp->private_data;
+	struct cafe_camera *cam = priv;
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_G_CTRL, ctrl);
+	ret = sensor_call(cam, core, g_ctrl, ctrl);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -1558,11 +1452,11 @@
 static int cafe_vidioc_s_ctrl(struct file *filp, void *priv,
 		struct v4l2_control *ctrl)
 {
-	struct cafe_camera *cam = filp->private_data;
+	struct cafe_camera *cam = priv;
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_S_CTRL, ctrl);
+	ret = sensor_call(cam, core, s_ctrl, ctrl);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -1601,10 +1495,8 @@
 	struct cafe_camera *cam = priv;
 	int ret;
 
-	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_ENUM_FMT, fmt);
+	ret = sensor_call(cam, video, enum_fmt, fmt);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -1617,7 +1509,7 @@
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_TRY_FMT, fmt);
+	ret = sensor_call(cam, video, try_fmt, fmt);
 	mutex_unlock(&cam->s_mutex);
 	return ret;
 }
@@ -1726,7 +1618,7 @@
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
+	ret = sensor_call(cam, video, g_parm, parms);
 	mutex_unlock(&cam->s_mutex);
 	parms->parm.capture.readbuffers = n_dma_bufs;
 	return ret;
@@ -1739,20 +1631,52 @@
 	int ret;
 
 	mutex_lock(&cam->s_mutex);
-	ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
+	ret = sensor_call(cam, video, s_parm, parms);
 	mutex_unlock(&cam->s_mutex);
 	parms->parm.capture.readbuffers = n_dma_bufs;
 	return ret;
 }
 
-
-static void cafe_v4l_dev_release(struct video_device *vd)
+static int cafe_vidioc_g_chip_ident(struct file *file, void *priv,
+		struct v4l2_dbg_chip_ident *chip)
 {
-	struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
+	struct cafe_camera *cam = priv;
 
-	kfree(cam);
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (v4l2_chip_match_host(&chip->match)) {
+		chip->ident = V4L2_IDENT_CAFE;
+		return 0;
+	}
+	return sensor_call(cam, core, g_chip_ident, chip);
 }
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cafe_vidioc_g_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg)
+{
+	struct cafe_camera *cam = priv;
+
+	if (v4l2_chip_match_host(&reg->match)) {
+		reg->val = cafe_reg_read(cam, reg->reg);
+		reg->size = 4;
+		return 0;
+	}
+	return sensor_call(cam, core, g_register, reg);
+}
+
+static int cafe_vidioc_s_register(struct file *file, void *priv,
+		struct v4l2_dbg_register *reg)
+{
+	struct cafe_camera *cam = priv;
+
+	if (v4l2_chip_match_host(&reg->match)) {
+		cafe_reg_write(cam, reg->reg, reg->val);
+		return 0;
+	}
+	return sensor_call(cam, core, s_register, reg);
+}
+#endif
 
 /*
  * This template device holds all of those v4l2 methods; we
@@ -1790,6 +1714,11 @@
 	.vidioc_s_ctrl		= cafe_vidioc_s_ctrl,
 	.vidioc_g_parm		= cafe_vidioc_g_parm,
 	.vidioc_s_parm		= cafe_vidioc_s_parm,
+	.vidioc_g_chip_ident    = cafe_vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register 	= cafe_vidioc_g_register,
+	.vidioc_s_register 	= cafe_vidioc_s_register,
+#endif
 };
 
 static struct video_device cafe_v4l_template = {
@@ -1800,15 +1729,10 @@
 
 	.fops = &cafe_v4l_fops,
 	.ioctl_ops = &cafe_v4l_ioctl_ops,
-	.release = cafe_v4l_dev_release,
+	.release = video_device_release_empty,
 };
 
 
-
-
-
-
-
 /* ---------------------------------------------------------------------- */
 /*
  * Interrupt handler stuff
@@ -1962,127 +1886,6 @@
 
 
 /* -------------------------------------------------------------------------- */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-/*
- * Debugfs stuff.
- */
-
-static char cafe_debug_buf[1024];
-static struct dentry *cafe_dfs_root;
-
-static void cafe_dfs_setup(void)
-{
-	cafe_dfs_root = debugfs_create_dir("cafe_ccic", NULL);
-	if (IS_ERR(cafe_dfs_root)) {
-		cafe_dfs_root = NULL;  /* Never mind */
-		printk(KERN_NOTICE "cafe_ccic unable to set up debugfs\n");
-	}
-}
-
-static void cafe_dfs_shutdown(void)
-{
-	if (cafe_dfs_root)
-		debugfs_remove(cafe_dfs_root);
-}
-
-static int cafe_dfs_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t cafe_dfs_read_regs(struct file *file,
-		char __user *buf, size_t count, loff_t *ppos)
-{
-	struct cafe_camera *cam = file->private_data;
-	char *s = cafe_debug_buf;
-	int offset;
-
-	for (offset = 0; offset < 0x44; offset += 4)
-		s += sprintf(s, "%02x: %08x\n", offset,
-				cafe_reg_read(cam, offset));
-	for (offset = 0x88; offset <= 0x90; offset += 4)
-		s += sprintf(s, "%02x: %08x\n", offset,
-				cafe_reg_read(cam, offset));
-	for (offset = 0xb4; offset <= 0xbc; offset += 4)
-		s += sprintf(s, "%02x: %08x\n", offset,
-				cafe_reg_read(cam, offset));
-	for (offset = 0x3000; offset <= 0x300c; offset += 4)
-		s += sprintf(s, "%04x: %08x\n", offset,
-				cafe_reg_read(cam, offset));
-	return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
-			s - cafe_debug_buf);
-}
-
-static const struct file_operations cafe_dfs_reg_ops = {
-	.owner = THIS_MODULE,
-	.read = cafe_dfs_read_regs,
-	.open = cafe_dfs_open
-};
-
-static ssize_t cafe_dfs_read_cam(struct file *file,
-		char __user *buf, size_t count, loff_t *ppos)
-{
-	struct cafe_camera *cam = file->private_data;
-	char *s = cafe_debug_buf;
-	int offset;
-
-	if (! cam->sensor)
-		return -EINVAL;
-	for (offset = 0x0; offset < 0x8a; offset++)
-	{
-		u8 v;
-
-		cafe_smbus_read_data(cam, cam->sensor->addr, offset, &v);
-		s += sprintf(s, "%02x: %02x\n", offset, v);
-	}
-	return simple_read_from_buffer(buf, count, ppos, cafe_debug_buf,
-			s - cafe_debug_buf);
-}
-
-static const struct file_operations cafe_dfs_cam_ops = {
-	.owner = THIS_MODULE,
-	.read = cafe_dfs_read_cam,
-	.open = cafe_dfs_open
-};
-
-
-
-static void cafe_dfs_cam_setup(struct cafe_camera *cam)
-{
-	char fname[40];
-
-	if (!cafe_dfs_root)
-		return;
-	sprintf(fname, "regs-%d", cam->v4ldev.num);
-	cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
-			cam, &cafe_dfs_reg_ops);
-	sprintf(fname, "cam-%d", cam->v4ldev.num);
-	cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root,
-			cam, &cafe_dfs_cam_ops);
-}
-
-
-static void cafe_dfs_cam_shutdown(struct cafe_camera *cam)
-{
-	if (! IS_ERR(cam->dfs_regs))
-		debugfs_remove(cam->dfs_regs);
-	if (! IS_ERR(cam->dfs_cam_regs))
-		debugfs_remove(cam->dfs_cam_regs);
-}
-
-#else
-
-#define cafe_dfs_setup()
-#define cafe_dfs_shutdown()
-#define cafe_dfs_cam_setup(cam)
-#define cafe_dfs_cam_shutdown(cam)
-#endif    /* CONFIG_VIDEO_ADV_DEBUG */
-
-
-
-
-/* ------------------------------------------------------------------------*/
 /*
  * PCI interface stuff.
  */
@@ -2100,6 +1903,10 @@
 	cam = kzalloc(sizeof(struct cafe_camera), GFP_KERNEL);
 	if (cam == NULL)
 		goto out;
+	ret = v4l2_device_register(&pdev->dev, &cam->v4l2_dev);
+	if (ret)
+		goto out_free;
+
 	mutex_init(&cam->s_mutex);
 	mutex_lock(&cam->s_mutex);
 	spin_lock_init(&cam->dev_lock);
@@ -2118,14 +1925,14 @@
 	 */
 	ret = pci_enable_device(pdev);
 	if (ret)
-		goto out_free;
+		goto out_unreg;
 	pci_set_master(pdev);
 
 	ret = -EIO;
 	cam->regs = pci_iomap(pdev, 0, 0);
 	if (! cam->regs) {
 		printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n");
-		goto out_free;
+		goto out_unreg;
 	}
 	ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam);
 	if (ret)
@@ -2145,17 +1952,31 @@
 	ret = cafe_smbus_setup(cam);
 	if (ret)
 		goto out_freeirq;
+
+	cam->sensor_addr = 0x42;
+	cam->sensor = v4l2_i2c_new_subdev(&cam->i2c_adapter,
+			"ov7670", "ov7670", cam->sensor_addr);
+	if (cam->sensor == NULL) {
+		ret = -ENODEV;
+		goto out_smbus;
+	}
+	ret = cafe_cam_init(cam);
+	if (ret)
+		goto out_smbus;
+
 	/*
 	 * Get the v4l2 setup done.
 	 */
 	mutex_lock(&cam->s_mutex);
-	cam->v4ldev = cafe_v4l_template;
-	cam->v4ldev.debug = 0;
-//	cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
-	cam->v4ldev.parent = &pdev->dev;
-	ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
+	cam->vdev = cafe_v4l_template;
+	cam->vdev.debug = 0;
+/*	cam->vdev.debug = V4L2_DEBUG_IOCTL_ARG;*/
+	cam->vdev.v4l2_dev = &cam->v4l2_dev;
+	ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret)
 		goto out_smbus;
+	video_set_drvdata(&cam->vdev, cam);
+
 	/*
 	 * If so requested, try to get our DMA buffers now.
 	 */
@@ -2165,21 +1986,21 @@
 					" will try again later.");
 	}
 
-	cafe_dfs_cam_setup(cam);
 	mutex_unlock(&cam->s_mutex);
-	cafe_add_dev(cam);
 	return 0;
 
-  out_smbus:
+out_smbus:
 	cafe_smbus_shutdown(cam);
-  out_freeirq:
+out_freeirq:
 	cafe_ctlr_power_down(cam);
 	free_irq(pdev->irq, cam);
-  out_iounmap:
+out_iounmap:
 	pci_iounmap(pdev, cam->regs);
-  out_free:
+out_free:
+	v4l2_device_unregister(&cam->v4l2_dev);
+out_unreg:
 	kfree(cam);
-  out:
+out:
 	return ret;
 }
 
@@ -2190,25 +2011,23 @@
 static void cafe_shutdown(struct cafe_camera *cam)
 {
 /* FIXME: Make sure we take care of everything here */
-	cafe_dfs_cam_shutdown(cam);
 	if (cam->n_sbufs > 0)
 		/* What if they are still mapped?  Shouldn't be, but... */
 		cafe_free_sio_buffers(cam);
-	cafe_remove_dev(cam);
 	cafe_ctlr_stop_dma(cam);
 	cafe_ctlr_power_down(cam);
 	cafe_smbus_shutdown(cam);
 	cafe_free_dma_bufs(cam);
 	free_irq(cam->pdev->irq, cam);
 	pci_iounmap(cam->pdev, cam->regs);
-	video_unregister_device(&cam->v4ldev);
-	/* kfree(cam); done in v4l_release () */
+	video_unregister_device(&cam->vdev);
 }
 
 
 static void cafe_pci_remove(struct pci_dev *pdev)
 {
-	struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct cafe_camera *cam = to_cam(v4l2_dev);
 
 	if (cam == NULL) {
 		printk(KERN_WARNING "pci_remove on unknown pdev %p\n", pdev);
@@ -2218,6 +2037,8 @@
 	if (cam->users > 0)
 		cam_warn(cam, "Removing a device with users!\n");
 	cafe_shutdown(cam);
+	v4l2_device_unregister(&cam->v4l2_dev);
+	kfree(cam);
 /* No unlock - it no longer exists */
 }
 
@@ -2228,7 +2049,8 @@
  */
 static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-	struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct cafe_camera *cam = to_cam(v4l2_dev);
 	int ret;
 	enum cafe_state cstate;
 
@@ -2246,7 +2068,8 @@
 
 static int cafe_pci_resume(struct pci_dev *pdev)
 {
-	struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct cafe_camera *cam = to_cam(v4l2_dev);
 	int ret = 0;
 
 	ret = pci_restore_state(pdev);
@@ -2307,13 +2130,11 @@
 
 	printk(KERN_NOTICE "Marvell M88ALP01 'CAFE' Camera Controller version %d\n",
 			CAFE_VERSION);
-	cafe_dfs_setup();
 	ret = pci_register_driver(&cafe_pci_driver);
 	if (ret) {
 		printk(KERN_ERR "Unable to register cafe_ccic driver\n");
 		goto out;
 	}
-	request_module("ov7670");  /* FIXME want something more general */
 	ret = 0;
 
   out:
@@ -2324,7 +2145,6 @@
 static void __exit cafe_exit(void)
 {
 	pci_unregister_driver(&cafe_pci_driver);
-	cafe_dfs_shutdown();
 }
 
 module_init(cafe_init);
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 9c25894..d4099f5 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/videodev.h>
 #include <media/v4l2-ioctl.h>
 
 #include "cpia2.h"
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c
index 87e9107..9714059 100644
--- a/drivers/media/video/cs5345.c
+++ b/drivers/media/video/cs5345.c
@@ -141,11 +141,6 @@
 	return 0;
 }
 
-static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops cs5345_core_ops = {
@@ -214,8 +209,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "cs5345",
-	.driverid = I2C_DRIVERID_CS5345,
-	.command = cs5345_command,
 	.probe = cs5345_probe,
 	.remove = cs5345_remove,
 	.id_table = cs5345_id,
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 7292a63..5aeb066 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -29,7 +29,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
 MODULE_AUTHOR("Martin Vaughan");
@@ -41,9 +41,6 @@
 
 MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
 
-static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
 
@@ -122,11 +119,6 @@
 	return 0;
 }
 
-static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
@@ -218,8 +210,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "cs53l32a",
-	.driverid = I2C_DRIVERID_CS53L32A,
-	.command = cs53l32a_command,
 	.remove = cs53l32a_remove,
 	.probe = cs53l32a_probe,
 	.id_table = cs53l32a_id,
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index 8940b53..e8a50a6 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -9,7 +9,7 @@
 	select VIDEO_CX2341X
 	select VIDEO_CS5345
 	select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This is a video4linux driver for Conexant cx23418 based
 	  PCI combo video recorder devices.
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
index 57beddf..bb5c516 100644
--- a/drivers/media/video/cx18/cx18-audio.c
+++ b/drivers/media/video/cx18/cx18-audio.c
@@ -23,7 +23,6 @@
 
 #include "cx18-driver.h"
 #include "cx18-io.h"
-#include "cx18-i2c.h"
 #include "cx18-cards.h"
 #include "cx18-audio.h"
 
@@ -33,55 +32,32 @@
    settings. */
 int cx18_audio_set_io(struct cx18 *cx)
 {
+	const struct cx18_card_audio_input *in;
 	struct v4l2_routing route;
-	u32 audio_input;
 	u32 val;
-	int mux_input;
 	int err;
 
 	/* Determine which input to use */
-	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
-		audio_input = cx->card->radio_input.audio_input;
-		mux_input = cx->card->radio_input.muxer_input;
-	} else {
-		audio_input =
-			cx->card->audio_inputs[cx->audio_input].audio_input;
-		mux_input =
-			cx->card->audio_inputs[cx->audio_input].muxer_input;
-	}
+	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
+		in = &cx->card->radio_input;
+	else
+		in = &cx->card->audio_inputs[cx->audio_input];
 
 	/* handle muxer chips */
-	route.input = mux_input;
+	route.input = in->muxer_input;
 	route.output = 0;
-	cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+	v4l2_subdev_call(cx->sd_extmux, audio, s_routing, &route);
 
-	route.input = audio_input;
-	err = cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
-			VIDIOC_INT_S_AUDIO_ROUTING, &route);
+	route.input = in->audio_input;
+	err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
+			       audio, s_routing, &route);
 	if (err)
 		return err;
 
+	/* FIXME - this internal mux should be abstracted to a subdev */
 	val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
-	val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
-					(audio_input << 4);
-	cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE);
-	cx18_vapi(cx, CX18_APU_RESETAI, 1, 0);
+	val |= (in->audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
+					(in->audio_input << 4);
+	cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30);
 	return 0;
 }
-
-void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route)
-{
-	cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
-			VIDIOC_INT_S_AUDIO_ROUTING, route);
-}
-
-void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq)
-{
-	static u32 freqs[3] = { 44100, 48000, 32000 };
-
-	/* The audio clock of the digitizer must match the codec sample
-	   rate otherwise you get some very strange effects. */
-	if (freq > 2)
-		return;
-	cx18_call_i2c_clients(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]);
-}
diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/video/cx18/cx18-audio.h
index cb569a6..2731d29 100644
--- a/drivers/media/video/cx18/cx18-audio.h
+++ b/drivers/media/video/cx18/cx18-audio.h
@@ -22,5 +22,3 @@
  */
 
 int cx18_audio_set_io(struct cx18 *cx);
-void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route);
-void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq);
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index a2f0ad5..9e30983 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -464,82 +464,76 @@
 	}
 }
 
-int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
+int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
 {
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
 	struct cx18_av_state *state = &cx->av_state;
-	struct v4l2_control *ctrl = arg;
 	int retval;
+	u8 v;
 
-	switch (cmd) {
-	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-	{
-		u8 v;
-		if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-			v = cx18_av_read(cx, 0x803) & ~0x10;
-			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-			cx18_av_write(cx, 0x8d3, 0x1f);
-		}
-		v = cx18_av_read(cx, 0x810) | 0x1;
-		cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-
-		retval = set_audclk_freq(cx, *(u32 *)arg);
-
-		v = cx18_av_read(cx, 0x810) & ~0x1;
-		cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-		if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-			v = cx18_av_read(cx, 0x803) | 0x10;
-			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-		}
-		return retval;
+	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+		v = cx18_av_read(cx, 0x803) & ~0x10;
+		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+		cx18_av_write(cx, 0x8d3, 0x1f);
 	}
+	v = cx18_av_read(cx, 0x810) | 0x1;
+	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
 
-	case VIDIOC_G_CTRL:
-		switch (ctrl->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-			ctrl->value = get_volume(cx);
-			break;
-		case V4L2_CID_AUDIO_BASS:
-			ctrl->value = get_bass(cx);
-			break;
-		case V4L2_CID_AUDIO_TREBLE:
-			ctrl->value = get_treble(cx);
-			break;
-		case V4L2_CID_AUDIO_BALANCE:
-			ctrl->value = get_balance(cx);
-			break;
-		case V4L2_CID_AUDIO_MUTE:
-			ctrl->value = get_mute(cx);
-			break;
-		default:
-			return -EINVAL;
-		}
+	retval = set_audclk_freq(cx, freq);
+
+	v = cx18_av_read(cx, 0x810) & ~0x1;
+	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+		v = cx18_av_read(cx, 0x803) | 0x10;
+		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+	}
+	return retval;
+}
+
+int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		ctrl->value = get_volume(cx);
 		break;
-
-	case VIDIOC_S_CTRL:
-		switch (ctrl->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-			set_volume(cx, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_BASS:
-			set_bass(cx, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_TREBLE:
-			set_treble(cx, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_BALANCE:
-			set_balance(cx, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_MUTE:
-			set_mute(cx, ctrl->value);
-			break;
-		default:
-			return -EINVAL;
-		}
+	case V4L2_CID_AUDIO_BASS:
+		ctrl->value = get_bass(cx);
 		break;
-
+	case V4L2_CID_AUDIO_TREBLE:
+		ctrl->value = get_treble(cx);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		ctrl->value = get_balance(cx);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value = get_mute(cx);
+		break;
 	default:
 		return -EINVAL;
 	}
+	return 0;
+}
 
+int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		set_volume(cx, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_BASS:
+		set_bass(cx, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_TREBLE:
+		set_treble(cx, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		set_balance(cx, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		set_mute(cx, ctrl->value);
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 0b1c84b..f4dd9d7 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -22,8 +22,10 @@
  *  02110-1301, USA.
  */
 
+#include <media/v4l2-chip-ident.h>
 #include "cx18-driver.h"
 #include "cx18-io.h"
+#include "cx18-cards.h"
 
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
 {
@@ -97,15 +99,6 @@
 			     or_value);
 }
 
-/* ----------------------------------------------------------------------- */
-
-static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
-					enum cx18_av_audio_input aud_input);
-static void log_audio_status(struct cx18 *cx);
-static void log_video_status(struct cx18 *cx);
-
-/* ----------------------------------------------------------------------- */
-
 static void cx18_av_initialize(struct cx18 *cx)
 {
 	struct cx18_av_state *state = &cx->av_state;
@@ -169,9 +162,14 @@
 	/* Set VGA_TRACK_RANGE to 0x20 */
 	cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
 
-	/* Enable VBI capture */
-	cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F);
-	/* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */
+	/*
+	 * Initial VBI setup
+	 * VIP-1.1, 10 bit mode, enable Raw, disable sliced,
+	 * don't clamp raw samples when codes are in use, 1 byte user D-words,
+	 * IDID0 has line #, RP code V bit transition on VBLANK, data during
+	 * blanking intervals
+	 */
+	cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e);
 
 	/* Set the video input.
 	   The setting in MODE_CTRL gets lost when we do the above setup */
@@ -195,11 +193,61 @@
 	state->default_volume = ((state->default_volume / 2) + 23) << 9;
 }
 
-/* ----------------------------------------------------------------------- */
+static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	cx18_av_initialize(cx);
+	return 0;
+}
+
+static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	switch (val) {
+	case CX18_AV_INIT_PLLS:
+		/*
+		 * The crystal freq used in calculations in this driver will be
+		 * 28.636360 MHz.
+		 * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+		 */
+
+		/*
+		 * VDCLK  Integer = 0x0f, Post Divider = 0x04
+		 * AIMCLK Integer = 0x0e, Post Divider = 0x16
+		 */
+		cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
+
+		/* VDCLK Fraction = 0x2be2fe */
+		/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
+		cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
+
+		/* AIMCLK Fraction = 0x05227ad */
+		/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
+		cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
+
+		/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+		cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+		break;
+
+	case CX18_AV_INIT_NORMAL:
+	default:
+		if (!state->is_initialized) {
+			/* initialize on first use */
+			state->is_initialized = 1;
+			cx18_av_initialize(cx);
+		}
+		break;
+	}
+	return 0;
+}
 
 void cx18_av_std_setup(struct cx18 *cx)
 {
 	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd = &state->sd;
 	v4l2_std_id std = state->std;
 	int hblank, hactive, burst, vblank, vactive, sc;
 	int vblank656, src_decimation;
@@ -213,6 +261,7 @@
 		cx18_av_write(cx, 0x49f, 0x14);
 
 	if (std & V4L2_STD_625_50) {
+		/* FIXME - revisit these for Sliced VBI */
 		hblank = 132;
 		hactive = 720;
 		burst = 93;
@@ -236,13 +285,40 @@
 			sc = 672351;
 		}
 	} else {
+		/*
+		 * The following relationships of half line counts should hold:
+		 * 525 = vsync + vactive + vblank656
+		 * 12 = vblank656 - vblank
+		 *
+		 * vsync:     always 6 half-lines of vsync pulses
+		 * vactive:   half lines of active video
+		 * vblank656: half lines, after line 3/mid-266, of blanked video
+		 * vblank:    half lines, after line 9/272, of blanked video
+		 *
+		 * As far as I can tell:
+		 * vblank656 starts counting from the falling edge of the first
+		 * 	vsync pulse (start of line 4 or mid-266)
+		 * vblank starts counting from the after the 6 vsync pulses and
+		 * 	6 or 5 equalization pulses (start of line 10 or 272)
+		 *
+		 * For 525 line systems the driver will extract VBI information
+		 * from lines 10-21 and lines 273-284.
+		 */
+		vblank656 = 38; /* lines  4 -  22  &  266 - 284 */
+		vblank = 26;	/* lines 10 -  22  &  272 - 284 */
+		vactive = 481;  /* lines 23 - 263  &  285 - 525 */
+
+		/*
+		 * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is
+		 * is 858 pixels = 720 active + 138 blanking.  The Hsync leading
+		 * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the
+		 * end of active video, leaving 122 pixels of hblank to ignore
+		 * before active video starts.
+		 */
 		hactive = 720;
 		hblank = 122;
-		vactive = 487;
 		luma_lpf = 1;
 		uv_lpf = 1;
-		vblank = 26;
-		vblank656 = 26;
 
 		src_decimation = 0x21f;
 		if (std == V4L2_STD_PAL_60) {
@@ -265,33 +341,35 @@
 	pll_int = cx18_av_read(cx, 0x108);
 	pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
 	pll_post = cx18_av_read(cx, 0x109);
-	CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
-			pll_int, pll_frac, pll_post);
+	CX18_DEBUG_INFO_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n",
+			    pll_int, pll_frac, pll_post);
 
 	if (pll_post) {
 		int fin, fsc, pll;
 
 		pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
 		pll /= pll_post;
-		CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
-					pll / 1000000, pll % 1000000);
-		CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
-					pll / 8000000, (pll / 8) % 1000000);
+		CX18_DEBUG_INFO_DEV(sd, "PLL = %d.%06d MHz\n",
+				    pll / 1000000, pll % 1000000);
+		CX18_DEBUG_INFO_DEV(sd, "PLL/8 = %d.%06d MHz\n",
+				    pll / 8000000, (pll / 8) % 1000000);
 
 		fin = ((u64)src_decimation * pll) >> 12;
-		CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
-					fin / 1000000, fin % 1000000);
+		CX18_DEBUG_INFO_DEV(sd, "ADC Sampling freq = %d.%06d MHz\n",
+				    fin / 1000000, fin % 1000000);
 
 		fsc = (((u64)sc) * pll) >> 24L;
-		CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
-					fsc / 1000000, fsc % 1000000);
+		CX18_DEBUG_INFO_DEV(sd,
+				    "Chroma sub-carrier freq = %d.%06d MHz\n",
+				    fsc / 1000000, fsc % 1000000);
 
-		CX18_DEBUG_INFO("hblank %i, hactive %i, "
-			"vblank %i , vactive %i, vblank656 %i, src_dec %i,"
-			"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
-			" sc 0x%06x\n",
-			hblank, hactive, vblank, vactive, vblank656,
-			src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+		CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
+				    "vactive %i, vblank656 %i, src_dec %i, "
+				    "burst 0x%02x, luma_lpf %i, uv_lpf %i, "
+				    "comb 0x%02x, sc 0x%06x\n",
+				    hblank, hactive, vblank, vactive, vblank656,
+				    src_decimation, burst, luma_lpf, uv_lpf,
+				    comb, sc);
 	}
 
 	/* Sets horizontal blanking delay and active lines */
@@ -325,18 +403,16 @@
 	cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
 	cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
 
-	/* Sets VBI parameters */
 	if (std & V4L2_STD_625_50) {
-		cx18_av_write(cx, 0x47f, 0x01);
-		state->vbi_line_offset = 5;
+		state->slicer_line_delay = 1;
+		state->slicer_line_offset = (6 + state->slicer_line_delay - 2);
 	} else {
-		cx18_av_write(cx, 0x47f, 0x00);
-		state->vbi_line_offset = 8;
+		state->slicer_line_delay = 0;
+		state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
 	}
+	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
 }
 
-/* ----------------------------------------------------------------------- */
-
 static void input_change(struct cx18 *cx)
 {
 	struct cx18_av_state *state = &cx->av_state;
@@ -382,17 +458,26 @@
 	}
 }
 
+static int cx18_av_s_frequency(struct v4l2_subdev *sd,
+			       struct v4l2_frequency *freq)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	input_change(cx);
+	return 0;
+}
+
 static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
 					enum cx18_av_audio_input aud_input)
 {
 	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd = &state->sd;
 	u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
 			   vid_input <= CX18_AV_COMPOSITE8);
 	u8 reg;
 	u8 v;
 
-	CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
-			vid_input, aud_input);
+	CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
+			    vid_input, aud_input);
 
 	if (is_composite) {
 		reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
@@ -405,8 +490,8 @@
 		    luma > CX18_AV_SVIDEO_LUMA8 ||
 		    chroma < CX18_AV_SVIDEO_CHROMA4 ||
 		    chroma > CX18_AV_SVIDEO_CHROMA8) {
-			CX18_ERR("0x%04x is not a valid video input!\n",
-					vid_input);
+			CX18_ERR_DEV(sd, "0x%04x is not a valid video input!\n",
+				     vid_input);
 			return -EINVAL;
 		}
 		reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
@@ -431,7 +516,8 @@
 	case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
 
 	default:
-		CX18_ERR("0x%04x is not a valid audio input!\n", aud_input);
+		CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
+			     aud_input);
 		return -EINVAL;
 	}
 
@@ -461,14 +547,118 @@
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-static int set_v4lstd(struct cx18 *cx)
+static int cx18_av_s_video_routing(struct v4l2_subdev *sd,
+				   const struct v4l2_routing *route)
 {
-	struct cx18_av_state *state = &cx->av_state;
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	return set_input(cx, route->input, state->aud_input);
+}
+
+static int cx18_av_s_audio_routing(struct v4l2_subdev *sd,
+				   const struct v4l2_routing *route)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	return set_input(cx, state->vid_input, route->input);
+}
+
+static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	u8 vpres;
+	u8 mode;
+	int val = 0;
+
+	if (state->radio)
+		return 0;
+
+	vpres = cx18_av_read(cx, 0x40e) & 0x20;
+	vt->signal = vpres ? 0xffff : 0x0;
+
+	vt->capability |=
+		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+	mode = cx18_av_read(cx, 0x804);
+
+	/* get rxsubchans and audmode */
+	if ((mode & 0xf) == 1)
+		val |= V4L2_TUNER_SUB_STEREO;
+	else
+		val |= V4L2_TUNER_SUB_MONO;
+
+	if (mode == 2 || mode == 4)
+		val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+	if (mode & 0x10)
+		val |= V4L2_TUNER_SUB_SAP;
+
+	vt->rxsubchans = val;
+	vt->audmode = state->audmode;
+	return 0;
+}
+
+static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	u8 v;
+
+	if (state->radio)
+		return 0;
+
+	v = cx18_av_read(cx, 0x809);
+	v &= ~0xf;
+
+	switch (vt->audmode) {
+	case V4L2_TUNER_MODE_MONO:
+		/* mono      -> mono
+		   stereo    -> mono
+		   bilingual -> lang1 */
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1:
+		/* mono      -> mono
+		   stereo    -> stereo
+		   bilingual -> lang1 */
+		v |= 0x4;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		/* mono      -> mono
+		   stereo    -> stereo
+		   bilingual -> lang1/lang2 */
+		v |= 0x7;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		/* mono      -> mono
+		   stereo    -> stereo
+		   bilingual -> lang2 */
+		v |= 0x1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	cx18_av_write_expect(cx, 0x809, v, v, 0xff);
+	state->audmode = vt->audmode;
+	return 0;
+}
+
+static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
 	u8 fmt = 0; 	/* zero is autodetect */
 	u8 pal_m = 0;
 
+	if (state->radio == 0 && state->std == norm)
+		return 0;
+
+	state->radio = 0;
+	state->std = norm;
+
 	/* First tests should be against specific std */
 	if (state->std == V4L2_STD_NTSC_M_JP) {
 		fmt = 0x2;
@@ -493,7 +683,7 @@
 			fmt = 0xc;
 	}
 
-	CX18_DEBUG_INFO("changing video std to fmt %i\n", fmt);
+	CX18_DEBUG_INFO_DEV(sd, "changing video std to fmt %i\n", fmt);
 
 	/* Follow step 9 of section 3.16 in the cx18_av datasheet.
 	   Without this PAL may display a vertical ghosting effect.
@@ -511,15 +701,22 @@
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+static int cx18_av_s_radio(struct v4l2_subdev *sd)
 {
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	state->radio = 1;
+	return 0;
+}
+
+static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
 		if (ctrl->value < 0 || ctrl->value > 255) {
-			CX18_ERR("invalid brightness setting %d\n",
-				    ctrl->value);
+			CX18_ERR_DEV(sd, "invalid brightness setting %d\n",
+				     ctrl->value);
 			return -ERANGE;
 		}
 
@@ -528,8 +725,8 @@
 
 	case V4L2_CID_CONTRAST:
 		if (ctrl->value < 0 || ctrl->value > 127) {
-			CX18_ERR("invalid contrast setting %d\n",
-				    ctrl->value);
+			CX18_ERR_DEV(sd, "invalid contrast setting %d\n",
+				     ctrl->value);
 			return -ERANGE;
 		}
 
@@ -538,8 +735,8 @@
 
 	case V4L2_CID_SATURATION:
 		if (ctrl->value < 0 || ctrl->value > 127) {
-			CX18_ERR("invalid saturation setting %d\n",
-				    ctrl->value);
+			CX18_ERR_DEV(sd, "invalid saturation setting %d\n",
+				     ctrl->value);
 			return -ERANGE;
 		}
 
@@ -548,8 +745,9 @@
 		break;
 
 	case V4L2_CID_HUE:
-		if (ctrl->value < -127 || ctrl->value > 127) {
-			CX18_ERR("invalid hue setting %d\n", ctrl->value);
+		if (ctrl->value < -128 || ctrl->value > 127) {
+			CX18_ERR_DEV(sd, "invalid hue setting %d\n",
+				     ctrl->value);
 			return -ERANGE;
 		}
 
@@ -561,17 +759,18 @@
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_MUTE:
-		return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl);
+		return cx18_av_audio_s_ctrl(cx, ctrl);
 
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
-static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
 		ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
@@ -590,31 +789,57 @@
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_MUTE:
-		return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl);
+		return cx18_av_audio_g_ctrl(cx, ctrl);
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-static int get_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 {
-	switch (fmt->type) {
-	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-		return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt);
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
+	default:
+		break;
+	}
+
+	switch (qc->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535,
+			65535 / 100, state->default_volume);
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 	default:
 		return -EINVAL;
 	}
-
-	return 0;
+	return -EINVAL;
 }
 
-static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 {
-	struct cx18_av_state *state = &cx->av_state;
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	return cx18_av_vbi_g_fmt(cx, fmt);
+}
+
+static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
 	struct v4l2_pix_format *pix;
 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
 	int is_50Hz = !(state->std & V4L2_STD_525_60);
@@ -629,12 +854,26 @@
 		Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
 		Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
 
-		Vlines = pix->height + (is_50Hz ? 4 : 7);
+		/*
+		 * This adjustment reflects the excess of vactive, set in
+		 * cx18_av_std_setup(), above standard values:
+		 *
+		 * 480 + 1 for 60 Hz systems
+		 * 576 + 4 for 50 Hz systems
+		 */
+		Vlines = pix->height + (is_50Hz ? 4 : 1);
 
+		/*
+		 * Invalid height and width scaling requests are:
+		 * 1. width less than 1/16 of the source width
+		 * 2. width greater than the source width
+		 * 3. height less than 1/8 of the source height
+		 * 4. height greater than the source height
+		 */
 		if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
 		    (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
-			CX18_ERR("%dx%d is not a valid size!\n",
-				    pix->width, pix->height);
+			CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
+				     pix->width, pix->height);
 			return -ERANGE;
 		}
 
@@ -651,8 +890,9 @@
 		else
 			filter = 3;
 
-		CX18_DEBUG_INFO("decoder set size %dx%d -> scale  %ux%u\n",
-			    pix->width, pix->height, HSC, VSC);
+		CX18_DEBUG_INFO_DEV(sd,
+				    "decoder set size %dx%d -> scale  %ux%u\n",
+				    pix->width, pix->height, HSC, VSC);
 
 		/* HSCALE=HSC */
 		cx18_av_write(cx, 0x418, HSC & 0xff);
@@ -666,231 +906,32 @@
 		break;
 
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-		return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+		return cx18_av_vbi_s_fmt(cx, fmt);
 
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+		return cx18_av_vbi_s_fmt(cx, fmt);
 
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
+static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
 {
-	struct cx18_av_state *state = &cx->av_state;
-	struct v4l2_tuner *vt = arg;
-	struct v4l2_routing *route = arg;
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
 
-	/* ignore these commands */
-	switch (cmd) {
-	case TUNER_SET_TYPE_ADDR:
-		return 0;
-	}
-
-	if (!state->is_initialized) {
-		CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd);
-		/* initialize on first use */
-		state->is_initialized = 1;
-		cx18_av_initialize(cx);
-	}
-
-	switch (cmd) {
-	case VIDIOC_INT_DECODE_VBI_LINE:
-		return cx18_av_vbi(cx, cmd, arg);
-
-	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-		return cx18_av_audio(cx, cmd, arg);
-
-	case VIDIOC_STREAMON:
-		CX18_DEBUG_INFO("enable output\n");
+	CX18_DEBUG_INFO_DEV(sd, "%s output\n", enable ? "enable" : "disable");
+	if (enable) {
 		cx18_av_write(cx, 0x115, 0x8c);
 		cx18_av_write(cx, 0x116, 0x07);
-		break;
-
-	case VIDIOC_STREAMOFF:
-		CX18_DEBUG_INFO("disable output\n");
+	} else {
 		cx18_av_write(cx, 0x115, 0x00);
 		cx18_av_write(cx, 0x116, 0x00);
-		break;
-
-	case VIDIOC_LOG_STATUS:
-		log_video_status(cx);
-		log_audio_status(cx);
-		break;
-
-	case VIDIOC_G_CTRL:
-		return get_v4lctrl(cx, (struct v4l2_control *)arg);
-
-	case VIDIOC_S_CTRL:
-		return set_v4lctrl(cx, (struct v4l2_control *)arg);
-
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *qc = arg;
-
-		switch (qc->id) {
-		case V4L2_CID_BRIGHTNESS:
-		case V4L2_CID_CONTRAST:
-		case V4L2_CID_SATURATION:
-		case V4L2_CID_HUE:
-			return v4l2_ctrl_query_fill_std(qc);
-		default:
-			break;
-		}
-
-		switch (qc->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-			return v4l2_ctrl_query_fill(qc, 0, 65535,
-				65535 / 100, state->default_volume);
-		case V4L2_CID_AUDIO_MUTE:
-		case V4L2_CID_AUDIO_BALANCE:
-		case V4L2_CID_AUDIO_BASS:
-		case V4L2_CID_AUDIO_TREBLE:
-			return v4l2_ctrl_query_fill_std(qc);
-		default:
-			return -EINVAL;
-		}
-		return -EINVAL;
 	}
-
-	case VIDIOC_G_STD:
-		*(v4l2_std_id *)arg = state->std;
-		break;
-
-	case VIDIOC_S_STD:
-		if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
-			return 0;
-		state->radio = 0;
-		state->std = *(v4l2_std_id *)arg;
-		return set_v4lstd(cx);
-
-	case AUDC_SET_RADIO:
-		state->radio = 1;
-		break;
-
-	case VIDIOC_INT_G_VIDEO_ROUTING:
-		route->input = state->vid_input;
-		route->output = 0;
-		break;
-
-	case VIDIOC_INT_S_VIDEO_ROUTING:
-		return set_input(cx, route->input, state->aud_input);
-
-	case VIDIOC_INT_G_AUDIO_ROUTING:
-		route->input = state->aud_input;
-		route->output = 0;
-		break;
-
-	case VIDIOC_INT_S_AUDIO_ROUTING:
-		return set_input(cx, state->vid_input, route->input);
-
-	case VIDIOC_S_FREQUENCY:
-		input_change(cx);
-		break;
-
-	case VIDIOC_G_TUNER:
-	{
-		u8 vpres = cx18_av_read(cx, 0x40e) & 0x20;
-		u8 mode;
-		int val = 0;
-
-		if (state->radio)
-			break;
-
-		vt->signal = vpres ? 0xffff : 0x0;
-
-		vt->capability |=
-		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
-		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-
-		mode = cx18_av_read(cx, 0x804);
-
-		/* get rxsubchans and audmode */
-		if ((mode & 0xf) == 1)
-			val |= V4L2_TUNER_SUB_STEREO;
-		else
-			val |= V4L2_TUNER_SUB_MONO;
-
-		if (mode == 2 || mode == 4)
-			val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-
-		if (mode & 0x10)
-			val |= V4L2_TUNER_SUB_SAP;
-
-		vt->rxsubchans = val;
-		vt->audmode = state->audmode;
-		break;
-	}
-
-	case VIDIOC_S_TUNER:
-	{
-		u8 v;
-
-		if (state->radio)
-			break;
-
-		v = cx18_av_read(cx, 0x809);
-		v &= ~0xf;
-
-		switch (vt->audmode) {
-		case V4L2_TUNER_MODE_MONO:
-			/* mono      -> mono
-			   stereo    -> mono
-			   bilingual -> lang1 */
-			break;
-		case V4L2_TUNER_MODE_STEREO:
-		case V4L2_TUNER_MODE_LANG1:
-			/* mono      -> mono
-			   stereo    -> stereo
-			   bilingual -> lang1 */
-			v |= 0x4;
-			break;
-		case V4L2_TUNER_MODE_LANG1_LANG2:
-			/* mono      -> mono
-			   stereo    -> stereo
-			   bilingual -> lang1/lang2 */
-			v |= 0x7;
-			break;
-		case V4L2_TUNER_MODE_LANG2:
-			/* mono      -> mono
-			   stereo    -> stereo
-			   bilingual -> lang2 */
-			v |= 0x1;
-			break;
-		default:
-			return -EINVAL;
-		}
-		cx18_av_write_expect(cx, 0x809, v, v, 0xff);
-		state->audmode = vt->audmode;
-		break;
-	}
-
-	case VIDIOC_G_FMT:
-		return get_v4lfmt(cx, (struct v4l2_format *)arg);
-
-	case VIDIOC_S_FMT:
-		return set_v4lfmt(cx, (struct v4l2_format *)arg);
-
-	case VIDIOC_INT_RESET:
-		cx18_av_initialize(cx);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-
-/* ----------------------------------------------------------------------- */
-
 static void log_video_status(struct cx18 *cx)
 {
 	static const char *const fmt_strs[] = {
@@ -903,36 +944,40 @@
 	};
 
 	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd = &state->sd;
 	u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
 	u8 gen_stat1 = cx18_av_read(cx, 0x40d);
 	u8 gen_stat2 = cx18_av_read(cx, 0x40e);
 	int vid_input = state->vid_input;
 
-	CX18_INFO("Video signal:              %spresent\n",
-		    (gen_stat2 & 0x20) ? "" : "not ");
-	CX18_INFO("Detected format:           %s\n",
-		    fmt_strs[gen_stat1 & 0xf]);
+	CX18_INFO_DEV(sd, "Video signal:              %spresent\n",
+		      (gen_stat2 & 0x20) ? "" : "not ");
+	CX18_INFO_DEV(sd, "Detected format:           %s\n",
+		      fmt_strs[gen_stat1 & 0xf]);
 
-	CX18_INFO("Specified standard:        %s\n",
-		    vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+	CX18_INFO_DEV(sd, "Specified standard:        %s\n",
+		      vidfmt_sel ? fmt_strs[vidfmt_sel]
+				 : "automatic detection");
 
 	if (vid_input >= CX18_AV_COMPOSITE1 &&
 	    vid_input <= CX18_AV_COMPOSITE8) {
-		CX18_INFO("Specified video input:     Composite %d\n",
-			vid_input - CX18_AV_COMPOSITE1 + 1);
+		CX18_INFO_DEV(sd, "Specified video input:     Composite %d\n",
+			      vid_input - CX18_AV_COMPOSITE1 + 1);
 	} else {
-		CX18_INFO("Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
-			(vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+		CX18_INFO_DEV(sd, "Specified video input:     "
+			      "S-Video (Luma In%d, Chroma In%d)\n",
+			      (vid_input & 0xf0) >> 4,
+			      (vid_input & 0xf00) >> 8);
 	}
 
-	CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq);
+	CX18_INFO_DEV(sd, "Specified audioclock freq: %d Hz\n",
+		      state->audclk_freq);
 }
 
-/* ----------------------------------------------------------------------- */
-
 static void log_audio_status(struct cx18 *cx)
 {
 	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd = &state->sd;
 	u8 download_ctl = cx18_av_read(cx, 0x803);
 	u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
 	u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
@@ -955,7 +1000,7 @@
 	case 0xfe: p = "forced mode"; break;
 	default: p = "not defined"; break;
 	}
-	CX18_INFO("Detected audio mode:       %s\n", p);
+	CX18_INFO_DEV(sd, "Detected audio mode:       %s\n", p);
 
 	switch (mod_det_stat1) {
 	case 0x00: p = "not defined"; break;
@@ -980,11 +1025,11 @@
 	case 0xff: p = "no detected audio standard"; break;
 	default: p = "not defined"; break;
 	}
-	CX18_INFO("Detected audio standard:   %s\n", p);
-	CX18_INFO("Audio muted:               %s\n",
-		    (mute_ctl & 0x2) ? "yes" : "no");
-	CX18_INFO("Audio microcontroller:     %s\n",
-		    (download_ctl & 0x10) ? "running" : "stopped");
+	CX18_INFO_DEV(sd, "Detected audio standard:   %s\n", p);
+	CX18_INFO_DEV(sd, "Audio muted:               %s\n",
+		      (mute_ctl & 0x2) ? "yes" : "no");
+	CX18_INFO_DEV(sd, "Audio microcontroller:     %s\n",
+		      (download_ctl & 0x10) ? "running" : "stopped");
 
 	switch (audio_config >> 4) {
 	case 0x00: p = "undefined"; break;
@@ -1005,7 +1050,7 @@
 	case 0x0f: p = "automatic detection"; break;
 	default: p = "undefined"; break;
 	}
-	CX18_INFO("Configured audio standard: %s\n", p);
+	CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p);
 
 	if ((audio_config >> 4) < 0xF) {
 		switch (audio_config & 0xF) {
@@ -1019,7 +1064,7 @@
 		case 0x07: p = "DUAL3 (AB)"; break;
 		default: p = "undefined";
 		}
-		CX18_INFO("Configured audio mode:     %s\n", p);
+		CX18_INFO_DEV(sd, "Configured audio mode:     %s\n", p);
 	} else {
 		switch (audio_config & 0xF) {
 		case 0x00: p = "BG"; break;
@@ -1037,14 +1082,14 @@
 		case 0x0f: p = "automatic standard and mode detection"; break;
 		default: p = "undefined"; break;
 		}
-		CX18_INFO("Configured audio system:   %s\n", p);
+		CX18_INFO_DEV(sd, "Configured audio system:   %s\n", p);
 	}
 
 	if (aud_input)
-		CX18_INFO("Specified audio input:     Tuner (In%d)\n",
-				aud_input);
+		CX18_INFO_DEV(sd, "Specified audio input:     Tuner (In%d)\n",
+			      aud_input);
 	else
-		CX18_INFO("Specified audio input:     External\n");
+		CX18_INFO_DEV(sd, "Specified audio input:     External\n");
 
 	switch (pref_mode & 0xf) {
 	case 0: p = "mono/language A"; break;
@@ -1057,14 +1102,14 @@
 	case 7: p = "language AB"; break;
 	default: p = "undefined"; break;
 	}
-	CX18_INFO("Preferred audio mode:      %s\n", p);
+	CX18_INFO_DEV(sd, "Preferred audio mode:      %s\n", p);
 
 	if ((audio_config & 0xf) == 0xf) {
 		switch ((afc0 >> 3) & 0x1) {
 		case 0: p = "system DK"; break;
 		case 1: p = "system L"; break;
 		}
-		CX18_INFO("Selected 65 MHz format:    %s\n", p);
+		CX18_INFO_DEV(sd, "Selected 65 MHz format:    %s\n", p);
 
 		switch (afc0 & 0x7) {
 		case 0: p = "Chroma"; break;
@@ -1074,6 +1119,131 @@
 		case 4: p = "autodetect"; break;
 		default: p = "undefined"; break;
 		}
-		CX18_INFO("Selected 45 MHz format:    %s\n", p);
+		CX18_INFO_DEV(sd, "Selected 45 MHz format:    %s\n", p);
 	}
 }
+
+static int cx18_av_log_status(struct v4l2_subdev *sd)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	log_video_status(cx);
+	log_audio_status(cx);
+	return 0;
+}
+
+static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match)
+{
+	return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1;
+}
+
+static int cx18_av_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+
+	if (cx18_av_dbg_match(&chip->match)) {
+		chip->ident = state->id;
+		chip->revision = state->rev;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx18_av_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	if (!cx18_av_dbg_match(&reg->match))
+		return -EINVAL;
+	if ((reg->reg & 0x3) != 0)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	reg->size = 4;
+	reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc);
+	return 0;
+}
+
+static int cx18_av_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	if (!cx18_av_dbg_match(&reg->match))
+		return -EINVAL;
+	if ((reg->reg & 0x3) != 0)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val);
+	return 0;
+}
+#endif
+
+static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
+	.g_chip_ident = cx18_av_g_chip_ident,
+	.log_status = cx18_av_log_status,
+	.init = cx18_av_init,
+	.reset = cx18_av_reset,
+	.queryctrl = cx18_av_queryctrl,
+	.g_ctrl = cx18_av_g_ctrl,
+	.s_ctrl = cx18_av_s_ctrl,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = cx18_av_g_register,
+	.s_register = cx18_av_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = {
+	.s_radio = cx18_av_s_radio,
+	.s_frequency = cx18_av_s_frequency,
+	.g_tuner = cx18_av_g_tuner,
+	.s_tuner = cx18_av_s_tuner,
+	.s_std = cx18_av_s_std,
+};
+
+static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
+	.s_clock_freq = cx18_av_s_clock_freq,
+	.s_routing = cx18_av_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
+	.s_routing = cx18_av_s_video_routing,
+	.decode_vbi_line = cx18_av_decode_vbi_line,
+	.s_stream = cx18_av_s_stream,
+	.g_fmt = cx18_av_g_fmt,
+	.s_fmt = cx18_av_s_fmt,
+};
+
+static const struct v4l2_subdev_ops cx18_av_ops = {
+	.core = &cx18_av_general_ops,
+	.tuner = &cx18_av_tuner_ops,
+	.audio = &cx18_av_audio_ops,
+	.video = &cx18_av_video_ops,
+};
+
+int cx18_av_probe(struct cx18 *cx)
+{
+	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd;
+
+	state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff;
+	state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO)
+		    ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN;
+
+	state->vid_input = CX18_AV_COMPOSITE7;
+	state->aud_input = CX18_AV_AUDIO8;
+	state->audclk_freq = 48000;
+	state->audmode = V4L2_TUNER_MODE_LANG1;
+	state->slicer_line_delay = 0;
+	state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
+
+	sd = &state->sd;
+	v4l2_subdev_init(sd, &cx18_av_ops);
+	v4l2_set_subdevdata(sd, cx);
+	snprintf(sd->name, sizeof(sd->name),
+		 "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
+	sd->grp_id = CX18_HW_418_AV;
+	return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+}
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index cf68a60..c458120 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -25,6 +25,8 @@
 #ifndef _CX18_AV_CORE_H_
 #define _CX18_AV_CORE_H_
 
+#include <media/v4l2-device.h>
+
 struct cx18;
 
 enum cx18_av_video_input {
@@ -73,17 +75,40 @@
 };
 
 struct cx18_av_state {
+	struct v4l2_subdev sd;
 	int radio;
 	v4l2_std_id std;
 	enum cx18_av_video_input vid_input;
 	enum cx18_av_audio_input aud_input;
 	u32 audclk_freq;
 	int audmode;
-	int vbi_line_offset;
 	int default_volume;
 	u32 id;
 	u32 rev;
 	int is_initialized;
+
+	/*
+	 * The VBI slicer starts operating and counting lines, begining at
+	 * slicer line count of 1, at D lines after the deassertion of VRESET.
+	 * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525
+	 * line systems respectively.  Sliced ancillary data captured on VBI
+	 * slicer line M is inserted after the VBI slicer is done with line M,
+	 * when VBI slicer line count is N = M+1.  Thus when the VBI slicer
+	 * reports a VBI slicer line number with ancillary data, the IDID0 byte
+	 * indicates VBI slicer line N.  The actual field line that the captured
+	 * data comes from is
+	 *
+	 * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2).
+	 *
+	 * L is the line in the field, not frame, from which the VBI data came.
+	 * N is the line reported by the slicer in the ancillary data.
+	 * D is the slicer_line_delay value programmed into register 0x47f.
+	 * S is 6 for 625 line systems or 10 for 525 line systems
+	 * (S+D-2) is the slicer_line_offset used to convert slicer reported
+	 * line counts to actual field lines.
+	 */
+	int slicer_line_delay;
+	int slicer_line_offset;
 };
 
 
@@ -298,6 +323,16 @@
 #define CXADEC_SELECT_AUDIO_STANDARD_FM    0xF9  /* FM radio */
 #define CXADEC_SELECT_AUDIO_STANDARD_AUTO  0xFF  /* Auto detect */
 
+static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cx18_av_state, sd);
+}
+
+enum cx18_av_subdev_init_arg {
+	CX18_AV_INIT_NORMAL = 0,
+	CX18_AV_INIT_PLLS = 1,
+};
+
 /* ----------------------------------------------------------------------- */
 /* cx18_av-core.c 							   */
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
@@ -310,20 +345,26 @@
 u32 cx18_av_read4(struct cx18 *cx, u16 addr);
 int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
 int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
-int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
 void cx18_av_std_setup(struct cx18 *cx);
 
+int cx18_av_probe(struct cx18 *cx);
+
 /* ----------------------------------------------------------------------- */
 /* cx18_av-firmware.c                                                      */
 int cx18_av_loadfw(struct cx18 *cx);
 
 /* ----------------------------------------------------------------------- */
 /* cx18_av-audio.c                                                         */
-int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg);
+int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
+int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
+int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
 void cx18_av_audio_set_path(struct cx18 *cx);
 
 /* ----------------------------------------------------------------------- */
 /* cx18_av-vbi.c                                                           */
-int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
+int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
+			   struct v4l2_decode_vbi_line *vbi);
+int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt);
+int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt);
 
 #endif
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index c64fd0a..49a55cc 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -29,6 +29,7 @@
 
 int cx18_av_loadfw(struct cx18 *cx)
 {
+	struct v4l2_subdev *sd = &cx->av_state.sd;
 	const struct firmware *fw = NULL;
 	u32 size;
 	u32 v;
@@ -36,8 +37,8 @@
 	int i;
 	int retries1 = 0;
 
-	if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
-		CX18_ERR("unable to open firmware %s\n", FWFILE);
+	if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) {
+		CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE);
 		return -EINVAL;
 	}
 
@@ -88,7 +89,7 @@
 		retries1++;
 	}
 	if (retries1 >= 5) {
-		CX18_ERR("unable to load firmware %s\n", FWFILE);
+		CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE);
 		release_firmware(fw);
 		return -EIO;
 	}
@@ -115,9 +116,9 @@
 	   are generated) */
 	cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
 
-	/* set alt I2s master clock to /16 and enable alt divider i2s
+	/* set alt I2s master clock to /0x16 and enable alt divider i2s
 	   passthrough */
-	cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
+	cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687);
 
 	cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
 								  0x3F00FFFF);
@@ -131,7 +132,8 @@
 	v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
 	/* If bit 11 is 1, clear bit 10 */
 	if (v & 0x800)
-		cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE);
+		cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
+				      0, 0x400);
 
 	/* Enable WW auto audio standard detection */
 	v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
@@ -142,6 +144,6 @@
 
 	release_firmware(fw);
 
-	CX18_INFO("loaded %s firmware (%d bytes)\n", FWFILE, size);
+	CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
 	return 0;
 }
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
index 1527ea4..23b3167 100644
--- a/drivers/media/video/cx18/cx18-av-vbi.c
+++ b/drivers/media/video/cx18/cx18-av-vbi.c
@@ -24,6 +24,52 @@
 
 #include "cx18-driver.h"
 
+/*
+ * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
+ * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
+ * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
+ * (should!) look like:
+ *	4 byte EAV code:          0xff 0x00 0x00 0xRP
+ *	unknown number of possible idle bytes
+ *	3 byte Anc data preamble: 0x00 0xff 0xff
+ *	1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
+ *	1 byte secondary data id: nessssss (parity bits, SDID bits)
+ *	1 byte data word count:   necccccc (parity bits, NN Dword count)
+ *	2 byte Internal DID:	  VBI-line-# 0x80
+ *	NN data bytes
+ *	1 byte checksum
+ *	Fill bytes needed to fil out to 4*NN bytes of payload
+ *
+ * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
+ * in the vertical blanking interval are:
+ *	0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
+ *	0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
+ *
+ * Since the V bit is only allowed to toggle in the EAV RP code, just
+ * before the first active region line and for active lines, they are:
+ *	0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
+ *	0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
+ *
+ * The user application DID bytes we care about are:
+ *	0x91 (1 0 010        0 !ActiveLine AncDataPresent)
+ *	0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
+ *
+ */
+static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
+
+struct vbi_anc_data {
+	/* u8 eav[4]; */
+	/* u8 idle[]; Variable number of idle bytes */
+	u8 preamble[3];
+	u8 did;
+	u8 sdid;
+	u8 data_count;
+	u8 idid[2];
+	u8 payload[1]; /* data_count of payload */
+	/* u8 checksum; */
+	/* u8 fill[]; Variable number of fill bytes */
+};
+
 static int odd_parity(u8 c)
 {
 	c ^= (c >> 4);
@@ -83,188 +129,189 @@
 	return err & 0xf0;
 }
 
-int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
+int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt)
 {
 	struct cx18_av_state *state = &cx->av_state;
-	struct v4l2_format *fmt;
 	struct v4l2_sliced_vbi_format *svbi;
+	static const u16 lcr2vbi[] = {
+		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
+		0, V4L2_SLICED_WSS_625, 0,	/* 4 */
+		V4L2_SLICED_CAPTION_525,	/* 6 */
+		0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
+		0, 0, 0, 0
+	};
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int i;
 
-	switch (cmd) {
-	case VIDIOC_G_FMT:
-	{
-		static u16 lcr2vbi[] = {
-			0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
-			0, V4L2_SLICED_WSS_625, 0,	/* 4 */
-			V4L2_SLICED_CAPTION_525,	/* 6 */
-			0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
-			0, 0, 0, 0
-		};
-		int is_pal = !(state->std & V4L2_STD_525_60);
-		int i;
+	if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+		return -EINVAL;
+	svbi = &fmt->fmt.sliced;
+	memset(svbi, 0, sizeof(*svbi));
+	/* we're done if raw VBI is active */
+	if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
+		return 0;
 
-		fmt = arg;
-		if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-			return -EINVAL;
-		svbi = &fmt->fmt.sliced;
-		memset(svbi, 0, sizeof(*svbi));
-		/* we're done if raw VBI is active */
-		if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
-			break;
+	if (is_pal) {
+		for (i = 7; i <= 23; i++) {
+			u8 v = cx18_av_read(cx, 0x424 + i - 7);
 
-		if (is_pal) {
-			for (i = 7; i <= 23; i++) {
-				u8 v = cx18_av_read(cx, 0x424 + i - 7);
-
-				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-				svbi->service_set |= svbi->service_lines[0][i] |
-					svbi->service_lines[1][i];
-			}
-		} else {
-			for (i = 10; i <= 21; i++) {
-				u8 v = cx18_av_read(cx, 0x424 + i - 10);
-
-				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-				svbi->service_set |= svbi->service_lines[0][i] |
-					svbi->service_lines[1][i];
-			}
+			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+			svbi->service_set |= svbi->service_lines[0][i] |
+				svbi->service_lines[1][i];
 		}
-		break;
+	} else {
+		for (i = 10; i <= 21; i++) {
+			u8 v = cx18_av_read(cx, 0x424 + i - 10);
+
+			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+			svbi->service_set |= svbi->service_lines[0][i] |
+				svbi->service_lines[1][i];
+		}
 	}
+	return 0;
+}
 
-	case VIDIOC_S_FMT:
-	{
-		int is_pal = !(state->std & V4L2_STD_525_60);
-		int vbi_offset = is_pal ? 1 : 0;
-		int i, x;
-		u8 lcr[24];
+int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
+	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_sliced_vbi_format *svbi;
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int i, x;
+	u8 lcr[24];
 
-		fmt = arg;
-		if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
-		    fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
-			return -EINVAL;
-		svbi = &fmt->fmt.sliced;
-		if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-			/* raw VBI */
-			memset(svbi, 0, sizeof(*svbi));
-
-			/* Setup standard */
-			cx18_av_std_setup(cx);
-
-			/* VBI Offset */
-			cx18_av_write(cx, 0x47f, vbi_offset);
-			cx18_av_write(cx, 0x404, 0x2e);
-			break;
-		}
-
-		for (x = 0; x <= 23; x++)
-			lcr[x] = 0x00;
+	if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
+			fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
+		return -EINVAL;
+	svbi = &fmt->fmt.sliced;
+	if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		/* raw VBI */
+		memset(svbi, 0, sizeof(*svbi));
 
 		/* Setup standard */
 		cx18_av_std_setup(cx);
 
-		/* Sliced VBI */
-		cx18_av_write(cx, 0x404, 0x32);	/* Ancillary data */
-		cx18_av_write(cx, 0x406, 0x13);
-		cx18_av_write(cx, 0x47f, vbi_offset);
+		/* VBI Offset */
+		cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+		cx18_av_write(cx, 0x404, 0x2e);
+		return 0;
+	}
 
-		if (is_pal) {
-			for (i = 0; i <= 6; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
-		} else {
-			for (i = 0; i <= 9; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
+	for (x = 0; x <= 23; x++)
+		lcr[x] = 0x00;
 
-			for (i = 22; i <= 23; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
-		}
+	/* Setup standard */
+	cx18_av_std_setup(cx);
 
-		for (i = 7; i <= 23; i++) {
-			for (x = 0; x <= 1; x++) {
-				switch (svbi->service_lines[1-x][i]) {
-				case V4L2_SLICED_TELETEXT_B:
-					lcr[i] |= 1 << (4 * x);
-					break;
-				case V4L2_SLICED_WSS_625:
-					lcr[i] |= 4 << (4 * x);
-					break;
-				case V4L2_SLICED_CAPTION_525:
-					lcr[i] |= 6 << (4 * x);
-					break;
-				case V4L2_SLICED_VPS:
-					lcr[i] |= 9 << (4 * x);
-					break;
-				}
+	/* Sliced VBI */
+	cx18_av_write(cx, 0x404, 0x32);	/* Ancillary data */
+	cx18_av_write(cx, 0x406, 0x13);
+	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+
+	/* Force impossible lines to 0 */
+	if (is_pal) {
+		for (i = 0; i <= 6; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+	} else {
+		for (i = 0; i <= 9; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+
+		for (i = 22; i <= 23; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+	}
+
+	/* Build register values for requested service lines */
+	for (i = 7; i <= 23; i++) {
+		for (x = 0; x <= 1; x++) {
+			switch (svbi->service_lines[1-x][i]) {
+			case V4L2_SLICED_TELETEXT_B:
+				lcr[i] |= 1 << (4 * x);
+				break;
+			case V4L2_SLICED_WSS_625:
+				lcr[i] |= 4 << (4 * x);
+				break;
+			case V4L2_SLICED_CAPTION_525:
+				lcr[i] |= 6 << (4 * x);
+				break;
+			case V4L2_SLICED_VPS:
+				lcr[i] |= 9 << (4 * x);
+				break;
 			}
 		}
-
-		if (is_pal) {
-			for (x = 1, i = 0x424; i <= 0x434; i++, x++)
-				cx18_av_write(cx, i, lcr[6 + x]);
-		} else {
-			for (x = 1, i = 0x424; i <= 0x430; i++, x++)
-				cx18_av_write(cx, i, lcr[9 + x]);
-			for (i = 0x431; i <= 0x434; i++)
-				cx18_av_write(cx, i, 0);
-		}
-
-		cx18_av_write(cx, 0x43c, 0x16);
-		cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22);
-		break;
 	}
 
-	case VIDIOC_INT_DECODE_VBI_LINE:
-	{
-		struct v4l2_decode_vbi_line *vbi = arg;
-		u8 *p = vbi->p;
-		int id1, id2, l, err = 0;
+	if (is_pal) {
+		for (x = 1, i = 0x424; i <= 0x434; i++, x++)
+			cx18_av_write(cx, i, lcr[6 + x]);
+	} else {
+		for (x = 1, i = 0x424; i <= 0x430; i++, x++)
+			cx18_av_write(cx, i, lcr[9 + x]);
+		for (i = 0x431; i <= 0x434; i++)
+			cx18_av_write(cx, i, 0);
+	}
 
-		if (p[0] || p[1] != 0xff || p[2] != 0xff ||
-		    (p[3] != 0x55 && p[3] != 0x91)) {
-			vbi->line = vbi->type = 0;
-			break;
-		}
+	cx18_av_write(cx, 0x43c, 0x16);
+	/* FIXME - should match vblank set in cx18_av_std_setup() */
+	cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26);
+	return 0;
+}
 
-		p += 4;
-		id1 = p[-1];
-		id2 = p[0] & 0xf;
-		l = p[2] & 0x3f;
-		l += state->vbi_line_offset;
-		p += 4;
+int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
+				   struct v4l2_decode_vbi_line *vbi)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	struct cx18_av_state *state = &cx->av_state;
+	struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
+	u8 *p;
+	int did, sdid, l, err = 0;
 
-		switch (id2) {
-		case 1:
-			id2 = V4L2_SLICED_TELETEXT_B;
-			break;
-		case 4:
-			id2 = V4L2_SLICED_WSS_625;
-			break;
-		case 6:
-			id2 = V4L2_SLICED_CAPTION_525;
-			err = !odd_parity(p[0]) || !odd_parity(p[1]);
-			break;
-		case 9:
-			id2 = V4L2_SLICED_VPS;
-			if (decode_vps(p, p) != 0)
-				err = 1;
-			break;
-		default:
-			id2 = 0;
+	/*
+	 * Check for the ancillary data header for sliced VBI
+	 */
+	if (anc->preamble[0] ||
+			anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
+			(anc->did != sliced_vbi_did[0] &&
+			 anc->did != sliced_vbi_did[1])) {
+		vbi->line = vbi->type = 0;
+		return 0;
+	}
+
+	did = anc->did;
+	sdid = anc->sdid & 0xf;
+	l = anc->idid[0] & 0x3f;
+	l += state->slicer_line_offset;
+	p = anc->payload;
+
+	/* Decode the SDID set by the slicer */
+	switch (sdid) {
+	case 1:
+		sdid = V4L2_SLICED_TELETEXT_B;
+		break;
+	case 4:
+		sdid = V4L2_SLICED_WSS_625;
+		break;
+	case 6:
+		sdid = V4L2_SLICED_CAPTION_525;
+		err = !odd_parity(p[0]) || !odd_parity(p[1]);
+		break;
+	case 9:
+		sdid = V4L2_SLICED_VPS;
+		if (decode_vps(p, p) != 0)
 			err = 1;
-			break;
-		}
-
-		vbi->type = err ? 0 : id2;
-		vbi->line = err ? 0 : l;
-		vbi->is_second_field = err ? 0 : (id1 == 0x55);
-		vbi->p = p;
+		break;
+	default:
+		sdid = 0;
+		err = 1;
 		break;
 	}
-	}
 
+	vbi->type = err ? 0 : sdid;
+	vbi->line = err ? 0 : l;
+	vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
+	vbi->p = p;
 	return 0;
 }
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index e274043..9bc2218 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -51,12 +51,12 @@
 static const struct cx18_card cx18_card_hvr1600_esmt = {
 	.type = CX18_CARD_HVR_1600_ESMT,
 	.name = "Hauppauge HVR-1600",
-	.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
+	.hw_audio_ctrl = CX18_HW_418_AV,
 	.hw_muxer = CX18_HW_CS5345,
-	.hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
-		  CX18_HW_CS5345 | CX18_HW_DVB,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
@@ -97,12 +97,12 @@
 static const struct cx18_card cx18_card_hvr1600_samsung = {
 	.type = CX18_CARD_HVR_1600_SAMSUNG,
 	.name = "Hauppauge HVR-1600 (Preproduction)",
-	.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
+	.hw_audio_ctrl = CX18_HW_418_AV,
 	.hw_muxer = CX18_HW_CS5345,
-	.hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
-		  CX18_HW_CS5345 | CX18_HW_DVB,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
@@ -152,10 +152,10 @@
 static const struct cx18_card cx18_card_h900 = {
 	.type = CX18_CARD_COMPRO_H900,
 	.name = "Compro VideoMate H900",
-	.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
+	.comment = "Analog TV capture supported\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
-	.hw_all = CX18_HW_TUNER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
@@ -201,8 +201,8 @@
 	.name = "Yuan MPC718",
 	.comment = "Analog video capture works; some audio line in may not.\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
-	.hw_all = CX18_HW_TUNER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
@@ -249,11 +249,11 @@
 static const struct cx18_card cx18_card_cnxt_raptor_pal = {
 	.type = CX18_CARD_CNXT_RAPTOR_PAL,
 	.name = "Conexant Raptor PAL/SECAM",
-	.comment = "Raw VBI supported; Sliced VBI is not yet supported\n",
+	.comment = "Analog TV capture supported\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
-	.hw_muxer = CX18_HW_GPIO,
-	.hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
@@ -306,8 +306,8 @@
 	.comment = "Experimenters and photos needed for device to work well.\n"
 		  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
-	.hw_all = CX18_HW_TUNER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE6 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
@@ -339,19 +339,21 @@
 /* Leadtek WinFast PVR2100 */
 
 static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
-	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 },
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100   */
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
 	{ 0, 0, 0 }
 };
 
 static const struct cx18_card cx18_card_leadtek_pvr2100 = {
 	.type = CX18_CARD_LEADTEK_PVR2100,
-	.name = "Leadtek WinFast PVR2100",
+	.name = "Leadtek WinFast PVR2100/DVR3100 H",
 	.comment = "Experimenters and photos needed for device to work well.\n"
 		  "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
 	.v4l2_capabilities = CX18_CAP_ENCODER,
-	.hw_audio_ctrl = CX18_HW_CX23418,
-	.hw_muxer = CX18_HW_GPIO,
-	.hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+		  CX18_HW_GPIO_RESET_CTRL,
 	.video_inputs = {
 		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
 		{ CX18_CARD_INPUT_SVIDEO1,    1,
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index 6fa7bcb..3c552b6 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -22,12 +22,13 @@
  */
 
 /* hardware flags */
-#define CX18_HW_TUNER     (1 << 0)
-#define CX18_HW_TVEEPROM  (1 << 1)
-#define CX18_HW_CS5345    (1 << 2)
-#define CX18_HW_GPIO      (1 << 3)
-#define CX18_HW_CX23418   (1 << 4)
-#define CX18_HW_DVB   	  (1 << 5)
+#define CX18_HW_TUNER		(1 << 0)
+#define CX18_HW_TVEEPROM	(1 << 1)
+#define CX18_HW_CS5345		(1 << 2)
+#define CX18_HW_DVB		(1 << 3)
+#define CX18_HW_418_AV		(1 << 4)
+#define CX18_HW_GPIO_MUX	(1 << 5)
+#define CX18_HW_GPIO_RESET_CTRL	(1 << 6)
 
 /* video inputs */
 #define	CX18_CARD_INPUT_VID_TUNER	1
@@ -49,8 +50,7 @@
 /* V4L2 capability aliases */
 #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
 			  V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
-			  V4L2_CAP_VBI_CAPTURE)
-/* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */
+			  V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
 
 struct cx18_card_video_input {
 	u8  video_type; 	/* video input type */
@@ -122,7 +122,7 @@
 	char *comment;
 	u32 v4l2_capabilities;
 	u32 hw_audio_ctrl;	/* hardware used for the V4L2 controls (only
-				   1 dev allowed) */
+				   1 dev allowed currently) */
 	u32 hw_muxer;		/* hardware used to multiplex audio input */
 	u32 hw_all;		/* all hardware used by the board */
 	struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 17edf30..82fc2f9 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -22,14 +22,13 @@
  */
 
 #include "cx18-driver.h"
-#include "cx18-av-core.h"
 #include "cx18-cards.h"
 #include "cx18-ioctl.h"
 #include "cx18-audio.h"
-#include "cx18-i2c.h"
 #include "cx18-mailbox.h"
 #include "cx18-controls.h"
 
+/* Must be sorted from low to high control ID! */
 static const u32 user_ctrls[] = {
 	V4L2_CID_USER_CLASS,
 	V4L2_CID_BRIGHTNESS,
@@ -66,7 +65,7 @@
 	case V4L2_CID_HUE:
 	case V4L2_CID_SATURATION:
 	case V4L2_CID_CONTRAST:
-		if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl))
+		if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl))
 			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
 		return 0;
 
@@ -76,7 +75,7 @@
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_LOUDNESS:
-		if (cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl))
+		if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl))
 			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
 		return 0;
 
@@ -125,7 +124,7 @@
 	case V4L2_CID_HUE:
 	case V4L2_CID_SATURATION:
 	case V4L2_CID_CONTRAST:
-		return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl);
+		return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl);
 
 	case V4L2_CID_AUDIO_VOLUME:
 	case V4L2_CID_AUDIO_MUTE:
@@ -133,7 +132,7 @@
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_LOUDNESS:
-		return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
+		return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl);
 
 	default:
 		CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
@@ -150,7 +149,7 @@
 	case V4L2_CID_HUE:
 	case V4L2_CID_SATURATION:
 	case V4L2_CID_CONTRAST:
-		return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl);
+		return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl);
 
 	case V4L2_CID_AUDIO_VOLUME:
 	case V4L2_CID_AUDIO_MUTE:
@@ -158,7 +157,8 @@
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_LOUDNESS:
-		return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
+		return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl);
+
 	default:
 		CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
 		return -EINVAL;
@@ -166,38 +166,57 @@
 	return 0;
 }
 
-static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt)
+static int cx18_setup_vbi_fmt(struct cx18 *cx,
+			      enum v4l2_mpeg_stream_vbi_fmt fmt,
+			      enum v4l2_mpeg_stream_type type)
 {
 	if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
 		return -EINVAL;
 	if (atomic_read(&cx->ana_capturing) > 0)
 		return -EBUSY;
 
-	/* First try to allocate sliced VBI buffers if needed. */
-	if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) {
+	if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
+	    type != V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
+		/* We don't do VBI insertion aside from IVTV format in a PS */
+		cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
+		CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
+				"the MPEG stream\n");
+		return 0;
+	}
+
+	/* Allocate sliced VBI buffers if needed. */
+	if (cx->vbi.sliced_mpeg_data[0] == NULL) {
 		int i;
 
 		for (i = 0; i < CX18_VBI_FRAMES; i++) {
-			/* Yuck, hardcoded. Needs to be a define */
-			cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
+			cx->vbi.sliced_mpeg_data[i] =
+			       kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL);
 			if (cx->vbi.sliced_mpeg_data[i] == NULL) {
 				while (--i >= 0) {
 					kfree(cx->vbi.sliced_mpeg_data[i]);
 					cx->vbi.sliced_mpeg_data[i] = NULL;
 				}
+				cx->vbi.insert_mpeg =
+						  V4L2_MPEG_STREAM_VBI_FMT_NONE;
+				CX18_WARN("Unable to allocate buffers for "
+					  "sliced VBI data insertion\n");
 				return -ENOMEM;
 			}
 		}
 	}
 
 	cx->vbi.insert_mpeg = fmt;
+	CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,"
+			"when sliced VBI is enabled\n");
 
-	if (cx->vbi.insert_mpeg == 0)
-		return 0;
-	/* Need sliced data for mpeg insertion */
+	/*
+	 * If our current settings have no lines set for capture, store a valid,
+	 * default set of service lines to capture, in our current settings.
+	 */
 	if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
 		if (cx->is_60hz)
-			cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
+			cx->vbi.sliced_in->service_set =
+							V4L2_SLICED_CAPTION_525;
 		else
 			cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
 		cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
@@ -259,10 +278,12 @@
 		return err;
 	}
 	if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+		static u32 freqs[3] = { 44100, 48000, 32000 };
 		struct cx18_api_func_private priv;
 		struct cx2341x_mpeg_params p = cx->params;
 		int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing),
 						c, VIDIOC_S_EXT_CTRLS);
+		unsigned int idx;
 
 		if (err)
 			return err;
@@ -277,16 +298,23 @@
 			fmt.fmt.pix.width = cx->params.width
 						/ (is_mpeg1 ? 2 : 1);
 			fmt.fmt.pix.height = cx->params.height;
-			cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
+			v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
 		}
 		priv.cx = cx;
 		priv.s = &cx->streams[id->type];
 		err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p);
-		if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
-			err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
+		if (!err &&
+		    (cx->params.stream_vbi_fmt != p.stream_vbi_fmt ||
+		     cx->params.stream_type != p.stream_type))
+			err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt,
+						 p.stream_type);
 		cx->params = p;
 		cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
-		cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
+		idx = p.audio_properties & 0x03;
+		/* The audio clock of the digitizer must match the codec sample
+		   rate otherwise you get some very strange effects. */
+		if (idx < sizeof(freqs))
+			cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
 		return err;
 	}
 	return -EINVAL;
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index f50cf21..210c68a 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -39,10 +39,6 @@
 
 #include <media/tveeprom.h>
 
-
-/* var to keep track of the number of array elements in use */
-int cx18_cards_active;
-
 /* If you have already X v4l cards, then set this to X. This way
    the device numbers stay matched. Example: you have a WinTV card
    without radio and a Compro H900 with. Normally this would give a
@@ -50,12 +46,6 @@
    setting this to 1 you ensure that radio0 is now also radio1. */
 int cx18_first_minor;
 
-/* Master variable for all cx18 info */
-struct cx18 *cx18_cards[CX18_MAX_CARDS];
-
-/* Protects cx18_cards_active */
-DEFINE_SPINLOCK(cx18_cards_lock);
-
 /* add your revision and whatnot here */
 static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
 	{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
@@ -65,6 +55,8 @@
 
 MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
 
+static atomic_t cx18_instance = ATOMIC_INIT(0);
+
 /* Parameter declarations */
 static int cardtype[CX18_MAX_CARDS];
 static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
@@ -159,7 +151,7 @@
 		 "\t\t\t 4 = Yuan MPC718\n"
 		 "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
 		 "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
-		 "\t\t\t 7 = Leadtek WinFast PVR2100\n"
+		 "\t\t\t 7 = Leadtek WinFast PVR2100/DVR3100 H\n"
 		 "\t\t\t 0 = Autodetect (default)\n"
 		 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -277,11 +269,16 @@
 /* Hauppauge card? get values from tveeprom */
 void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
 {
+	struct i2c_client c;
 	u8 eedata[256];
 
-	cx->i2c_client[0].addr = 0xA0 >> 1;
-	tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata));
-	tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata);
+	memset(&c, 0, sizeof(c));
+	strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name));
+	c.adapter = &cx->i2c_adap[0];
+	c.addr = 0xA0 >> 1;
+
+	tveeprom_read(&c, eedata, sizeof(eedata));
+	tveeprom_hauppauge_analog(&c, tv, eedata);
 }
 
 static void cx18_process_eeprom(struct cx18 *cx)
@@ -448,34 +445,38 @@
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize;
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize;
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize;
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36;
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize;
 	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */
 
-	/* Except for VBI ensure stream_buffers & stream_buf_size are valid */
+	/* Ensure stream_buffers & stream_buf_size are valid */
 	for (i = 0; i < CX18_MAX_STREAMS; i++) {
-		/* User said to use 0 buffers */
-		if (cx->stream_buffers[i] == 0) {
-			cx->options.megabytes[i] = 0;
-			cx->stream_buf_size[i] = 0;
-			continue;
-		}
-		/* User said to use 0 MB total */
-		if (cx->options.megabytes[i] <= 0) {
+		if (cx->stream_buffers[i] == 0 ||     /* User said 0 buffers */
+		    cx->options.megabytes[i] <= 0 ||  /* User said 0 MB total */
+		    cx->stream_buf_size[i] <= 0) {    /* User said buf size 0 */
 			cx->options.megabytes[i] = 0;
 			cx->stream_buffers[i] = 0;
 			cx->stream_buf_size[i] = 0;
 			continue;
 		}
-		/* VBI is computed later or user said buffer has size 0 */
-		if (cx->stream_buf_size[i] <= 0) {
-			if (i != CX18_ENC_STREAM_TYPE_VBI) {
-				cx->options.megabytes[i] = 0;
-				cx->stream_buffers[i] = 0;
-				cx->stream_buf_size[i] = 0;
+		/*
+		 * VBI is a special case where the stream_buf_size is fixed
+		 * and already in bytes
+		 */
+		if (i == CX18_ENC_STREAM_TYPE_VBI) {
+			if (cx->stream_buffers[i] < 0) {
+				cx->stream_buffers[i] =
+					cx->options.megabytes[i] * 1024 * 1024
+					/ cx->stream_buf_size[i];
+			} else {
+				/* N.B. This might round down to 0 */
+				cx->options.megabytes[i] =
+					cx->stream_buffers[i]
+					* cx->stream_buf_size[i]/(1024 * 1024);
 			}
 			continue;
 		}
+		/* All other streams have stream_buf_size in kB at this point */
 		if (cx->stream_buffers[i] < 0) {
 			cx->stream_buffers[i] = cx->options.megabytes[i] * 1024
 						/ cx->stream_buf_size[i];
@@ -487,9 +488,9 @@
 		cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */
 	}
 
-	cx->options.cardtype = cardtype[cx->num];
-	cx->options.tuner = tuner[cx->num];
-	cx->options.radio = radio[cx->num];
+	cx->options.cardtype = cardtype[cx->instance];
+	cx->options.tuner = tuner[cx->instance];
+	cx->options.radio = radio[cx->instance];
 
 	cx->std = cx18_parse_std(cx);
 	if (cx->options.cardtype == -1) {
@@ -502,7 +503,7 @@
 	else if (cx->options.cardtype != 0)
 		CX18_ERR("Unknown user specified type, trying to autodetect card\n");
 	if (cx->card == NULL) {
-		if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
+		if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
 			cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 			CX18_INFO("Autodetected Hauppauge card\n");
 		}
@@ -512,13 +513,13 @@
 			if (cx->card->pci_list == NULL)
 				continue;
 			for (j = 0; cx->card->pci_list[j].device; j++) {
-				if (cx->dev->device !=
+				if (cx->pci_dev->device !=
 				    cx->card->pci_list[j].device)
 					continue;
-				if (cx->dev->subsystem_vendor !=
+				if (cx->pci_dev->subsystem_vendor !=
 				    cx->card->pci_list[j].subsystem_vendor)
 					continue;
-				if (cx->dev->subsystem_device !=
+				if (cx->pci_dev->subsystem_device !=
 				    cx->card->pci_list[j].subsystem_device)
 					continue;
 				CX18_INFO("Autodetected %s card\n", cx->card->name);
@@ -531,9 +532,10 @@
 	if (cx->card == NULL) {
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
-		     cx->dev->vendor, cx->dev->device);
+			 cx->pci_dev->vendor, cx->pci_dev->device);
 		CX18_ERR("              subsystem vendor/device: [%04x:%04x]\n",
-		     cx->dev->subsystem_vendor, cx->dev->subsystem_device);
+			 cx->pci_dev->subsystem_vendor,
+			 cx->pci_dev->subsystem_device);
 		CX18_ERR("Defaulting to %s card\n", cx->card->name);
 		CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
 		CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
@@ -545,7 +547,7 @@
 }
 
 /* Precondition: the cx18 structure has been memset to 0. Only
-   the dev and num fields have been filled in.
+   the dev and instance fields have been filled in.
    No assumptions on the card type may be made here (see cx18_init_struct2
    for that).
  */
@@ -553,18 +555,14 @@
 {
 	int i;
 
-	cx->base_addr = pci_resource_start(cx->dev, 0);
+	cx->base_addr = pci_resource_start(cx->pci_dev, 0);
 
 	mutex_init(&cx->serialize_lock);
-	mutex_init(&cx->i2c_bus_lock[0]);
-	mutex_init(&cx->i2c_bus_lock[1]);
 	mutex_init(&cx->gpio_lock);
 	mutex_init(&cx->epu2apu_mb_lock);
 	mutex_init(&cx->epu2cpu_mb_lock);
 
-	spin_lock_init(&cx->lock);
-
-	cx->work_queue = create_singlethread_workqueue(cx->name);
+	cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
 	if (cx->work_queue == NULL) {
 		CX18_ERR("Unable to create work hander thread\n");
 		return -ENOMEM;
@@ -587,7 +585,8 @@
 		(cx->params.video_temporal_filter_mode << 1) |
 		(cx->params.video_median_filter_type << 2);
 	cx->params.port = CX2341X_PORT_MEMORY;
-	cx->params.capabilities = CX2341X_CAP_HAS_TS;
+	cx->params.capabilities =
+				CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
 	init_waitqueue_head(&cx->cap_w);
 	init_waitqueue_head(&cx->mb_apu_waitq);
 	init_waitqueue_head(&cx->mb_cpu_waitq);
@@ -597,49 +596,6 @@
 	cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
 	cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
 
-	/*
-	 * The VBI line sizes depend on the pixel clock and the horiz rate
-	 *
-	 * (1/Fh)*(2*Fp) = Samples/line
-	 *     = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
-	 *
-	 *  Sliced VBI is sent as ancillary data during horizontal blanking
-	 *  Raw VBI is sent as active video samples during vertcal blanking
-	 *
-	 *  We use a  BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
-	 *  length of 720 pixels @ 4:2:2 sampling.  Thus...
-	 *
-	 *  For systems that use a 15.734 kHz horizontal rate, such as
-	 *  NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
-	 *
-	 *  (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
-	 *  4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
-	 *
-	 *  For systems that use a 15.625 kHz horizontal rate, such as
-	 *  PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
-	 *
-	 *  (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
-	 *  4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
-	 *
-	 */
-
-	/* FIXME: init these based on tuner std & modify when std changes */
-	/* CX18-AV-Core number of VBI samples output per horizontal line */
-	cx->vbi.raw_decoder_line_size = 1444;   /* 4 byte SAV + 2 * 720 */
-	cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */
-
-	/* CX18-AV-Core VBI samples/line possibly rounded up */
-	cx->vbi.raw_size = 1444;   /* Real max size is 1444 */
-	cx->vbi.sliced_size = 284; /* Real max size is  284 */
-
-	/*
-	 * CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode
-	 * Task Field VerticalBlank HorizontalBlank 0 0 0 0
-	 */
-	cx->vbi.raw_decoder_sav_odd_field = 0x20;     /*   V  */
-	cx->vbi.raw_decoder_sav_even_field = 0x60;    /*  FV  */
-	cx->vbi.sliced_decoder_sav_odd_field = 0xB0;  /* T VH - actually EAV */
-	cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */
 	return 0;
 }
 
@@ -668,15 +624,9 @@
 		i = 0;
 	cx->active_input = i;
 	cx->audio_input = cx->card->video_inputs[i].audio_index;
-	cx->av_state.vid_input = CX18_AV_COMPOSITE7;
-	cx->av_state.aud_input = CX18_AV_AUDIO8;
-	cx->av_state.audclk_freq = 48000;
-	cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
-	/* FIXME - 8 is NTSC value, investigate */
-	cx->av_state.vbi_line_offset = 8;
 }
 
-static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
+static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
 			  const struct pci_device_id *pci_id)
 {
 	u16 cmd;
@@ -684,124 +634,125 @@
 
 	CX18_DEBUG_INFO("Enabling pci device\n");
 
-	if (pci_enable_device(dev)) {
-		CX18_ERR("Can't enable device %d!\n", cx->num);
+	if (pci_enable_device(pci_dev)) {
+		CX18_ERR("Can't enable device %d!\n", cx->instance);
 		return -EIO;
 	}
-	if (pci_set_dma_mask(dev, 0xffffffff)) {
-		CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
+	if (pci_set_dma_mask(pci_dev, 0xffffffff)) {
+		CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
 		return -EIO;
 	}
 	if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
-		CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
+		CX18_ERR("Cannot request encoder memory region, card %d\n",
+			 cx->instance);
 		return -EIO;
 	}
 
 	/* Enable bus mastering and memory mapped IO for the CX23418 */
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
 	cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-	pci_write_config_word(dev, PCI_COMMAND, cmd);
+	pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
 
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &cx->card_rev);
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
 
 	if (pci_latency < 64 && cx18_pci_latency) {
 		CX18_INFO("Unreasonably low latency timer, "
 			       "setting to 64 (was %d)\n", pci_latency);
-		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-		pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64);
+		pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
 	}
 
 	CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
 		   "irq: %d, latency: %d, memory: 0x%lx\n",
-		   cx->dev->device, cx->card_rev, dev->bus->number,
-		   PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
-		   cx->dev->irq, pci_latency, (unsigned long)cx->base_addr);
+		   cx->pci_dev->device, cx->card_rev, pci_dev->bus->number,
+		   PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn),
+		   cx->pci_dev->irq, pci_latency, (unsigned long)cx->base_addr);
 
 	return 0;
 }
 
-#ifdef MODULE
-static u32 cx18_request_module(struct cx18 *cx, u32 hw,
-		const char *name, u32 id)
-{
-	if ((hw & id) == 0)
-		return hw;
-	if (request_module(name) != 0) {
-		CX18_ERR("Failed to load module %s\n", name);
-		return hw & ~id;
-	}
-	CX18_DEBUG_INFO("Loaded module %s\n", name);
-	return hw;
-}
-#endif
-
-static void cx18_load_and_init_modules(struct cx18 *cx)
+static void cx18_init_subdevs(struct cx18 *cx)
 {
 	u32 hw = cx->card->hw_all;
+	u32 device;
 	int i;
 
-#ifdef MODULE
-	/* load modules */
-#ifdef CONFIG_MEDIA_TUNER_MODULE
-	hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
-#endif
-#ifdef CONFIG_VIDEO_CS5345_MODULE
-	hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
-#endif
-#endif
-
-	/* check which i2c devices are actually found */
-	for (i = 0; i < 32; i++) {
-		u32 device = 1 << i;
+	for (i = 0, device = 1; i < 32; i++, device <<= 1) {
 
 		if (!(device & hw))
 			continue;
-		if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM ||
-		    device == CX18_HW_CX23418 || device == CX18_HW_DVB) {
-			/* These 'devices' do not use i2c probing */
+
+		switch (device) {
+		case CX18_HW_DVB:
+		case CX18_HW_TVEEPROM:
+			/* These subordinate devices do not use probing */
 			cx->hw_flags |= device;
-			continue;
+			break;
+		case CX18_HW_418_AV:
+			/* The A/V decoder gets probed earlier to set PLLs */
+			/* Just note that the card uses it (i.e. has analog) */
+			cx->hw_flags |= device;
+			break;
+		case CX18_HW_GPIO_RESET_CTRL:
+			/*
+			 * The Reset Controller gets probed and added to
+			 * hw_flags earlier for i2c adapter/bus initialization
+			 */
+			break;
+		case CX18_HW_GPIO_MUX:
+			if (cx18_gpio_register(cx, device) == 0)
+				cx->hw_flags |= device;
+			break;
+		default:
+			if (cx18_i2c_register(cx, i) == 0)
+				cx->hw_flags |= device;
+			break;
 		}
-		cx18_i2c_register(cx, i);
-		if (cx18_i2c_hw_addr(cx, device) > 0)
-			cx->hw_flags |= device;
 	}
 
-	hw = cx->hw_flags;
+	if (cx->hw_flags & CX18_HW_418_AV)
+		cx->sd_av = cx18_find_hw(cx, CX18_HW_418_AV);
+
+	if (cx->card->hw_muxer != 0)
+		cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer);
 }
 
-static int __devinit cx18_probe(struct pci_dev *dev,
+static int __devinit cx18_probe(struct pci_dev *pci_dev,
 				const struct pci_device_id *pci_id)
 {
 	int retval = 0;
 	int i;
-	int vbi_buf_size;
 	u32 devtype;
 	struct cx18 *cx;
 
-	spin_lock(&cx18_cards_lock);
-
-	/* Make sure we've got a place for this card */
-	if (cx18_cards_active == CX18_MAX_CARDS) {
-		printk(KERN_ERR "cx18:  Maximum number of cards detected (%d).\n",
-			      cx18_cards_active);
-		spin_unlock(&cx18_cards_lock);
+	/* FIXME - module parameter arrays constrain max instances */
+	i = atomic_inc_return(&cx18_instance) - 1;
+	if (i >= CX18_MAX_CARDS) {
+		printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
+		       "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
 		return -ENOMEM;
 	}
 
 	cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-	if (!cx) {
-		spin_unlock(&cx18_cards_lock);
+	if (cx == NULL) {
+		printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
+		       i);
 		return -ENOMEM;
 	}
-	cx18_cards[cx18_cards_active] = cx;
-	cx->dev = dev;
-	cx->num = cx18_cards_active++;
-	snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
-	CX18_INFO("Initializing card #%d\n", cx->num);
+	cx->pci_dev = pci_dev;
+	cx->instance = i;
 
-	spin_unlock(&cx18_cards_lock);
+	retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
+	if (retval) {
+		printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
+		       "\n", cx->instance);
+		kfree(cx);
+		return retval;
+	}
+	snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
+		 cx->instance);
+	CX18_INFO("Initializing card %d\n", cx->instance);
 
 	cx18_process_options(cx);
 	if (cx->options.cardtype == -1) {
@@ -816,13 +767,10 @@
 	CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
 
 	/* PCI Device Setup */
-	retval = cx18_setup_pci(cx, dev, pci_id);
+	retval = cx18_setup_pci(cx, pci_dev, pci_id);
 	if (retval != 0)
 		goto free_workqueue;
 
-	/* save cx in the pci struct for later use */
-	pci_set_drvdata(dev, cx);
-
 	/* map io memory */
 	CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
 		   cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
@@ -856,6 +804,23 @@
 
 	cx18_gpio_init(cx);
 
+	/* Initialize integrated A/V decoder early to set PLLs, just in case */
+	retval = cx18_av_probe(cx);
+	if (retval) {
+		CX18_ERR("Could not register A/V decoder subdevice\n");
+		goto free_map;
+	}
+	cx18_call_hw(cx, CX18_HW_418_AV, core, init, (u32) CX18_AV_INIT_PLLS);
+
+	/* Initialize GPIO Reset Controller to do chip resets during i2c init */
+	if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
+		if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0)
+			CX18_WARN("Could not register GPIO reset controller"
+				  "subdevice; proceeding anyway.\n");
+		else
+			cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL;
+	}
+
 	/* active i2c  */
 	CX18_DEBUG_INFO("activating i2c...\n");
 	retval = init_cx18_i2c(cx);
@@ -864,8 +829,6 @@
 		goto free_map;
 	}
 
-	CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
-
 	if (cx->card->hw_all & CX18_HW_TVEEPROM) {
 		/* Based on the model number the cardtype may be changed.
 		   The PCI IDs are not always reliable. */
@@ -881,8 +844,9 @@
 	cx18_init_scb(cx);
 
 	/* Register IRQ */
-	retval = request_irq(cx->dev->irq, cx18_irq_handler,
-			     IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
+	retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
+			     IRQF_SHARED | IRQF_DISABLED,
+			     cx->v4l2_dev.name, (void *)cx);
 	if (retval) {
 		CX18_ERR("Failed to register irq %d\n", retval);
 		goto free_i2c;
@@ -917,33 +881,14 @@
 	   initialization. */
 	cx18_init_struct2(cx);
 
-	cx18_load_and_init_modules(cx);
+	cx18_init_subdevs(cx);
 
-	if (cx->std & V4L2_STD_525_60) {
+	if (cx->std & V4L2_STD_525_60)
 		cx->is_60hz = 1;
-		cx->is_out_60hz = 1;
-	} else {
-		cx->is_50hz = 1;
-		cx->is_out_50hz = 1;
-	}
-	cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
-
-	/*
-	 * FIXME: setting the buffer size based on the tuner standard is
-	 * suboptimal, as the CVBS and SVideo inputs could use a different std
-	 * and the buffer could end up being too small in that case.
-	 */
-	vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
-	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
-
-	if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0)
-		cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] =
-		   cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024
-		   / vbi_buf_size;
 	else
-		cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] =
-		     cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size
-		     / (1024 * 1024);
+		cx->is_50hz = 1;
+
+	cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
 
 	if (cx->options.radio > 0)
 		cx->v4l2_cap |= V4L2_CAP_RADIO;
@@ -956,7 +901,7 @@
 		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
 		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
 			cx18_reset_tuner_gpio : NULL;
-		cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup);
+		cx18_call_all(cx, tuner, s_type_addr, &setup);
 		if (setup.type == TUNER_XC2028) {
 			static struct xc2028_ctrl ctrl = {
 				.fname = XC2028_DEFAULT_FIRMWARE,
@@ -966,7 +911,7 @@
 				.tuner = cx->options.tuner,
 				.priv = &ctrl,
 			};
-			cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg);
+			cx18_call_all(cx, tuner, s_config, &cfg);
 		}
 	}
 
@@ -985,14 +930,13 @@
 		goto free_streams;
 	}
 
-	CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
-
+	CX18_INFO("Initialized card: %s\n", cx->card_name);
 	return 0;
 
 free_streams:
 	cx18_streams_cleanup(cx, 1);
 free_irq:
-	free_irq(cx->dev->irq, (void *)cx);
+	free_irq(cx->pci_dev->irq, (void *)cx);
 free_i2c:
 	exit_cx18_i2c(cx);
 free_map:
@@ -1006,11 +950,8 @@
 		retval = -ENODEV;
 	CX18_ERR("Error %d on initialization\n", retval);
 
-	i = cx->num;
-	spin_lock(&cx18_cards_lock);
-	kfree(cx18_cards[i]);
-	cx18_cards[i] = NULL;
-	spin_unlock(&cx18_cards_lock);
+	v4l2_device_unregister(&cx->v4l2_dev);
+	kfree(cx);
 	return retval;
 }
 
@@ -1043,8 +984,21 @@
 	}
 	set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
 
-	/* Init the firmware twice to work around a silicon bug
-	 * transport related. */
+	/*
+	 * Init the firmware twice to work around a silicon bug
+	 * with the digital TS.
+	 *
+	 * The second firmware load requires us to normalize the APU state,
+	 * or the audio for the first analog capture will be badly incorrect.
+	 *
+	 * I can't seem to call APU_RESETAI and have it succeed without the
+	 * APU capturing audio, so we start and stop it here to do the reset
+	 */
+
+	/* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
+	cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
+	cx18_vapi(cx, CX18_APU_RESETAI, 0);
+	cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
 
 	fw_retry_count = 3;
 	while (--fw_retry_count > 0) {
@@ -1060,6 +1014,22 @@
 		return -ENXIO;
 	}
 
+	/*
+	 * The second firmware load requires us to normalize the APU state,
+	 * or the audio for the first analog capture will be badly incorrect.
+	 *
+	 * I can't seem to call APU_RESETAI and have it succeed without the
+	 * APU capturing audio, so we start and stop it here to do the reset
+	 */
+
+	/* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
+	cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
+	cx18_vapi(cx, CX18_APU_RESETAI, 0);
+	cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
+
+	/* Init the A/V decoder, if it hasn't been already */
+	v4l2_subdev_call(cx->sd_av, core, init, (u32) CX18_AV_INIT_NORMAL);
+
 	vf.tuner = 0;
 	vf.type = V4L2_TUNER_ANALOG_TV;
 	vf.frequency = 6400; /* the tuner 'baseline' frequency */
@@ -1092,9 +1062,11 @@
 
 static void cx18_remove(struct pci_dev *pci_dev)
 {
-	struct cx18 *cx = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx18 *cx = to_cx18(v4l2_dev);
+	int i;
 
-	CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+	CX18_DEBUG_INFO("Removing Card\n");
 
 	/* Stop all captures */
 	CX18_DEBUG_INFO("Stopping all streams\n");
@@ -1115,15 +1087,22 @@
 
 	exit_cx18_i2c(cx);
 
-	free_irq(cx->dev->irq, (void *)cx);
+	free_irq(cx->pci_dev->irq, (void *)cx);
 
 	cx18_iounmap(cx);
 
 	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
 
-	pci_disable_device(cx->dev);
+	pci_disable_device(cx->pci_dev);
 
-	CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+	if (cx->vbi.sliced_mpeg_data[0] != NULL)
+		for (i = 0; i < CX18_VBI_FRAMES; i++)
+			kfree(cx->vbi.sliced_mpeg_data[i]);
+
+	CX18_INFO("Removed %s\n", cx->card_name);
+
+	v4l2_device_unregister(v4l2_dev);
+	kfree(cx);
 }
 
 /* define a pci_driver for card detection */
@@ -1138,8 +1117,6 @@
 {
 	printk(KERN_INFO "cx18:  Start initialization, version %s\n", CX18_VERSION);
 
-	memset(cx18_cards, 0, sizeof(cx18_cards));
-
 	/* Validate parameters */
 	if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
 		printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
@@ -1162,16 +1139,7 @@
 
 static void module_cleanup(void)
 {
-	int i;
-
 	pci_unregister_driver(&cx18_pci_driver);
-
-	for (i = 0; i < cx18_cards_active; i++) {
-		if (cx18_cards[i] == NULL)
-			continue;
-		kfree(cx18_cards[i]);
-	}
-
 }
 
 module_init(module_start);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 0d2edeb..ece4f28 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -48,6 +48,7 @@
 #include <linux/dvb/audio.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
 #include <media/tuner.h>
 #include "cx18-mailbox.h"
 #include "cx18-av-core.h"
@@ -79,7 +80,7 @@
 #define CX18_CARD_YUAN_MPC718 	      3	/* Yuan MPC718 */
 #define CX18_CARD_CNXT_RAPTOR_PAL     4	/* Conexant Raptor PAL */
 #define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
-#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100/DVR3100 H */
 #define CX18_CARD_LAST 		      6
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
@@ -143,12 +144,12 @@
 /* Flag to turn on high volume debugging */
 #define CX18_DBGFLG_HIGHVOL (1 << 8)
 
-/* NOTE: extra space before comma in 'cx->num , ## args' is required for
+/* NOTE: extra space before comma in 'fmt , ## args' is required for
    gcc-2.95, otherwise it won't compile. */
 #define CX18_DEBUG(x, type, fmt, args...) \
 	do { \
 		if ((x) & cx18_debug) \
-			printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
+			v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
 	} while (0)
 #define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
@@ -162,7 +163,7 @@
 #define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
 	do { \
 		if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
-			printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
+			v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
 	} while (0)
 #define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
 #define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
@@ -174,9 +175,58 @@
 #define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
 
 /* Standard kernel messages */
-#define CX18_ERR(fmt, args...)      printk(KERN_ERR  "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_WARN(fmt, args...)     printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
-#define CX18_INFO(fmt, args...)     printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_ERR(fmt, args...)      v4l2_err(&cx->v4l2_dev, fmt , ## args)
+#define CX18_WARN(fmt, args...)     v4l2_warn(&cx->v4l2_dev, fmt , ## args)
+#define CX18_INFO(fmt, args...)     v4l2_info(&cx->v4l2_dev, fmt , ## args)
+
+/* Messages for internal subdevs to use */
+#define CX18_DEBUG_DEV(x, dev, type, fmt, args...) \
+	do { \
+		if ((x) & cx18_debug) \
+			v4l2_info(dev, " " type ": " fmt , ## args); \
+	} while (0)
+#define CX18_DEBUG_WARN_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
+#define CX18_DEBUG_INFO_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
+#define CX18_DEBUG_API_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
+#define CX18_DEBUG_DMA_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
+#define CX18_DEBUG_I2C_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ_DEV(dev, fmt, args...) \
+		CX18_DEBUG_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL_DEV(x, dev, type, fmt, args...) \
+	do { \
+		if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+			v4l2_info(dev, " " type ": " fmt , ## args); \
+	} while (0)
+#define CX18_DEBUG_HI_WARN_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
+#define CX18_DEBUG_HI_INFO_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
+#define CX18_DEBUG_HI_API_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
+#define CX18_DEBUG_HI_IRQ_DEV(dev, fmt, args...) \
+	CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
+
+#define CX18_ERR_DEV(dev, fmt, args...)      v4l2_err(dev, fmt , ## args)
+#define CX18_WARN_DEV(dev, fmt, args...)     v4l2_warn(dev, fmt , ## args)
+#define CX18_INFO_DEV(dev, fmt, args...)     v4l2_info(dev, fmt , ## args)
 
 /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
 #define MPEG_FRAME_TYPE_IFRAME 1
@@ -279,7 +329,7 @@
 struct cx18_stream {
 	/* These first four fields are always set, even if the stream
 	   is not actually created. */
-	struct video_device *v4l2dev;	/* NULL when stream not created */
+	struct video_device *video_dev;	/* NULL when stream not created */
 	struct cx18 *cx; 		/* for ease of use */
 	const char *name;		/* name of the stream */
 	int type;			/* stream type */
@@ -292,7 +342,6 @@
 	int dma;		/* can be PCI_DMA_TODEVICE,
 				   PCI_DMA_FROMDEVICE or
 				   PCI_DMA_NONE */
-	u64 dma_pts;
 	wait_queue_head_t waitq;
 
 	/* Buffer Stats */
@@ -318,59 +367,121 @@
 /* forward declaration of struct defined in cx18-cards.h */
 struct cx18_card;
 
+/*
+ * A note about "sliced" VBI data as implemented in this driver:
+ *
+ * Currently we collect the sliced VBI in the form of Ancillary Data
+ * packets, inserted by the AV core decoder/digitizer/slicer in the
+ * horizontal blanking region of the VBI lines, in "raw" mode as far as
+ * the Encoder is concerned.  We don't ever tell the Encoder itself
+ * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode)
+ *
+ * We then process the ancillary data ourselves to send the sliced data
+ * to the user application directly or build up MPEG-2 private stream 1
+ * packets to splice into (only!) MPEG-2 PS streams for the user app.
+ *
+ * (That's how ivtv essentially does it.)
+ *
+ * The Encoder should be able to extract certain sliced VBI data for
+ * us and provide it in a separate stream or splice it into any type of
+ * MPEG PS or TS stream, but this isn't implemented yet.
+ */
+
+/*
+ * Number of "raw" VBI samples per horizontal line we tell the Encoder to
+ * grab from the decoder/digitizer/slicer output for raw or sliced VBI.
+ * It depends on the pixel clock and the horiz rate:
+ *
+ * (1/Fh)*(2*Fp) = Samples/line
+ *     = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
+ *
+ *  Sliced VBI data is sent as ancillary data during horizontal blanking
+ *  Raw VBI is sent as active video samples during vertcal blanking
+ *
+ *  We use a  BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
+ *  length of 720 pixels @ 4:2:2 sampling.  Thus...
+ *
+ *  For systems that use a 15.734 kHz horizontal rate, such as
+ *  NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
+ *
+ *  (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
+ *  4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
+ *
+ *  For systems that use a 15.625 kHz horizontal rate, such as
+ *  PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
+ *
+ *  (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
+ *  4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
+ */
+static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */
+static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */
+static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */
 
 #define CX18_VBI_FRAMES 32
 
-/* VBI data */
 struct vbi_info {
-	u32 enc_size;
-	u32 frame;
-	u8 cc_data_odd[256];
-	u8 cc_data_even[256];
-	int cc_pos;
-	u8 cc_no_update;
-	u8 vps[5];
-	u8 vps_found;
-	int wss;
-	u8 wss_found;
-	u8 wss_no_update;
-	u32 raw_decoder_line_size;
-	u8 raw_decoder_sav_odd_field;
-	u8 raw_decoder_sav_even_field;
-	u32 sliced_decoder_line_size;
-	u8 sliced_decoder_sav_odd_field;
-	u8 sliced_decoder_sav_even_field;
+	/* Current state of v4l2 VBI settings for this device */
 	struct v4l2_format in;
-	/* convenience pointer to sliced struct in vbi_in union */
-	struct v4l2_sliced_vbi_format *sliced_in;
-	u32 service_set_in;
+	struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */
+	u32 count;    /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */
+	u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */
+
+	u32 frame; /* Count of VBI buffers/frames received from Encoder */
+
+	/*
+	 * Vars for creation and insertion of MPEG Private Stream 1 packets
+	 * of sliced VBI data into an MPEG PS
+	 */
+
+	/* Boolean: create and insert Private Stream 1 packets into the PS */
 	int insert_mpeg;
 
-	/* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
-	   One for /dev/vbi0 and one for /dev/vbi8 */
+	/*
+	 * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
+	 * Used in cx18-vbi.c only for collecting sliced data, and as a source
+	 * during conversion of sliced VBI data into MPEG Priv Stream 1 packets.
+	 * We don't need to save state here, but the array may have been a bit
+	 * too big (2304 bytes) to alloc from the stack.
+	 */
 	struct v4l2_sliced_vbi_data sliced_data[36];
 
-	/* Buffer for VBI data inserted into MPEG stream.
-	   The first byte is a dummy byte that's never used.
-	   The next 16 bytes contain the MPEG header for the VBI data,
-	   the remainder is the actual VBI data.
-	   The max size accepted by the MPEG VBI reinsertion turns out
-	   to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
-	   where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
-	   a single line header byte and 2 * 18 is the number of VBI lines per frame.
-
-	   However, it seems that the data must be 1K aligned, so we have to
-	   pad the data until the 1 or 2 K boundary.
-
-	   This pointer array will allocate 2049 bytes to store each VBI frame. */
+	/*
+	 * A ring buffer of driver-generated MPEG-2 PS
+	 * Program Pack/Private Stream 1 packets for sliced VBI data insertion
+	 * into the MPEG PS stream.
+	 *
+	 * In each sliced_mpeg_data[] buffer is:
+	 * 	16 byte MPEG-2 PS Program Pack Header
+	 * 	16 byte MPEG-2 Private Stream 1 PES Header
+	 * 	 4 byte magic number: "itv0" or "ITV0"
+	 * 	 4 byte first  field line mask, if "itv0"
+	 * 	 4 byte second field line mask, if "itv0"
+	 * 	36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data
+	 *
+	 * 	Each line in the payload is
+	 *	 1 byte line header derived from the SDID (WSS, CC, VPS, etc.)
+	 *	42 bytes of line data
+	 *
+	 * That's a maximum 1552 bytes of payload in the Private Stream 1 packet
+	 * which is the payload size a PVR-350 (CX23415) MPEG decoder will
+	 * accept for VBI data. So, including the headers, it's a maximum 1584
+	 * bytes total.
+	 */
+#define CX18_SLICED_MPEG_DATA_MAXSZ	1584
+	/* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */
+#define CX18_SLICED_MPEG_DATA_BUFSZ	(CX18_SLICED_MPEG_DATA_MAXSZ+8)
 	u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
 	u32 sliced_mpeg_size[CX18_VBI_FRAMES];
-	struct cx18_buffer sliced_mpeg_buf;
+
+	/* Count of Program Pack/Program Stream 1 packets inserted into PS */
 	u32 inserted_frame;
 
-	u32 start[2], count;
-	u32 raw_size;
-	u32 sliced_size;
+	/*
+	 * A dummy driver stream transfer buffer with a copy of the next
+	 * sliced_mpeg_data[] buffer for output to userland apps.
+	 * Only used in cx18-fileops.c, but its state needs to persist at times.
+	 */
+	struct cx18_buffer sliced_mpeg_buf;
 };
 
 /* Per cx23418, per I2C bus private algo callback data */
@@ -383,16 +494,17 @@
 
 /* Struct to hold info about cx18 cards */
 struct cx18 {
-	int num;		/* board number, -1 during init! */
-	char name[8];		/* board name for printk and interrupts (e.g. 'cx180') */
-	struct pci_dev *dev;	/* PCI device */
+	int instance;
+	struct pci_dev *pci_dev;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_subdev *sd_av;     /* A/V decoder/digitizer sub-device */
+	struct v4l2_subdev *sd_extmux; /* External multiplexer sub-dev */
+
 	const struct cx18_card *card;	/* card information */
 	const char *card_name;  /* full name of the card */
 	const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
 	u8 is_50hz;
 	u8 is_60hz;
-	u8 is_out_50hz;
-	u8 is_out_60hz;
 	u8 nof_inputs;		/* number of video inputs */
 	u8 nof_audio_inputs;	/* number of audio inputs */
 	u16 buffer_id;		/* buffer ID counter */
@@ -413,10 +525,7 @@
 
 	/* dualwatch */
 	unsigned long dualwatch_jiffies;
-	u16 dualwatch_stereo_mode;
-
-	/* Digitizer type */
-	int digitizer;		/* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
+	u32 dualwatch_stereo_mode;
 
 	struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
 	struct cx18_options options; 	/* User options */
@@ -426,7 +535,6 @@
 	unsigned long i_flags;  /* global cx18 flags */
 	atomic_t ana_capturing;	/* count number of active analog capture streams */
 	atomic_t tot_capturing;	/* total count number of active capture streams */
-	spinlock_t lock;        /* lock access to this struct */
 	int search_pack_header;
 
 	int open_id;		/* incremented each time an open occurs, used as
@@ -468,30 +576,30 @@
 	struct i2c_adapter i2c_adap[2];
 	struct i2c_algo_bit_data i2c_algo[2];
 	struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
-	struct i2c_client i2c_client[2];
-	struct mutex i2c_bus_lock[2];
-	struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
 
 	/* gpio */
 	u32 gpio_dir;
 	u32 gpio_val;
 	struct mutex gpio_lock;
+	struct v4l2_subdev sd_gpiomux;
+	struct v4l2_subdev sd_resetctrl;
 
 	/* v4l2 and User settings */
 
 	/* codec settings */
 	u32 audio_input;
 	u32 active_input;
-	u32 active_output;
 	v4l2_std_id std;
 	v4l2_std_id tuner_std;	/* The norm of the tuner (fixed) */
 };
 
+static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx18, v4l2_dev);
+}
+
 /* Globals */
-extern struct cx18 *cx18_cards[];
-extern int cx18_cards_active;
 extern int cx18_first_minor;
-extern spinlock_t cx18_cards_lock;
 
 /*==============Prototypes==================*/
 
@@ -511,4 +619,22 @@
 	return cx->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
 }
 
+/* Call the specified callback for all subdevs with a grp_id bit matching the
+ * mask in hw (if 0, then match them all). Ignore any errors. */
+#define cx18_call_hw(cx, hw, o, f, args...) \
+	__v4l2_device_call_subdevs(&(cx)->v4l2_dev, \
+				   !(hw) || (sd->grp_id & (hw)), o, f , ##args)
+
+#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args)
+
+/* Call the specified callback for all subdevs with a grp_id bit matching the
+ * mask in hw (if 0, then match them all). If the callback returns an error
+ * other than 0 or -ENOIOCTLCMD, then return with that error code. */
+#define cx18_call_hw_err(cx, hw, o, f, args...) \
+	__v4l2_device_call_subdevs_until_err( \
+		   &(cx)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
+
+#define cx18_call_all_err(cx, o, f, args...) \
+	cx18_call_hw_err(cx, 0, o, f , ##args)
+
 #endif /* CX18_DRIVER_H */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
index bd5e6f3..3b86f57 100644
--- a/drivers/media/video/cx18/cx18-dvb.c
+++ b/drivers/media/video/cx18/cx18-dvb.c
@@ -167,7 +167,7 @@
 
 	ret = dvb_register_adapter(&dvb->dvb_adapter,
 			CX18_DRIVER_NAME,
-			THIS_MODULE, &cx->dev->dev, adapter_nr);
+			THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
 	if (ret < 0)
 		goto err_out;
 
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 055f6e0..4d7d6d5 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -128,15 +128,15 @@
 static void cx18_dualwatch(struct cx18 *cx)
 {
 	struct v4l2_tuner vt;
-	u16 new_bitmap;
-	u16 new_stereo_mode;
-	const u16 stereo_mask = 0x0300;
-	const u16 dual = 0x0200;
+	u32 new_bitmap;
+	u32 new_stereo_mode;
+	const u32 stereo_mask = 0x0300;
+	const u32 dual = 0x0200;
 	u32 h;
 
 	new_stereo_mode = cx->params.audio_properties & stereo_mask;
 	memset(&vt, 0, sizeof(vt));
-	cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, &vt);
+	cx18_call_all(cx, tuner, g_tuner, &vt);
 	if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
 			(vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
 		new_stereo_mode = dual;
@@ -176,6 +176,8 @@
 	*err = 0;
 	while (1) {
 		if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+			/* Process pending program info updates and pending
+			   VBI data */
 
 			if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
 				cx->dualwatch_jiffies = jiffies;
@@ -186,7 +188,6 @@
 				while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) {
 					/* byteswap and process VBI data */
 					cx18_process_vbi_data(cx, buf,
-							      s_vbi->dma_pts,
 							      s_vbi->type);
 					cx18_stream_put_buf_fw(s_vbi, buf);
 				}
@@ -207,8 +208,7 @@
 				cx18_buf_swap(buf);
 			else {
 				/* byteswap and process VBI data */
-				cx18_process_vbi_data(cx, buf,
-						s->dma_pts, s->type);
+				cx18_process_vbi_data(cx, buf, s->type);
 			}
 			return buf;
 		}
@@ -260,6 +260,20 @@
 		len = ucount;
 	if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
 	    !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
+		/*
+		 * Try to find a good splice point in the PS, just before
+		 * an MPEG-2 Program Pack start code, and provide only
+		 * up to that point to the user, so it's easy to insert VBI data
+		 * the next time around.
+		 */
+		/* FIXME - This only works for an MPEG-2 PS, not a TS */
+		/*
+		 * An MPEG-2 Program Stream (PS) is a series of
+		 * MPEG-2 Program Packs terminated by an
+		 * MPEG Program End Code after the last Program Pack.
+		 * A Program Pack may hold a PS System Header packet and any
+		 * number of Program Elementary Stream (PES) Packets
+		 */
 		const char *start = buf->buf + buf->readpos;
 		const char *p = start + 1;
 		const u8 *q;
@@ -267,38 +281,54 @@
 		int stuffing, i;
 
 		while (start + len > p) {
+			/* Scan for a 0 to find a potential MPEG-2 start code */
 			q = memchr(p, 0, start + len - p);
 			if (q == NULL)
 				break;
 			p = q + 1;
+			/*
+			 * Keep looking if not a
+			 * MPEG-2 Pack header start code:  0x00 0x00 0x01 0xba
+			 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
+			 */
 			if ((char *)q + 15 >= buf->buf + buf->bytesused ||
 			    q[1] != 0 || q[2] != 1 || q[3] != ch)
 				continue;
+
+			/* If expecting the primary video PES */
 			if (!cx->search_pack_header) {
+				/* Continue if it couldn't be a PES packet */
 				if ((q[6] & 0xc0) != 0x80)
 					continue;
-				if (((q[7] & 0xc0) == 0x80 &&
-				     (q[9] & 0xf0) == 0x20) ||
-				    ((q[7] & 0xc0) == 0xc0 &&
-				     (q[9] & 0xf0) == 0x30)) {
-					ch = 0xba;
+				/* Check if a PTS or PTS & DTS follow */
+				if (((q[7] & 0xc0) == 0x80 &&  /* PTS only */
+				     (q[9] & 0xf0) == 0x20) || /* PTS only */
+				    ((q[7] & 0xc0) == 0xc0 &&  /* PTS & DTS */
+				     (q[9] & 0xf0) == 0x30)) { /* DTS follows */
+					/* Assume we found the video PES hdr */
+					ch = 0xba; /* next want a Program Pack*/
 					cx->search_pack_header = 1;
-					p = q + 9;
+					p = q + 9; /* Skip this video PES hdr */
 				}
 				continue;
 			}
+
+			/* We may have found a Program Pack start code */
+
+			/* Get the count of stuffing bytes & verify them */
 			stuffing = q[13] & 7;
 			/* all stuffing bytes must be 0xff */
 			for (i = 0; i < stuffing; i++)
 				if (q[14 + i] != 0xff)
 					break;
-			if (i == stuffing &&
-			    (q[4] & 0xc4) == 0x44 &&
-			    (q[12] & 3) == 3 &&
-			    q[14 + stuffing] == 0 &&
+			if (i == stuffing && /* right number of stuffing bytes*/
+			    (q[4] & 0xc4) == 0x44 && /* marker check */
+			    (q[12] & 3) == 3 &&  /* marker check */
+			    q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
 			    q[15 + stuffing] == 0 &&
 			    q[16 + stuffing] == 1) {
-				cx->search_pack_header = 0;
+				/* We declare we actually found a Program Pack*/
+				cx->search_pack_header = 0; /* expect vid PES */
 				len = (char *)q - start;
 				cx18_setup_sliced_vbi_buf(cx);
 				break;
@@ -578,7 +608,7 @@
 		/* Mark that the radio is no longer in use */
 		clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
 		/* Switch tuner to TV */
-		cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+		cx18_call_all(cx, tuner, s_std, cx->std);
 		/* Select correct audio input (i.e. TV tuner or Line in) */
 		cx18_audio_set_io(cx);
 		if (atomic_read(&cx->ana_capturing) > 0) {
@@ -641,7 +671,7 @@
 		/* We have the radio */
 		cx18_mute(cx);
 		/* Switch tuner to radio */
-		cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL);
+		cx18_call_all(cx, tuner, s_radio);
 		/* Select the correct audio input (i.e. radio tuner) */
 		cx18_audio_set_io(cx);
 		/* Done! Unmute and continue. */
@@ -652,38 +682,15 @@
 
 int cx18_v4l2_open(struct file *filp)
 {
-	int res, x, y = 0;
-	struct cx18 *cx = NULL;
-	struct cx18_stream *s = NULL;
-	int minor = video_devdata(filp)->minor;
-
-	/* Find which card this open was on */
-	spin_lock(&cx18_cards_lock);
-	for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
-		/* find out which stream this open was on */
-		for (y = 0; y < CX18_MAX_STREAMS; y++) {
-			if (cx18_cards[x] == NULL)
-				continue;
-			s = &cx18_cards[x]->streams[y];
-			if (s->v4l2dev && s->v4l2dev->minor == minor) {
-				cx = cx18_cards[x];
-				break;
-			}
-		}
-	}
-	spin_unlock(&cx18_cards_lock);
-
-	if (cx == NULL) {
-		/* Couldn't find a device registered
-		   on that minor, shouldn't happen! */
-		printk(KERN_WARNING "No cx18 device found on minor %d\n",
-				minor);
-		return -ENXIO;
-	}
+	int res;
+	struct video_device *video_dev = video_devdata(filp);
+	struct cx18_stream *s = video_get_drvdata(video_dev);
+	struct cx18 *cx = s->cx;;
 
 	mutex_lock(&cx->serialize_lock);
 	if (cx18_init_on_first_open(cx)) {
-		CX18_ERR("Failed to initialize on minor %d\n", minor);
+		CX18_ERR("Failed to initialize on minor %d\n",
+			 video_dev->minor);
 		mutex_unlock(&cx->serialize_lock);
 		return -ENXIO;
 	}
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 1fa95da..83cd559 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -26,7 +26,6 @@
 #include "cx18-irq.h"
 #include "cx18-firmware.h"
 #include "cx18-cards.h"
-#include "cx18-av-core.h"
 #include <linux/firmware.h>
 
 #define CX18_PROC_SOFT_RESET 		0xc70010
@@ -107,7 +106,7 @@
 	u32 __iomem *dst = (u32 __iomem *)mem;
 	const u32 *src;
 
-	if (request_firmware(&fw, fn, &cx->dev->dev)) {
+	if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
 		CX18_ERR("Unable to open firmware %s\n", fn);
 		CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
 		return -ENOMEM;
@@ -151,7 +150,7 @@
 	u32 apu_version = 0;
 	int sz;
 
-	if (request_firmware(&fw, fn, &cx->dev->dev)) {
+	if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
 		CX18_ERR("unable to open firmware %s\n", fn);
 		CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
 		cx18_setup_page(cx, 0);
@@ -286,23 +285,6 @@
 	cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
 	cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
 
-	/*
-	 * VDCLK  Integer = 0x0f, Post Divider = 0x04
-	 * AIMCLK Integer = 0x0e, Post Divider = 0x16
-	 */
-	cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
-
-	/* VDCLK Fraction = 0x2be2fe */
-	/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
-	cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
-
-	/* AIMCLK Fraction = 0x05227ad */
-	/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz before post-divide */
-	cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
-
-	/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
-	cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
-
 	/* Defaults */
 	/* APU = SC or SC/2 = 125/62.5 */
 	/* EPU = SC = 125 */
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index 1a99329..5518d14 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -46,6 +46,9 @@
  * gpio13: cs5345 reset pin
 */
 
+/*
+ * File scope utility functions
+ */
 static void gpio_write(struct cx18 *cx)
 {
 	u32 dir_lo = cx->gpio_dir & 0xffff;
@@ -63,73 +66,201 @@
 					CX18_REG_GPIO_OUT2, val_hi, dir_hi);
 }
 
-void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
+static void gpio_update(struct cx18 *cx, u32 mask, u32 data)
 {
-	const struct cx18_gpio_i2c_slave_reset *p;
-
-	p = &cx->card->gpio_i2c_slave_reset;
-
-	if ((p->active_lo_mask | p->active_hi_mask) == 0)
+	if (mask == 0)
 		return;
 
-	/* Assuming that the masks are a subset of the bits in gpio_dir */
+	mutex_lock(&cx->gpio_lock);
+	cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
+	gpio_write(cx);
+	mutex_unlock(&cx->gpio_lock);
+}
+
+static void gpio_reset_seq(struct cx18 *cx, u32 active_lo, u32 active_hi,
+			   unsigned int assert_msecs,
+			   unsigned int recovery_msecs)
+{
+	u32 mask;
+
+	mask = active_lo | active_hi;
+	if (mask == 0)
+		return;
+
+	/*
+	 * Assuming that active_hi and active_lo are a subsets of the bits in
+	 * gpio_dir.  Also assumes that active_lo and active_hi don't overlap
+	 * in any bit position
+	 */
 
 	/* Assert */
-	mutex_lock(&cx->gpio_lock);
-	cx->gpio_val =
-		(cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
-	gpio_write(cx);
-	schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
+	gpio_update(cx, mask, ~active_lo);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs));
 
 	/* Deassert */
-	cx->gpio_val =
-		(cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
-	gpio_write(cx);
-	schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
-	mutex_unlock(&cx->gpio_lock);
+	gpio_update(cx, mask, ~active_hi);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs));
 }
 
-void cx18_reset_ir_gpio(void *data)
+/*
+ * GPIO Multiplexer - logical device
+ */
+static int gpiomux_log_status(struct v4l2_subdev *sd)
 {
-	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	mutex_lock(&cx->gpio_lock);
+	CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
+		      cx->gpio_dir, cx->gpio_val);
+	mutex_unlock(&cx->gpio_lock);
+	return 0;
+}
+
+static int gpiomux_s_radio(struct v4l2_subdev *sd)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	/*
+	 * FIXME - work out the cx->active/audio_input mess - this is
+	 * intended to handle the switch to radio mode and set the
+	 * audio routing, but we need to update the state in cx
+	 */
+	gpio_update(cx, cx->card->gpio_audio_input.mask,
+			cx->card->gpio_audio_input.radio);
+	return 0;
+}
+
+static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	u32 data;
+
+	switch (cx->card->audio_inputs[cx->audio_input].muxer_input) {
+	case 1:
+		data = cx->card->gpio_audio_input.linein;
+		break;
+	case 0:
+		data = cx->card->gpio_audio_input.tuner;
+		break;
+	default:
+		/*
+		 * FIXME - work out the cx->active/audio_input mess - this is
+		 * intended to handle the switch from radio mode and set the
+		 * audio routing, but we need to update the state in cx
+		 */
+		data = cx->card->gpio_audio_input.tuner;
+		break;
+	}
+	gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+	return 0;
+}
+
+static int gpiomux_s_audio_routing(struct v4l2_subdev *sd,
+				   const struct v4l2_routing *route)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	u32 data;
+
+	switch (route->input) {
+	case 0:
+		data = cx->card->gpio_audio_input.tuner;
+		break;
+	case 1:
+		data = cx->card->gpio_audio_input.linein;
+		break;
+	case 2:
+		data = cx->card->gpio_audio_input.radio;
+		break;
+	default:
+		return -EINVAL;
+	}
+	gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops gpiomux_core_ops = {
+	.log_status = gpiomux_log_status,
+};
+
+static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = {
+	.s_std = gpiomux_s_std,
+	.s_radio = gpiomux_s_radio,
+};
+
+static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = {
+	.s_routing = gpiomux_s_audio_routing,
+};
+
+static const struct v4l2_subdev_ops gpiomux_ops = {
+	.core = &gpiomux_core_ops,
+	.tuner = &gpiomux_tuner_ops,
+	.audio = &gpiomux_audio_ops,
+};
+
+/*
+ * GPIO Reset Controller - logical device
+ */
+static int resetctrl_log_status(struct v4l2_subdev *sd)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	mutex_lock(&cx->gpio_lock);
+	CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
+		      cx->gpio_dir, cx->gpio_val);
+	mutex_unlock(&cx->gpio_lock);
+	return 0;
+}
+
+static int resetctrl_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
 	const struct cx18_gpio_i2c_slave_reset *p;
 
 	p = &cx->card->gpio_i2c_slave_reset;
-
-	if (p->ir_reset_mask == 0)
-		return;
-
-	CX18_DEBUG_INFO("Resetting IR microcontroller\n");
-
-	/*
-	   Assert timing for the Z8F0811 on HVR-1600 boards:
-	   1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
-	   2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
-		(6,601,085 nanoseconds ~= 7 milliseconds)
-	   3. DBG pin must be high before chip exits reset for normal operation.
-		DBG is open drain and hopefully pulled high since we don't
-		normally drive it (GPIO 1?) for the HVR-1600
-	   4. Z8F0811 won't exit reset until RESET is deasserted
-	*/
-	mutex_lock(&cx->gpio_lock);
-	cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
-	gpio_write(cx);
-	mutex_unlock(&cx->gpio_lock);
-	schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
-
-	/*
-	   Zilog comes out of reset, loads reset vector address and executes
-	   from there. Required recovery delay unknown.
-	*/
-	mutex_lock(&cx->gpio_lock);
-	cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
-	gpio_write(cx);
-	mutex_unlock(&cx->gpio_lock);
-	schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+	switch (val) {
+	case CX18_GPIO_RESET_I2C:
+		gpio_reset_seq(cx, p->active_lo_mask, p->active_hi_mask,
+			       p->msecs_asserted, p->msecs_recovery);
+		break;
+	case CX18_GPIO_RESET_Z8F0811:
+		/*
+		 * Assert timing for the Z8F0811 on HVR-1600 boards:
+		 * 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to
+		 *    initiate
+		 * 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock
+		 *    cycles (6,601,085 nanoseconds ~= 7 milliseconds)
+		 * 3. DBG pin must be high before chip exits reset for normal
+		 *    operation.  DBG is open drain and hopefully pulled high
+		 *    since we don't normally drive it (GPIO 1?) for the
+		 *    HVR-1600
+		 * 4. Z8F0811 won't exit reset until RESET is deasserted
+		 * 5. Zilog comes out of reset, loads reset vector address and
+		 *    executes from there. Required recovery delay unknown.
+		 */
+		gpio_reset_seq(cx, p->ir_reset_mask, 0,
+			       p->msecs_asserted, p->msecs_recovery);
+		break;
+	case CX18_GPIO_RESET_XC2028:
+		if (cx->card->tuners[0].tuner == TUNER_XC2028)
+			gpio_reset_seq(cx, (1 << cx->card->xceive_pin), 0,
+				       1, 1);
+		break;
+	}
+	return 0;
 }
-EXPORT_SYMBOL(cx18_reset_ir_gpio);
-/* This symbol is exported for use by an infrared module for the IR-blaster */
 
+static const struct v4l2_subdev_core_ops resetctrl_core_ops = {
+	.log_status = resetctrl_log_status,
+	.reset = resetctrl_reset,
+};
+
+static const struct v4l2_subdev_ops resetctrl_ops = {
+	.core = &resetctrl_core_ops,
+};
+
+/*
+ * External entry points
+ */
 void cx18_gpio_init(struct cx18 *cx)
 {
 	mutex_lock(&cx->gpio_lock);
@@ -156,6 +287,49 @@
 	mutex_unlock(&cx->gpio_lock);
 }
 
+int cx18_gpio_register(struct cx18 *cx, u32 hw)
+{
+	struct v4l2_subdev *sd;
+	const struct v4l2_subdev_ops *ops;
+	char *str;
+
+	switch (hw) {
+	case CX18_HW_GPIO_MUX:
+		sd = &cx->sd_gpiomux;
+		ops = &gpiomux_ops;
+		str = "gpio-mux";
+		break;
+	case CX18_HW_GPIO_RESET_CTRL:
+		sd = &cx->sd_resetctrl;
+		ops = &resetctrl_ops;
+		str = "gpio-reset-ctrl";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	v4l2_subdev_init(sd, ops);
+	v4l2_set_subdevdata(sd, cx);
+	snprintf(sd->name, sizeof(sd->name), "%s %s", cx->v4l2_dev.name, str);
+	sd->grp_id = hw;
+	return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+}
+
+void cx18_reset_ir_gpio(void *data)
+{
+	struct cx18 *cx = to_cx18((struct v4l2_device *)data);
+
+	if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
+		return;
+
+	CX18_DEBUG_INFO("Resetting IR microcontroller\n");
+
+	v4l2_subdev_call(&cx->sd_resetctrl,
+			 core, reset, CX18_GPIO_RESET_Z8F0811);
+}
+EXPORT_SYMBOL(cx18_reset_ir_gpio);
+/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */
+
 /* Xceive tuner reset function */
 int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
 {
@@ -163,56 +337,11 @@
 	struct cx18_i2c_algo_callback_data *cb_data = algo->data;
 	struct cx18 *cx = cb_data->cx;
 
-	if (cmd != XC2028_TUNER_RESET)
+	if (cmd != XC2028_TUNER_RESET ||
+	    cx->card->tuners[0].tuner != TUNER_XC2028)
 		return 0;
-	CX18_DEBUG_INFO("Resetting tuner\n");
 
-	mutex_lock(&cx->gpio_lock);
-	cx->gpio_val &= ~(1 << cx->card->xceive_pin);
-	gpio_write(cx);
-	mutex_unlock(&cx->gpio_lock);
-	schedule_timeout_interruptible(msecs_to_jiffies(1));
-
-	mutex_lock(&cx->gpio_lock);
-	cx->gpio_val |= 1 << cx->card->xceive_pin;
-	gpio_write(cx);
-	mutex_unlock(&cx->gpio_lock);
-	schedule_timeout_interruptible(msecs_to_jiffies(1));
-	return 0;
-}
-
-int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg)
-{
-	struct v4l2_routing *route = arg;
-	u32 mask, data;
-
-	switch (command) {
-	case VIDIOC_INT_S_AUDIO_ROUTING:
-		if (route->input > 2)
-			return -EINVAL;
-		mask = cx->card->gpio_audio_input.mask;
-		switch (route->input) {
-		case 0:
-			data = cx->card->gpio_audio_input.tuner;
-			break;
-		case 1:
-			data = cx->card->gpio_audio_input.linein;
-			break;
-		case 2:
-		default:
-			data = cx->card->gpio_audio_input.radio;
-			break;
-		}
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (mask) {
-		mutex_lock(&cx->gpio_lock);
-		cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
-		gpio_write(cx);
-		mutex_unlock(&cx->gpio_lock);
-	}
-	return 0;
+	CX18_DEBUG_INFO("Resetting XCeive tuner\n");
+	return v4l2_subdev_call(&cx->sd_resetctrl,
+				core, reset, CX18_GPIO_RESET_XC2028);
 }
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index 39ffccc..f9a5ca3 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -22,7 +22,13 @@
  */
 
 void cx18_gpio_init(struct cx18 *cx);
-void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
+int cx18_gpio_register(struct cx18 *cx, u32 hw);
+
+enum cx18_gpio_reset_type {
+	CX18_GPIO_RESET_I2C     = 0,
+	CX18_GPIO_RESET_Z8F0811 = 1,
+	CX18_GPIO_RESET_XC2028  = 2,
+};
+
 void cx18_reset_ir_gpio(void *data);
 int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
-int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 83e1c63..d092643 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -26,7 +26,6 @@
 #include "cx18-io.h"
 #include "cx18-cards.h"
 #include "cx18-gpio.h"
-#include "cx18-av-core.h"
 #include "cx18-i2c.h"
 #include "cx18-irq.h"
 
@@ -43,31 +42,37 @@
 #define CX18_CS5345_I2C_ADDR		0x4c
 
 /* This array should match the CX18_HW_ defines */
-static const u8 hw_driverids[] = {
-	I2C_DRIVERID_TUNER,
-	I2C_DRIVERID_TVEEPROM,
-	I2C_DRIVERID_CS5345,
-	0, 		/* CX18_HW_GPIO dummy driver ID */
-	0 		/* CX18_HW_CX23418 dummy driver ID */
-};
-
-/* This array should match the CX18_HW_ defines */
 static const u8 hw_addrs[] = {
-	0,
-	0,
-	CX18_CS5345_I2C_ADDR,
-	0, 		/* CX18_HW_GPIO dummy driver ID */
-	0,		/* CX18_HW_CX23418 dummy driver ID */
+	0,			/* CX18_HW_TUNER */
+	0,			/* CX18_HW_TVEEPROM */
+	CX18_CS5345_I2C_ADDR,	/* CX18_HW_CS5345 */
+	0,			/* CX18_HW_DVB */
+	0,			/* CX18_HW_418_AV */
+	0,			/* CX18_HW_GPIO_MUX */
+	0,			/* CX18_HW_GPIO_RESET_CTRL */
 };
 
 /* This array should match the CX18_HW_ defines */
 /* This might well become a card-specific array */
 static const u8 hw_bus[] = {
-	0,
-	0,
-	0,
-	0, 		/* CX18_HW_GPIO dummy driver ID */
-	0,		/* CX18_HW_CX23418 dummy driver ID */
+	1,	/* CX18_HW_TUNER */
+	0,	/* CX18_HW_TVEEPROM */
+	0,	/* CX18_HW_CS5345 */
+	0,	/* CX18_HW_DVB */
+	0,	/* CX18_HW_418_AV */
+	0,	/* CX18_HW_GPIO_MUX */
+	0,	/* CX18_HW_GPIO_RESET_CTRL */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const char * const hw_modules[] = {
+	"tuner",	/* CX18_HW_TUNER */
+	NULL,		/* CX18_HW_TVEEPROM */
+	"cs5345",	/* CX18_HW_CS5345 */
+	NULL,		/* CX18_HW_DVB */
+	NULL,		/* CX18_HW_418_AV */
+	NULL,		/* CX18_HW_GPIO_MUX */
+	NULL,		/* CX18_HW_GPIO_RESET_CTRL */
 };
 
 /* This array should match the CX18_HW_ defines */
@@ -75,83 +80,67 @@
 	"tuner",
 	"tveeprom",
 	"cs5345",
-	"gpio",
-	"cx23418",
+	"cx23418_DTV",
+	"cx23418_AV",
+	"gpio_mux",
+	"gpio_reset_ctrl",
 };
 
 int cx18_i2c_register(struct cx18 *cx, unsigned idx)
 {
-	struct i2c_board_info info;
-	struct i2c_client *c;
-	u8 id, bus;
-	int i;
+	struct v4l2_subdev *sd;
+	int bus = hw_bus[idx];
+	struct i2c_adapter *adap = &cx->i2c_adap[bus];
+	const char *mod = hw_modules[idx];
+	const char *type = hw_devicenames[idx];
+	u32 hw = 1 << idx;
 
-	CX18_DEBUG_I2C("i2c client register\n");
-	if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0)
+	if (idx >= ARRAY_SIZE(hw_addrs))
 		return -1;
-	id = hw_driverids[idx];
-	bus = hw_bus[idx];
-	memset(&info, 0, sizeof(info));
-	strlcpy(info.type, hw_devicenames[idx], sizeof(info.type));
-	info.addr = hw_addrs[idx];
-	for (i = 0; i < I2C_CLIENTS_MAX; i++)
-		if (cx->i2c_clients[i] == NULL)
-			break;
 
-	if (i == I2C_CLIENTS_MAX) {
-		CX18_ERR("insufficient room for new I2C client!\n");
-		return -ENOMEM;
+	if (hw == CX18_HW_TUNER) {
+		/* special tuner group handling */
+		sd = v4l2_i2c_new_probed_subdev(adap, mod, type,
+						cx->card_i2c->radio);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		sd = v4l2_i2c_new_probed_subdev(adap, mod, type,
+						cx->card_i2c->demod);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		sd = v4l2_i2c_new_probed_subdev(adap, mod, type,
+						cx->card_i2c->tv);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		return sd != NULL ? 0 : -1;
 	}
 
-	if (id != I2C_DRIVERID_TUNER) {
-		c = i2c_new_device(&cx->i2c_adap[bus], &info);
-		if (c->driver == NULL)
-			i2c_unregister_device(c);
-		else
-			cx->i2c_clients[i] = c;
-		return cx->i2c_clients[i] ? 0 : -ENODEV;
-	}
+	/* Is it not an I2C device or one we do not wish to register? */
+	if (!hw_addrs[idx])
+		return -1;
 
-	/* special tuner handling */
-	c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio);
-	if (c && c->driver == NULL)
-		i2c_unregister_device(c);
-	else if (c)
-		cx->i2c_clients[i++] = c;
-	c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod);
-	if (c && c->driver == NULL)
-		i2c_unregister_device(c);
-	else if (c)
-		cx->i2c_clients[i++] = c;
-	c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv);
-	if (c && c->driver == NULL)
-		i2c_unregister_device(c);
-	else if (c)
-		cx->i2c_clients[i++] = c;
-	return 0;
+	/* It's an I2C device other than an analog tuner */
+	sd = v4l2_i2c_new_subdev(adap, mod, type, hw_addrs[idx]);
+	if (sd != NULL)
+		sd->grp_id = hw;
+	return sd != NULL ? 0 : -1;
 }
 
-static int attach_inform(struct i2c_client *client)
+/* Find the first member of the subdev group id in hw */
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)
 {
-	return 0;
-}
+	struct v4l2_subdev *result = NULL;
+	struct v4l2_subdev *sd;
 
-static int detach_inform(struct i2c_client *client)
-{
-	int i;
-	struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
-
-	CX18_DEBUG_I2C("i2c client detach\n");
-	for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-		if (cx->i2c_clients[i] == client) {
-			cx->i2c_clients[i] = NULL;
+	spin_lock(&cx->v4l2_dev.lock);
+	v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {
+		if (sd->grp_id == hw) {
+			result = sd;
 			break;
 		}
 	}
-	CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n",
-		   client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
-
-	return 0;
+	spin_unlock(&cx->v4l2_dev.lock);
+	return result;
 }
 
 static void cx18_setscl(void *data, int state)
@@ -204,8 +193,6 @@
 	.id = I2C_HW_B_CX2341X,
 	.algo = NULL,                   /* set by i2c-algo-bit */
 	.algo_data = NULL,              /* filled from template */
-	.client_register = attach_inform,
-	.client_unregister = detach_inform,
 	.owner = THIS_MODULE,
 };
 
@@ -221,152 +208,28 @@
 	.timeout	= CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
 };
 
-static struct i2c_client cx18_i2c_client_template = {
-	.name = "cx18 internal",
-};
-
-int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
-{
-	struct i2c_client *client;
-	int retval;
-	int i;
-
-	CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
-	for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-		client = cx->i2c_clients[i];
-		if (client == NULL || client->driver == NULL ||
-				client->driver->command == NULL)
-			continue;
-		if (addr == client->addr) {
-			retval = client->driver->command(client, cmd, arg);
-			return retval;
-		}
-	}
-	if (cmd != VIDIOC_DBG_G_CHIP_IDENT)
-		CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
-			       addr, cmd);
-	return -ENODEV;
-}
-
-/* Find the i2c device based on the driver ID and return
-   its i2c address or -ENODEV if no matching device was found. */
-static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
-{
-	struct i2c_client *client;
-	int retval = -ENODEV;
-	int i;
-
-	for (i = 0; i < I2C_CLIENTS_MAX; i++) {
-		client = cx->i2c_clients[i];
-		if (client == NULL || client->driver == NULL)
-			continue;
-		if (id == client->driver->id) {
-			retval = client->addr;
-			break;
-		}
-	}
-	return retval;
-}
-
-/* Find the i2c device name matching the CX18_HW_ flag */
-static const char *cx18_i2c_hw_name(u32 hw)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-		if (1 << i == hw)
-			return hw_devicenames[i];
-	return "unknown device";
-}
-
-/* Find the i2c device matching the CX18_HW_ flag and return
-   its i2c address or -ENODEV if no matching device was found. */
-int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
-		if (1 << i == hw)
-			return cx18_i2c_id_addr(cx, hw_driverids[i]);
-	return -ENODEV;
-}
-
-/* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing.
-   If hw == CX18_HW_GPIO then call the gpio handler. */
-int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
-{
-	int addr;
-
-	if (hw == 0)
-		return 0;
-
-	if (hw == CX18_HW_GPIO)
-		return cx18_gpio(cx, cmd, arg);
-
-	if (hw == CX18_HW_CX23418)
-		return cx18_av_cmd(cx, cmd, arg);
-
-	addr = cx18_i2c_hw_addr(cx, hw);
-	if (addr < 0) {
-		CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n",
-			       hw, cx18_i2c_hw_name(hw), cmd);
-		return addr;
-	}
-	return cx18_call_i2c_client(cx, addr, cmd, arg);
-}
-
-/* broadcast cmd for all I2C clients and for the gpio subsystem */
-void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
-{
-	if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) {
-		CX18_ERR("adapter is not set\n");
-		return;
-	}
-	cx18_av_cmd(cx, cmd, arg);
-	i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
-	i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
-	if (cx->hw_flags & CX18_HW_GPIO)
-		cx18_gpio(cx, cmd, arg);
-}
-
 /* init + register i2c algo-bit adapter */
 int init_cx18_i2c(struct cx18 *cx)
 {
 	int i;
 	CX18_DEBUG_I2C("i2c init\n");
 
-	/* Sanity checks for the I2C hardware arrays. They must be the
-	 * same size and GPIO/CX23418 must be the last entries.
-	 */
-	if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) ||
-	    ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
-	    CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) ||
-	    CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) ||
-	    hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) {
-		CX18_ERR("Mismatched I2C hardware arrays\n");
-		return -ENODEV;
-	}
-
 	for (i = 0; i < 2; i++) {
-		memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
-			sizeof(struct i2c_adapter));
+		/* Setup algorithm for adapter */
 		memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
 			sizeof(struct i2c_algo_bit_data));
 		cx->i2c_algo_cb_data[i].cx = cx;
 		cx->i2c_algo_cb_data[i].bus_index = i;
 		cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
+
+		/* Setup adapter */
+		memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
+			sizeof(struct i2c_adapter));
 		cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
-
 		sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
-				" #%d-%d", cx->num, i);
-		i2c_set_adapdata(&cx->i2c_adap[i], cx);
-
-		memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
-			sizeof(struct i2c_client));
-		sprintf(cx->i2c_client[i].name +
-				strlen(cx->i2c_client[i].name), "%d", i);
-		cx->i2c_client[i].adapter = &cx->i2c_adap[i];
-		cx->i2c_adap[i].dev.parent = &cx->dev->dev;
+				" #%d-%d", cx->instance, i);
+		i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev);
+		cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev;
 	}
 
 	if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
@@ -402,7 +265,8 @@
 	cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
 	cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 
-	cx18_reset_i2c_slaves_gpio(cx);
+	cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+		     core, reset, (u32) CX18_GPIO_RESET_I2C);
 
 	return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
 		i2c_bit_add_bus(&cx->i2c_adap[1]);
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
index 4869739..bdfd192 100644
--- a/drivers/media/video/cx18/cx18-i2c.h
+++ b/drivers/media/video/cx18/cx18-i2c.h
@@ -21,11 +21,8 @@
  *  02111-1307  USA
  */
 
-int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
-int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
-int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
-void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
 int cx18_i2c_register(struct cx18 *cx, unsigned idx);
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
 
 /* init + register i2c algo-bit adapter */
 int init_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 7086aab..e4c9e3d 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -58,12 +58,21 @@
 	}
 }
 
+/* Check if VBI services are allowed on the (field, line) for the video std */
 static int valid_service_line(int field, int line, int is_pal)
 {
-	return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
+	return (is_pal && line >= 6 &&
+		((field == 0 && line <= 23) || (field == 1 && line <= 22))) ||
 	       (!is_pal && line >= 10 && line < 22);
 }
 
+/*
+ * For a (field, line, std) and inbound potential set of services for that line,
+ * return the first valid service of those passed in the incoming set for that
+ * line in priority order:
+ * CC, VPS, or WSS over TELETEXT for well known lines
+ * TELETEXT, before VPS, before CC, before WSS, for other lines
+ */
 static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
 {
 	u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
@@ -90,6 +99,10 @@
 	return 0;
 }
 
+/*
+ * Expand the service_set of *fmt into valid service_lines for the std,
+ * and clear the passed in fmt->service_set
+ */
 void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
 {
 	u16 set = fmt->service_set;
@@ -102,7 +115,25 @@
 	}
 }
 
+/*
+ * Sanitize the service_lines in *fmt per the video std, and return 1
+ * if any service_line is left as valid after santization
+ */
+static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+	int f, l;
+	u16 set = 0;
 
+	for (f = 0; f < 2; f++) {
+		for (l = 0; l < 24; l++) {
+			fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
+			set |= fmt->service_lines[f][l];
+		}
+	}
+	return set != 0;
+}
+
+/* Compute the service_set from the assumed valid service_lines of *fmt */
 u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
 {
 	int f, l;
@@ -129,10 +160,8 @@
 	pixfmt->priv = 0;
 	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
-		/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
-		pixfmt->sizeimage =
-			pixfmt->height * pixfmt->width +
-			pixfmt->height * (pixfmt->width / 2);
+		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
+		pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
 		pixfmt->bytesperline = 720;
 	} else {
 		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -149,8 +178,8 @@
 	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
 
 	vbifmt->sampling_rate = 27000000;
-	vbifmt->offset = 248;
-	vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4;
+	vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
+	vbifmt->samples_per_line = vbi_active_samples - 4;
 	vbifmt->sample_format = V4L2_PIX_FMT_GREY;
 	vbifmt->start[0] = cx->vbi.start[0];
 	vbifmt->start[1] = cx->vbi.start[1];
@@ -164,7 +193,30 @@
 static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	return -EINVAL;
+	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+	/* sane, V4L2 spec compliant, defaults */
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+	memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
+	vbifmt->service_set = 0;
+
+	/*
+	 * Fetch the configured service_lines and total service_set from the
+	 * digitizer/slicer.  Note, cx18_av_vbi() wipes the passed in
+	 * fmt->fmt.sliced under valid calling conditions
+	 */
+	if (v4l2_subdev_call(cx->sd_av, video, g_fmt, fmt))
+		return -EINVAL;
+
+	/* Ensure V4L2 spec compliant output */
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+	vbifmt->service_set = cx18_get_service_set(vbifmt);
+	return 0;
 }
 
 static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
@@ -174,11 +226,18 @@
 	struct cx18 *cx = id->cx;
 	int w = fmt->fmt.pix.width;
 	int h = fmt->fmt.pix.height;
+	int min_h = 2;
 
 	w = min(w, 720);
-	w = max(w, 1);
+	w = max(w, 2);
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+		/* YUV height must be a multiple of 32 */
+		h &= ~0x1f;
+		min_h = 32;
+	}
 	h = min(h, cx->is_50hz ? 576 : 480);
-	h = max(h, 2);
+	h = max(h, min_h);
+
 	cx18_g_fmt_vid_cap(file, fh, fmt);
 	fmt->fmt.pix.width = w;
 	fmt->fmt.pix.height = h;
@@ -194,7 +253,20 @@
 static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	return -EINVAL;
+	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+
+	/* If given a service set, expand it validly & clear passed in set */
+	if (vbifmt->service_set)
+		cx18_expand_service_set(vbifmt, cx->is_50hz);
+	/* Sanitize the service_lines, and compute the new set if any valid */
+	if (check_service_set(vbifmt, cx->is_50hz))
+		vbifmt->service_set = cx18_get_service_set(vbifmt);
+	return 0;
 }
 
 static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
@@ -223,7 +295,7 @@
 
 	cx->params.width = w;
 	cx->params.height = h;
-	cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+	v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt);
 	return cx18_g_fmt_vid_cap(file, fh, fmt);
 }
 
@@ -238,54 +310,131 @@
 	if (ret)
 		return ret;
 
+	/*
+	 * Changing the Encoder's Raw VBI parameters won't have any effect
+	 * if any analog capture is ongoing
+	 */
 	if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
 		return -EBUSY;
 
+	/*
+	 * Set the digitizer registers for raw active VBI.
+	 * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid
+	 * calling conditions
+	 */
+	ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt);
+	if (ret)
+		return ret;
+
+	/* Store our new v4l2 (non-)sliced VBI state */
 	cx->vbi.sliced_in->service_set = 0;
 	cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
-	cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+
 	return cx18_g_fmt_vbi_cap(file, fh, fmt);
 }
 
 static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	return -EINVAL;
+	struct cx18_open_id *id = fh;
+	struct cx18 *cx = id->cx;
+	int ret;
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+	ret = v4l2_prio_check(&cx->prio, &id->prio);
+	if (ret)
+		return ret;
+
+	cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
+
+	/*
+	 * Changing the Encoder's Raw VBI parameters won't have any effect
+	 * if any analog capture is ongoing
+	 */
+	if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
+		return -EBUSY;
+
+	/*
+	 * Set the service_lines requested in the digitizer/slicer registers.
+	 * Note, cx18_av_vbi() wipes some "impossible" service lines in the
+	 * passed in fmt->fmt.sliced under valid calling conditions
+	 */
+	ret = v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt);
+	if (ret)
+		return ret;
+	/* Store our current v4l2 sliced VBI settings */
+	cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+	memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
+	return 0;
 }
 
 static int cx18_g_chip_ident(struct file *file, void *fh,
 				struct v4l2_dbg_chip_ident *chip)
 {
 	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	int err = 0;
 
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
-	if (v4l2_chip_match_host(&chip->match)) {
-		chip->ident = V4L2_IDENT_CX23418;
-		return 0;
+	switch (chip->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		switch (chip->match.addr) {
+		case 0:
+			chip->ident = V4L2_IDENT_CX23418;
+			chip->revision = cx18_read_reg(cx, 0xC72028);
+			break;
+		case 1:
+			/*
+			 * The A/V decoder is always present, but in the rare
+			 * case that the card doesn't have analog, we don't
+			 * use it.  We find it w/o using the cx->sd_av pointer
+			 */
+			cx18_call_hw(cx, CX18_HW_418_AV,
+				     core, g_chip_ident, chip);
+			break;
+		default:
+			/*
+			 * Could return ident = V4L2_IDENT_UNKNOWN if we had
+			 * other host chips at higher addresses, but we don't
+			 */
+			err = -EINVAL; /* per V4L2 spec */
+			break;
+		}
+		break;
+	case V4L2_CHIP_MATCH_I2C_DRIVER:
+		/* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
+		cx18_call_all(cx, core, g_chip_ident, chip);
+		break;
+	case V4L2_CHIP_MATCH_I2C_ADDR:
+		/*
+		 * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
+		 * to look if a chip is at the address with no driver.  That's a
+		 * dangerous thing to do with EEPROMs anyway.
+		 */
+		cx18_call_all(cx, core, g_chip_ident, chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
 	}
-	cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip);
-	return 0;
+	return err;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 {
 	struct v4l2_dbg_register *regs = arg;
-	unsigned long flags;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
 		return -EINVAL;
 
-	spin_lock_irqsave(&cx18_cards_lock, flags);
 	regs->size = 4;
-	if (cmd == VIDIOC_DBG_G_REGISTER)
-		regs->val = cx18_read_enc(cx, regs->reg);
-	else
+	if (cmd == VIDIOC_DBG_S_REGISTER)
 		cx18_write_enc(cx, regs->val, regs->reg);
-	spin_unlock_irqrestore(&cx18_cards_lock, flags);
+	else
+		regs->val = cx18_read_enc(cx, regs->reg);
 	return 0;
 }
 
@@ -296,7 +445,8 @@
 
 	if (v4l2_chip_match_host(&reg->match))
 		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
-	cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg);
+	/* FIXME - errors shouldn't be ignored */
+	cx18_call_all(cx, core, g_register, reg);
 	return 0;
 }
 
@@ -307,7 +457,8 @@
 
 	if (v4l2_chip_match_host(&reg->match))
 		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
-	cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg);
+	/* FIXME - errors shouldn't be ignored */
+	cx18_call_all(cx, core, s_register, reg);
 	return 0;
 }
 #endif
@@ -335,7 +486,8 @@
 
 	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
-	snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev));
+	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+		 "PCI:%s", pci_name(cx->pci_dev));
 	vcap->version = CX18_DRIVER_VERSION; 	    /* version */
 	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
 	return 0;
@@ -403,7 +555,8 @@
 
 	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	return cx18_av_cmd(cx, VIDIOC_S_CROP, crop);
+	CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
+	return -EINVAL;
 }
 
 static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
@@ -412,7 +565,8 @@
 
 	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	return cx18_av_cmd(cx, VIDIOC_G_CROP, crop);
+	CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
+	return -EINVAL;
 }
 
 static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
@@ -483,7 +637,7 @@
 	if (vf->tuner != 0)
 		return -EINVAL;
 
-	cx18_call_i2c_clients(cx, VIDIOC_G_FREQUENCY, vf);
+	cx18_call_all(cx, tuner, g_frequency, vf);
 	return 0;
 }
 
@@ -502,7 +656,7 @@
 
 	cx18_mute(cx);
 	CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
-	cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf);
+	cx18_call_all(cx, tuner, s_frequency, vf);
 	cx18_unmute(cx);
 	return 0;
 }
@@ -547,12 +701,11 @@
 	cx->vbi.count = cx->is_50hz ? 18 : 12;
 	cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
 	cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
-	cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
 	CX18_DEBUG_INFO("Switching standard to %llx.\n",
 			(unsigned long long) cx->std);
 
 	/* Tuner */
-	cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+	cx18_call_all(cx, tuner, s_std, cx->std);
 	return 0;
 }
 
@@ -569,9 +722,7 @@
 	if (vt->index != 0)
 		return -EINVAL;
 
-	/* Setting tuner can only set audio mode */
-	cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);
-
+	cx18_call_all(cx, tuner, s_tuner, vt);
 	return 0;
 }
 
@@ -582,7 +733,7 @@
 	if (vt->index != 0)
 		return -EINVAL;
 
-	cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
+	cx18_call_all(cx, tuner, g_tuner, vt);
 
 	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
 		strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
@@ -598,7 +749,30 @@
 static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_sliced_vbi_cap *cap)
 {
-	return -EINVAL;
+	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+	int f, l;
+
+	if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+		return -EINVAL;
+
+	cap->service_set = 0;
+	for (f = 0; f < 2; f++) {
+		for (l = 0; l < 24; l++) {
+			if (valid_service_line(f, l, cx->is_50hz)) {
+				/*
+				 * We can find all v4l2 supported vbi services
+				 * for the standard, on a valid line for the std
+				 */
+				cap->service_lines[f][l] = set;
+				cap->service_set |= set;
+			} else
+				cap->service_lines[f][l] = 0;
+		}
+	}
+	for (f = 0; f < 3; f++)
+		cap->reserved[f] = 0;
+	return 0;
 }
 
 static int cx18_g_enc_index(struct file *file, void *fh,
@@ -708,13 +882,15 @@
 	struct v4l2_audio audin;
 	int i;
 
-	CX18_INFO("=================  START STATUS CARD #%d  =================\n", cx->num);
+	CX18_INFO("=================  START STATUS CARD #%d  "
+		  "=================\n", cx->instance);
+	CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
 	if (cx->hw_flags & CX18_HW_TVEEPROM) {
 		struct tveeprom tv;
 
 		cx18_read_eeprom(cx, &tv);
 	}
-	cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
+	cx18_call_all(cx, core, log_status);
 	cx18_get_input(cx, cx->active_input, &vidin);
 	cx18_get_audio_input(cx, cx->audio_input, &audin);
 	CX18_INFO("Video Input: %s\n", vidin.name);
@@ -725,12 +901,12 @@
 	mutex_unlock(&cx->gpio_lock);
 	CX18_INFO("Tuner: %s\n",
 		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
-	cx2341x_log_status(&cx->params, cx->name);
+	cx2341x_log_status(&cx->params, cx->v4l2_dev.name);
 	CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
 	for (i = 0; i < CX18_MAX_STREAMS; i++) {
 		struct cx18_stream *s = &cx->streams[i];
 
-		if (s->v4l2dev == NULL || s->buffers == 0)
+		if (s->video_dev == NULL || s->buffers == 0)
 			continue;
 		CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
 			  s->name, s->s_flags,
@@ -740,7 +916,8 @@
 	CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
 			(long long)cx->mpg_data_received,
 			(long long)cx->vbi_data_inserted);
-	CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
+	CX18_INFO("==================  END STATUS CARD #%d  "
+		  "==================\n", cx->instance);
 	return 0;
 }
 
@@ -754,7 +931,8 @@
 
 		CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n",
 			route->input, route->output);
-		cx18_audio_set_route(cx, route);
+		cx18_call_hw(cx, cx->card->hw_audio_ctrl, audio, s_routing,
+			     route);
 		break;
 	}
 
@@ -762,7 +940,8 @@
 		u32 val = *(u32 *)arg;
 
 		if ((val == 0) || (val & 0x01))
-			cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]);
+			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
+				     (u32) CX18_GPIO_RESET_Z8F0811);
 		break;
 	}
 
@@ -782,6 +961,8 @@
 
 	mutex_lock(&cx->serialize_lock);
 
+	/* FIXME - consolidate v4l2_prio_check()'s here */
+
 	if (cx18_debug & CX18_DBGFLG_IOCTL)
 		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
 	res = video_ioctl2(filp, cmd, arg);
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index de5e723..2226e57 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -83,6 +83,8 @@
 	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,			0),
 	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,			API_FAST),
 	API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,			API_SLOW),
+	API_ENTRY(APU, CX18_APU_START,				0),
+	API_ENTRY(APU, CX18_APU_STOP,				0),
 	API_ENTRY(APU, CX18_APU_RESETAI,			0),
 	API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32,			0),
 	API_ENTRY(0, 0,						0),
@@ -98,21 +100,30 @@
 	return NULL;
 }
 
+/* Call with buf of n*11+1 bytes */
+static char *u32arr2hex(u32 data[], int n, char *buf)
+{
+	char *p;
+	int i;
+
+	for (i = 0, p = buf; i < n; i++, p += 11) {
+		/* kernel snprintf() appends '\0' always */
+		snprintf(p, 12, " %#010x", data[i]);
+	}
+	*p = '\0';
+	return buf;
+}
+
 static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name)
 {
 	char argstr[MAX_MB_ARGUMENTS*11+1];
-	char *p;
-	int i;
 
 	if (!(cx18_debug & CX18_DBGFLG_API))
 		return;
 
-	for (i = 0, p = argstr; i < MAX_MB_ARGUMENTS; i++, p += 11) {
-		/* kernel snprintf() appends '\0' always */
-		snprintf(p, 12, " %#010x", mb->args[i]);
-	}
 	CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
-		"\n", name, mb->request, mb->ack, mb->cmd, mb->error, argstr);
+		       "\n", name, mb->request, mb->ack, mb->cmd, mb->error,
+		       u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr));
 }
 
 
@@ -439,7 +450,8 @@
 				"incoming %s to EPU mailbox (sequence no. %u)"
 				"\n",
 				rpu_str[rpu], rpu_str[rpu], order_mb->request);
-		dump_mb(cx, order_mb, "incoming");
+		if (cx18_debug & CX18_DBGFLG_WARN)
+			dump_mb(cx, order_mb, "incoming");
 		order->flags = CX18_F_EWO_MB_STALE_UPON_RECEIPT;
 	}
 
@@ -468,16 +480,24 @@
 	struct mutex *mb_lock;
 	long int timeout, ret;
 	int i;
+	char argstr[MAX_MB_ARGUMENTS*11+1];
 
 	if (info == NULL) {
 		CX18_WARN("unknown cmd %x\n", cmd);
 		return -EINVAL;
 	}
 
-	if (cmd == CX18_CPU_DE_SET_MDL)
-		CX18_DEBUG_HI_API("%s\n", info->name);
-	else
-		CX18_DEBUG_API("%s\n", info->name);
+	if (cx18_debug & CX18_DBGFLG_API) { /* only call u32arr2hex if needed */
+		if (cmd == CX18_CPU_DE_SET_MDL) {
+			if (cx18_debug & CX18_DBGFLG_HIGHVOL)
+				CX18_DEBUG_HI_API("%s\tcmd %#010x args%s\n",
+						info->name, cmd,
+						u32arr2hex(data, args, argstr));
+		} else
+			CX18_DEBUG_API("%s\tcmd %#010x args%s\n",
+				       info->name, cmd,
+				       u32arr2hex(data, args, argstr));
+	}
 
 	switch (info->rpu) {
 	case APU:
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
index 8d9441e..3046b8e 100644
--- a/drivers/media/video/cx18/cx18-queue.c
+++ b/drivers/media/video/cx18/cx18-queue.c
@@ -204,7 +204,7 @@
 		}
 		buf->id = cx->buffer_id++;
 		INIT_LIST_HEAD(&buf->list);
-		buf->dma_handle = pci_map_single(s->cx->dev,
+		buf->dma_handle = pci_map_single(s->cx->pci_dev,
 				buf->buf, s->buf_size, s->dma);
 		cx18_buf_sync_for_cpu(s, buf);
 		cx18_enqueue(s, buf, &s->q_free);
@@ -227,7 +227,7 @@
 
 	/* empty q_free */
 	while ((buf = cx18_dequeue(s, &s->q_free))) {
-		pci_unmap_single(s->cx->dev, buf->dma_handle,
+		pci_unmap_single(s->cx->pci_dev, buf->dma_handle,
 				s->buf_size, s->dma);
 		kfree(buf->buf);
 		kfree(buf);
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
index 456cec3..4de0626 100644
--- a/drivers/media/video/cx18/cx18-queue.h
+++ b/drivers/media/video/cx18/cx18-queue.h
@@ -29,14 +29,14 @@
 static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
 	struct cx18_buffer *buf)
 {
-	pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle,
+	pci_dma_sync_single_for_cpu(s->cx->pci_dev, buf->dma_handle,
 				s->buf_size, s->dma);
 }
 
 static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
 	struct cx18_buffer *buf)
 {
-	pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle,
+	pci_dma_sync_single_for_device(s->cx->pci_dev, buf->dma_handle,
 				s->buf_size, s->dma);
 }
 
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 89c1ec9..0932b76 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -32,7 +32,6 @@
 #include "cx18-streams.h"
 #include "cx18-cards.h"
 #include "cx18-scb.h"
-#include "cx18-av-core.h"
 #include "cx18-dvb.h"
 
 #define CX18_DSP0_INTERRUPT_MASK     	0xd0004C
@@ -101,11 +100,11 @@
 static void cx18_stream_init(struct cx18 *cx, int type)
 {
 	struct cx18_stream *s = &cx->streams[type];
-	struct video_device *dev = s->v4l2dev;
+	struct video_device *video_dev = s->video_dev;
 
-	/* we need to keep v4l2dev, so restore it afterwards */
+	/* we need to keep video_dev, so restore it afterwards */
 	memset(s, 0, sizeof(*s));
-	s->v4l2dev = dev;
+	s->video_dev = video_dev;
 
 	/* initialize cx18_stream fields */
 	s->cx = cx;
@@ -130,12 +129,12 @@
 	struct cx18_stream *s = &cx->streams[type];
 	u32 cap = cx->v4l2_cap;
 	int num_offset = cx18_stream_info[type].num_offset;
-	int num = cx->num + cx18_first_minor + num_offset;
+	int num = cx->instance + cx18_first_minor + num_offset;
 
-	/* These four fields are always initialized. If v4l2dev == NULL, then
+	/* These four fields are always initialized. If video_dev == NULL, then
 	   this stream is not in use. In that case no other fields but these
 	   four can be used. */
-	s->v4l2dev = NULL;
+	s->video_dev = NULL;
 	s->cx = cx;
 	s->type = type;
 	s->name = cx18_stream_info[type].name;
@@ -163,22 +162,22 @@
 		return 0;
 
 	/* allocate and initialize the v4l2 video device structure */
-	s->v4l2dev = video_device_alloc();
-	if (s->v4l2dev == NULL) {
+	s->video_dev = video_device_alloc();
+	if (s->video_dev == NULL) {
 		CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
 				s->name);
 		return -ENOMEM;
 	}
 
-	snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
-			cx->num);
+	snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+		 cx->v4l2_dev.name, s->name);
 
-	s->v4l2dev->num = num;
-	s->v4l2dev->parent = &cx->dev->dev;
-	s->v4l2dev->fops = &cx18_v4l2_enc_fops;
-	s->v4l2dev->release = video_device_release;
-	s->v4l2dev->tvnorms = V4L2_STD_ALL;
-	cx18_set_funcs(s->v4l2dev);
+	s->video_dev->num = num;
+	s->video_dev->v4l2_dev = &cx->v4l2_dev;
+	s->video_dev->fops = &cx18_v4l2_enc_fops;
+	s->video_dev->release = video_device_release;
+	s->video_dev->tvnorms = V4L2_STD_ALL;
+	cx18_set_funcs(s->video_dev);
 	return 0;
 }
 
@@ -227,28 +226,30 @@
 		}
 	}
 
-	if (s->v4l2dev == NULL)
+	if (s->video_dev == NULL)
 		return 0;
 
-	num = s->v4l2dev->num;
+	num = s->video_dev->num;
 	/* card number + user defined offset + device offset */
 	if (type != CX18_ENC_STREAM_TYPE_MPG) {
 		struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
 
-		if (s_mpg->v4l2dev)
-			num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset;
+		if (s_mpg->video_dev)
+			num = s_mpg->video_dev->num
+			    + cx18_stream_info[type].num_offset;
 	}
+	video_set_drvdata(s->video_dev, s);
 
 	/* Register device. First try the desired minor, then any free one. */
-	ret = video_register_device(s->v4l2dev, vfl_type, num);
+	ret = video_register_device(s->video_dev, vfl_type, num);
 	if (ret < 0) {
 		CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
 			s->name, num);
-		video_device_release(s->v4l2dev);
-		s->v4l2dev = NULL;
+		video_device_release(s->video_dev);
+		s->video_dev = NULL;
 		return ret;
 	}
-	num = s->v4l2dev->num;
+	num = s->video_dev->num;
 
 	switch (vfl_type) {
 	case VFL_TYPE_GRABBER:
@@ -312,9 +313,9 @@
 			cx->streams[type].dvb.enabled = false;
 		}
 
-		vdev = cx->streams[type].v4l2dev;
+		vdev = cx->streams[type].video_dev;
 
-		cx->streams[type].v4l2dev = NULL;
+		cx->streams[type].video_dev = NULL;
 		if (vdev == NULL)
 			continue;
 
@@ -346,46 +347,88 @@
 	}
 
 	/* setup VBI registers */
-	cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
+	v4l2_subdev_call(cx->sd_av, video, s_fmt, &cx->vbi.in);
 
-	/* determine number of lines and total number of VBI bytes.
-	   A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720
-	   A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
-	   header, 42 data bytes + checksum (to be confirmed) */
+	/*
+	 * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw
+	 * VBI when the first analog capture channel starts, as once it starts
+	 * (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup
+	 * (i.e. for the VBI capture channels).  We also send it for each
+	 * analog capture channel anyway just to make sure we get the proper
+	 * behavior
+	 */
 	if (raw) {
 		lines = cx->vbi.count * 2;
 	} else {
-		lines = cx->is_60hz ? 24 : 38;
-		if (cx->is_60hz)
-			lines += 2;
+		/*
+		 * For 525/60 systems, according to the VIP 2 & BT.656 std:
+		 * The EAV RP code's Field bit toggles on line 4, a few lines
+		 * after the Vertcal Blank bit has already toggled.
+		 * Tell the encoder to capture 21-4+1=18 lines per field,
+		 * since we want lines 10 through 21.
+		 *
+		 * FIXME - revisit for 625/50 systems
+		 */
+		lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38;
 	}
 
-	cx->vbi.enc_size = lines *
-		(raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
-
 	data[0] = s->handle;
 	/* Lines per field */
 	data[1] = (lines / 2) | ((lines / 2) << 16);
 	/* bytes per line */
-	data[2] = (raw ? cx->vbi.raw_decoder_line_size
-		       : cx->vbi.sliced_decoder_line_size);
+	data[2] = (raw ? vbi_active_samples
+		       : (cx->is_60hz ? vbi_hblank_samples_60Hz
+				      : vbi_hblank_samples_50Hz));
 	/* Every X number of frames a VBI interrupt arrives
 	   (frames as in 25 or 30 fps) */
 	data[3] = 1;
-	/* Setup VBI for the cx25840 digitizer */
+	/*
+	 * Set the SAV/EAV RP codes to look for as start/stop points
+	 * when in VIP-1.1 mode
+	 */
 	if (raw) {
+		/*
+		 * Start codes for beginning of "active" line in vertical blank
+		 * 0x20 (               VerticalBlank                )
+		 * 0x60 (     EvenField VerticalBlank                )
+		 */
 		data[4] = 0x20602060;
+		/*
+		 * End codes for end of "active" raw lines and regular lines
+		 * 0x30 (               VerticalBlank HorizontalBlank)
+		 * 0x70 (     EvenField VerticalBlank HorizontalBlank)
+		 * 0x90 (Task                         HorizontalBlank)
+		 * 0xd0 (Task EvenField               HorizontalBlank)
+		 */
 		data[5] = 0x307090d0;
 	} else {
+		/*
+		 * End codes for active video, we want data in the hblank region
+		 * 0xb0 (Task         0 VerticalBlank HorizontalBlank)
+		 * 0xf0 (Task EvenField VerticalBlank HorizontalBlank)
+		 *
+		 * Since the V bit is only allowed to toggle in the EAV RP code,
+		 * just before the first active region line, these two
+		 * are problematic:
+		 * 0x90 (Task                         HorizontalBlank)
+		 * 0xd0 (Task EvenField               HorizontalBlank)
+		 *
+		 * We have set the digitzer such that we don't have to worry
+		 * about these problem codes.
+		 */
 		data[4] = 0xB0F0B0F0;
+		/*
+		 * Start codes for beginning of active line in vertical blank
+		 * 0xa0 (Task           VerticalBlank                )
+		 * 0xe0 (Task EvenField VerticalBlank                )
+		 */
 		data[5] = 0xA0E0A0E0;
 	}
 
 	CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
 			data[0], data[1], data[2], data[3], data[4], data[5]);
 
-	if (s->type == CX18_ENC_STREAM_TYPE_VBI)
-		cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+	cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
 }
 
 struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
@@ -434,10 +477,10 @@
 	u32 data[MAX_MB_ARGUMENTS];
 	struct cx18 *cx = s->cx;
 	struct cx18_buffer *buf;
-	int ts = 0;
 	int captype = 0;
+	struct cx18_api_func_private priv;
 
-	if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+	if (s->video_dev == NULL && s->dvb.enabled == 0)
 		return -EINVAL;
 
 	CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
@@ -453,7 +496,6 @@
 
 	case CX18_ENC_STREAM_TYPE_TS:
 		captype = CAPTURE_CHANNEL_TYPE_TS;
-		ts = 1;
 		break;
 	case CX18_ENC_STREAM_TYPE_YUV:
 		captype = CAPTURE_CHANNEL_TYPE_YUV;
@@ -462,8 +504,16 @@
 		captype = CAPTURE_CHANNEL_TYPE_PCM;
 		break;
 	case CX18_ENC_STREAM_TYPE_VBI:
+#ifdef CX18_ENCODER_PARSES_SLICED
 		captype = cx18_raw_vbi(cx) ?
 		     CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI;
+#else
+		/*
+		 * Currently we set things up so that Sliced VBI from the
+		 * digitizer is handled as Raw VBI by the encoder
+		 */
+		captype = CAPTURE_CHANNEL_TYPE_VBI;
+#endif
 		cx->vbi.frame = 0;
 		cx->vbi.inserted_frame = 0;
 		memset(cx->vbi.sliced_mpeg_size,
@@ -473,10 +523,6 @@
 		return -EINVAL;
 	}
 
-	/* mute/unmute video */
-	cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
-		  s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags));
-
 	/* Clear Streamoff flags in case left from last capture */
 	clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
 
@@ -484,31 +530,63 @@
 	s->handle = data[0];
 	cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
 
-	if (atomic_read(&cx->ana_capturing) == 0 && !ts) {
-		struct cx18_api_func_private priv;
-
-		/* Stuff from Windows, we don't know what it is */
+	/*
+	 * For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and
+	 * set up all the parameters, as it is not obvious which parameters the
+	 * firmware shares across capture channel types and which it does not.
+	 *
+	 * Some of the cx18_vapi() calls below apply to only certain capture
+	 * channel types.  We're hoping there's no harm in calling most of them
+	 * anyway, as long as the values are all consistent.  Setting some
+	 * shared parameters will have no effect once an analog capture channel
+	 * has started streaming.
+	 */
+	if (captype != CAPTURE_CHANNEL_TYPE_TS) {
 		cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
 		cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
 		cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
 		cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
-		cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12);
 
+		/*
+		 * Audio related reset according to
+		 * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+		 */
+		if (atomic_read(&cx->ana_capturing) == 0)
+			cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
+				  s->handle, 12);
+
+		/*
+		 * Number of lines for Field 1 & Field 2 according to
+		 * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+		 * Field 1 is 312 for 625 line systems in BT.656
+		 * Field 2 is 313 for 625 line systems in BT.656
+		 */
 		cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
-			       s->handle, cx->digitizer, cx->digitizer);
+			  s->handle, 312, 313);
 
-		/* Setup VBI */
 		if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
 			cx18_vbi_setup(s);
 
-		/* assign program index info.
-		   Mask 7: select I/P/B, Num_req: 400 max */
+		/*
+		 * assign program index info.
+		 * Mask 7: select I/P/B, Num_req: 400 max
+		 * FIXME - currently we have this hardcoded as disabled
+		 */
 		cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0);
 
-		/* Setup API for Stream */
+		/* Call out to the common CX2341x API setup for user controls */
 		priv.cx = cx;
 		priv.s = s;
 		cx2341x_update(&priv, cx18_api_func, NULL, &cx->params);
+
+		/*
+		 * When starting a capture and we're set for radio,
+		 * ensure the video is muted, despite the user control.
+		 */
+		if (!cx->params.video_mute &&
+		    test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
+			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+				  (cx->params.video_mute_yuv << 8) | 1);
 	}
 
 	if (atomic_read(&cx->tot_capturing) == 0) {
@@ -552,7 +630,7 @@
 	}
 
 	/* you're live! sit back and await interrupts :) */
-	if (!ts)
+	if (captype != CAPTURE_CHANNEL_TYPE_TS)
 		atomic_inc(&cx->ana_capturing);
 	atomic_inc(&cx->tot_capturing);
 	return 0;
@@ -565,7 +643,7 @@
 	for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
 		struct cx18_stream *s = &cx->streams[i];
 
-		if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+		if (s->video_dev == NULL && s->dvb.enabled == 0)
 			continue;
 		if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
 			cx18_stop_v4l2_encode_stream(s, 0);
@@ -577,7 +655,7 @@
 	struct cx18 *cx = s->cx;
 	unsigned long then;
 
-	if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+	if (s->video_dev == NULL && s->dvb.enabled == 0)
 		return -EINVAL;
 
 	/* This function assumes that you are allowed to stop the capture
@@ -629,7 +707,7 @@
 	for (i = 0; i < CX18_MAX_STREAMS; i++) {
 		struct cx18_stream *s = &cx->streams[i];
 
-		if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE))
+		if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
 			return s->handle;
 	}
 	return CX18_INVALID_TASK_HANDLE;
@@ -647,7 +725,7 @@
 		s = &cx->streams[i];
 		if (s->handle != handle)
 			continue;
-		if (s->v4l2dev || s->dvb.enabled)
+		if (s->video_dev || s->dvb.enabled)
 			return s;
 	}
 	return NULL;
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c
index fb595bd..c2aef4a 100644
--- a/drivers/media/video/cx18/cx18-vbi.c
+++ b/drivers/media/video/cx18/cx18-vbi.c
@@ -25,7 +25,16 @@
 #include "cx18-vbi.h"
 #include "cx18-ioctl.h"
 #include "cx18-queue.h"
-#include "cx18-av-core.h"
+
+/*
+ * Raster Reference/Protection (RP) bytes, used in Start/End Active
+ * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
+ * of VBI sample or VBI ancilliary data regions in the digitial ratser line.
+ *
+ * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
+ */
+static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 };    /* __V_, _FV_ */
+static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */
 
 static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
 {
@@ -34,10 +43,17 @@
 	u32 linemask[2] = { 0, 0 };
 	unsigned short size;
 	static const u8 mpeg_hdr_data[] = {
-		0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
-		0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
-		0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
-		0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
+		/* MPEG-2 Program Pack */
+		0x00, 0x00, 0x01, 0xba,		    /* Prog Pack start code */
+		0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */
+		0x01, 0xd1, 0xd3,		    /* Mux Rate, markers */
+		0xfa, 0xff, 0xff,		    /* Res, Suff cnt, Stuff */
+		/* MPEG-2 Private Stream 1 PES Packet */
+		0x00, 0x00, 0x01, 0xbd,		    /* Priv Stream 1 start */
+		0x00, 0x1a,			    /* length */
+		0x84, 0x80, 0x07,		    /* flags, hdr data len */
+		0x21, 0x00, 0x5d, 0x63, 0xa7, 	    /* PTS, markers */
+		0xff, 0xff			    /* stuffing */
 	};
 	const int sd = sizeof(mpeg_hdr_data);	/* start of vbi data */
 	int idx = cx->vbi.frame % CX18_VBI_FRAMES;
@@ -71,7 +87,9 @@
 		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
 		size = 4 + ((43 * line + 3) & ~3);
 	} else {
-		memcpy(dst + sd, "cx0", 4);
+		memcpy(dst + sd, "itv0", 4);
+		cpu_to_le32s(&linemask[0]);
+		cpu_to_le32s(&linemask[1]);
 		memcpy(dst + sd + 4, &linemask[0], 8);
 		size = 12 + ((43 * line + 3) & ~3);
 	}
@@ -86,58 +104,76 @@
 }
 
 /* Compress raw VBI format, removes leading SAV codes and surplus space
-   after the field.
-   Returns new compressed size. */
-static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
+   after the frame.  Returns new compressed size. */
+static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
 {
-	u32 line_size = cx->vbi.raw_decoder_line_size;
-	u32 lines = cx->vbi.count;
-	u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
-	u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
+	u32 line_size = vbi_active_samples;
+	u32 lines = cx->vbi.count * 2;
 	u8 *q = buf;
 	u8 *p;
 	int i;
 
+	/* Skip the header */
+	buf += hdr_size;
+
 	for (i = 0; i < lines; i++) {
 		p = buf + i * line_size;
 
 		/* Look for SAV code */
 		if (p[0] != 0xff || p[1] || p[2] ||
-		    (p[3] != sav1 && p[3] != sav2))
+		    (p[3] != raw_vbi_sav_rp[0] &&
+		     p[3] != raw_vbi_sav_rp[1]))
 			break;
-		memcpy(q, p + 4, line_size - 4);
-		q += line_size - 4;
+		if (i == lines - 1) {
+			/* last line is hdr_size bytes short - extrapolate it */
+			memcpy(q, p + 4, line_size - 4 - hdr_size);
+			q += line_size - 4 - hdr_size;
+			p += line_size - hdr_size - 1;
+			memset(q, (int) *p, hdr_size);
+		} else {
+			memcpy(q, p + 4, line_size - 4);
+			q += line_size - 4;
+		}
 	}
 	return lines * (line_size - 4);
 }
 
-
-/* Compressed VBI format, all found sliced blocks put next to one another
-   Returns new compressed size */
-static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
-			       u32 size, u8 sav)
+static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
+			       const u32 hdr_size)
 {
-	u32 line_size = cx->vbi.sliced_decoder_line_size;
 	struct v4l2_decode_vbi_line vbi;
 	int i;
+	u32 line = 0;
+	u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
+				    : vbi_hblank_samples_50Hz;
 
 	/* find the first valid line */
-	for (i = 0; i < size; i++, buf++) {
-		if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+	for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) {
+		if (buf[0] == 0xff && !buf[1] && !buf[2] &&
+		    (buf[3] == sliced_vbi_eav_rp[0] ||
+		     buf[3] == sliced_vbi_eav_rp[1]))
 			break;
 	}
 
-	size -= i;
+	/*
+	 * The last line is short by hdr_size bytes, but for the remaining
+	 * checks against size, we pretend that it is not, by counting the
+	 * header bytes we knowingly skipped
+	 */
+	size -= (i - hdr_size);
 	if (size < line_size)
 		return line;
+
 	for (i = 0; i < size / line_size; i++) {
 		u8 *p = buf + i * line_size;
 
-		/* Look for SAV code  */
-		if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
+		/* Look for EAV code  */
+		if (p[0] != 0xff || p[1] || p[2] ||
+		    (p[3] != sliced_vbi_eav_rp[0] &&
+		     p[3] != sliced_vbi_eav_rp[1]))
 			continue;
 		vbi.p = p + 4;
-		cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
+		v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi);
 		if (vbi.type) {
 			cx->vbi.sliced_data[line].id = vbi.type;
 			cx->vbi.sliced_data[line].field = vbi.is_second_field;
@@ -150,51 +186,56 @@
 }
 
 void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
-			   u64 pts_stamp, int streamtype)
+			   int streamtype)
 {
+	/*
+	 * The CX23418 provides a 12 byte header in its raw VBI buffers to us:
+	 * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp]
+	 */
+	struct vbi_data_hdr {
+		__be32 magic;
+		__be32 unknown;
+		__be32 pts;
+	} *hdr = (struct vbi_data_hdr *) buf->buf;
+
 	u8 *p = (u8 *) buf->buf;
 	u32 size = buf->bytesused;
+	u32 pts;
 	int lines;
 
 	if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
 		return;
 
+	/*
+	 * The CX23418 sends us data that is 32 bit little-endian swapped,
+	 * but we want the raw VBI bytes in the order they were in the raster
+	 * line.  This has a side effect of making the header big endian
+	 */
+	cx18_buf_swap(buf);
+
 	/* Raw VBI data */
 	if (cx18_raw_vbi(cx)) {
-		u8 type;
 
-		cx18_buf_swap(buf);
+		size = buf->bytesused =
+		     compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr));
 
-		/* Skip 12 bytes of header that gets stuffed in */
-		size -= 12;
-		memcpy(p, &buf->buf[12], size);
-		type = p[3];
-
-		size = buf->bytesused = compress_raw_buf(cx, p, size);
-
-		/* second field of the frame? */
-		if (type == cx->vbi.raw_decoder_sav_even_field) {
-			/* Dirty hack needed for backwards
-			   compatibility of old VBI software. */
-			p += size - 4;
-			memcpy(p, &cx->vbi.frame, 4);
-			cx->vbi.frame++;
-		}
+		/*
+		 * Hack needed for compatibility with old VBI software.
+		 * Write the frame # at the last 4 bytes of the frame
+		 */
+		p += size - 4;
+		memcpy(p, &cx->vbi.frame, 4);
+		cx->vbi.frame++;
 		return;
 	}
 
 	/* Sliced VBI data with data insertion */
-	cx18_buf_swap(buf);
 
-	/* first field */
-	lines = compress_sliced_buf(cx, 0, p, size / 2,
-			cx->vbi.sliced_decoder_sav_odd_field);
-	/* second field */
-	/* experimentation shows that the second half does not always
-	   begin at the exact address. So start a bit earlier
-	   (hence 32). */
-	lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
-			size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
+	pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts)
+						      : 0;
+
+	lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr));
+
 	/* always return at least one empty line */
 	if (lines == 0) {
 		cx->vbi.sliced_data[0].id = 0;
@@ -206,6 +247,6 @@
 	memcpy(p, &cx->vbi.sliced_data[0], size);
 
 	if (cx->vbi.insert_mpeg)
-		copy_vbi_data(cx, lines, pts_stamp);
+		copy_vbi_data(cx, lines, pts);
 	cx->vbi.frame++;
 }
diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h
index c56ff7d..e7e1ae4 100644
--- a/drivers/media/video/cx18/cx18-vbi.h
+++ b/drivers/media/video/cx18/cx18-vbi.h
@@ -22,5 +22,5 @@
  */
 
 void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
-			   u64 pts_stamp, int streamtype);
+			   int streamtype);
 int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
index 84c0ff1..bd9bd44 100644
--- a/drivers/media/video/cx18/cx18-version.h
+++ b/drivers/media/video/cx18/cx18-version.h
@@ -24,8 +24,8 @@
 
 #define CX18_DRIVER_NAME "cx18"
 #define CX18_DRIVER_VERSION_MAJOR 1
-#define CX18_DRIVER_VERSION_MINOR 0
-#define CX18_DRIVER_VERSION_PATCHLEVEL 4
+#define CX18_DRIVER_VERSION_MINOR 1
+#define CX18_DRIVER_VERSION_PATCHLEVEL 0
 
 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
 #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c
index 2e5c419..6fdaded 100644
--- a/drivers/media/video/cx18/cx18-video.c
+++ b/drivers/media/video/cx18/cx18-video.c
@@ -21,7 +21,6 @@
 
 #include "cx18-driver.h"
 #include "cx18-video.h"
-#include "cx18-av-core.h"
 #include "cx18-cards.h"
 
 void cx18_video_set_io(struct cx18 *cx)
@@ -32,7 +31,7 @@
 
 	route.input = cx->card->video_inputs[inp].video_input;
 	route.output = 0;
-	cx18_av_cmd(cx, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+	v4l2_subdev_call(cx->sd_av, video, s_routing, &route);
 
 	type = cx->card->video_inputs[inp].video_type;
 
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index 601f3a2..9956abf 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -56,6 +56,22 @@
 #define APU_CMD_MASK 				0x10000000
 #define APU_CMD_MASK_ACK 			(APU_CMD_MASK | 0x80000000)
 
+#define CX18_APU_ENCODING_METHOD_MPEG		(0 << 28)
+#define CX18_APU_ENCODING_METHOD_AC3		(1 << 28)
+
+/* Description: Command APU to start audio
+   IN[0] - audio parameters (same as CX18_CPU_SET_AUDIO_PARAMETERS?)
+   IN[1] - caller buffer address, or 0
+   ReturnCode - ??? */
+#define CX18_APU_START				(APU_CMD_MASK | 0x01)
+
+/* Description: Command APU to stop audio
+   IN[0] - encoding method to stop
+   ReturnCode - ??? */
+#define CX18_APU_STOP				(APU_CMD_MASK | 0x02)
+
+/* Description: Command APU to reset the AI
+   ReturnCode - ??? */
 #define CX18_APU_RESETAI 			(APU_CMD_MASK | 0x05)
 
 /* Description: This command indicates that a Memory Descriptor List has been
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index cbbe47f..8ded529 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -1,5 +1,5 @@
 /*
- * cx2341x - generic code for cx23415/6 based devices
+ * cx2341x - generic code for cx23415/6/8 based devices
  *
  * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
  *
@@ -30,7 +30,7 @@
 #include <media/cx2341x.h>
 #include <media/v4l2-common.h>
 
-MODULE_DESCRIPTION("cx23415/6 driver");
+MODULE_DESCRIPTION("cx23415/6/8 driver");
 MODULE_AUTHOR("Hans Verkuil");
 MODULE_LICENSE("GPL");
 
@@ -38,6 +38,7 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+/* Must be sorted from low to high control ID! */
 const u32 cx2341x_mpeg_ctrls[] = {
 	V4L2_CID_MPEG_CLASS,
 	V4L2_CID_MPEG_STREAM_TYPE,
@@ -50,6 +51,7 @@
 	V4L2_CID_MPEG_AUDIO_EMPHASIS,
 	V4L2_CID_MPEG_AUDIO_CRC,
 	V4L2_CID_MPEG_AUDIO_MUTE,
+	V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
 	V4L2_CID_MPEG_VIDEO_ENCODING,
 	V4L2_CID_MPEG_VIDEO_ASPECT,
 	V4L2_CID_MPEG_VIDEO_B_FRAMES,
@@ -94,6 +96,7 @@
 	.audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
 	.audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
 	.audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+	.audio_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_224K,
 	.audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
 	.audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
 	.audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
@@ -148,6 +151,9 @@
 	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
 		ctrl->value = params->audio_l2_bitrate;
 		break;
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		ctrl->value = params->audio_ac3_bitrate;
+		break;
 	case V4L2_CID_MPEG_AUDIO_MODE:
 		ctrl->value = params->audio_mode;
 		break;
@@ -256,6 +262,12 @@
 		params->audio_sampling_freq = ctrl->value;
 		break;
 	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		if (busy)
+			return -EBUSY;
+		if (params->capabilities & CX2341X_CAP_HAS_AC3)
+			if (ctrl->value != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+			    ctrl->value != V4L2_MPEG_AUDIO_ENCODING_AC3)
+				return -ERANGE;
 		params->audio_encoding = ctrl->value;
 		break;
 	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
@@ -263,6 +275,13 @@
 			return -EBUSY;
 		params->audio_l2_bitrate = ctrl->value;
 		break;
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		if (busy)
+			return -EBUSY;
+		if (!(params->capabilities & CX2341X_CAP_HAS_AC3))
+			return -EINVAL;
+		params->audio_ac3_bitrate = ctrl->value;
+		break;
 	case V4L2_CID_MPEG_AUDIO_MODE:
 		params->audio_mode = ctrl->value;
 		break;
@@ -481,29 +500,106 @@
 	int err;
 
 	switch (qctrl->id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
+			return v4l2_ctrl_query_fill(qctrl,
+					V4L2_MPEG_STREAM_VBI_FMT_NONE,
+					V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
+					V4L2_MPEG_STREAM_VBI_FMT_NONE);
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
+				default_params.stream_vbi_fmt);
+
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+
 	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		if (params->capabilities & CX2341X_CAP_HAS_AC3) {
+			/*
+			 * The state of L2 & AC3 bitrate controls can change
+			 * when this control changes, but v4l2_ctrl_query_fill()
+			 * already sets V4L2_CTRL_FLAG_UPDATE for
+			 * V4L2_CID_MPEG_AUDIO_ENCODING, so we don't here.
+			 */
+			return v4l2_ctrl_query_fill(qctrl,
+					V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+					V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
+					default_params.audio_encoding);
+		}
+
 		return v4l2_ctrl_query_fill(qctrl,
 				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
 				V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
 				default_params.audio_encoding);
 
 	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl,
+		err = v4l2_ctrl_query_fill(qctrl,
 				V4L2_MPEG_AUDIO_L2_BITRATE_192K,
 				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
 				default_params.audio_l2_bitrate);
+		if (err)
+			return err;
+		if (params->capabilities & CX2341X_CAP_HAS_AC3 &&
+		    params->audio_encoding != V4L2_MPEG_AUDIO_ENCODING_LAYER_2)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
 
-	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
-	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
-		return -EINVAL;
+	case V4L2_CID_MPEG_AUDIO_MODE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_MODE_STEREO,
+				V4L2_MPEG_AUDIO_MODE_MONO, 1,
+				V4L2_MPEG_AUDIO_MODE_STEREO);
 
 	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
-		err = v4l2_ctrl_query_fill_std(qctrl);
+		err = v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
 		if (err == 0 &&
 		    params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
 			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 		return err;
 
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+				V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
+				V4L2_MPEG_AUDIO_EMPHASIS_NONE);
+
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_CRC_NONE,
+				V4L2_MPEG_AUDIO_CRC_CRC16, 1,
+				V4L2_MPEG_AUDIO_CRC_NONE);
+
+	case V4L2_CID_MPEG_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		err = v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_48K,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 1,
+				default_params.audio_ac3_bitrate);
+		if (err)
+			return err;
+		if (params->capabilities & CX2341X_CAP_HAS_AC3) {
+			if (params->audio_encoding !=
+						   V4L2_MPEG_AUDIO_ENCODING_AC3)
+				qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		} else
+			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+		return 0;
+
 	case V4L2_CID_MPEG_VIDEO_ENCODING:
 		/* this setting is read-only for the cx2341x since the
 		   V4L2_CID_MPEG_STREAM_TYPE really determines the
@@ -516,32 +612,51 @@
 			qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 		return err;
 
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ASPECT_1x1,
+				V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
+				V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
+
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
+				params->is_50hz ? 12 : 15);
+
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
+
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-		err = v4l2_ctrl_query_fill_std(qctrl);
+		err = v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 		if (err == 0 &&
 		    params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
 			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 		return err;
 
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
+
 	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-		err = v4l2_ctrl_query_fill_std(qctrl);
+		err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
 		if (err == 0 &&
 		    params->video_bitrate_mode ==
 				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
 		return err;
 
-	case V4L2_CID_MPEG_STREAM_VBI_FMT:
-		if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
-			return v4l2_ctrl_query_fill_std(qctrl);
-		return cx2341x_ctrl_query_fill(qctrl,
-				V4L2_MPEG_STREAM_VBI_FMT_NONE,
-				V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
-				default_params.stream_vbi_fmt);
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
 
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
-				params->is_50hz ? 12 : 15);
+	case V4L2_CID_MPEG_VIDEO_MUTE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+
+	case V4L2_CID_MPEG_VIDEO_MUTE_YUV:  /* Init YUV (really YCbCr) to black */
+		return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
 
 	/* CX23415/6 specific */
 	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
@@ -643,7 +758,7 @@
 				default_params.stream_insert_nav_packets);
 
 	default:
-		return v4l2_ctrl_query_fill_std(qctrl);
+		return -EINVAL;
 
 	}
 }
@@ -671,6 +786,15 @@
 		NULL
 	};
 
+	static const char *mpeg_audio_encoding_l2_ac3[] = {
+		"",
+		"MPEG-1/2 Layer II",
+		"",
+		"",
+		"AC-3",
+		NULL
+	};
+
 	static const char *cx2341x_video_spatial_filter_mode_menu[] = {
 		"Manual",
 		"Auto",
@@ -711,6 +835,9 @@
 	case V4L2_CID_MPEG_STREAM_TYPE:
 		return (p->capabilities & CX2341X_CAP_HAS_TS) ?
 			mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return (p->capabilities & CX2341X_CAP_HAS_AC3) ?
+			mpeg_audio_encoding_l2_ac3 : v4l2_ctrl_get_menu(id);
 	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
 	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
 		return NULL;
@@ -730,16 +857,34 @@
 }
 EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
 
+/* definitions for audio properties bits 29-28 */
+#define CX2341X_AUDIO_ENCODING_METHOD_MPEG	0
+#define CX2341X_AUDIO_ENCODING_METHOD_AC3	1
+#define CX2341X_AUDIO_ENCODING_METHOD_LPCM	2
+
 static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
 {
-	params->audio_properties = (params->audio_sampling_freq << 0) |
-		((3 - params->audio_encoding) << 2) |
-		((1 + params->audio_l2_bitrate) << 4) |
+	params->audio_properties =
+		(params->audio_sampling_freq << 0) |
 		(params->audio_mode << 8) |
 		(params->audio_mode_extension << 10) |
 		(((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
 		  ? 3 : params->audio_emphasis) << 12) |
 		(params->audio_crc << 14);
+
+	if ((params->capabilities & CX2341X_CAP_HAS_AC3) &&
+	    params->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+		params->audio_properties |=
+			/* Not sure if this MPEG Layer II setting is required */
+			((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
+			(params->audio_ac3_bitrate << 4) |
+			(CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
+	} else {
+		/* Assuming MPEG Layer II */
+		params->audio_properties |=
+			((3 - params->audio_encoding) << 2) |
+			((1 + params->audio_l2_bitrate) << 4);
+	}
 }
 
 int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
@@ -1022,7 +1167,10 @@
 		prefix,
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
-		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
+		cx2341x_menu_item(p,
+			   p->audio_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3
+					      ? V4L2_CID_MPEG_AUDIO_AC3_BITRATE
+					      : V4L2_CID_MPEG_AUDIO_L2_BITRATE),
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
 		p->audio_mute ? " (muted)" : "");
 	if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index 00f1e2e..fd3fc3e 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -15,12 +15,15 @@
 	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+	select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select DVB_STV6110 if !DVB_FE_CUSTOMISE
+	select DVB_STV0900 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This is a video4linux driver for Conexant 23885 based
 	  TV cards.
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
index 29c23b4..ab8ea35 100644
--- a/drivers/media/video/cx23885/Makefile
+++ b/drivers/media/video/cx23885/Makefile
@@ -1,4 +1,6 @@
-cx23885-objs	:= cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
+cx23885-objs	:= cx23885-cards.o cx23885-video.o cx23885-vbi.o \
+		    cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
+		    netup-init.o cimax2.o netup-eeprom.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 
diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c
new file mode 100644
index 0000000..9a65369
--- /dev/null
+++ b/drivers/media/video/cx23885/cimax2.c
@@ -0,0 +1,472 @@
+/*
+ * cimax2.c
+ *
+ * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 "cx23885.h"
+#include "dvb_ca_en50221.h"
+/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
+  bits 31-16
++-----------+
+| Reserved  |
++-----------+
+  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
++-------+-------+-------+-------+-------+-------+-------+-------+
+|  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+/* MC417 */
+#define NETUP_DATA		0x000000ff
+#define NETUP_WR		0x00008000
+#define NETUP_RD		0x00004000
+#define NETUP_ACK		0x00001000
+#define NETUP_ADHI		0x00000800
+#define NETUP_ADLO		0x00000400
+#define NETUP_CS1		0x00000200
+#define NETUP_CS0		0x00000100
+#define NETUP_EN_ALL		0x00001000
+#define NETUP_CTRL_OFF		(NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)
+#define NETUP_CI_CTL		0x04
+#define NETUP_CI_RD		1
+
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+#define ci_dbg_print(args...) \
+	do { \
+		if (ci_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+/* stores all private variables for communication with CI */
+struct netup_ci_state {
+	struct dvb_ca_en50221 ca;
+	struct mutex ca_mutex;
+	struct i2c_adapter *i2c_adap;
+	u8 ci_i2c_addr;
+	int status;
+	struct work_struct work;
+	void *priv;
+};
+
+struct mutex gpio_mutex;/* Two CiMax's uses same GPIO lines */
+
+int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+						u8 *buf, int len)
+{
+	int ret;
+	struct i2c_msg msg[] = {
+		{
+			.addr	= addr,
+			.flags	= 0,
+			.buf	= &reg,
+			.len	= 1
+		}, {
+			.addr	= addr,
+			.flags	= I2C_M_RD,
+			.buf	= buf,
+			.len	= len
+		}
+	};
+
+	ret = i2c_transfer(i2c_adap, msg, 2);
+
+	if (ret != 2) {
+		ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",
+						__func__, reg, ret);
+
+		return -1;
+	}
+
+	ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",
+						__func__, addr, reg, buf[0]);
+
+	return 0;
+}
+
+int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+						u8 *buf, int len)
+{
+	int ret;
+	u8 buffer[len + 1];
+
+	struct i2c_msg msg = {
+		.addr	= addr,
+		.flags	= 0,
+		.buf	= &buffer[0],
+		.len	= len + 1
+	};
+
+	buffer[0] = reg;
+	memcpy(&buffer[1], buf, len);
+
+	ret = i2c_transfer(i2c_adap, &msg, 1);
+
+	if (ret != 1) {
+		ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",
+						__func__, reg, ret);
+		return -1;
+	}
+
+	return 0;
+}
+
+int netup_ci_get_mem(struct cx23885_dev *dev)
+{
+	int mem;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+	for (;;) {
+		mem = cx_read(MC417_RWD);
+		if ((mem & NETUP_ACK) == 0)
+			break;
+		if (time_after(jiffies, timeout))
+			break;
+		udelay(1);
+	}
+
+	cx_set(MC417_RWD, NETUP_CTRL_OFF);
+
+	return mem & 0xff;
+}
+
+int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+				u8 flag, u8 read, int addr, u8 data)
+{
+	struct netup_ci_state *state = en50221->data;
+	struct cx23885_tsport *port = state->priv;
+	struct cx23885_dev *dev = port->dev;
+
+	u8 store;
+	int mem;
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &store, 1);
+	if (ret != 0)
+		return ret;
+
+	store &= ~0x0c;
+	store |= flag;
+
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &store, 1);
+	if (ret != 0)
+		return ret;
+
+	mutex_lock(&gpio_mutex);
+
+	/* write addr */
+	cx_write(MC417_OEN, NETUP_EN_ALL);
+	cx_write(MC417_RWD, NETUP_CTRL_OFF |
+				NETUP_ADLO | (0xff & addr));
+	cx_clear(MC417_RWD, NETUP_ADLO);
+	cx_write(MC417_RWD, NETUP_CTRL_OFF |
+				NETUP_ADHI | (0xff & (addr >> 8)));
+	cx_clear(MC417_RWD, NETUP_ADHI);
+
+	if (read) /* data in */
+		cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
+	else /* data out */
+		cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
+
+	/* choose chip */
+	cx_clear(MC417_RWD,
+			(state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);
+	/* read/write */
+	cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);
+	mem = netup_ci_get_mem(dev);
+
+	mutex_unlock(&gpio_mutex);
+
+	if (!read)
+		if (mem < 0)
+			return -EREMOTEIO;
+
+	ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
+			(read) ? "read" : "write", addr,
+			(flag == NETUP_CI_CTL) ? "ctl" : "mem",
+			(read) ? mem : data);
+
+	if (read)
+		return mem;
+
+	return 0;
+}
+
+int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr)
+{
+	return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);
+}
+
+int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr, u8 data)
+{
+	return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
+}
+
+int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
+							NETUP_CI_RD, addr, 0);
+}
+
+int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+							u8 addr, u8 data)
+{
+	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);
+}
+
+int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct netup_ci_state *state = en50221->data;
+	u8 buf =  0x80;
+	int ret;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	udelay(500);
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &buf, 1);
+
+	if (ret != 0)
+		return ret;
+
+	udelay(500);
+
+	buf = 0x00;
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &buf, 1);
+
+	msleep(1000);
+	dvb_ca_en50221_camready_irq(&state->ca, 0);
+
+	return 0;
+
+}
+
+int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+	/* not implemented */
+	return 0;
+}
+
+int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct netup_ci_state *state = en50221->data;
+	u8 buf = 0x60;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &buf, 1);
+}
+
+/* work handler */
+static void netup_read_ci_status(struct work_struct *work)
+{
+	struct netup_ci_state *state =
+			container_of(work, struct netup_ci_state, work);
+	u8 buf[33];
+	int ret;
+
+	ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0, &buf[0], 33);
+
+	if (ret != 0)
+		return;
+
+	ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, "
+		"TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0],
+		buf[32]);
+
+	if (buf[0] && 1)
+		state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
+			DVB_CA_EN50221_POLL_CAM_READY;
+	else
+		state->status = 0;
+}
+
+/* CI irq handler */
+int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
+{
+	struct cx23885_tsport *port = NULL;
+	struct netup_ci_state *state = NULL;
+
+	if (pci_status & PCI_MSK_GPIO0)
+		port = &dev->ts1;
+	else if (pci_status & PCI_MSK_GPIO1)
+		port = &dev->ts2;
+	else /* who calls ? */
+		return 0;
+
+	state = port->port_priv;
+
+	schedule_work(&state->work);
+
+	return 1;
+}
+
+int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+{
+	struct netup_ci_state *state = en50221->data;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	return state->status;
+}
+
+int netup_ci_init(struct cx23885_tsport *port)
+{
+	struct netup_ci_state *state;
+	u8 cimax_init[34] = {
+		0x00, /* module A control*/
+		0x00, /* auto select mask high A */
+		0x00, /* auto select mask low A */
+		0x00, /* auto select pattern high A */
+		0x00, /* auto select pattern low A */
+		0x44, /* memory access time A */
+		0x00, /* invert input A */
+		0x00, /* RFU */
+		0x00, /* RFU */
+		0x00, /* module B control*/
+		0x00, /* auto select mask high B */
+		0x00, /* auto select mask low B */
+		0x00, /* auto select pattern high B */
+		0x00, /* auto select pattern low B */
+		0x44, /* memory access time B */
+		0x00, /* invert input B */
+		0x00, /* RFU */
+		0x00, /* RFU */
+		0x00, /* auto select mask high Ext */
+		0x00, /* auto select mask low Ext */
+		0x00, /* auto select pattern high Ext */
+		0x00, /* auto select pattern low Ext */
+		0x00, /* RFU */
+		0x02, /* destination - module A */
+		0x01, /* power on (use it like store place) */
+		0x00, /* RFU */
+		0x00, /* int status read only */
+		0x01, /* all int unmasked */
+		0x04, /* int config */
+		0x00, /* USCG1 */
+		0x04, /* ack active low */
+		0x00, /* LOCK = 0 */
+		0x33, /* serial mode, rising in, rising out, MSB first*/
+		0x31, /* syncronization */
+	};
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+	state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);
+	if (!state) {
+		ci_dbg_print("%s: Unable create CI structure!\n", __func__);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	port->port_priv = state;
+
+	switch (port->nr) {
+	case 1:
+		state->ci_i2c_addr = 0x40;
+		mutex_init(&gpio_mutex);
+		break;
+	case 2:
+		state->ci_i2c_addr = 0x41;
+		break;
+	}
+
+	state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = netup_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = netup_ci_write_attribute_mem;
+	state->ca.read_cam_control = netup_ci_read_cam_ctl;
+	state->ca.write_cam_control = netup_ci_write_cam_ctl;
+	state->ca.slot_reset = netup_ci_slot_reset;
+	state->ca.slot_shutdown = netup_ci_slot_shutdown;
+	state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;
+	state->ca.poll_slot_status = netup_poll_ci_slot_status;
+	state->ca.data = state;
+	state->priv = port;
+
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+						0, &cimax_init[0], 34);
+	/* lock registers */
+	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+						0x1f, &cimax_init[0x18], 1);
+	/* power on slots */
+	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+						0x18, &cimax_init[0x18], 1);
+
+	if (0 != ret)
+		goto err;
+
+	ret = dvb_ca_en50221_init(&port->frontends.adapter,
+				   &state->ca,
+				   /* flags */ 0,
+				   /* n_slots */ 1);
+	if (0 != ret)
+		goto err;
+
+	INIT_WORK(&state->work, netup_read_ci_status);
+
+	ci_dbg_print("%s: CI initialized!\n", __func__);
+
+	return 0;
+err:
+	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
+	kfree(state);
+	return ret;
+}
+
+void netup_ci_exit(struct cx23885_tsport *port)
+{
+	struct netup_ci_state *state;
+
+	if (NULL == port)
+		return;
+
+	state = (struct netup_ci_state *)port->port_priv;
+	if (NULL == state)
+		return;
+
+	if (NULL == state->ca.data)
+		return;
+
+	dvb_ca_en50221_release(&state->ca);
+	kfree(state);
+}
diff --git a/drivers/media/video/cx23885/cimax2.h b/drivers/media/video/cx23885/cimax2.h
new file mode 100644
index 0000000..518744a
--- /dev/null
+++ b/drivers/media/video/cx23885/cimax2.h
@@ -0,0 +1,47 @@
+/*
+ * cimax2.h
+ *
+ * CIMax(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 CIMAX2_H
+#define CIMAX2_H
+#include "dvb_ca_en50221.h"
+
+extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr);
+extern int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr, u8 data);
+extern int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
+						int slot, u8 addr);
+extern int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
+						int slot, u8 addr, u8 data);
+extern int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status);
+extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+						int slot, int open);
+extern int netup_ci_init(struct cx23885_tsport *port);
+extern void netup_ci_exit(struct cx23885_tsport *port);
+
+#endif
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index bfe2584..6f5df90 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -896,7 +896,7 @@
 	if (retval != 0) {
 		printk(KERN_ERR
 			"ERROR: Hotplug firmware request failed (%s).\n",
-			CX2341X_FIRM_ENC_FILENAME);
+			CX23885_FIRM_IMAGE_NAME);
 		printk(KERN_ERR "Please fix your hotplug setup, the board will "
 			"not work without firmware loaded!\n");
 		return -1;
@@ -1198,21 +1198,16 @@
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 	struct cx23885_input *input;
-	unsigned int n;
+	int n;
 
-	n = i->index;
-
-	if (n >= 4)
+	if (i->index >= 4)
 		return -EINVAL;
 
-	input = &cx23885_boards[dev->board].input[n];
+	input = &cx23885_boards[dev->board].input[i->index];
 
 	if (input->type == 0)
 		return -EINVAL;
 
-	memset(i, 0, sizeof(*i));
-	i->index = n;
-
 	/* FIXME
 	 * strcpy(i->name, input->name); */
 	strcpy(i->name, "unset");
@@ -1255,10 +1250,8 @@
 		return -EINVAL;
 	if (0 != t->index)
 		return -EINVAL;
-	memset(t, 0, sizeof(*t));
 	strcpy(t->name, "Television");
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
+	call_all(dev, tuner, g_tuner, t);
 
 	dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
 
@@ -1275,7 +1268,7 @@
 		return -EINVAL;
 
 	/* Update the A/V core */
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
+	call_all(dev, tuner, s_tuner, t);
 
 	return 0;
 }
@@ -1286,14 +1279,12 @@
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	memset(f, 0, sizeof(*f));
 	if (UNSET == dev->tuner_type)
 		return -EINVAL;
 	f->type = V4L2_TUNER_ANALOG_TV;
 	f->frequency = dev->freq;
 
-	/* Assumption that tuner is always on bus 1 */
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+	call_all(dev, tuner, g_frequency, f);
 
 	return 0;
 }
@@ -1320,8 +1311,7 @@
 		return -EINVAL;
 	dev->freq = f->frequency;
 
-	/* Assumption that tuner is always on bus 1 */
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+	call_all(dev, tuner, s_frequency, f);
 
 	cx23885_initialize_codec(dev);
 
@@ -1335,7 +1325,7 @@
 	struct cx23885_dev *dev = fh->dev;
 
 	/* Update the A/V core */
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
+	call_all(dev, core, s_ctrl, ctl);
 	return 0;
 }
 
@@ -1346,7 +1336,6 @@
 	struct cx23885_dev *dev = fh->dev;
 	struct cx23885_tsport  *tsport = &dev->ts1;
 
-	memset(cap, 0, sizeof(*cap));
 	strcpy(cap->driver, dev->name);
 	strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
 		sizeof(cap->card));
@@ -1366,16 +1355,10 @@
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *f)
 {
-	int index;
-
-	index = f->index;
-	if (index != 0)
+	if (f->index != 0)
 		return -EINVAL;
 
-	memset(f, 0, sizeof(*f));
-	f->index = index;
 	strlcpy(f->description, "MPEG", sizeof(f->description));
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->pixelformat = V4L2_PIX_FMT_MPEG;
 
 	return 0;
@@ -1387,8 +1370,6 @@
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	memset(f, 0, sizeof(*f));
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    =
@@ -1408,12 +1389,10 @@
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    =
 		dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
-	f->fmt.pix.sizeimage    =
 	f->fmt.pix.colorspace   = 0;
 	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
 		dev->ts1.width, dev->ts1.height, fh->mpegq.field);
@@ -1426,7 +1405,6 @@
 	struct cx23885_fh  *fh  = file->private_data;
 	struct cx23885_dev *dev = fh->dev;
 
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    =
@@ -1543,12 +1521,7 @@
 	printk(KERN_INFO
 		"%s/2: ============  START LOG STATUS  ============\n",
 	       dev->name);
-	cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
-		NULL);
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
-		NULL);
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
-		NULL);
+	call_all(dev, core, log_status);
 	cx2341x_log_status(&dev->mpeg_params, name);
 	printk(KERN_INFO
 		"%s/2: =============  END LOG STATUS  =============\n",
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index caa098b..5e4b7e7 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -27,6 +27,7 @@
 
 #include "cx23885.h"
 #include "tuner-xc2028.h"
+#include "netup-init.h"
 
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
@@ -162,6 +163,24 @@
 		.name		= "Compro VideoMate E650F",
 		.portc		= CX23885_MPEG_DVB,
 	},
+	[CX23885_BOARD_TBS_6920] = {
+		.name		= "TurboSight TBS 6920",
+		.portb		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_TEVII_S470] = {
+		.name		= "TeVii S470",
+		.portb		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_DVBWORLD_2005] = {
+		.name		= "DVBWorld DVB-S2 2005",
+		.portb		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = {
+		.cimax		= 1,
+		.name		= "NetUP Dual DVB-S2 CI",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -245,6 +264,22 @@
 		.subvendor = 0x185b,
 		.subdevice = 0xe800,
 		.card      = CX23885_BOARD_COMPRO_VIDEOMATE_E650F,
+	}, {
+		.subvendor = 0x6920,
+		.subdevice = 0x8888,
+		.card      = CX23885_BOARD_TBS_6920,
+	}, {
+		.subvendor = 0xd470,
+		.subdevice = 0x9022,
+		.card      = CX23885_BOARD_TEVII_S470,
+	}, {
+		.subvendor = 0x0001,
+		.subdevice = 0x2005,
+		.card      = CX23885_BOARD_DVBWORLD_2005,
+	}, {
+		.subvendor = 0x1b55,
+		.subdevice = 0x2a2c,
+		.card      = CX23885_BOARD_NETUP_DUAL_DVBS2_CI,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -552,6 +587,38 @@
 		mdelay(20);
 		cx_set(GP0_IO, 0x00040004);
 		break;
+	case CX23885_BOARD_TBS_6920:
+	case CX23885_BOARD_TEVII_S470:
+		cx_write(MC417_CTL, 0x00000036);
+		cx_write(MC417_OEN, 0x00001000);
+		cx_write(MC417_RWD, 0x00001800);
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		/* GPIO-0 INTA from CiMax1
+		   GPIO-1 INTB from CiMax2
+		   GPIO-2 reset chips
+		   GPIO-3 to GPIO-10 data/addr for CA
+		   GPIO-11 ~CS0 to CiMax1
+		   GPIO-12 ~CS1 to CiMax2
+		   GPIO-13 ADL0 load LSB addr
+		   GPIO-14 ADL1 load MSB addr
+		   GPIO-15 ~RDY from CiMax
+		   GPIO-17 ~RD to CiMax
+		   GPIO-18 ~WR to CiMax
+		 */
+		cx_set(GP0_IO, 0x00040000); /* GPIO as out */
+		/* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */
+		cx_clear(GP0_IO, 0x00030004);
+		mdelay(100);/* reset delay */
+		cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */
+		cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
+		/* GPIO-15 IN as ~ACK, rest as OUT */
+		cx_write(MC417_OEN, 0x00001000);
+		/* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
+		cx_write(MC417_RWD, 0x0000c300);
+		/* enable irq */
+		cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+		break;
 	}
 }
 
@@ -632,6 +699,21 @@
 		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_TBS_6920:
+	case CX23885_BOARD_DVBWORLD_2005:
+		ts1->gen_ctrl_val  = 0x5; /* Parallel */
+		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+		ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		break;
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -656,7 +738,17 @@
 	case CX23885_BOARD_HAUPPAUGE_HVR1700:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-		request_module("cx25840");
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->i2c_bus[2].i2c_adap,
+				"cx25840", "cx25840", 0x88 >> 1);
+		v4l2_subdev_call(dev->sd_cx25840, core, init, 0);
+		break;
+	}
+
+	/* AUX-PLL 27MHz CLK */
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		netup_initialize(dev);
 		break;
 	}
 }
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 8f6fb2a..dc7fff2 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -31,6 +31,7 @@
 #include <asm/div64.h>
 
 #include "cx23885.h"
+#include "cimax2.h"
 
 MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
@@ -791,6 +792,8 @@
 	dev->pci_bus  = dev->pci->bus->number;
 	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
 	dev->pci_irqmask = 0x001f00;
+	if (cx23885_boards[dev->board].cimax > 0)
+		dev->pci_irqmask |= 0x01800000; /* for CiMaxes */
 
 	/* External Master 1 Bus */
 	dev->i2c_bus[0].nr = 0;
@@ -872,7 +875,7 @@
 	cx23885_i2c_register(&dev->i2c_bus[1]);
 	cx23885_i2c_register(&dev->i2c_bus[2]);
 	cx23885_card_setup(dev);
-	cx23885_call_i2c_clients(&dev->i2c_bus[0], TUNER_SET_STANDBY, NULL);
+	call_all(dev, core, s_standby, 0);
 	cx23885_ir_init(dev);
 
 	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
@@ -1643,7 +1646,9 @@
 	    (pci_status & PCI_MSK_VID_B) ||
 	    (pci_status & PCI_MSK_VID_A) ||
 	    (pci_status & PCI_MSK_AUD_INT) ||
-	    (pci_status & PCI_MSK_AUD_EXT)) {
+	    (pci_status & PCI_MSK_AUD_EXT) ||
+	    (pci_status & PCI_MSK_GPIO0) ||
+	    (pci_status & PCI_MSK_GPIO1)) {
 
 		if (pci_status & PCI_MSK_RISC_RD)
 			dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
@@ -1685,8 +1690,20 @@
 			dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n",
 				PCI_MSK_AUD_EXT);
 
+		if (pci_status & PCI_MSK_GPIO0)
+			dprintk(7, " (PCI_MSK_GPIO0     0x%08x)\n",
+				PCI_MSK_GPIO0);
+
+		if (pci_status & PCI_MSK_GPIO1)
+			dprintk(7, " (PCI_MSK_GPIO1     0x%08x)\n",
+				PCI_MSK_GPIO1);
 	}
 
+	if (cx23885_boards[dev->board].cimax > 0 &&
+		((pci_status & PCI_MSK_GPIO0) || (pci_status & PCI_MSK_GPIO1)))
+		/* handled += cx23885_irq_gpio(dev, pci_status); */
+		handled += netup_ci_slot_status(dev, pci_status);
+
 	if (ts1_status) {
 		if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
 			handled += cx23885_irq_ts(ts1, ts1_status);
@@ -1722,16 +1739,20 @@
 	if (NULL == dev)
 		return -ENOMEM;
 
+	err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+	if (err < 0)
+		goto fail_free;
+
 	/* pci init */
 	dev->pci = pci_dev;
 	if (pci_enable_device(pci_dev)) {
 		err = -EIO;
-		goto fail_free;
+		goto fail_unreg;
 	}
 
 	if (cx23885_dev_setup(dev) < 0) {
 		err = -EINVAL;
-		goto fail_free;
+		goto fail_unreg;
 	}
 
 	/* print pci info */
@@ -1758,11 +1779,18 @@
 		goto fail_irq;
 	}
 
-	pci_set_drvdata(pci_dev, dev);
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */
+		break;
+	}
+
 	return 0;
 
 fail_irq:
 	cx23885_dev_unregister(dev);
+fail_unreg:
+	v4l2_device_unregister(&dev->v4l2_dev);
 fail_free:
 	kfree(dev);
 	return err;
@@ -1770,7 +1798,8 @@
 
 static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
 {
-	struct cx23885_dev *dev = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx23885_dev *dev = to_cx23885(v4l2_dev);
 
 	cx23885_shutdown(dev);
 
@@ -1778,13 +1807,13 @@
 
 	/* unregister stuff */
 	free_irq(pci_dev->irq, dev);
-	pci_set_drvdata(pci_dev, NULL);
 
 	mutex_lock(&devlist);
 	list_del(&dev->devlist);
 	mutex_unlock(&devlist);
 
 	cx23885_dev_unregister(dev);
+	v4l2_device_unregister(v4l2_dev);
 	kfree(dev);
 }
 
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 1c45412..d43c743 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -30,6 +30,7 @@
 #include "cx23885.h"
 #include <media/v4l2-common.h>
 
+#include "dvb_ca_en50221.h"
 #include "s5h1409.h"
 #include "s5h1411.h"
 #include "mt2131.h"
@@ -43,6 +44,13 @@
 #include "dib7000p.h"
 #include "dibx000_common.h"
 #include "zl10353.h"
+#include "stv0900.h"
+#include "stv6110.h"
+#include "lnbh24.h"
+#include "cx24116.h"
+#include "cimax2.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
 
 static unsigned int debug;
 
@@ -308,11 +316,63 @@
 	.no_tuner      = 1,
 };
 
+static struct stv0900_config netup_stv0900_config = {
+	.demod_address = 0x68,
+	.xtal = 27000000,
+	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+	.diseqc_mode = 2,/* 2/3 PWM */
+	.path1_mode = 2,/*Serial continues clock */
+	.path2_mode = 2,/*Serial continues clock */
+	.tun1_maddress = 0,/* 0x60 */
+	.tun2_maddress = 3,/* 0x63 */
+	.tun1_adc = 1,/* 1 Vpp */
+	.tun2_adc = 1,/* 1 Vpp */
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_a = {
+	.i2c_address = 0x60,
+	.mclk = 27000000,
+	.iq_wiring = 0,
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_b = {
+	.i2c_address = 0x63,
+	.mclk = 27000000,
+	.iq_wiring = 1,
+};
+
+static int tbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct cx23885_tsport *port = fe->dvb->priv;
+	struct cx23885_dev *dev = port->dev;
+
+	if (voltage == SEC_VOLTAGE_18)
+		cx_write(MC417_RWD, 0x00001e00);/* GPIO-13 high */
+	else if (voltage == SEC_VOLTAGE_13)
+		cx_write(MC417_RWD, 0x00001a00);/* GPIO-13 low */
+	else
+		cx_write(MC417_RWD, 0x00001800);/* GPIO-12 low */
+	return 0;
+}
+
+static struct cx24116_config tbs_cx24116_config = {
+	.demod_address = 0x05,
+};
+
+static struct cx24116_config tevii_cx24116_config = {
+	.demod_address = 0x55,
+};
+
+static struct cx24116_config dvbworld_cx24116_config = {
+	.demod_address = 0x05,
+};
+
 static int dvb_register(struct cx23885_tsport *port)
 {
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_i2c *i2c_bus = NULL;
 	struct videobuf_dvb_frontend *fe0;
+	int ret;
 
 	/* Get the first frontend */
 	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
@@ -526,6 +586,78 @@
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
 		break;
+	case CX23885_BOARD_TBS_6920:
+		i2c_bus = &dev->i2c_bus[0];
+
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+			&tbs_cx24116_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage;
+
+		break;
+	case CX23885_BOARD_TEVII_S470:
+		i2c_bus = &dev->i2c_bus[1];
+
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+			&tevii_cx24116_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage;
+
+		break;
+	case CX23885_BOARD_DVBWORLD_2005:
+		i2c_bus = &dev->i2c_bus[1];
+
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+			&dvbworld_cx24116_config,
+			&i2c_bus->i2c_adap);
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		i2c_bus = &dev->i2c_bus[0];
+		switch (port->nr) {
+		/* port B */
+		case 1:
+			fe0->dvb.frontend = dvb_attach(stv0900_attach,
+							&netup_stv0900_config,
+							&i2c_bus->i2c_adap, 0);
+			if (fe0->dvb.frontend != NULL) {
+				if (dvb_attach(stv6110_attach,
+						fe0->dvb.frontend,
+						&netup_stv6110_tunerconfig_a,
+						&i2c_bus->i2c_adap)) {
+					if (!dvb_attach(lnbh24_attach,
+							fe0->dvb.frontend,
+							&i2c_bus->i2c_adap,
+							LNBH24_PCL, 0, 0x09))
+						printk(KERN_ERR
+							"No LNBH24 found!\n");
+
+				}
+			}
+			break;
+		/* port C */
+		case 2:
+			fe0->dvb.frontend = dvb_attach(stv0900_attach,
+							&netup_stv0900_config,
+							&i2c_bus->i2c_adap, 1);
+			if (fe0->dvb.frontend != NULL) {
+				if (dvb_attach(stv6110_attach,
+						fe0->dvb.frontend,
+						&netup_stv6110_tunerconfig_b,
+						&i2c_bus->i2c_adap)) {
+					if (!dvb_attach(lnbh24_attach,
+							fe0->dvb.frontend,
+							&i2c_bus->i2c_adap,
+							LNBH24_PCL, 0, 0x0a))
+						printk(KERN_ERR
+							"No LNBH24 found!\n");
+
+				}
+			}
+			break;
+		}
+		break;
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
@@ -541,15 +673,39 @@
 	fe0->dvb.frontend->callback = cx23885_tuner_callback;
 
 	/* Put the analog decoder in standby to keep it quiet */
-	cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
+	call_all(dev, core, s_standby, 0);
 
 	if (fe0->dvb.frontend->ops.analog_ops.standby)
 		fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
 
 	/* register everything */
-	return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+	ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
 		&dev->pci->dev, adapter_nr, 0);
 
+	/* init CI & MAC */
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
+		static struct netup_card_info cinfo;
+
+		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+		memcpy(port->frontends.adapter.proposed_mac,
+				cinfo.port[port->nr - 1].mac, 6);
+		printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC="
+			"%02X:%02X:%02X:%02X:%02X:%02X\n",
+			port->nr,
+			port->frontends.adapter.proposed_mac[0],
+			port->frontends.adapter.proposed_mac[1],
+			port->frontends.adapter.proposed_mac[2],
+			port->frontends.adapter.proposed_mac[3],
+			port->frontends.adapter.proposed_mac[4],
+			port->frontends.adapter.proposed_mac[5]);
+
+		netup_ci_init(port);
+		break;
+		}
+	}
+
+	return ret;
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -622,6 +778,12 @@
 	if (fe0->dvb.frontend)
 		videobuf_dvb_unregister_bus(&port->frontends);
 
+	switch (port->dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		netup_ci_exit(port);
+		break;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index bb7f71a..3421bd1 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -268,64 +268,6 @@
 	return retval;
 }
 
-static int attach_inform(struct i2c_client *client)
-{
-	struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter);
-	struct cx23885_dev *dev = bus->dev;
-	struct tuner_setup tun_setup;
-
-	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->driver.name, client->addr, client->name);
-
-	if (!client->driver->command)
-		return 0;
-
-	if (dev->tuner_type != UNSET) {
-
-		dprintk(1, "%s  (tuner) i2c attach [addr=0x%x,client=%s]\n",
-			client->driver->driver.name, client->addr,
-			client->name);
-
-		if ((dev->tuner_addr == ADDR_UNSET) ||
-			(dev->tuner_addr == client->addr)) {
-
-			dprintk(1, "%s (tuner || addr UNSET)\n",
-				client->driver->driver.name);
-
-			dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-				client->driver->driver.name,
-				client->addr, client->name);
-
-			tun_setup.mode_mask = T_ANALOG_TV;
-			tun_setup.type = dev->tuner_type;
-			tun_setup.addr = dev->tuner_addr;
-
-			client->driver->command(client, TUNER_SET_TYPE_ADDR,
-				&tun_setup);
-		}
-	}
-
-	return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
-	struct cx23885_dev *dev = i2c_get_adapdata(client->adapter);
-
-	dprintk(1, "i2c detach [client=%s]\n", client->name);
-
-	return 0;
-}
-
-void cx23885_call_i2c_clients(struct cx23885_i2c *bus,
-			      unsigned int cmd, void *arg)
-{
-	if (bus->i2c_rc != 0)
-		return;
-
-	i2c_clients_command(&bus->i2c_adap, cmd, arg);
-}
-
 static u32 cx23885_functionality(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
@@ -343,9 +285,6 @@
 	.owner             = THIS_MODULE,
 	.id                = I2C_HW_B_CX23885,
 	.algo              = &cx23885_i2c_algo_template,
-	.class             = I2C_CLASS_TV_ANALOG,
-	.client_register   = attach_inform,
-	.client_unregister = detach_inform,
 };
 
 static struct i2c_client cx23885_i2c_client_template = {
@@ -402,15 +341,18 @@
 
 	bus->i2c_algo.data = bus;
 	bus->i2c_adap.algo_data = bus;
-	i2c_set_adapdata(&bus->i2c_adap, bus);
+	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
 	i2c_add_adapter(&bus->i2c_adap);
 
 	bus->i2c_client.adapter = &bus->i2c_adap;
 
 	if (0 == bus->i2c_rc) {
 		dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
-		if (i2c_scan)
+		if (i2c_scan) {
+			printk(KERN_INFO "%s: scan bus %d:\n",
+					dev->name, bus->nr);
 			do_i2c_scan(dev->name, &bus->i2c_client);
+		}
 	} else
 		printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
 			dev->name, bus->nr);
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
index 20b68a2..eafbe52 100644
--- a/drivers/media/video/cx23885/cx23885-reg.h
+++ b/drivers/media/video/cx23885/cx23885-reg.h
@@ -212,6 +212,8 @@
 
 #define DEV_CNTRL2	0x00040000
 
+#define PCI_MSK_GPIO1   (1 << 24)
+#define PCI_MSK_GPIO0   (1 << 23)
 #define PCI_MSK_APB_DMA   (1 << 12)
 #define PCI_MSK_AL_WR     (1 << 11)
 #define PCI_MSK_AL_RD     (1 << 10)
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index eaa1189..f0ac62c 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -35,11 +35,6 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
-
 MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
 MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
 MODULE_LICENSE("GPL");
@@ -244,6 +239,7 @@
 };
 static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
 
+/* Must be sorted from low to high control ID! */
 static const u32 cx23885_user_ctrls[] = {
 	V4L2_CID_USER_CLASS,
 	V4L2_CID_BRIGHTNESS,
@@ -303,11 +299,7 @@
 
 	dev->tvnorm = norm;
 
-	/* Tell the analog tuner/demods */
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_STD, &norm);
-
-	/* Tell the internal A/V decoder */
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_STD, &norm);
+	call_all(dev, tuner, s_std, norm);
 
 	return 0;
 }
@@ -324,8 +316,8 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor   = -1;
-	vfd->parent  = &pci->dev;
+	vfd->minor = -1;
+	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 dev->name, type, cx23885_boards[dev->board].name);
@@ -414,8 +406,7 @@
 	route.input = INPUT(input)->vmux;
 
 	/* Tell the internal A/V decoder */
-	cx23885_call_i2c_clients(&dev->i2c_bus[2],
-		VIDIOC_INT_S_VIDEO_ROUTING, &route);
+	v4l2_subdev_call(dev->sd_cx25840, video, s_routing, &route);
 
 	return 0;
 }
@@ -891,7 +882,7 @@
 	struct v4l2_control *ctl)
 {
 	dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
+	call_all(dev, core, g_ctrl, ctl);
 	return 0;
 }
 
@@ -1005,7 +996,7 @@
 	fh->vidq.field = f->fmt.pix.field;
 	dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
 		fh->width, fh->height, fh->vidq.field);
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f);
+	call_all(dev, video, s_fmt, f);
 	return 0;
 }
 
@@ -1285,7 +1276,7 @@
 	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	f->frequency = dev->freq;
 
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
+	call_all(dev, tuner, g_frequency, f);
 
 	return 0;
 }
@@ -1300,7 +1291,7 @@
 	mutex_lock(&dev->lock);
 	dev->freq = f->frequency;
 
-	cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
+	call_all(dev, tuner, s_frequency, f);
 
 	/* When changing channels it is required to reset TVAUDIO */
 	msleep(10);
@@ -1334,7 +1325,7 @@
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
 
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
+	call_all(dev, core, g_register, reg);
 
 	return 0;
 }
@@ -1347,7 +1338,7 @@
 	if (!v4l2_chip_match_host(&reg->match))
 		return -EINVAL;
 
-	cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
+	call_all(dev, core, s_register, reg);
 
 	return 0;
 }
@@ -1528,6 +1519,26 @@
 	/* Don't enable VBI yet */
 	cx_set(PCI_INT_MSK, 1);
 
+	if (TUNER_ABSENT != dev->tuner_type) {
+		struct v4l2_subdev *sd = NULL;
+
+		if (dev->tuner_addr)
+			sd = v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap,
+				"tuner", "tuner", dev->tuner_addr);
+		else
+			sd = v4l2_i2c_new_probed_subdev(&dev->i2c_bus[1].i2c_adap,
+				"tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV));
+		if (sd) {
+			struct tuner_setup tun_setup;
+
+			tun_setup.mode_mask = T_ANALOG_TV;
+			tun_setup.type = dev->tuner_type;
+			tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+
+			v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
+		}
+	}
+
 
 	/* register v4l devices */
 	dev->video_dev = cx23885_vdev_init(dev, dev->pci,
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index 6782802..02d980a 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -24,7 +24,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/kdev_t.h>
 
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/videobuf-dma-sg.h>
@@ -67,6 +67,10 @@
 #define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11
 #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12
 #define CX23885_BOARD_COMPRO_VIDEOMATE_E650F   13
+#define CX23885_BOARD_TBS_6920                 14
+#define CX23885_BOARD_TEVII_S470               15
+#define CX23885_BOARD_DVBWORLD_2005            16
+#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI      17
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -184,6 +188,7 @@
 	 */
 	u32			clk_freq;
 	struct cx23885_input    input[MAX_CX23885_INPUT];
+	int			cimax; /* for NetUP */
 };
 
 struct cx23885_subid {
@@ -266,11 +271,13 @@
 
 	/* Allow a single tsport to have multiple frontends */
 	u32                        num_frontends;
+	void                       *port_priv;
 };
 
 struct cx23885_dev {
 	struct list_head           devlist;
 	atomic_t                   refcount;
+	struct v4l2_device 	   v4l2_dev;
 
 	/* pci stuff */
 	struct pci_dev             *pci;
@@ -316,6 +323,7 @@
 	unsigned int               radio_type;
 	unsigned char              radio_addr;
 	unsigned int               has_radio;
+	struct v4l2_subdev 	   *sd_cx25840;
 
 	/* V4l */
 	u32                        freq;
@@ -336,6 +344,14 @@
 
 };
 
+static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev);
+}
+
+#define call_all(dev, o, f, args...) \
+	v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
 extern struct list_head cx23885_devlist;
 
 #define SRAM_CH01  0 /* Video A */
@@ -452,8 +468,6 @@
 /* cx23885-i2c.c                                                */
 extern int cx23885_i2c_register(struct cx23885_i2c *bus);
 extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
-extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
-				     void *arg);
 extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/cx23885/netup-eeprom.c b/drivers/media/video/cx23885/netup-eeprom.c
new file mode 100644
index 0000000..042bbbb
--- /dev/null
+++ b/drivers/media/video/cx23885/netup-eeprom.c
@@ -0,0 +1,107 @@
+
+/*
+ * netup-eeprom.c
+ *
+ * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 "cx23885.h"
+#include "netup-eeprom.h"
+
+#define EEPROM_I2C_ADDR 0x50
+
+int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr)
+{
+	int ret;
+	unsigned char buf[2];
+
+	/* Read from EEPROM */
+	struct i2c_msg msg[] = {
+		{
+			.addr	= EEPROM_I2C_ADDR,
+			.flags	= 0,
+			.buf	= &buf[0],
+			.len	= 1
+		}, {
+			.addr	= EEPROM_I2C_ADDR,
+			.flags	= I2C_M_RD,
+			.buf	= &buf[1],
+			.len	= 1
+		}
+
+	};
+
+	buf[0] = addr;
+	buf[1] = 0x0;
+
+	ret = i2c_transfer(i2c_adap, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret);
+		return -1;
+	}
+
+	return buf[1];
+};
+
+int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data)
+{
+	int ret;
+	unsigned char bufw[2];
+
+	/* Write into EEPROM */
+	struct i2c_msg msg[] = {
+		{
+			.addr	= EEPROM_I2C_ADDR,
+			.flags	= 0,
+			.buf	= &bufw[0],
+			.len	= 2
+		}
+	};
+
+	bufw[0] = addr;
+	bufw[1] = data;
+
+	ret = i2c_transfer(i2c_adap, msg, 1);
+
+	if (ret != 1) {
+		printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret);
+		return -1;
+	}
+
+	mdelay(10); /* prophylactic delay, datasheet write cycle time = 5 ms */
+	return 0;
+};
+
+void netup_get_card_info(struct i2c_adapter *i2c_adap,
+				struct netup_card_info *cinfo)
+{
+	int i, j;
+
+	cinfo->rev =  netup_eeprom_read(i2c_adap, 13);
+
+	for (i = 0, j = 0; i < 6; i++, j++)
+		cinfo->port[0].mac[j] =  netup_eeprom_read(i2c_adap, i);
+
+	for (i = 6, j = 0; i < 12; i++, j++)
+		cinfo->port[1].mac[j] =  netup_eeprom_read(i2c_adap, i);
+};
diff --git a/drivers/media/video/cx23885/netup-eeprom.h b/drivers/media/video/cx23885/netup-eeprom.h
new file mode 100644
index 0000000..13926e1
--- /dev/null
+++ b/drivers/media/video/cx23885/netup-eeprom.h
@@ -0,0 +1,42 @@
+/*
+ * netup-eeprom.h
+ *
+ * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 NETUP_EEPROM_H
+#define NETUP_EEPROM_H
+
+struct netup_port_info {
+	u8 mac[6];/* card MAC address */
+};
+
+struct netup_card_info {
+	struct netup_port_info port[2];/* ports - 1,2 */
+	u8 rev;/* card revision */
+};
+
+extern int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr);
+extern int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data);
+extern void netup_get_card_info(struct i2c_adapter *i2c_adap,
+				struct netup_card_info *cinfo);
+
+#endif
diff --git a/drivers/media/video/cx23885/netup-init.c b/drivers/media/video/cx23885/netup-init.c
new file mode 100644
index 0000000..f4893e6
--- /dev/null
+++ b/drivers/media/video/cx23885/netup-init.c
@@ -0,0 +1,125 @@
+/*
+ * netup-init.c
+ *
+ * NetUP Dual DVB-S2 CI driver
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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 "cx23885.h"
+
+static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
+{
+	int ret;
+	u8 buf[3];
+	struct i2c_msg msg = {
+		.addr	= 0x88 >> 1,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 3
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	buf[2] = val;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+}
+
+static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val)
+{
+	int ret;
+	u8 buf[6];
+	struct i2c_msg msg = {
+		.addr	= 0x88 >> 1,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 6
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	buf[2] = val & 0xff;
+	buf[3] = (val >> 8) & 0xff;
+	buf[4] = (val >> 16) & 0xff;
+	buf[5] = val >> 24;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+}
+
+static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg)
+{
+	int ret;
+	u8 buf[2];
+	struct i2c_msg msg = {
+		.addr	= 0x88 >> 1,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 2
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+
+	msg.flags = I2C_M_RD;
+	msg.len = 1;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c read error!\n", __func__);
+
+	return buf[0];
+}
+
+static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask,
+								u8 or_value)
+{
+	i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value);
+}
+/* set 27MHz on AUX_CLK */
+void netup_initialize(struct cx23885_dev *dev)
+{
+	struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2];
+	struct i2c_adapter *i2c = &i2c_bus->i2c_adap;
+
+	/* Stop microcontroller */
+	i2c_av_and_or(i2c, 0x803, ~0x10, 0x00);
+
+	/* Aux PLL frac for 27 MHz */
+	i2c_av_write4(i2c, 0x114, 0xea0eb3);
+
+	/* Aux PLL int for 27 MHz */
+	i2c_av_write4(i2c, 0x110, 0x090319);
+
+	/* start microcontroller */
+	i2c_av_and_or(i2c, 0x803, ~0x10, 0x10);
+}
diff --git a/drivers/media/video/cx23885/netup-init.h b/drivers/media/video/cx23885/netup-init.h
new file mode 100644
index 0000000..d26ae4b
--- /dev/null
+++ b/drivers/media/video/cx23885/netup-init.h
@@ -0,0 +1,25 @@
+/*
+ * netup-init.h
+ *
+ * NetUP Dual DVB-S2 CI driver
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ */
+extern void netup_initialize(struct cx23885_dev *dev);
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index d199d80..93d74be 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -363,75 +363,74 @@
 	}
 }
 
-int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
+int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
 {
-	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
-	struct v4l2_control *ctrl = arg;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
 	int retval;
 
-	switch (cmd) {
-	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-		if (!state->is_cx25836)
-			cx25840_and_or(client, 0x810, ~0x1, 1);
-		if (state->aud_input != CX25840_AUDIO_SERIAL) {
-			cx25840_and_or(client, 0x803, ~0x10, 0);
-			cx25840_write(client, 0x8d3, 0x1f);
-		}
-		retval = set_audclk_freq(client, *(u32 *)arg);
-		if (state->aud_input != CX25840_AUDIO_SERIAL) {
-			cx25840_and_or(client, 0x803, ~0x10, 0x10);
-		}
-		if (!state->is_cx25836)
-			cx25840_and_or(client, 0x810, ~0x1, 0);
-		return retval;
+	if (!state->is_cx25836)
+		cx25840_and_or(client, 0x810, ~0x1, 1);
+	if (state->aud_input != CX25840_AUDIO_SERIAL) {
+		cx25840_and_or(client, 0x803, ~0x10, 0);
+		cx25840_write(client, 0x8d3, 0x1f);
+	}
+	retval = set_audclk_freq(client, freq);
+	if (state->aud_input != CX25840_AUDIO_SERIAL)
+		cx25840_and_or(client, 0x803, ~0x10, 0x10);
+	if (!state->is_cx25836)
+		cx25840_and_or(client, 0x810, ~0x1, 0);
+	return retval;
+}
 
-	case VIDIOC_G_CTRL:
-		switch (ctrl->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-			ctrl->value = get_volume(client);
-			break;
-		case V4L2_CID_AUDIO_BASS:
-			ctrl->value = get_bass(client);
-			break;
-		case V4L2_CID_AUDIO_TREBLE:
-			ctrl->value = get_treble(client);
-			break;
-		case V4L2_CID_AUDIO_BALANCE:
-			ctrl->value = get_balance(client);
-			break;
-		case V4L2_CID_AUDIO_MUTE:
-			ctrl->value = get_mute(client);
-			break;
-		default:
-			return -EINVAL;
-		}
+int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		ctrl->value = get_volume(client);
 		break;
-
-	case VIDIOC_S_CTRL:
-		switch (ctrl->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-			set_volume(client, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_BASS:
-			set_bass(client, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_TREBLE:
-			set_treble(client, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_BALANCE:
-			set_balance(client, ctrl->value);
-			break;
-		case V4L2_CID_AUDIO_MUTE:
-			set_mute(client, ctrl->value);
-			break;
-		default:
-			return -EINVAL;
-		}
+	case V4L2_CID_AUDIO_BASS:
+		ctrl->value = get_bass(client);
 		break;
-
+	case V4L2_CID_AUDIO_TREBLE:
+		ctrl->value = get_treble(client);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		ctrl->value = get_balance(client);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value = get_mute(client);
+		break;
 	default:
 		return -EINVAL;
 	}
+	return 0;
+}
 
+int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		set_volume(client, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_BASS:
+		set_bass(client, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_TREBLE:
+		set_treble(client, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		set_balance(client, ctrl->value);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		set_mute(client, ctrl->value);
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 25eb3bec..737ee4e 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -39,7 +39,7 @@
 #include <linux/delay.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 #include <media/cx25840.h>
 
 #include "cx25840-core.h"
@@ -48,15 +48,12 @@
 MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-
 static int cx25840_debug;
 
 module_param_named(debug,cx25840_debug, int, 0644);
 
 MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
 
-I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
 
@@ -763,7 +760,7 @@
 		break;
 
 	case V4L2_CID_HUE:
-		if (ctrl->value < -127 || ctrl->value > 127) {
+		if (ctrl->value < -128 || ctrl->value > 127) {
 			v4l_err(client, "invalid hue setting %d\n", ctrl->value);
 			return -ERANGE;
 		}
@@ -778,7 +775,7 @@
 	case V4L2_CID_AUDIO_MUTE:
 		if (state->is_cx25836)
 			return -EINVAL;
-		return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
+		return cx25840_audio_s_ctrl(sd, ctrl);
 
 	default:
 		return -EINVAL;
@@ -815,7 +812,7 @@
 	case V4L2_CID_AUDIO_MUTE:
 		if (state->is_cx25836)
 			return -EINVAL;
-		return cx25840_audio(client, VIDIOC_G_CTRL, ctrl);
+		return cx25840_audio_g_ctrl(sd, ctrl);
 	default:
 		return -EINVAL;
 	}
@@ -827,11 +824,9 @@
 
 static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
 	switch (fmt->type) {
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-		return cx25840_vbi(client, VIDIOC_G_FMT, fmt);
+		return cx25840_vbi_g_fmt(sd, fmt);
 	default:
 		return -EINVAL;
 	}
@@ -893,10 +888,10 @@
 		break;
 
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);
+		return cx25840_vbi_s_fmt(sd, fmt);
 
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		return cx25840_vbi(client, VIDIOC_S_FMT, fmt);
+		return cx25840_vbi_s_fmt(sd, fmt);
 
 	default:
 		return -EINVAL;
@@ -1101,6 +1096,16 @@
 
 /* ----------------------------------------------------------------------- */
 
+/* This init operation must be called to load the driver's firmware.
+   Without this the audio standard detection will fail and you will
+   only get mono.
+
+   Since loading the firmware is often problematic when the driver is
+   compiled into the kernel I recommend postponing calling this function
+   until the first open of the video device. Another reason for
+   postponing it is that loading this firmware takes a long time (seconds)
+   due to the slow i2c bus speed. So it will speed up the boot process if
+   you can avoid loading the fw as long as the video device isn't used.  */
 static int cx25840_init(struct v4l2_subdev *sd, u32 val)
 {
 	struct cx25840_state *state = to_state(sd);
@@ -1146,20 +1151,6 @@
 }
 #endif
 
-static int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	return cx25840_vbi(client, VIDIOC_INT_DECODE_VBI_LINE, vbi);
-}
-
-static int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
-{
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	return cx25840_audio(client, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq);
-}
-
 static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct cx25840_state *state = to_state(sd);
@@ -1195,10 +1186,12 @@
 
 	switch (qc->id) {
 	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
 	case V4L2_CID_CONTRAST:
 	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
 	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill_std(qc);
+		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 	default:
 		break;
 	}
@@ -1210,10 +1203,11 @@
 		return v4l2_ctrl_query_fill(qc, 0, 65535,
 				65535 / 100, state->default_volume);
 	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill_std(qc);
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 	default:
 		return -EINVAL;
 	}
@@ -1380,19 +1374,6 @@
 	return 0;
 }
 
-static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	/* ignore this command */
-	if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG)
-		return 0;
-
-	/* Old-style drivers rely on initialization on first use, so
-	   call the init whenever a command is issued to this driver.
-	   New-style drivers using v4l2_subdev should call init explicitly. */
-	cx25840_init(i2c_get_clientdata(client), 0);
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops cx25840_core_ops = {
@@ -1528,8 +1509,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "cx25840",
-	.driverid = I2C_DRIVERID_CX25840,
-	.command = cx25840_command,
 	.probe = cx25840_probe,
 	.remove = cx25840_remove,
 	.id_table = cx25840_id,
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index be05582..9ad0eb8 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -75,11 +75,15 @@
 
 /* ----------------------------------------------------------------------- */
 /* cx25850-audio.c                                                         */
-int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg);
 void cx25840_audio_set_path(struct i2c_client *client);
+int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
 
 /* ----------------------------------------------------------------------- */
 /* cx25850-vbi.c                                                           */
-int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg);
+int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi);
 
 #endif
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 03f09b2..35f6592 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -82,199 +82,181 @@
 	return err & 0xf0;
 }
 
-int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
+int cx25840_vbi_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 {
-	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
-	struct v4l2_format *fmt;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
 	struct v4l2_sliced_vbi_format *svbi;
+	static const u16 lcr2vbi[] = {
+		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
+		0, V4L2_SLICED_WSS_625, 0,	/* 4 */
+		V4L2_SLICED_CAPTION_525,	/* 6 */
+		0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
+		0, 0, 0, 0
+	};
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int i;
 
-	switch (cmd) {
-	case VIDIOC_G_FMT:
-	{
-		static u16 lcr2vbi[] = {
-			0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
-			0, V4L2_SLICED_WSS_625, 0,	/* 4 */
-			V4L2_SLICED_CAPTION_525,	/* 6 */
-			0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
-			0, 0, 0, 0
-		};
-		int is_pal = !(state->std & V4L2_STD_525_60);
-		int i;
+	if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+		return -EINVAL;
+	svbi = &fmt->fmt.sliced;
+	memset(svbi, 0, sizeof(*svbi));
+	/* we're done if raw VBI is active */
+	if ((cx25840_read(client, 0x404) & 0x10) == 0)
+		return 0;
 
-		fmt = arg;
-		if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-			return -EINVAL;
-		svbi = &fmt->fmt.sliced;
-		memset(svbi, 0, sizeof(*svbi));
-		/* we're done if raw VBI is active */
-		if ((cx25840_read(client, 0x404) & 0x10) == 0)
-			break;
+	if (is_pal) {
+		for (i = 7; i <= 23; i++) {
+			u8 v = cx25840_read(client, 0x424 + i - 7);
 
-		if (is_pal) {
-			for (i = 7; i <= 23; i++) {
-				u8 v = cx25840_read(client, 0x424 + i - 7);
-
-				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-				svbi->service_set |=
-					svbi->service_lines[0][i] | svbi->service_lines[1][i];
-			}
+			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+			svbi->service_set |= svbi->service_lines[0][i] |
+					     svbi->service_lines[1][i];
 		}
-		else {
-			for (i = 10; i <= 21; i++) {
-				u8 v = cx25840_read(client, 0x424 + i - 10);
+	} else {
+		for (i = 10; i <= 21; i++) {
+			u8 v = cx25840_read(client, 0x424 + i - 10);
 
-				svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-				svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-				svbi->service_set |=
-					svbi->service_lines[0][i] | svbi->service_lines[1][i];
-			}
+			svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+			svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+			svbi->service_set |= svbi->service_lines[0][i] |
+					     svbi->service_lines[1][i];
 		}
-		break;
 	}
+	return 0;
+}
 
-	case VIDIOC_S_FMT:
-	{
-		int is_pal = !(state->std & V4L2_STD_525_60);
-		int vbi_offset = is_pal ? 1 : 0;
-		int i, x;
-		u8 lcr[24];
+int cx25840_vbi_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
+	struct v4l2_sliced_vbi_format *svbi;
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int vbi_offset = is_pal ? 1 : 0;
+	int i, x;
+	u8 lcr[24];
 
-		fmt = arg;
-		if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
-		    fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
-			return -EINVAL;
-		svbi = &fmt->fmt.sliced;
-		if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-			/* raw VBI */
-			memset(svbi, 0, sizeof(*svbi));
-
-			/* Setup standard */
-			cx25840_std_setup(client);
-
-			/* VBI Offset */
-			cx25840_write(client, 0x47f, vbi_offset);
-			cx25840_write(client, 0x404, 0x2e);
-			break;
-		}
-
-		for (x = 0; x <= 23; x++)
-			lcr[x] = 0x00;
+	if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
+			fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
+		return -EINVAL;
+	svbi = &fmt->fmt.sliced;
+	if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		/* raw VBI */
+		memset(svbi, 0, sizeof(*svbi));
 
 		/* Setup standard */
 		cx25840_std_setup(client);
 
-		/* Sliced VBI */
-		cx25840_write(client, 0x404, 0x32);	/* Ancillary data */
-		cx25840_write(client, 0x406, 0x13);
+		/* VBI Offset */
 		cx25840_write(client, 0x47f, vbi_offset);
-
-		if (is_pal) {
-			for (i = 0; i <= 6; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
-		} else {
-			for (i = 0; i <= 9; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
-
-			for (i = 22; i <= 23; i++)
-				svbi->service_lines[0][i] =
-					svbi->service_lines[1][i] = 0;
-		}
-
-		for (i = 7; i <= 23; i++) {
-			for (x = 0; x <= 1; x++) {
-				switch (svbi->service_lines[1-x][i]) {
-				case V4L2_SLICED_TELETEXT_B:
-					lcr[i] |= 1 << (4 * x);
-					break;
-				case V4L2_SLICED_WSS_625:
-					lcr[i] |= 4 << (4 * x);
-					break;
-				case V4L2_SLICED_CAPTION_525:
-					lcr[i] |= 6 << (4 * x);
-					break;
-				case V4L2_SLICED_VPS:
-					lcr[i] |= 9 << (4 * x);
-					break;
-				}
-			}
-		}
-
-		if (is_pal) {
-			for (x = 1, i = 0x424; i <= 0x434; i++, x++) {
-				cx25840_write(client, i, lcr[6 + x]);
-			}
-		}
-		else {
-			for (x = 1, i = 0x424; i <= 0x430; i++, x++) {
-				cx25840_write(client, i, lcr[9 + x]);
-			}
-			for (i = 0x431; i <= 0x434; i++) {
-				cx25840_write(client, i, 0);
-			}
-		}
-
-		cx25840_write(client, 0x43c, 0x16);
-
-		if (is_pal) {
-			cx25840_write(client, 0x474, 0x2a);
-		} else {
-			cx25840_write(client, 0x474, 0x22);
-		}
-		break;
+		cx25840_write(client, 0x404, 0x2e);
+		return 0;
 	}
 
-	case VIDIOC_INT_DECODE_VBI_LINE:
-	{
-		struct v4l2_decode_vbi_line *vbi = arg;
-		u8 *p = vbi->p;
-		int id1, id2, l, err = 0;
+	for (x = 0; x <= 23; x++)
+		lcr[x] = 0x00;
 
-		if (p[0] || p[1] != 0xff || p[2] != 0xff ||
-		    (p[3] != 0x55 && p[3] != 0x91)) {
-			vbi->line = vbi->type = 0;
-			break;
-		}
+	/* Setup standard */
+	cx25840_std_setup(client);
 
-		p += 4;
-		id1 = p[-1];
-		id2 = p[0] & 0xf;
-		l = p[2] & 0x3f;
-		l += state->vbi_line_offset;
-		p += 4;
+	/* Sliced VBI */
+	cx25840_write(client, 0x404, 0x32);	/* Ancillary data */
+	cx25840_write(client, 0x406, 0x13);
+	cx25840_write(client, 0x47f, vbi_offset);
 
-		switch (id2) {
-		case 1:
-			id2 = V4L2_SLICED_TELETEXT_B;
-			break;
-		case 4:
-			id2 = V4L2_SLICED_WSS_625;
-			break;
-		case 6:
-			id2 = V4L2_SLICED_CAPTION_525;
-			err = !odd_parity(p[0]) || !odd_parity(p[1]);
-			break;
-		case 9:
-			id2 = V4L2_SLICED_VPS;
-			if (decode_vps(p, p) != 0) {
-				err = 1;
+	if (is_pal) {
+		for (i = 0; i <= 6; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+	} else {
+		for (i = 0; i <= 9; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+
+		for (i = 22; i <= 23; i++)
+			svbi->service_lines[0][i] =
+				svbi->service_lines[1][i] = 0;
+	}
+
+	for (i = 7; i <= 23; i++) {
+		for (x = 0; x <= 1; x++) {
+			switch (svbi->service_lines[1-x][i]) {
+			case V4L2_SLICED_TELETEXT_B:
+				lcr[i] |= 1 << (4 * x);
+				break;
+			case V4L2_SLICED_WSS_625:
+				lcr[i] |= 4 << (4 * x);
+				break;
+			case V4L2_SLICED_CAPTION_525:
+				lcr[i] |= 6 << (4 * x);
+				break;
+			case V4L2_SLICED_VPS:
+				lcr[i] |= 9 << (4 * x);
+				break;
 			}
-			break;
-		default:
-			id2 = 0;
+		}
+	}
+
+	if (is_pal) {
+		for (x = 1, i = 0x424; i <= 0x434; i++, x++)
+			cx25840_write(client, i, lcr[6 + x]);
+	} else {
+		for (x = 1, i = 0x424; i <= 0x430; i++, x++)
+			cx25840_write(client, i, lcr[9 + x]);
+		for (i = 0x431; i <= 0x434; i++)
+			cx25840_write(client, i, 0);
+	}
+
+	cx25840_write(client, 0x43c, 0x16);
+	cx25840_write(client, 0x474, is_pal ? 0x2a : 0x22);
+	return 0;
+}
+
+int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
+{
+	struct cx25840_state *state = to_state(sd);
+	u8 *p = vbi->p;
+	int id1, id2, l, err = 0;
+
+	if (p[0] || p[1] != 0xff || p[2] != 0xff ||
+			(p[3] != 0x55 && p[3] != 0x91)) {
+		vbi->line = vbi->type = 0;
+		return 0;
+	}
+
+	p += 4;
+	id1 = p[-1];
+	id2 = p[0] & 0xf;
+	l = p[2] & 0x3f;
+	l += state->vbi_line_offset;
+	p += 4;
+
+	switch (id2) {
+	case 1:
+		id2 = V4L2_SLICED_TELETEXT_B;
+		break;
+	case 4:
+		id2 = V4L2_SLICED_WSS_625;
+		break;
+	case 6:
+		id2 = V4L2_SLICED_CAPTION_525;
+		err = !odd_parity(p[0]) || !odd_parity(p[1]);
+		break;
+	case 9:
+		id2 = V4L2_SLICED_VPS;
+		if (decode_vps(p, p) != 0)
 			err = 1;
-			break;
-		}
-
-		vbi->type = err ? 0 : id2;
-		vbi->line = err ? 0 : l;
-		vbi->is_second_field = err ? 0 : (id1 == 0x55);
-		vbi->p = p;
+		break;
+	default:
+		id2 = 0;
+		err = 1;
 		break;
 	}
-	}
 
+	vbi->type = err ? 0 : id2;
+	vbi->line = err ? 0 : l;
+	vbi->is_second_field = err ? 0 : (id1 == 0x55);
+	vbi->p = p;
 	return 0;
 }
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 2d250a2..4995298 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -61,7 +61,7 @@
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_STV0288 if !DVB_FE_CUSTOMISE
 	select DVB_STB6000 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This adds support for DVB/ATSC cards based on the
 	  Conexant 2388x chip.
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 7f5b8bf..44eacfb 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -746,7 +746,6 @@
 		return -EINVAL;
 
 	strlcpy(f->description, "MPEG", sizeof(f->description));
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->pixelformat = V4L2_PIX_FMT_MPEG;
 	return 0;
 }
@@ -757,7 +756,6 @@
 	struct cx8802_fh  *fh   = priv;
 	struct cx8802_dev *dev  = fh->dev;
 
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
@@ -776,7 +774,6 @@
 	struct cx8802_fh  *fh   = priv;
 	struct cx8802_dev *dev  = fh->dev;
 
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
@@ -793,7 +790,6 @@
 	struct cx8802_dev *dev  = fh->dev;
 	struct cx88_core  *core = dev->core;
 
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.bytesperline = 0;
 	f->fmt.pix.sizeimage    = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
@@ -919,7 +915,7 @@
 	snprintf(name, sizeof(name), "%s/2", core->name);
 	printk("%s/2: ============  START LOG STATUS  ============\n",
 		core->name);
-	cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
+	call_all(core, core, log_status);
 	cx2341x_log_status(&dev->params, name);
 	printk("%s/2: =============  END LOG STATUS  =============\n",
 		core->name);
@@ -974,7 +970,7 @@
 
 	f->type = V4L2_TUNER_ANALOG_TV;
 	f->frequency = core->freq;
-	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+	call_all(core, tuner, g_frequency, f);
 
 	return 0;
 }
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 733ede3..0363971 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -732,6 +732,8 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		/* Some variants use a tda9874 and so need the tvaudio module. */
+		.audio_chip     = V4L2_IDENT_TVAUDIO,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -1934,6 +1936,39 @@
 		} },
 		.mpeg           = CX88_MPEG_DVB,
 	},
+	[CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = {
+		.name           = "Terratec Cinergy HT PCI MKII",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.radio_type     = TUNER_XC2028,
+		.radio_addr     = 0x61,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x004ff,
+			.gpio1  = 0x010ff,
+			.gpio2  = 0x00001,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x004fb,
+			.gpio1  = 0x010ef,
+			.audioroute = 1,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x004fb,
+			.gpio1  = 0x010ef,
+			.audioroute = 1,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x004ff,
+			.gpio1  = 0x010ff,
+			.gpio2  = 0x0ff,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
 };
 
 /* ------------------------------------------------------------------ */
@@ -2343,6 +2378,10 @@
 		.subvendor = 0xb200,
 		.subdevice = 0x4200,
 		.card      = CX88_BOARD_SATTRADE_ST4200,
+	}, {
+		.subvendor = 0x153b,
+		.subdevice = 0x1177,
+		.card      = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
 	},
 };
 
@@ -2819,6 +2858,7 @@
 		 */
 		break;
 	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
 		ctl->demod = XC3028_FE_ZARLINK456;
 		ctl->mts = 1;
 		break;
@@ -2947,7 +2987,7 @@
 		tea5767_cfg.tuner = TUNER_TEA5767;
 		tea5767_cfg.priv  = &ctl;
 
-		cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
+		call_all(core, tuner, s_config, &tea5767_cfg);
 		break;
 	}
 	case  CX88_BOARD_TEVII_S420:
@@ -2972,7 +3012,7 @@
 		tun_setup.type           = core->board.radio_type;
 		tun_setup.addr           = core->board.radio_addr;
 		tun_setup.tuner_callback = cx88_tuner_callback;
-		cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+		call_all(core, tuner, s_type_addr, &tun_setup);
 		mode_mask &= ~T_RADIO;
 	}
 
@@ -2982,7 +3022,7 @@
 		tun_setup.addr           = core->board.tuner_addr;
 		tun_setup.tuner_callback = cx88_tuner_callback;
 
-		cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+		call_all(core, tuner, s_type_addr, &tun_setup);
 	}
 
 	if (core->board.tda9887_conf) {
@@ -2991,7 +3031,7 @@
 		tda9887_cfg.tuner = TUNER_TDA9887;
 		tda9887_cfg.priv  = &core->board.tda9887_conf;
 
-		cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg);
+		call_all(core, tuner, s_config, &tda9887_cfg);
 	}
 
 	if (core->board.tuner_type == TUNER_XC2028) {
@@ -3007,9 +3047,9 @@
 		xc2028_cfg.priv  = &ctl;
 		info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
 			    ctl.fname);
-		cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
+		call_all(core, tuner, s_config, &xc2028_cfg);
 	}
-	cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
+	call_all(core, core, s_standby, 0);
 }
 
 /* ------------------------------------------------------------------ */
@@ -3089,6 +3129,8 @@
 	int i;
 
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (core == NULL)
+		return NULL;
 
 	atomic_inc(&core->refcount);
 	core->pci_bus  = pci->bus->number;
@@ -3100,7 +3142,15 @@
 
 	core->nr = nr;
 	sprintf(core->name, "cx88[%d]", core->nr);
+
+	strcpy(core->v4l2_dev.name, core->name);
+	if (v4l2_device_register(NULL, &core->v4l2_dev)) {
+		kfree(core);
+		return NULL;
+	}
+
 	if (0 != cx88_get_resources(core, pci)) {
+		v4l2_device_unregister(&core->v4l2_dev);
 		kfree(core);
 		return NULL;
 	}
@@ -3111,6 +3161,11 @@
 			      pci_resource_len(pci, 0));
 	core->bmmio = (u8 __iomem *)core->lmmio;
 
+	if (core->lmmio == NULL) {
+		kfree(core);
+		return NULL;
+	}
+
 	/* board config */
 	core->boardnr = UNSET;
 	if (card[core->nr] < ARRAY_SIZE(cx88_boards))
@@ -3149,8 +3204,36 @@
 	cx88_i2c_init(core, pci);
 
 	/* load tuner module, if needed */
-	if (TUNER_ABSENT != core->board.tuner_type)
-		request_module("tuner");
+	if (TUNER_ABSENT != core->board.tuner_type) {
+		/* Ignore 0x6b and 0x6f on cx88 boards.
+		 * FusionHDTV5 RT Gold has an ir receiver at 0x6b
+		 * and an RTC at 0x6f which can get corrupted if probed. */
+		static const unsigned short tv_addrs[] = {
+			0x42, 0x43, 0x4a, 0x4b,		/* tda8290 */
+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+			0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e,
+			I2C_CLIENT_END
+		};
+		int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
+
+		/* I don't trust the radio_type as is stored in the card
+		   definitions, so we just probe for it.
+		   The radio_type is sometimes missing, or set to UNSET but
+		   later code configures a tea5767.
+		 */
+		v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner", "tuner",
+				v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+		if (has_demod)
+			v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		if (core->board.tuner_addr == ADDR_UNSET) {
+			v4l2_i2c_new_probed_subdev(&core->i2c_adap, "tuner",
+				"tuner", has_demod ? tv_addrs + 4 : tv_addrs);
+		} else {
+			v4l2_i2c_new_subdev(&core->i2c_adap,
+				"tuner", "tuner", core->board.tuner_addr);
+		}
+	}
 
 	cx88_card_setup(core);
 	cx88_ir_init(core, pci);
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index b045874..f2fb9f3 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -991,7 +991,7 @@
 	set_tvaudio(core);
 
 	// tell i2c chips
-	cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
+	call_all(core, tuner, s_std, norm);
 
 	// done
 	return 0;
@@ -1011,7 +1011,8 @@
 		return NULL;
 	*vfd = *template;
 	vfd->minor   = -1;
-	vfd->parent  = &pci->dev;
+	vfd->v4l2_dev = &core->v4l2_dev;
+	vfd->parent = &pci->dev;
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 core->name, type, core->board.name);
@@ -1058,12 +1059,16 @@
 
 	mutex_lock(&devlist);
 	cx88_ir_fini(core);
-	if (0 == core->i2c_rc)
+	if (0 == core->i2c_rc) {
+		if (core->i2c_rtc)
+			i2c_unregister_device(core->i2c_rtc);
 		i2c_del_adapter(&core->i2c_adap);
+	}
 	list_del(&core->devlist);
 	iounmap(core->lmmio);
 	cx88_devcount--;
 	mutex_unlock(&devlist);
+	v4l2_device_unregister(&core->v4l2_dev);
 	kfree(core);
 }
 
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index aef5297..4ff4d9f 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -241,6 +241,12 @@
 	.demod_init    = dvico_dual_demod_init,
 };
 
+static struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner      = 1,
+	.if2           = 45600,
+};
+
 #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
 static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
 {
@@ -1131,6 +1137,16 @@
 		if (fe0->dvb.frontend != NULL)
 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		break;
+	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &cx88_terratec_cinergy_ht_pci_mkii_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+			if (attach_xc3028(0x61, dev) < 0)
+				goto frontend_detach;
+		}
+		break;
 	default:
 		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
 		       core->name);
@@ -1152,7 +1168,7 @@
 		fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
 
 	/* Put the analog decoder in standby to keep it quiet */
-	cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
+	call_all(core, core, s_standby, 0);
 
 	/* register everything */
 	return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index c0ff230..996b4ed 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -97,37 +97,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int attach_inform(struct i2c_client *client)
-{
-	struct cx88_core *core = i2c_get_adapdata(client->adapter);
-
-	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->driver.name, client->addr, client->name);
-	return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
-	struct cx88_core *core = i2c_get_adapdata(client->adapter);
-
-	dprintk(1, "i2c detach [client=%s]\n", client->name);
-	return 0;
-}
-
-void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
-{
-	if (0 != core->i2c_rc)
-		return;
-
-	if (core->gate_ctrl)
-		core->gate_ctrl(core, 1);
-
-	i2c_clients_command(&core->i2c_adap, cmd, arg);
-
-	if (core->gate_ctrl)
-		core->gate_ctrl(core, 0);
-}
-
 static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
 	.setsda  = cx8800_bit_setsda,
 	.setscl  = cx8800_bit_setscl,
@@ -173,20 +142,14 @@
 	memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
 	       sizeof(core->i2c_algo));
 
-	if (core->board.tuner_type != TUNER_ABSENT)
-		core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
-	if (core->board.mpeg & CX88_MPEG_DVB)
-		core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
 
 	core->i2c_adap.dev.parent = &pci->dev;
 	strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
 	core->i2c_adap.owner = THIS_MODULE;
 	core->i2c_adap.id = I2C_HW_B_CX2388x;
-	core->i2c_adap.client_register = attach_inform;
-	core->i2c_adap.client_unregister = detach_inform;
 	core->i2c_algo.udelay = i2c_udelay;
 	core->i2c_algo.data = core;
-	i2c_set_adapdata(&core->i2c_adap,core);
+	i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
 	core->i2c_adap.algo_data = &core->i2c_algo;
 	core->i2c_client.adapter = &core->i2c_adap;
 	strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
@@ -222,8 +185,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-EXPORT_SYMBOL(cx88_call_i2c_clients);
-
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 8683d10..ec05312 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -48,8 +48,7 @@
 
 	/* poll external decoder */
 	int polling;
-	struct work_struct work;
-	struct timer_list timer;
+	struct delayed_work work;
 	u32 gpio_addr;
 	u32 last_gpio;
 	u32 mask_keycode;
@@ -143,27 +142,19 @@
 	}
 }
 
-static void ir_timer(unsigned long data)
-{
-	struct cx88_IR *ir = (struct cx88_IR *)data;
-
-	schedule_work(&ir->work);
-}
-
 static void cx88_ir_work(struct work_struct *work)
 {
-	struct cx88_IR *ir = container_of(work, struct cx88_IR, work);
+	struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work);
 
 	cx88_ir_handle_key(ir);
-	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
 void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
 {
 	if (ir->polling) {
-		setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
-		INIT_WORK(&ir->work, cx88_ir_work);
-		schedule_work(&ir->work);
+		INIT_DELAYED_WORK(&ir->work, cx88_ir_work);
+		schedule_delayed_work(&ir->work, 0);
 	}
 	if (ir->sampling) {
 		core->pci_irqmask |= PCI_INT_IR_SMPINT;
@@ -179,10 +170,8 @@
 		core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
 	}
 
-	if (ir->polling) {
-		del_timer_sync(&ir->timer);
-		flush_scheduled_work();
-	}
+	if (ir->polling)
+		cancel_delayed_work_sync(&ir->work);
 }
 
 /* ---------------------------------------------------------------------- */
@@ -226,6 +215,8 @@
 	case CX88_BOARD_HAUPPAUGE_HVR3000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+	case CX88_BOARD_PCHDTV_HD3000:
+	case CX88_BOARD_PCHDTV_HD5500:
 		ir_codes = ir_codes_hauppauge_new;
 		ir_type = IR_TYPE_RC5;
 		ir->sampling = 1;
@@ -466,6 +457,8 @@
 	case CX88_BOARD_HAUPPAUGE_HVR3000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+	case CX88_BOARD_PCHDTV_HD3000:
+	case CX88_BOARD_PCHDTV_HD5500:
 		ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
 		ir_dprintk("biphase decoded: %x\n", ircode);
 		/*
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 791e69d..434237a 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -41,11 +41,6 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
-
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
@@ -298,6 +293,7 @@
 };
 static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
 
+/* Must be sorted from low to high control ID! */
 const u32 cx88_user_ctrls[] = {
 	V4L2_CID_USER_CLASS,
 	V4L2_CID_BRIGHTNESS,
@@ -435,8 +431,7 @@
 			struct v4l2_routing route;
 
 			route.input = INPUT(input).audioroute;
-			cx88_call_i2c_clients(core,
-				VIDIOC_INT_S_AUDIO_ROUTING, &route);
+			call_all(core, audio, s_routing, &route);
 		}
 		/* cx2388's C-ADC is connected to the tuner only.
 		   When used with S-Video, that ADC is busy dealing with
@@ -831,8 +826,7 @@
 				struct v4l2_routing route;
 
 				route.input = core->board.radio.audioroute;
-				cx88_call_i2c_clients(core,
-					VIDIOC_INT_S_AUDIO_ROUTING, &route);
+				call_all(core, audio, s_routing, &route);
 			}
 			/* "I2S ADC mode" */
 			core->tvaudio = WW_I2SADC;
@@ -843,7 +837,7 @@
 			cx88_set_tvaudio(core);
 			cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
 		}
-		cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
+		call_all(core, tuner, s_radio);
 	}
 	unlock_kernel();
 
@@ -937,7 +931,7 @@
 	kfree(fh);
 
 	if(atomic_dec_and_test(&dev->core->users))
-		cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+		call_all(dev->core, core, s_standby, 0);
 
 	return 0;
 }
@@ -1276,15 +1270,12 @@
 		[ CX88_VMUX_DVB        ] = "DVB",
 		[ CX88_VMUX_DEBUG      ] = "for debug only",
 	};
-	unsigned int n;
+	unsigned int n = i->index;
 
-	n = i->index;
 	if (n >= 4)
 		return -EINVAL;
 	if (0 == INPUT(n).type)
 		return -EINVAL;
-	memset(i,0,sizeof(*i));
-	i->index = n;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
 	strcpy(i->name,iname[INPUT(n).type]);
 	if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
@@ -1402,7 +1393,7 @@
 	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 	f->frequency = core->freq;
 
-	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
+	call_all(core, tuner, g_frequency, f);
 
 	return 0;
 }
@@ -1418,7 +1409,7 @@
 	mutex_lock(&core->lock);
 	core->freq = f->frequency;
 	cx88_newstation(core);
-	cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
+	call_all(core, tuner, s_frequency, f);
 
 	/* When changing channels it is required to reset TVAUDIO */
 	msleep (10);
@@ -1500,7 +1491,7 @@
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
 
-	cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
+	call_all(core, tuner, g_tuner, t);
 	return 0;
 }
 
@@ -1520,7 +1511,6 @@
 	if (unlikely(a->index))
 		return -EINVAL;
 
-	memset(a,0,sizeof(*a));
 	strcpy(a->name,"Radio");
 	return 0;
 }
@@ -1535,7 +1525,7 @@
 	if (0 != t->index)
 		return -EINVAL;
 
-	cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
+	call_all(core, tuner, s_tuner, t);
 
 	return 0;
 }
@@ -1892,12 +1882,30 @@
 	/* load and configure helper modules */
 
 	if (core->board.audio_chip == V4L2_IDENT_WM8775)
-		request_module("wm8775");
+		v4l2_i2c_new_subdev(&core->i2c_adap,
+				"wm8775", "wm8775", 0x36 >> 1);
+
+	if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
+		/* This probes for a tda9874 as is used on some
+		   Pixelview Ultra boards. */
+		static const unsigned short i2c_addr[] = {
+			0xb0 >> 1, I2C_CLIENT_END
+		};
+
+		v4l2_i2c_new_probed_subdev(&core->i2c_adap,
+				"tvaudio", "tvaudio", i2c_addr);
+	}
 
 	switch (core->boardnr) {
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
+		static struct i2c_board_info rtc_info = {
+			I2C_BOARD_INFO("isl1208", 0x6f)
+		};
+
 		request_module("rtc-isl1208");
+		core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
+	}
 		/* break intentionally omitted */
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
 		request_module("ir-kbd-i2c");
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 6025fdd..9a43fdf 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -25,7 +25,7 @@
 #include <linux/videodev2.h>
 #include <linux/kdev_t.h>
 
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/videobuf-dma-sg.h>
@@ -231,6 +231,7 @@
 #define CX88_BOARD_SATTRADE_ST4200         76
 #define CX88_BOARD_TBS_8910                77
 #define CX88_BOARD_PROF_6200               78
+#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -302,7 +303,6 @@
 	struct btcx_riscmem    stopper;
 	u32                    count;
 };
-struct cx88_core;
 
 struct cx88_core {
 	struct list_head           devlist;
@@ -327,6 +327,8 @@
 	u32                        i2c_state, i2c_rc;
 
 	/* config info -- analog */
+	struct v4l2_device 	   v4l2_dev;
+	struct i2c_client 	   *i2c_rtc;
 	unsigned int               boardnr;
 	struct cx88_board	   board;
 
@@ -365,6 +367,22 @@
 	int			   active_fe_id;
 };
 
+static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
+}
+
+#define call_all(core, o, f, args...) 				\
+	do {							\
+		if (!core->i2c_rc) {				\
+			if (core->gate_ctrl)			\
+				core->gate_ctrl(core, 1);	\
+			v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
+			if (core->gate_ctrl)			\
+				core->gate_ctrl(core, 0);	\
+		}						\
+	} while (0)
+
 struct cx8800_dev;
 struct cx8802_dev;
 
@@ -610,8 +628,6 @@
 /* cx88-i2c.c                                                  */
 
 extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
-extern void cx88_call_i2c_clients(struct cx88_core *core,
-				  unsigned int cmd, void *arg);
 
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 298810d..ba3709b 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -189,17 +189,20 @@
 					dst += len;
 				}
 				else
-					err("dabusb_iso_complete: invalid len %d", len);
+					dev_err(&purb->dev->dev,
+						"dabusb_iso_complete: invalid len %d\n", len);
 			}
 			else
 				dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status);
 		if (dst != purb->actual_length)
-			err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
+			dev_err(&purb->dev->dev,
+				"dst!=purb->actual_length:%d!=%d\n",
+					dst, purb->actual_length);
 	}
 
 	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
 		s->overruns++;
-		err("overrun (%d)", s->overruns);
+		dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns);
 	}
 	wake_up (&s->wait);
 }
@@ -220,13 +223,14 @@
 	while (transfer_len < (s->total_buffer_size << 10)) {
 		b = kzalloc(sizeof (buff_t), GFP_KERNEL);
 		if (!b) {
-			err("kzalloc(sizeof(buff_t))==NULL");
+			dev_err(&s->usbdev->dev,
+				"kzalloc(sizeof(buff_t))==NULL\n");
 			goto err;
 		}
 		b->s = s;
 		b->purb = usb_alloc_urb(packets, GFP_KERNEL);
 		if (!b->purb) {
-			err("usb_alloc_urb == NULL");
+			dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n");
 			kfree (b);
 			goto err;
 		}
@@ -235,7 +239,8 @@
 		if (!b->purb->transfer_buffer) {
 			kfree (b->purb);
 			kfree (b);
-			err("kmalloc(%d)==NULL", transfer_buffer_length);
+			dev_err(&s->usbdev->dev,
+				"kmalloc(%d)==NULL\n", transfer_buffer_length);
 			goto err;
 		}
 
@@ -279,10 +284,11 @@
 
 	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
 	if(ret<0) {
-		err("dabusb: usb_bulk_msg failed(%d)",ret);
+		dev_err(&s->usbdev->dev,
+			"usb_bulk_msg failed(%d)\n", ret);
 
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-			err("set_interface failed");
+			dev_err(&s->usbdev->dev, "set_interface failed\n");
 			return -EINVAL;
 		}
 
@@ -291,7 +297,7 @@
 	if( ret == -EPIPE ) {
 		dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n");
 		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
-			err("request failed");
+			dev_err(&s->usbdev->dev, "request failed\n");
 	}
 
 	pb->size = actual_length;
@@ -305,7 +311,8 @@
 	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
 
 	if (!transfer_buffer) {
-		err("dabusb_writemem: kmalloc(%d) failed.", len);
+		dev_err(&s->usbdev->dev,
+			"dabusb_writemem: kmalloc(%d) failed.\n", len);
 		return -ENOMEM;
 	}
 
@@ -327,13 +334,14 @@
 {
 	int ret;
 	const struct ihex_binrec *rec;
-	const struct firmware *fw;
+	const struct firmware *uninitialized_var(fw);
 
 	dbg("Enter dabusb_loadmem (internal)");
 
 	ret = request_ihex_firmware(&fw, "dabusb/firmware.fw", &s->usbdev->dev);
 	if (ret) {
-		err("Failed to load \"dabusb/firmware.fw\": %d\n", ret);
+		dev_err(&s->usbdev->dev,
+			"Failed to load \"dabusb/firmware.fw\": %d\n", ret);
 		goto out;
 	}
 	ret = dabusb_8051_reset (s, 1);
@@ -346,9 +354,10 @@
 		ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data,
 				       be16_to_cpu(rec->len));
 		if (ret < 0) {
-			err("dabusb_writemem failed (%d %04X %p %d)", ret,
-			    be32_to_cpu(rec->addr), rec->data,
-			    be16_to_cpu(rec->len));
+			dev_err(&s->usbdev->dev,
+				"dabusb_writemem failed (%d %04X %p %d)\n",
+				ret, be32_to_cpu(rec->addr),
+				rec->data, be16_to_cpu(rec->len));
 			break;
 		}
 	}
@@ -396,13 +405,15 @@
 	dbg("Enter dabusb_fpga_download (internal)");
 
 	if (!b) {
-		err("kmalloc(sizeof(bulk_transfer_t))==NULL");
+		dev_err(&s->usbdev->dev,
+			"kmalloc(sizeof(bulk_transfer_t))==NULL\n");
 		return -ENOMEM;
 	}
 
 	ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev);
 	if (ret) {
-		err("Failed to load \"dabusb/bitstream.bin\": %d\n", ret);
+		dev_err(&s->usbdev->dev,
+			"Failed to load \"dabusb/bitstream.bin\": %d\n", ret);
 		kfree(b);
 		return ret;
 	}
@@ -425,7 +436,7 @@
 		memcpy (b->data + 4, fw->data + 74 + n, 60);
 		ret = dabusb_bulk (s, b);
 		if (ret < 0) {
-			err("dabusb_bulk failed.");
+			dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n");
 			break;
 		}
 		mdelay (1);
@@ -478,9 +489,11 @@
 
 			ret = usb_submit_urb (end->purb, GFP_KERNEL);
 			if (ret) {
-				err("usb_submit_urb returned:%d", ret);
+				dev_err(&s->usbdev->dev,
+					"usb_submit_urb returned:%d\n", ret);
 				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-					err("startrek: dabusb_add_buf_tail failed");
+					dev_err(&s->usbdev->dev,
+						"startrek: dabusb_add_buf_tail failed\n");
 				break;
 			}
 			else
@@ -523,7 +536,8 @@
 
 			spin_unlock_irqrestore(&s->lock, flags);
 
-			err("error: rec_buf_list is empty");
+			dev_err(&s->usbdev->dev,
+				"error: rec_buf_list is empty\n");
 			goto err;
 		}
 
@@ -552,7 +566,8 @@
 
 			if (list_empty (&s->rec_buff_list)) {
 				spin_unlock_irqrestore(&s->lock, flags);
-				err("error: still no buffer available.");
+				dev_err(&s->usbdev->dev,
+					"error: still no buffer available.\n");
 				goto err;
 			}
 			spin_unlock_irqrestore(&s->lock, flags);
@@ -573,7 +588,7 @@
 		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
 
 		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
-			err("read: copy_to_user failed");
+			dev_err(&s->usbdev->dev, "read: copy_to_user failed\n");
 			if (!ret)
 				ret = -EFAULT;
 			goto err;
@@ -587,7 +602,8 @@
 		if (s->readptr == purb->actual_length) {
 			// finished, take next buffer
 			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-				err("read: dabusb_add_buf_tail failed");
+				dev_err(&s->usbdev->dev,
+					"read: dabusb_add_buf_tail failed\n");
 			s->readptr = 0;
 		}
 	}
@@ -623,7 +639,7 @@
 	}
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
 		mutex_unlock(&s->mutex);
-		err("set_interface failed");
+		dev_err(&s->usbdev->dev, "set_interface failed\n");
 		return -EINVAL;
 	}
 	s->opened = 1;
@@ -648,7 +664,7 @@
 
 	if (!s->remove_pending) {
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
-			err("set_interface failed");
+			dev_err(&s->usbdev->dev, "set_interface failed\n");
 	}
 	else
 		wake_up (&s->remove_ok);
@@ -657,7 +673,7 @@
 	return 0;
 }
 
-static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
 {
 	pdabusb_t s = (pdabusb_t) file->private_data;
 	pbulk_transfer_t pbulk;
@@ -666,13 +682,17 @@
 
 	dbg("dabusb_ioctl");
 
-	if (s->remove_pending)
+	lock_kernel();
+	if (s->remove_pending) {
+		unlock_kernel();
 		return -EIO;
+	}
 
 	mutex_lock(&s->mutex);
 
 	if (!s->usbdev) {
 		mutex_unlock(&s->mutex);
+		unlock_kernel();
 		return -EIO;
 	}
 
@@ -713,6 +733,7 @@
 		break;
 	}
 	mutex_unlock(&s->mutex);
+	unlock_kernel();
 	return ret;
 }
 
@@ -721,7 +742,7 @@
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.read =		dabusb_read,
-	.ioctl =	dabusb_ioctl,
+	.unlocked_ioctl =	dabusb_ioctl,
 	.open =		dabusb_open,
 	.release =	dabusb_release,
 };
@@ -764,7 +785,7 @@
 	s->devnum = intf->minor;
 
 	if (usb_reset_configuration (usbdev) < 0) {
-		err("reset_configuration failed");
+		dev_err(&intf->dev, "reset_configuration failed\n");
 		goto reject;
 	}
 	if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) {
@@ -775,7 +796,7 @@
 		dabusb_fpga_download (s, NULL);
 
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
-			err("set_interface failed");
+			dev_err(&intf->dev, "set_interface failed\n");
 			goto reject;
 		}
 	}
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index f132e31..0131322 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -56,7 +56,7 @@
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 
-static int em28xx_isoc_audio_deinit(struct em28xx *dev)
+static int em28xx_deinit_isoc_audio(struct em28xx *dev)
 {
 	int i;
 
@@ -66,6 +66,7 @@
 			usb_kill_urb(dev->adev.urb[i]);
 		else
 			usb_unlink_urb(dev->adev.urb[i]);
+
 		usb_free_urb(dev->adev.urb[i]);
 		dev->adev.urb[i] = NULL;
 
@@ -87,6 +88,20 @@
 	unsigned int             stride;
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_runtime   *runtime;
+
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:            /* error */
+		dprintk("urb completition error %d.\n", urb->status);
+		break;
+	}
+
 	if (dev->adev.capture_pcm_substream) {
 		substream = dev->adev.capture_pcm_substream;
 		runtime = substream->runtime;
@@ -137,9 +152,6 @@
 	}
 	urb->status = 0;
 
-	if (dev->adev.shutdown)
-		return;
-
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status < 0) {
 		em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
@@ -197,8 +209,7 @@
 	for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
 		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
 		if (errCode) {
-			em28xx_isoc_audio_deinit(dev);
-
+			em28xx_deinit_isoc_audio(dev);
 			return errCode;
 		}
 	}
@@ -213,14 +224,16 @@
 
 	switch (cmd) {
 	case EM28XX_CAPTURE_STREAM_EN:
-		if (dev->adev.capture_stream == STREAM_OFF && arg == 1) {
+		if (dev->adev.capture_stream == STREAM_OFF &&
+		    arg == EM28XX_START_AUDIO) {
 			dev->adev.capture_stream = STREAM_ON;
 			em28xx_init_audio_isoc(dev);
-		} else if (dev->adev.capture_stream == STREAM_ON && arg == 0) {
+		} else if (dev->adev.capture_stream == STREAM_ON &&
+			   arg == EM28XX_STOP_AUDIO) {
 			dev->adev.capture_stream = STREAM_OFF;
-			em28xx_isoc_audio_deinit(dev);
+			em28xx_deinit_isoc_audio(dev);
 		} else {
-			printk(KERN_ERR "An underrun very likely occurred. "
+			em28xx_errdev("An underrun very likely occurred. "
 					"Ignoring it.\n");
 		}
 		return 0;
@@ -234,7 +247,7 @@
 {
 	struct snd_pcm_runtime *runtime = subs->runtime;
 
-	dprintk("Alocating vbuffer\n");
+	dprintk("Allocating vbuffer\n");
 	if (runtime->dma_area) {
 		if (runtime->dma_bytes > size)
 			return 0;
@@ -302,7 +315,9 @@
 		dprintk("changing alternate number to 7\n");
 	}
 
+	mutex_lock(&dev->lock);
 	dev->adev.users++;
+	mutex_unlock(&dev->lock);
 
 	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
 	dev->adev.capture_pcm_substream = substream;
@@ -317,22 +332,15 @@
 static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
 {
 	struct em28xx *dev = snd_pcm_substream_chip(substream);
-	dev->adev.users--;
 
 	dprintk("closing device\n");
 
 	dev->mute = 1;
 	mutex_lock(&dev->lock);
+	dev->adev.users--;
 	em28xx_audio_analog_set(dev);
 	mutex_unlock(&dev->lock);
 
-	if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
-		dprintk("audio users: %d\n", dev->adev.users);
-		dprintk("disabling audio stream!\n");
-		dev->adev.shutdown = 0;
-		dprintk("released lock\n");
-		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
-	}
 	return 0;
 }
 
@@ -363,7 +371,7 @@
 	dprintk("Stop capture, if needed\n");
 
 	if (dev->adev.capture_stream == STREAM_ON)
-		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
+		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO);
 
 	return 0;
 }
@@ -377,33 +385,40 @@
 				      int cmd)
 {
 	struct em28xx *dev = snd_pcm_substream_chip(substream);
+	int retval;
 
-	dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)?
-				       "start": "stop");
+	dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ?
+				       "start" : "stop");
+
+	spin_lock(&dev->adev.slock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
-		return 0;
+		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_START_AUDIO);
+		retval = 0;
+		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		dev->adev.shutdown = 1;
-		return 0;
+		em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO);
+		retval = 0;
+		break;
 	default:
-		return -EINVAL;
+		retval = -EINVAL;
 	}
+
+	spin_unlock(&dev->adev.slock);
+	return retval;
 }
 
 static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
 						    *substream)
 {
-       unsigned long flags;
-
+	unsigned long flags;
 	struct em28xx *dev;
 	snd_pcm_uframes_t hwptr_done;
 
 	dev = snd_pcm_substream_chip(substream);
-       spin_lock_irqsave(&dev->adev.slock, flags);
+	spin_lock_irqsave(&dev->adev.slock, flags);
 	hwptr_done = dev->adev.hwptr_done_capture;
-       spin_unlock_irqrestore(&dev->adev.slock, flags);
+	spin_unlock_irqrestore(&dev->adev.slock, flags);
 
 	return hwptr_done;
 }
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 3b3ca3f..0f48c0f 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -122,6 +122,22 @@
 	{  -1,			-1,		-1,		-1},
 };
 
+/* Mute/unmute */
+static struct em28xx_reg_seq compro_unmute_tv_gpio[] = {
+	{EM28XX_R08_GPIO,	5,		7,		10},
+	{  -1,			-1,		-1,		-1},
+};
+
+static struct em28xx_reg_seq compro_unmute_svid_gpio[] = {
+	{EM28XX_R08_GPIO,	4,		7,		10},
+	{  -1,			-1,		-1,		-1},
+};
+
+static struct em28xx_reg_seq compro_mute_gpio[] = {
+	{EM28XX_R08_GPIO,	6,		7,		10},
+	{  -1,			-1,		-1,		-1},
+};
+
 /*
  *  Board definitions
  */
@@ -183,6 +199,25 @@
 			.amux     = EM28XX_AMUX_LINE_IN,
 		} },
 	},
+	[EM2820_BOARD_GADMEI_TVR200] = {
+		.name         = "Gadmei TVR200",
+		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+		.tda9887_conf = TDA9887_PRESENT,
+		.decoder      = EM28XX_SAA711X,
+		.input        = { {
+			.type     = EM28XX_VMUX_TELEVISION,
+			.vmux     = SAA7115_COMPOSITE2,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		}, {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = SAA7115_COMPOSITE0,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = SAA7115_SVIDEO3,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		} },
+	},
 	[EM2820_BOARD_TERRATEC_CINERGY_250] = {
 		.name         = "Terratec Cinergy 250 USB",
 		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
@@ -225,7 +260,7 @@
 		.name         = "Hauppauge WinTV USB 2",
 		.tuner_type   = TUNER_PHILIPS_FM1236_MK3,
 		.tda9887_conf = TDA9887_PRESENT |
-				TDA9887_PORT1_ACTIVE|
+				TDA9887_PORT1_ACTIVE |
 				TDA9887_PORT2_ACTIVE,
 		.decoder      = EM28XX_TVP5150,
 		.has_msp34xx  = 1,
@@ -350,26 +385,6 @@
 			.amux     = EM28XX_AMUX_VIDEO,
 		} },
 	},
-	[EM2821_BOARD_PROLINK_PLAYTV_USB2] = {
-		.name         = "SIIG AVTuner-PVR/Prolink PlayTV USB 2.0",
-		.valid        = EM28XX_BOARD_NOT_VALIDATED,
-		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,	/* unknown? */
-		.tda9887_conf = TDA9887_PRESENT,	/* unknown? */
-		.decoder      = EM28XX_SAA711X,
-		.input        = { {
-			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = SAA7115_COMPOSITE2,
-			.amux     = EM28XX_AMUX_LINE_IN,
-		}, {
-			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = SAA7115_COMPOSITE0,
-			.amux     = EM28XX_AMUX_LINE_IN,
-		}, {
-			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = SAA7115_SVIDEO3,
-			.amux     = EM28XX_AMUX_LINE_IN,
-		} },
-	},
 	[EM2821_BOARD_SUPERCOMP_USB_2] = {
 		.name         = "Supercomp USB 2.0 TV",
 		.valid        = EM28XX_BOARD_NOT_VALIDATED,
@@ -498,7 +513,7 @@
 	},
 	[EM2861_BOARD_YAKUMO_MOVIE_MIXER] = {
 		.name          = "Yakumo MovieMixer",
-		.tuner_type   = TUNER_ABSENT,	/* Capture only device */
+		.tuner_type    = TUNER_ABSENT,	/* Capture only device */
 		.decoder       = EM28XX_TVP5150,
 		.input         = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -604,6 +619,7 @@
 		.mts_firmware = 1,
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900_digital,
+		.ir_codes     = ir_codes_hauppauge_new,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -628,6 +644,7 @@
 		.tuner_type   = TUNER_XC2028,
 		.tuner_gpio   = default_tuner_gpio,
 		.mts_firmware = 1,
+		.ir_codes     = ir_codes_hauppauge_new,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -842,11 +859,11 @@
 		} },
 	},
 	[EM2800_BOARD_GRABBEEX_USB2800] = {
-		.name         = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder",
-		.is_em2800    = 1,
-		.decoder      = EM28XX_SAA711X,
-		.tuner_type   = TUNER_ABSENT, /* capture only board */
-		.input        = { {
+		.name       = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder",
+		.is_em2800  = 1,
+		.decoder    = EM28XX_SAA711X,
+		.tuner_type = TUNER_ABSENT, /* capture only board */
+		.input      = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = EM28XX_AMUX_LINE_IN,
@@ -897,7 +914,7 @@
 		} },
 	},
 	[EM2820_BOARD_PINNACLE_DVC_90] = {
-		.name         = "Pinnacle Dazzle DVC 90/DVC 100",
+		.name         = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker",
 		.tuner_type   = TUNER_ABSENT, /* capture only board */
 		.decoder      = EM28XX_SAA711X,
 		.input        = { {
@@ -952,7 +969,7 @@
 		} },
 	},
 	[EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
-		.name         = "Pixelview Prolink PlayTV USB 2.0",
+		.name         = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0",
 		.has_snapshot_button = 1,
 		.tda9887_conf = TDA9887_PRESENT,
 		.tuner_type   = TUNER_YMEC_TVF_5533MF,
@@ -1198,7 +1215,9 @@
 		.has_dvb      = 1,
 		.dvb_gpio     = kworld_330u_digital,
 		.xclk             = EM28XX_XCLK_FREQUENCY_12MHZ,
-		.i2c_speed        = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID,
+		.i2c_speed        = EM28XX_I2C_CLK_WAIT_ENABLE |
+				    EM28XX_I2C_EEPROM_ON_BOARD |
+				    EM28XX_I2C_EEPROM_KEY_VALID,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
@@ -1223,21 +1242,88 @@
 		.tuner_type   = TUNER_LG_PAL_NEW_TAPC,
 		.tda9887_conf = TDA9887_PRESENT,
 		.decoder      = EM28XX_TVP5150,
+		.adecoder     = EM28XX_TVAUDIO,
+		.mute_gpio    = compro_mute_gpio,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
 			.vmux     = TVP5150_COMPOSITE0,
+			.amux     = EM28XX_AMUX_VIDEO,
+			.gpio     = compro_unmute_tv_gpio,
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = TVP5150_SVIDEO,
+			.amux     = EM28XX_AMUX_LINE_IN,
+			.gpio     = compro_unmute_svid_gpio,
+		} },
+	},
+	[EM2860_BOARD_KAIOMY_TVNPC_U2] = {
+		.name	      = "Kaiomy TVnPC U2",
+		.vchannels    = 3,
+		.tuner_type   = TUNER_XC2028,
+		.tuner_addr   = 0x61,
+		.mts_firmware = 1,
+		.decoder      = EM28XX_TVP5150,
+		.tuner_gpio   = default_tuner_gpio,
+		.ir_codes     = ir_codes_kaiomy,
+		.input          = { {
+			.type     = EM28XX_VMUX_TELEVISION,
+			.vmux     = TVP5150_COMPOSITE0,
+			.amux     = EM28XX_AMUX_VIDEO,
+
+		}, {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = TVP5150_COMPOSITE1,
 			.amux     = EM28XX_AMUX_LINE_IN,
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = TVP5150_SVIDEO,
 			.amux     = EM28XX_AMUX_LINE_IN,
 		} },
+		.radio		= {
+			.type     = EM28XX_RADIO,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		}
+	},
+	[EM2860_BOARD_EASYCAP] = {
+		.name         = "Easy Cap Capture DC-60",
+		.vchannels    = 2,
+		.tuner_type   = TUNER_ABSENT,
+		.decoder      = EM28XX_SAA711X,
+		.input           = { {
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = SAA7115_COMPOSITE0,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		}, {
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = SAA7115_SVIDEO3,
+			.amux     = EM28XX_AMUX_LINE_IN,
+		} },
+	},
+	[EM2820_BOARD_IODATA_GVMVP_SZ] = {
+		.name       = "IO-DATA GV-MVP/SZ",
+		.tuner_type   = TUNER_PHILIPS_FM1236_MK3,
+		.tuner_gpio   = default_tuner_gpio,
+		.tda9887_conf = TDA9887_PRESENT,
+		.decoder      = EM28XX_TVP5150,
+		.input        = { {
+			.type     = EM28XX_VMUX_TELEVISION,
+			.vmux     = TVP5150_COMPOSITE0,
+			.amux     = EM28XX_AMUX_VIDEO,
+		}, { /* Composite has not been tested yet */
+			.type     = EM28XX_VMUX_COMPOSITE1,
+			.vmux     = TVP5150_COMPOSITE1,
+			.amux     = EM28XX_AMUX_VIDEO,
+		}, { /* S-video has not been tested yet */
+			.type     = EM28XX_VMUX_SVIDEO,
+			.vmux     = TVP5150_SVIDEO,
+			.amux     = EM28XX_AMUX_VIDEO,
+		} },
 	},
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
 /* table of devices that work with this driver */
-struct usb_device_id em28xx_id_table [] = {
+struct usb_device_id em28xx_id_table[] = {
 	{ USB_DEVICE(0xeb1a, 0x2750),
 			.driver_info = EM2750_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0x2751),
@@ -1260,6 +1346,8 @@
 			.driver_info = EM2820_BOARD_UNKNOWN },
 	{ USB_DEVICE(0xeb1a, 0xe300),
 			.driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
+	{ USB_DEVICE(0xeb1a, 0xe303),
+			.driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 },
 	{ USB_DEVICE(0xeb1a, 0xe305),
 			.driver_info = EM2880_BOARD_KWORLD_DVB_305U },
 	{ USB_DEVICE(0xeb1a, 0xe310),
@@ -1278,6 +1366,8 @@
 			.driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
 	{ USB_DEVICE(0xeb1a, 0xe357),
 			.driver_info = EM2870_BOARD_KWORLD_355U },
+	{ USB_DEVICE(0x1b80, 0xe302),
+			.driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
 	{ USB_DEVICE(0x0ccd, 0x0036),
 			.driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
 	{ USB_DEVICE(0x0ccd, 0x004c),
@@ -1330,6 +1420,8 @@
 			.driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
 	{ USB_DEVICE(0x093b, 0xa005),
 			.driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
+	{ USB_DEVICE(0x04bb, 0x0515),
+			.driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -1337,7 +1429,7 @@
 /*
  * EEPROM hash table for devices with generic USB IDs
  */
-static struct em28xx_hash_table em28xx_eeprom_hash [] = {
+static struct em28xx_hash_table em28xx_eeprom_hash[] = {
 	/* P/N: SA 60002070465 Tuner: TVF7533-MF */
 	{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
 	{0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
@@ -1349,6 +1441,7 @@
 	{0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
 	{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
 	{0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
+	{0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
 };
 
 int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
@@ -1368,7 +1461,7 @@
 }
 EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
 
-static void inline em28xx_set_model(struct em28xx *dev)
+static inline void em28xx_set_model(struct em28xx *dev)
 {
 	memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board));
 
@@ -1504,6 +1597,34 @@
 		/* enables audio for that devices */
 		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
 		break;
+
+	case EM2860_BOARD_KAIOMY_TVNPC_U2:
+		em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1);
+		em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+		em28xx_write_regs(dev, 0x0d, "\x42", 1);
+		em28xx_write_regs(dev, 0x08, "\xfd", 1);
+		msleep(10);
+		em28xx_write_regs(dev, 0x08, "\xff", 1);
+		msleep(10);
+		em28xx_write_regs(dev, 0x08, "\x7f", 1);
+		msleep(10);
+		em28xx_write_regs(dev, 0x08, "\x6b", 1);
+
+		break;
+	case EM2860_BOARD_EASYCAP:
+		em28xx_write_regs(dev, 0x08, "\xf8", 1);
+		break;
+
+	case EM2820_BOARD_IODATA_GVMVP_SZ:
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+		msleep(70);
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+		msleep(10);
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+		msleep(70);
+		em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+		msleep(70);
+		break;
 	}
 
 	em28xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -1610,7 +1731,7 @@
 			em28xx_errdev("If the board were missdetected, "
 				      "please email this log to:\n");
 			em28xx_errdev("\tV4L Mailing List "
-				      " <video4linux-list@redhat.com>\n");
+				      " <linux-media@vger.kernel.org>\n");
 			em28xx_errdev("Board detected as %s\n",
 				      em28xx_boards[dev->model].name);
 
@@ -1642,7 +1763,7 @@
 			em28xx_errdev("If the board were missdetected, "
 				      "please email this log to:\n");
 			em28xx_errdev("\tV4L Mailing List "
-				      " <video4linux-list@redhat.com>\n");
+				      " <linux-media@vger.kernel.org>\n");
 			em28xx_errdev("Board detected as %s\n",
 				      em28xx_boards[dev->model].name);
 
@@ -1655,7 +1776,7 @@
 	em28xx_errdev("You may try to use card=<n> insmod option to "
 		      "workaround that.\n");
 	em28xx_errdev("Please send an email with this log to:\n");
-	em28xx_errdev("\tV4L Mailing List <video4linux-list@redhat.com>\n");
+	em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n");
 	em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash);
 	em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash);
 
@@ -1800,6 +1921,8 @@
 		request_module("tvp5150");
 	if (dev->board.tuner_type != TUNER_ABSENT)
 		request_module("tuner");
+	if (dev->board.adecoder == EM28XX_TVAUDIO)
+		request_module("tvaudio");
 #endif
 
 	em28xx_config_tuner(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 94fb1b6..8f1999c 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -33,8 +33,8 @@
 /* #define ENABLE_DEBUG_ISOC_FRAMES */
 
 static unsigned int core_debug;
-module_param(core_debug,int,0644);
-MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
 
 #define em28xx_coredbg(fmt, arg...) do {\
 	if (core_debug) \
@@ -42,8 +42,8 @@
 			 dev->name, __func__ , ##arg); } while (0)
 
 static unsigned int reg_debug;
-module_param(reg_debug,int,0644);
-MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
+module_param(reg_debug, int, 0644);
+MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
 
 #define em28xx_regdbg(fmt, arg...) do {\
 	if (reg_debug) \
@@ -77,7 +77,7 @@
 		return -EINVAL;
 
 	if (reg_debug) {
-		printk( KERN_DEBUG "(pipe 0x%08x): "
+		printk(KERN_DEBUG "(pipe 0x%08x): "
 			"IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
 			pipe,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -154,7 +154,7 @@
 	if (reg_debug) {
 		int byte;
 
-		printk( KERN_DEBUG "(pipe 0x%08x): "
+		printk(KERN_DEBUG "(pipe 0x%08x): "
 			"OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
 			pipe,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -378,6 +378,11 @@
 		}
 	}
 
+	if (dev->board.mute_gpio && dev->mute)
+		em28xx_gpio_set(dev, dev->board.mute_gpio);
+	else
+		em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
+
 	ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
 	if (ret < 0)
 		return ret;
@@ -424,7 +429,7 @@
 
 	xclk = dev->board.xclk & 0x7f;
 	if (!dev->mute)
-		xclk |= 0x80;
+		xclk |= EM28XX_XCLK_AUDIO_UNMUTE;
 
 	ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk);
 	if (ret < 0)
@@ -462,7 +467,8 @@
 		if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
 			int sel = ac97_return_record_select(dev->ctl_aoutput);
 
-			/* Use the same input for both left and right channels */
+			/* Use the same input for both left and right
+			   channels */
 			sel |= (sel << 8);
 
 			em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel);
@@ -698,7 +704,7 @@
 		em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
 		/* it seems that both H and V scalers must be active
 		   to work correctly */
-		mode = (h || v)? 0x30: 0x00;
+		mode = (h || v) ? 0x30 : 0x00;
 	}
 	return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
 }
@@ -827,6 +833,19 @@
 	struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
 	int rc, i;
 
+	switch (urb->status) {
+	case 0:             /* success */
+	case -ETIMEDOUT:    /* NAK */
+		break;
+	case -ECONNRESET:   /* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:            /* error */
+		em28xx_isocdbg("urb completition error %d.\n", urb->status);
+		break;
+	}
+
 	/* Copy data from URB */
 	spin_lock(&dev->slock);
 	rc = dev->isoc_ctl.isoc_copy(dev, urb);
@@ -945,7 +964,7 @@
 			em28xx_err("unable to allocate %i bytes for transfer"
 					" buffer %i%s\n",
 					sb_size, i,
-					in_interrupt()?" while in int":"");
+					in_interrupt() ? " while in int" : "");
 			em28xx_uninit_isoc(dev);
 			return -ENOMEM;
 		}
@@ -963,7 +982,7 @@
 				 em28xx_irq_callback, dma_q, 1);
 
 		urb->number_of_packets = max_packets;
-		urb->transfer_flags = URB_ISO_ASAP;
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 
 		k = 0;
 		for (j = 0; j < max_packets; j++) {
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 9ad8527..fcd2551 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -29,9 +29,6 @@
 #include "lgdt330x.h"
 #include "zl10353.h"
 #include "s5h1409.h"
-#ifdef EM28XX_DRX397XD_SUPPORT
-#include "drx397xD.h"
-#endif
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index d69f0ef..02c12fe 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -402,10 +402,12 @@
 				 dev->name);
 		break;
 	case 2:
-		printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", dev->name);
+		printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
+				 dev->name);
 		break;
 	case 3:
-		printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", dev->name);
+		printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
+				 dev->name);
 		break;
 	}
 
@@ -508,12 +510,17 @@
 		dprintk1(1, "attach_inform: tvp5150 detected.\n");
 		break;
 
+	case 0xb0:
+		dprintk1(1, "attach_inform: tda9874 detected\n");
+		break;
+
 	default:
 		if (!dev->tuner_addr)
 			dev->tuner_addr = client->addr;
 
 		dprintk1(1, "attach inform: detected I2C address %x\n",
 				client->addr << 1);
+		dprintk1(1, "driver id %d\n", client->driver->id);
 
 	}
 
@@ -552,6 +559,7 @@
 	[0x80 >> 1] = "msp34xx",
 	[0x88 >> 1] = "msp34xx",
 	[0xa0 >> 1] = "eeprom",
+	[0xb0 >> 1] = "tda9874",
 	[0xb8 >> 1] = "tvp5150a",
 	[0xba >> 1] = "tvp5150a",
 	[0xc0 >> 1] = "tuner (analog)",
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 0443afe..a5abfd7 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -68,8 +68,7 @@
 
 	/* poll external decoder */
 	int polling;
-	struct work_struct work;
-	struct timer_list timer;
+	struct delayed_work work;
 	unsigned int last_toggle:1;
 	unsigned int last_readcount;
 	unsigned int repeat_interval;
@@ -292,32 +291,23 @@
 	return;
 }
 
-static void ir_timer(unsigned long data)
-{
-	struct em28xx_IR *ir = (struct em28xx_IR *)data;
-
-	schedule_work(&ir->work);
-}
-
 static void em28xx_ir_work(struct work_struct *work)
 {
-	struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work);
+	struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work);
 
 	em28xx_ir_handle_key(ir);
-	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
 static void em28xx_ir_start(struct em28xx_IR *ir)
 {
-	setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
-	INIT_WORK(&ir->work, em28xx_ir_work);
-	schedule_work(&ir->work);
+	INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
+	schedule_delayed_work(&ir->work, 0);
 }
 
 static void em28xx_ir_stop(struct em28xx_IR *ir)
 {
-	del_timer_sync(&ir->timer);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&ir->work);
 }
 
 int em28xx_ir_init(struct em28xx *dev)
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 8e61b2c..575472f 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -186,7 +186,8 @@
 		em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
 			       ((char *)startwrite + lencopy) -
 			       ((char *)outp + buf->vb.size));
-		lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite;
+		remain = (char *)outp + buf->vb.size - (char *)startwrite;
+		lencopy = remain;
 	}
 	if (lencopy <= 0)
 		return;
@@ -202,7 +203,8 @@
 		else
 			lencopy = bytesperline;
 
-		if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+		if ((char *)startwrite + lencopy > (char *)outp +
+		    buf->vb.size) {
 			em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
 				       ((char *)startwrite + lencopy) -
 				       ((char *)outp + buf->vb.size));
@@ -347,7 +349,7 @@
 		}
 		if (p[0] == 0x22 && p[1] == 0x5a) {
 			em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
-				       len, (p[2] & 1)? "odd" : "even");
+				       len, (p[2] & 1) ? "odd" : "even");
 
 			if (!(p[2] & 1)) {
 				if (buf != NULL)
@@ -476,7 +478,9 @@
 static void
 buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
 {
-	struct em28xx_buffer    *buf     = container_of(vb, struct em28xx_buffer, vb);
+	struct em28xx_buffer    *buf     = container_of(vb,
+							struct em28xx_buffer,
+							vb);
 	struct em28xx_fh        *fh      = vq->priv_data;
 	struct em28xx           *dev     = fh->dev;
 	struct em28xx_dmaqueue  *vidq    = &dev->vidq;
@@ -489,7 +493,9 @@
 static void buffer_release(struct videobuf_queue *vq,
 				struct videobuf_buffer *vb)
 {
-	struct em28xx_buffer   *buf  = container_of(vb, struct em28xx_buffer, vb);
+	struct em28xx_buffer   *buf  = container_of(vb,
+						    struct em28xx_buffer,
+						    vb);
 	struct em28xx_fh       *fh   = vq->priv_data;
 	struct em28xx          *dev  = (struct em28xx *)fh->dev;
 
@@ -534,6 +540,13 @@
 			&route);
 	}
 
+	if (dev->board.adecoder != EM28XX_NOADECODER) {
+		route.input = dev->ctl_ainput;
+		route.output = dev->ctl_aoutput;
+		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING,
+			&route);
+	}
+
 	em28xx_audio_analog_set(dev);
 }
 
@@ -557,7 +570,7 @@
 
 static int res_check(struct em28xx_fh *fh)
 {
-	return (fh->stream_on);
+	return fh->stream_on;
 }
 
 static void res_free(struct em28xx_fh *fh)
@@ -791,7 +804,7 @@
 	return rc;
 }
 
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
 	struct em28xx_fh   *fh  = priv;
 	struct em28xx      *dev = fh->dev;
@@ -1008,8 +1021,13 @@
 
 	if (dev->board.has_msp34xx)
 		em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
-	else
+	else {
 		rc = em28xx_get_ctrl(dev, ctrl);
+		if (rc < 0) {
+			em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);
+			rc = 0;
+		}
+	}
 
 	mutex_unlock(&dev->lock);
 	return rc;
@@ -1345,7 +1363,7 @@
 
 	strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
 	strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
-	strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
 	cap->version = EM28XX_VERSION_CODE;
 
@@ -1431,7 +1449,7 @@
 	if (rc < 0)
 		return rc;
 
-	return (videobuf_reqbufs(&fh->vb_vidq, rb));
+	return videobuf_reqbufs(&fh->vb_vidq, rb);
 }
 
 static int vidioc_querybuf(struct file *file, void *priv,
@@ -1445,7 +1463,7 @@
 	if (rc < 0)
 		return rc;
 
-	return (videobuf_querybuf(&fh->vb_vidq, b));
+	return videobuf_querybuf(&fh->vb_vidq, b);
 }
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1458,7 +1476,7 @@
 	if (rc < 0)
 		return rc;
 
-	return (videobuf_qbuf(&fh->vb_vidq, b));
+	return videobuf_qbuf(&fh->vb_vidq, b);
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -1471,8 +1489,7 @@
 	if (rc < 0)
 		return rc;
 
-	return (videobuf_dqbuf(&fh->vb_vidq, b,
-				file->f_flags & O_NONBLOCK));
+	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
 }
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -1496,7 +1513,7 @@
 
 	strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
 	strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
-	strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 
 	cap->version = EM28XX_VERSION_CODE;
 	cap->capabilities = V4L2_CAP_TUNER;
@@ -1781,7 +1798,7 @@
  * em28xx_v4l2_poll()
  * will allocate buffers when called for the first time
  */
-static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait)
+static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
 {
 	struct em28xx_fh *fh = filp->private_data;
 	struct em28xx *dev = fh->dev;
@@ -1934,8 +1951,8 @@
 
 
 static struct video_device *em28xx_vdev_init(struct em28xx *dev,
-					     const struct video_device *template,
-					     const char *type_name)
+					const struct video_device *template,
+					const char *type_name)
 {
 	struct video_device *vfd;
 
@@ -1984,8 +2001,9 @@
 	/* enable vbi capturing */
 
 /*	em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
-       val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
-       em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val));
+	val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
+	em28xx_write_reg(dev, EM28XX_R0F_XCLK,
+			 (EM28XX_XCLK_AUDIO_UNMUTE | val));
 	em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
 
 	em28xx_set_outfmt(dev);
@@ -2020,7 +2038,8 @@
 	}
 
 	if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
-		dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");
+		dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
+						  "radio");
 		if (!dev->radio_dev) {
 			em28xx_errdev("cannot allocate video_device.\n");
 			return -ENODEV;
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index dd2cd36..a33a58d 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -70,7 +70,6 @@
 #define EM2820_BOARD_VIDEOLOGY_20K14XUSB	  30
 #define EM2821_BOARD_USBGEAR_VD204		  31
 #define EM2821_BOARD_SUPERCOMP_USB_2		  32
-#define EM2821_BOARD_PROLINK_PLAYTV_USB2	  33
 #define EM2860_BOARD_TERRATEC_HYBRID_XS		  34
 #define EM2860_BOARD_TYPHOON_DVD_MAKER		  35
 #define EM2860_BOARD_NETGMBH_CAM		  36
@@ -98,6 +97,10 @@
 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU	  58
 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850	  60
 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2	  61
+#define EM2820_BOARD_GADMEI_TVR200		  62
+#define EM2860_BOARD_KAIOMY_TVNPC_U2              63
+#define EM2860_BOARD_EASYCAP                      64
+#define EM2820_BOARD_IODATA_GVMVP_SZ		  65
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -110,6 +113,10 @@
 #define EM28XX_BOARD_NOT_VALIDATED 1
 #define EM28XX_BOARD_VALIDATED	   0
 
+/* Params for em28xx_cmd() audio */
+#define EM28XX_START_AUDIO      1
+#define EM28XX_STOP_AUDIO       0
+
 /* maximum number of em28xx boards */
 #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
 
@@ -154,7 +161,8 @@
 */
 
 /* time to wait when stopping the isoc transfer */
-#define EM28XX_URB_TIMEOUT       msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS)
+#define EM28XX_URB_TIMEOUT \
+			msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS)
 
 /* time in msecs to wait for i2c writes to finish */
 #define EM2800_I2C_WRITE_TIMEOUT 20
@@ -348,6 +356,11 @@
 	EM28XX_SAA711X,
 };
 
+enum em28xx_adecoder {
+	EM28XX_NOADECODER = 0,
+	EM28XX_TVAUDIO,
+};
+
 struct em28xx_board {
 	char *name;
 	int vchannels;
@@ -361,6 +374,7 @@
 	struct em28xx_reg_seq *dvb_gpio;
 	struct em28xx_reg_seq *suspend_gpio;
 	struct em28xx_reg_seq *tuner_gpio;
+	struct em28xx_reg_seq *mute_gpio;
 
 	unsigned int is_em2800:1;
 	unsigned int has_msp34xx:1;
@@ -373,6 +387,7 @@
 	unsigned char xclk, i2c_speed;
 
 	enum em28xx_decoder decoder;
+	enum em28xx_adecoder adecoder;
 
 	struct em28xx_input       input[MAX_EM28XX_INPUT];
 	struct em28xx_input	  radio;
@@ -420,7 +435,7 @@
 	unsigned int hwptr_done_capture;
 	struct snd_card            *sndcard;
 
-	int users, shutdown;
+	int users;
 	enum em28xx_stream_state capture_stream;
 	spinlock_t slock;
 };
@@ -523,7 +538,8 @@
 	int num_alt;		/* Number of alternative settings */
 	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
 	struct urb *urb[EM28XX_NUM_BUFS];	/* urb for isoc transfers */
-	char *transfer_buffer[EM28XX_NUM_BUFS];	/* transfer buffers for isoc transfer */
+	char *transfer_buffer[EM28XX_NUM_BUFS];	/* transfer buffers for isoc
+						   transfer */
 	char urb_buf[URB_MAX_CTRL_SIZE];	/* urb control msg buffer */
 
 	/* helper funcs that call usb_control_msg */
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index ee6a691..578dc4f 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -56,6 +56,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_mars.
 
+config USB_GSPCA_MR97310A
+	tristate "Mars-Semi MR97310A USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the MR97310A chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_mr97310a.
+
 config USB_GSPCA_OV519
 	tristate "OV519 USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
@@ -167,6 +176,24 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_spca561.
 
+config USB_GSPCA_SQ905
+	tristate "SQ Technologies SQ905 based USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the SQ905 chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_sq905.
+
+config USB_GSPCA_SQ905C
+	tristate "SQ Technologies SQ905C based USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the SQ905C chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_sq905c.
+
 config USB_GSPCA_STK014
 	tristate "Syntek DV4000 (STK014) USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index bd8d9ee..8a6643e 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -1,50 +1,56 @@
-obj-$(CONFIG_USB_GSPCA)		+= gspca_main.o
-obj-$(CONFIG_USB_GSPCA_CONEX)	+= gspca_conex.o
-obj-$(CONFIG_USB_GSPCA_ETOMS)	+= gspca_etoms.o
-obj-$(CONFIG_USB_GSPCA_FINEPIX)	+= gspca_finepix.o
-obj-$(CONFIG_USB_GSPCA_MARS)	+= gspca_mars.o
-obj-$(CONFIG_USB_GSPCA_OV519)	+= gspca_ov519.o
-obj-$(CONFIG_USB_GSPCA_OV534)	+= gspca_ov534.o
-obj-$(CONFIG_USB_GSPCA_PAC207)	+= gspca_pac207.o
-obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
-obj-$(CONFIG_USB_GSPCA_SONIXB)	+= gspca_sonixb.o
-obj-$(CONFIG_USB_GSPCA_SONIXJ)	+= gspca_sonixj.o
-obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
-obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o
-obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
-obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
-obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
-obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
-obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
-obj-$(CONFIG_USB_GSPCA_STK014)	+= gspca_stk014.o
-obj-$(CONFIG_USB_GSPCA_T613)	+= gspca_t613.o
-obj-$(CONFIG_USB_GSPCA_TV8532)	+= gspca_tv8532.o
-obj-$(CONFIG_USB_GSPCA_VC032X)	+= gspca_vc032x.o
-obj-$(CONFIG_USB_GSPCA_ZC3XX)	+= gspca_zc3xx.o
+obj-$(CONFIG_USB_GSPCA)          += gspca_main.o
+obj-$(CONFIG_USB_GSPCA_CONEX)    += gspca_conex.o
+obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
+obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
+obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
+obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
+obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
+obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
+obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
+obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
+obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
+obj-$(CONFIG_USB_GSPCA_SPCA500)  += gspca_spca500.o
+obj-$(CONFIG_USB_GSPCA_SPCA501)  += gspca_spca501.o
+obj-$(CONFIG_USB_GSPCA_SPCA505)  += gspca_spca505.o
+obj-$(CONFIG_USB_GSPCA_SPCA506)  += gspca_spca506.o
+obj-$(CONFIG_USB_GSPCA_SPCA508)  += gspca_spca508.o
+obj-$(CONFIG_USB_GSPCA_SPCA561)  += gspca_spca561.o
+obj-$(CONFIG_USB_GSPCA_SQ905)    += gspca_sq905.o
+obj-$(CONFIG_USB_GSPCA_SQ905C)   += gspca_sq905c.o
+obj-$(CONFIG_USB_GSPCA_SUNPLUS)  += gspca_sunplus.o
+obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.o
+obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TV8532)   += gspca_tv8532.o
+obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
+obj-$(CONFIG_USB_GSPCA_ZC3XX)    += gspca_zc3xx.o
 
-gspca_main-objs			:= gspca.o
-gspca_conex-objs		:= conex.o
-gspca_etoms-objs		:= etoms.o
-gspca_finepix-objs		:= finepix.o
-gspca_mars-objs			:= mars.o
-gspca_ov519-objs		:= ov519.o
-gspca_ov534-objs		:= ov534.o
-gspca_pac207-objs		:= pac207.o
-gspca_pac7311-objs		:= pac7311.o
-gspca_sonixb-objs		:= sonixb.o
-gspca_sonixj-objs		:= sonixj.o
-gspca_spca500-objs		:= spca500.o
-gspca_spca501-objs		:= spca501.o
-gspca_spca505-objs		:= spca505.o
-gspca_spca506-objs		:= spca506.o
-gspca_spca508-objs		:= spca508.o
-gspca_spca561-objs		:= spca561.o
-gspca_stk014-objs		:= stk014.o
-gspca_sunplus-objs		:= sunplus.o
-gspca_t613-objs			:= t613.o
-gspca_tv8532-objs		:= tv8532.o
-gspca_vc032x-objs		:= vc032x.o
-gspca_zc3xx-objs		:= zc3xx.o
+gspca_main-objs     := gspca.o
+gspca_conex-objs    := conex.o
+gspca_etoms-objs    := etoms.o
+gspca_finepix-objs  := finepix.o
+gspca_mars-objs     := mars.o
+gspca_mr97310a-objs := mr97310a.o
+gspca_ov519-objs    := ov519.o
+gspca_ov534-objs    := ov534.o
+gspca_pac207-objs   := pac207.o
+gspca_pac7311-objs  := pac7311.o
+gspca_sonixb-objs   := sonixb.o
+gspca_sonixj-objs   := sonixj.o
+gspca_spca500-objs  := spca500.o
+gspca_spca501-objs  := spca501.o
+gspca_spca505-objs  := spca505.o
+gspca_spca506-objs  := spca506.o
+gspca_spca508-objs  := spca508.o
+gspca_spca561-objs  := spca561.o
+gspca_sq905-objs    := sq905.o
+gspca_sq905c-objs   := sq905c.o
+gspca_stk014-objs   := stk014.o
+gspca_sunplus-objs  := sunplus.o
+gspca_t613-objs     := t613.o
+gspca_tv8532-objs   := tv8532.o
+gspca_vc032x-objs   := vc032x.o
+gspca_zc3xx-objs    := zc3xx.o
 
-obj-$(CONFIG_USB_M5602)		+= m5602/
-obj-$(CONFIG_USB_STV06XX) 	+= stv06xx/
+obj-$(CONFIG_USB_M5602)   += m5602/
+obj-$(CONFIG_USB_STV06XX) += stv06xx/
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 1753f5b..219cfa6 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -36,8 +36,12 @@
 	unsigned char brightness;
 	unsigned char contrast;
 	unsigned char colors;
+	u8 quality;
+#define QUALITY_MIN 30
+#define QUALITY_MAX 60
+#define QUALITY_DEF 40
 
-	unsigned char qindex;
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -815,14 +819,13 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
 
-	sd->qindex = 0;			/* set the quantization */
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->contrast = CONTRAST_DEF;
 	sd->colors = COLOR_DEF;
+	sd->quality = QUALITY_DEF;
 	return 0;
 }
 
@@ -839,6 +842,14 @@
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x22);		/* JPEG 411 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	cx11646_initsize(gspca_dev);
 	cx11646_fw(gspca_dev);
 	cx_sensor(gspca_dev);
@@ -849,8 +860,11 @@
 /* called on streamoff with alt 0 and on disconnect */
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	int retry = 50;
 
+	kfree(sd->jpeg_hdr);
+
 	if (!gspca_dev->present)
 		return;
 	reg_w_val(gspca_dev, 0x0000, 0x00);
@@ -876,6 +890,8 @@
 			__u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
 	if (data[0] == 0xff && data[1] == 0xd8) {
 
 		/* start of frame */
@@ -883,9 +899,8 @@
 					data, 0);
 
 		/* put the JPEG header in the new frame */
-		jpeg_put_header(gspca_dev, frame,
-				((struct sd *) gspca_dev)->qindex,
-				0x22);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
 		data += 2;
 		len -= 2;
 	}
@@ -988,6 +1003,34 @@
 	return 0;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -998,6 +1041,8 @@
 	.start = sd_start,
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -1029,8 +1074,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index f3cd8ff..2c20d06 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -472,19 +472,6 @@
 		reg_w_val(gspca_dev, ET_O_RED + i, brightness);
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int i;
-	int brightness = 0;
-
-	for (i = 0; i < 4; i++) {
-		reg_r(gspca_dev, ET_O_RED + i, 1);
-		brightness += gspca_dev->usb_buf[0];
-	}
-	sd->brightness = brightness >> 3;
-}
-
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -495,19 +482,6 @@
 	reg_w(gspca_dev, ET_G_RED, RGBG, 6);
 }
 
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int i;
-	int contrast = 0;
-
-	for (i = 0; i < 4; i++) {
-		reg_r(gspca_dev, ET_G_RED + i, 1);
-		contrast += gspca_dev->usb_buf[0];
-	}
-	sd->contrast = contrast >> 2;
-}
-
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -658,7 +632,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 1;
 	sd->sensor = id->driver_info;
 	if (sd->sensor == SENSOR_PAS106) {
 		cam->cam_mode = sif_mode;
@@ -821,7 +794,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -840,7 +812,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcontrast(gspca_dev);
 	*val = sd->contrast;
 	return 0;
 }
@@ -859,7 +830,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcolors(gspca_dev);
 	*val = sd->colors;
 	return 0;
 }
@@ -928,8 +898,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
index afc8b2d..00e6863 100644
--- a/drivers/media/video/gspca/finepix.c
+++ b/drivers/media/video/gspca/finepix.c
@@ -27,7 +27,7 @@
 MODULE_LICENSE("GPL");
 
 /* Default timeout, in ms */
-#define FPIX_TIMEOUT (HZ / 10)
+#define FPIX_TIMEOUT 250
 
 /* Maximum transfer size to use. The windows driver reads by chunks of
  * 0x2000 bytes, so do the same. Note: reading more seems to work
@@ -38,38 +38,15 @@
 struct usb_fpix {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	/*
-	 * USB stuff
-	 */
-	struct usb_ctrlrequest ctrlreq;
-	struct urb *control_urb;
-	struct timer_list bulk_timer;
-
-	enum {
-		FPIX_NOP,	/* inactive, else streaming */
-		FPIX_RESET,	/* must reset */
-		FPIX_REQ_FRAME,	/* requesting a frame */
-		FPIX_READ_FRAME,	/* reading frame */
-	} state;
-
-	/*
-	 * Driver stuff
-	 */
-	struct delayed_work wqe;
-	struct completion can_close;
-	int streaming;
+	struct work_struct work_struct;
+	struct workqueue_struct *work_thread;
 };
 
 /* Delay after which claim the next frame. If the delay is too small,
  * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
- * will fail every 4 or 5 frames, but 30ms is perfect. */
-#define NEXT_FRAME_DELAY  (((HZ * 30) + 999) / 1000)
-
-#define dev_new_state(new_state) {				\
-		PDEBUG(D_STREAM, "new state from %d to %d at %s:%d",	\
-			dev->state, new_state, __func__, __LINE__);	\
-		dev->state = new_state;					\
-}
+ * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
+ * 30ms is bad while 35ms is perfect. */
+#define NEXT_FRAME_DELAY 35
 
 /* These cameras only support 320x200. */
 static const struct v4l2_pix_format fpix_mode[1] = {
@@ -80,316 +57,183 @@
 		.priv = 0}
 };
 
-/* Reads part of a frame */
-static void read_frame_part(struct usb_fpix *dev)
+/* send a command to the webcam */
+static int command(struct gspca_dev *gspca_dev,
+		int order)	/* 0: reset, 1: frame request */
 {
-	int ret;
+	static u8 order_values[2][12] = {
+		{0xc6, 0, 0, 0, 0, 0, 0,    0, 0x20, 0, 0, 0},	/* reset */
+		{0xd3, 0, 0, 0, 0, 0, 0, 0x01,    0, 0, 0, 0},	/* fr req */
+	};
 
-	PDEBUG(D_STREAM, "read_frame_part");
-
-	/* Reads part of a frame */
-	ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC);
-	if (ret) {
-		dev_new_state(FPIX_RESET);
-		schedule_delayed_work(&dev->wqe, 1);
-		PDEBUG(D_STREAM, "usb_submit_urb failed with %d",
-			ret);
-	} else {
-		/* Sometimes we never get a callback, so use a timer.
-		 * Is this masking a bug somewhere else? */
-		dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150);
-		add_timer(&dev->bulk_timer);
-	}
+	memcpy(gspca_dev->usb_buf, order_values[order], 12);
+	return usb_control_msg(gspca_dev->dev,
+			usb_sndctrlpipe(gspca_dev->dev, 0),
+			USB_REQ_GET_STATUS,
+			USB_DIR_OUT | USB_TYPE_CLASS |
+			USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+			12, FPIX_TIMEOUT);
 }
 
-/* Callback for URBs. */
-static void urb_callback(struct urb *urb)
+/* workqueue */
+static void dostream(struct work_struct *work)
 {
-	struct gspca_dev *gspca_dev = urb->context;
-	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+	struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
+	struct gspca_dev *gspca_dev = &dev->gspca_dev;
+	struct urb *urb = gspca_dev->urb[0];
+	u8 *data = urb->transfer_buffer;
+	struct gspca_frame *frame;
+	int ret = 0;
+	int len;
 
-	PDEBUG(D_PACK,
-		"enter urb_callback - status=%d, length=%d",
-		urb->status, urb->actual_length);
+	/* synchronize with the main driver */
+	mutex_lock(&gspca_dev->usb_lock);
+	mutex_unlock(&gspca_dev->usb_lock);
+	PDEBUG(D_STREAM, "dostream started");
 
-	if (dev->state == FPIX_READ_FRAME)
-		del_timer(&dev->bulk_timer);
+	/* loop reading a frame */
+again:
+	while (gspca_dev->present && gspca_dev->streaming) {
 
-	if (urb->status != 0) {
-		/* We kill a stuck urb every 50 frames on average, so don't
-		 * display a log message for that. */
-		if (urb->status != -ECONNRESET)
-			PDEBUG(D_STREAM, "bad URB status %d", urb->status);
-		dev_new_state(FPIX_RESET);
-		schedule_delayed_work(&dev->wqe, 1);
-	}
+		/* request a frame */
+		mutex_lock(&gspca_dev->usb_lock);
+		ret = command(gspca_dev, 1);
+		mutex_unlock(&gspca_dev->usb_lock);
+		if (ret < 0)
+			break;
+		if (!gspca_dev->present || !gspca_dev->streaming)
+			break;
 
-	switch (dev->state) {
-	case FPIX_REQ_FRAME:
-		dev_new_state(FPIX_READ_FRAME);
-		read_frame_part(dev);
-		break;
+		/* the frame comes in parts */
+		for (;;) {
+			ret = usb_bulk_msg(gspca_dev->dev,
+					urb->pipe,
+					data,
+					FPIX_MAX_TRANSFER,
+					&len, FPIX_TIMEOUT);
+			if (ret < 0) {
+				/* Most of the time we get a timeout
+				 * error. Just restart. */
+				goto again;
+			}
+			if (!gspca_dev->present || !gspca_dev->streaming)
+				goto out;
+			frame = gspca_get_i_frame(&dev->gspca_dev);
+			if (frame == NULL)
+				gspca_dev->last_packet_type = DISCARD_PACKET;
 
-	case FPIX_READ_FRAME: {
-		unsigned char *data = urb->transfer_buffer;
-		struct gspca_frame *frame;
+			if (len < FPIX_MAX_TRANSFER ||
+				(data[len - 2] == 0xff &&
+					data[len - 1] == 0xd9)) {
 
-		frame = gspca_get_i_frame(&dev->gspca_dev);
-		if (frame == NULL)
-			gspca_dev->last_packet_type = DISCARD_PACKET;
-		if (urb->actual_length < FPIX_MAX_TRANSFER ||
-			(data[urb->actual_length-2] == 0xff &&
-				data[urb->actual_length-1] == 0xd9)) {
-
-			/* If the result is less than what was asked
-			 * for, then it's the end of the
-			 * frame. Sometime the jpeg is not complete,
-			 * but there's nothing we can do. We also end
-			 * here if the the jpeg ends right at the end
-			 * of the frame. */
-			if (frame)
-				gspca_frame_add(gspca_dev, LAST_PACKET,
-						frame,
-						data, urb->actual_length);
-			dev_new_state(FPIX_REQ_FRAME);
-			schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY);
-		} else {
+				/* If the result is less than what was asked
+				 * for, then it's the end of the
+				 * frame. Sometimes the jpeg is not complete,
+				 * but there's nothing we can do. We also end
+				 * here if the the jpeg ends right at the end
+				 * of the frame. */
+				if (frame)
+					frame = gspca_frame_add(gspca_dev,
+							LAST_PACKET,
+							frame,
+							data, len);
+				break;
+			}
 
 			/* got a partial image */
 			if (frame)
 				gspca_frame_add(gspca_dev,
 						gspca_dev->last_packet_type
-								== LAST_PACKET
+							== LAST_PACKET
 						? FIRST_PACKET : INTER_PACKET,
-						frame,
-					data, urb->actual_length);
-			read_frame_part(dev);
+						frame, data, len);
 		}
-		break;
-	    }
 
-	case FPIX_NOP:
-	case FPIX_RESET:
-		PDEBUG(D_STREAM, "invalid state %d", dev->state);
-		break;
-	}
-}
-
-/* Request a new frame */
-static void request_frame(struct usb_fpix *dev)
-{
-	int ret;
-	struct gspca_dev *gspca_dev = &dev->gspca_dev;
-
-	/* Setup command packet */
-	memset(gspca_dev->usb_buf, 0, 12);
-	gspca_dev->usb_buf[0] = 0xd3;
-	gspca_dev->usb_buf[7] = 0x01;
-
-	/* Request a frame */
-	dev->ctrlreq.bRequestType =
-		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	dev->ctrlreq.bRequest = USB_REQ_GET_STATUS;
-	dev->ctrlreq.wValue = 0;
-	dev->ctrlreq.wIndex = 0;
-	dev->ctrlreq.wLength = cpu_to_le16(12);
-
-	usb_fill_control_urb(dev->control_urb,
-			     gspca_dev->dev,
-			     usb_sndctrlpipe(gspca_dev->dev, 0),
-			     (unsigned char *) &dev->ctrlreq,
-			     gspca_dev->usb_buf,
-			     12, urb_callback, gspca_dev);
-
-	ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC);
-	if (ret) {
-		dev_new_state(FPIX_RESET);
-		schedule_delayed_work(&dev->wqe, 1);
-		PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret);
-	}
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* State machine. */
-static void fpix_sm(struct work_struct *work)
-{
-	struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work);
-
-	PDEBUG(D_STREAM, "fpix_sm state %d", dev->state);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->gspca_dev.present) {
-		PDEBUG(D_STREAM, "device is gone");
-		dev_new_state(FPIX_NOP);
-		complete(&dev->can_close);
-		return;
+		/* We must wait before trying reading the next
+		 * frame. If we don't, or if the delay is too short,
+		 * the camera will disconnect. */
+		msleep(NEXT_FRAME_DELAY);
 	}
 
-	if (!dev->streaming) {
-		PDEBUG(D_STREAM, "stopping state machine");
-		dev_new_state(FPIX_NOP);
-		complete(&dev->can_close);
-		return;
-	}
-
-	switch (dev->state) {
-	case FPIX_RESET:
-		dev_new_state(FPIX_REQ_FRAME);
-		schedule_delayed_work(&dev->wqe, HZ / 10);
-		break;
-
-	case FPIX_REQ_FRAME:
-		/* get an image */
-		request_frame(dev);
-		break;
-
-	case FPIX_NOP:
-	case FPIX_READ_FRAME:
-		PDEBUG(D_STREAM, "invalid state %d", dev->state);
-		break;
-	}
+out:
+	PDEBUG(D_STREAM, "dostream stopped");
 }
 
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
 		const struct usb_device_id *id)
 {
+	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
 	struct cam *cam = &gspca_dev->cam;
 
 	cam->cam_mode = fpix_mode;
 	cam->nmodes = 1;
-	cam->epaddr = 0x01;	/* todo: correct for all cams? */
 	cam->bulk_size = FPIX_MAX_TRANSFER;
 
-/*	gspca_dev->nbalt = 1;	 * use bulk transfer */
+	INIT_WORK(&dev->work_struct, dostream);
+
 	return 0;
 }
 
-/* Stop streaming and free the ressources allocated by sd_start. */
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
-	dev->streaming = 0;
-
-	/* Stop the state machine */
-	if (dev->state != FPIX_NOP)
-		wait_for_completion(&dev->can_close);
-}
-
-/* called on streamoff with alt 0 and disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
-	usb_free_urb(dev->control_urb);
-	dev->control_urb = NULL;
-}
-
-/* Kill an URB that hasn't completed. */
-static void timeout_kill(unsigned long data)
-{
-	struct urb *urb = (struct urb *) data;
-
-	usb_unlink_urb(urb);
-}
-
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
-	INIT_DELAYED_WORK(&dev->wqe, fpix_sm);
-
-	init_timer(&dev->bulk_timer);
-	dev->bulk_timer.function = timeout_kill;
-
 	return 0;
 }
 
+/* start the camera */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-	int ret;
-	int size_ret;
+	int ret, len;
 
 	/* Init the device */
-	memset(gspca_dev->usb_buf, 0, 12);
-	gspca_dev->usb_buf[0] = 0xc6;
-	gspca_dev->usb_buf[8] = 0x20;
-
-	ret = usb_control_msg(gspca_dev->dev,
-			usb_sndctrlpipe(gspca_dev->dev, 0),
-			USB_REQ_GET_STATUS,
-			USB_DIR_OUT | USB_TYPE_CLASS |
-			USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
-			12, FPIX_TIMEOUT);
-
-	if (ret != 12) {
-		PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
-		ret = -EIO;
-		goto error;
+	ret = command(gspca_dev, 0);
+	if (ret < 0) {
+		PDEBUG(D_STREAM, "init failed %d", ret);
+		return ret;
 	}
 
 	/* Read the result of the command. Ignore the result, for it
 	 * varies with the device. */
 	ret = usb_bulk_msg(gspca_dev->dev,
-			usb_rcvbulkpipe(gspca_dev->dev,
-					gspca_dev->cam.epaddr),
-			gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret,
+			gspca_dev->urb[0]->pipe,
+			gspca_dev->urb[0]->transfer_buffer,
+			FPIX_MAX_TRANSFER, &len,
 			FPIX_TIMEOUT);
-	if (ret != 0) {
-		PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret);
-		ret = -EIO;
-		goto error;
+	if (ret < 0) {
+		PDEBUG(D_STREAM, "usb_bulk_msg failed %d", ret);
+		return ret;
 	}
 
 	/* Request a frame, but don't read it */
-	memset(gspca_dev->usb_buf, 0, 12);
-	gspca_dev->usb_buf[0] = 0xd3;
-	gspca_dev->usb_buf[7] = 0x01;
-
-	ret = usb_control_msg(gspca_dev->dev,
-			usb_sndctrlpipe(gspca_dev->dev, 0),
-			USB_REQ_GET_STATUS,
-			USB_DIR_OUT | USB_TYPE_CLASS |
-			USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
-			12, FPIX_TIMEOUT);
-	if (ret != 12) {
-		PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
-		ret = -EIO;
-		goto error;
+	ret = command(gspca_dev, 1);
+	if (ret < 0) {
+		PDEBUG(D_STREAM, "frame request failed %d", ret);
+		return ret;
 	}
 
 	/* Again, reset bulk in endpoint */
-	usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
+	usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
 
-	/* Allocate a control URB */
-	dev->control_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->control_urb) {
-		PDEBUG(D_STREAM, "No free urbs available");
-		ret = -EIO;
-		goto error;
-	}
-
-	/* Various initializations. */
-	init_completion(&dev->can_close);
-	dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0];
-	dev->gspca_dev.urb[0]->complete = urb_callback;
-	dev->streaming = 1;
-
-	/* Schedule a frame request. */
-	dev_new_state(FPIX_REQ_FRAME);
-	schedule_delayed_work(&dev->wqe, 1);
+	/* Start the workqueue function to do the streaming */
+	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+	queue_work(dev->work_thread, &dev->work_struct);
 
 	return 0;
+}
 
-error:
-	/* Free the ressources */
-	sd_stopN(gspca_dev);
-	sd_stop0(gspca_dev);
-	return ret;
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+	/* wait for the work queue to terminate */
+	mutex_unlock(&gspca_dev->usb_lock);
+	destroy_workqueue(dev->work_thread);
+	mutex_lock(&gspca_dev->usb_lock);
+	dev->work_thread = NULL;
 }
 
 /* Table of supported USB devices */
@@ -424,12 +268,11 @@
 
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
-	.name = MODULE_NAME,
+	.name   = MODULE_NAME,
 	.config = sd_config,
-	.init = sd_init,
-	.start = sd_start,
-	.stopN = sd_stopN,
-	.stop0 = sd_stop0,
+	.init   = sd_init,
+	.start  = sd_start,
+	.stop0  = sd_stop0,
 };
 
 /* -- device connect -- */
@@ -443,24 +286,28 @@
 }
 
 static struct usb_driver sd_driver = {
-	.name = MODULE_NAME,
-	.id_table = device_table,
-	.probe = sd_probe,
+	.name       = MODULE_NAME,
+	.id_table   = device_table,
+	.probe      = sd_probe,
 	.disconnect = gspca_disconnect,
 #ifdef CONFIG_PM
 	.suspend = gspca_suspend,
-	.resume = gspca_resume,
+	.resume  = gspca_resume,
 #endif
 };
 
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
+
 static void __exit sd_mod_exit(void)
 {
 	usb_deregister(&sd_driver);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 65e4901..a75c1ca 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -38,15 +38,16 @@
 #include "gspca.h"
 
 /* global values */
-#define DEF_NURBS 2		/* default number of URBs */
+#define DEF_NURBS 3		/* default number of URBs */
+#if DEF_NURBS > MAX_NURBS
+#error "DEF_NURBS too big"
+#endif
 
 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 4, 0)
-
-static int video_nr = -1;
+#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(2, 5, 0)
 
 #ifdef GSPCA_DEBUG
 int gspca_debug = D_ERR | D_PROBE;
@@ -126,16 +127,18 @@
 			struct urb *urb)
 {
 	struct gspca_frame *frame;
-	__u8 *data;		/* address of data in the iso message */
+	u8 *data;		/* address of data in the iso message */
 	int i, len, st;
 	cam_pkt_op pkt_scan;
 
 	if (urb->status != 0) {
+		if (urb->status == -ESHUTDOWN)
+			return;		/* disconnection */
 #ifdef CONFIG_PM
 		if (!gspca_dev->frozen)
 #endif
 			PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
-		return;		/* disconnection ? */
+		return;
 	}
 	pkt_scan = gspca_dev->sd_desc->pkt_scan;
 	for (i = 0; i < urb->number_of_packets; i++) {
@@ -166,7 +169,7 @@
 		/* let the packet be analyzed by the subdriver */
 		PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
 			i, urb->iso_frame_desc[i].offset, len);
-		data = (__u8 *) urb->transfer_buffer
+		data = (u8 *) urb->transfer_buffer
 					+ urb->iso_frame_desc[i].offset;
 		pkt_scan(gspca_dev, frame, data, len);
 	}
@@ -182,8 +185,7 @@
  *
  * Analyse each packet and call the subdriver for copy to the frame buffer.
  */
-static void isoc_irq(struct urb *urb
-)
+static void isoc_irq(struct urb *urb)
 {
 	struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
 
@@ -196,8 +198,7 @@
 /*
  * bulk message interrupt from the USB device
  */
-static void bulk_irq(struct urb *urb
-)
+static void bulk_irq(struct urb *urb)
 {
 	struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
 	struct gspca_frame *frame;
@@ -209,6 +210,8 @@
 	switch (urb->status) {
 	case 0:
 		break;
+	case -ESHUTDOWN:
+		return;		/* disconnection */
 	case -ECONNRESET:
 		urb->status = 0;
 		break;
@@ -217,7 +220,7 @@
 		if (!gspca_dev->frozen)
 #endif
 			PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
-		return;		/* disconnection ? */
+		return;
 	}
 
 	/* check the availability of the frame buffer */
@@ -322,6 +325,7 @@
 	case V4L2_PIX_FMT_JPEG:
 	case V4L2_PIX_FMT_SPCA561:
 	case V4L2_PIX_FMT_PAC207:
+	case V4L2_PIX_FMT_MR97310A:
 		return 1;
 	}
 	return 0;
@@ -422,10 +426,8 @@
 		if (urb == NULL)
 			break;
 
-		BUG_ON(!gspca_dev->dev);
 		gspca_dev->urb[i] = NULL;
-		if (!gspca_dev->present)
-			usb_kill_urb(urb);
+		usb_kill_urb(urb);
 		if (urb->transfer_buffer != NULL)
 			usb_buffer_free(gspca_dev->dev,
 					urb->transfer_buffer_length,
@@ -439,22 +441,16 @@
  * look for an input transfer endpoint in an alternate setting
  */
 static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
-					  __u8 epaddr,
 					  __u8 xfer)
 {
 	struct usb_host_endpoint *ep;
 	int i, attr;
 
-	epaddr |= USB_DIR_IN;
 	for (i = 0; i < alt->desc.bNumEndpoints; i++) {
 		ep = &alt->endpoint[i];
-		if (ep->desc.bEndpointAddress == epaddr) {
-			attr = ep->desc.bmAttributes
-						& USB_ENDPOINT_XFERTYPE_MASK;
-			if (attr == xfer)
-				return ep;
-			break;
-		}
+		attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+		if (attr == xfer)
+			return ep;
 	}
 	return NULL;
 }
@@ -478,23 +474,23 @@
 	i = gspca_dev->alt;			/* previous alt setting */
 
 	/* try isoc */
-	while (--i > 0) {			/* alt 0 is unusable */
+	while (--i >= 0) {
 		ep = alt_xfer(&intf->altsetting[i],
-				gspca_dev->cam.epaddr,
 				USB_ENDPOINT_XFER_ISOC);
 		if (ep)
 			break;
 	}
 
-	/* if no isoc, try bulk */
+	/* if no isoc, try bulk (alt 0 only) */
 	if (ep == NULL) {
 		ep = alt_xfer(&intf->altsetting[0],
-				gspca_dev->cam.epaddr,
 				USB_ENDPOINT_XFER_BULK);
 		if (ep == NULL) {
 			err("no transfer endpoint found");
 			return NULL;
 		}
+		i = 0;
+		gspca_dev->bulk = 1;
 	}
 	PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
 			i, ep->desc.bEndpointAddress);
@@ -521,7 +517,7 @@
 	/* calculate the packet size and the number of packets */
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize);
 
-	if (gspca_dev->alt != 0) {		/* isoc */
+	if (!gspca_dev->bulk) {			/* isoc */
 
 		/* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
 		psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
@@ -601,6 +597,11 @@
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
 
+	if (!gspca_dev->present) {
+		ret = -ENODEV;
+		goto out;
+	}
+
 	/* set the higher alternate setting and
 	 * loop until urb submit succeeds */
 	gspca_dev->alt = gspca_dev->nbalt;
@@ -616,10 +617,9 @@
 			goto out;
 
 		/* clear the bulk endpoint */
-		if (gspca_dev->alt == 0)	/* if bulk transfer */
+		if (gspca_dev->bulk)
 			usb_clear_halt(gspca_dev->dev,
-					usb_rcvintpipe(gspca_dev->dev,
-						 gspca_dev->cam.epaddr));
+					gspca_dev->urb[0]->pipe);
 
 		/* start the cam */
 		ret = gspca_dev->sd_desc->start(gspca_dev);
@@ -630,7 +630,7 @@
 		gspca_dev->streaming = 1;
 
 		/* some bulk transfers are started by the subdriver */
-		if (gspca_dev->alt == 0 && gspca_dev->cam.bulk_nurbs == 0)
+		if (gspca_dev->bulk && gspca_dev->cam.bulk_nurbs == 0)
 			break;
 
 		/* submit the URBs */
@@ -671,11 +671,14 @@
 static void gspca_stream_off(struct gspca_dev *gspca_dev)
 {
 	gspca_dev->streaming = 0;
-	if (gspca_dev->present
-	    && gspca_dev->sd_desc->stopN)
-		gspca_dev->sd_desc->stopN(gspca_dev);
-	destroy_urbs(gspca_dev);
-	gspca_set_alt0(gspca_dev);
+	if (gspca_dev->present) {
+		if (gspca_dev->sd_desc->stopN)
+			gspca_dev->sd_desc->stopN(gspca_dev);
+		destroy_urbs(gspca_dev);
+		gspca_set_alt0(gspca_dev);
+	}
+
+	/* always call stop0 to free the subdriver's resources */
 	if (gspca_dev->sd_desc->stop0)
 		gspca_dev->sd_desc->stop0(gspca_dev);
 	PDEBUG(D_STREAM, "stream off OK");
@@ -762,7 +765,6 @@
 	fmtdesc->pixelformat = fmt_tb[index];
 	if (gspca_is_compressed(fmt_tb[index]))
 		fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
-	fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
 	fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
 	fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
@@ -957,8 +959,15 @@
 			   struct v4l2_capability *cap)
 {
 	struct gspca_dev *gspca_dev = priv;
+	int ret;
 
-	memset(cap, 0, sizeof *cap);
+	/* protect the access to the usb device */
+	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+		return -ERESTARTSYS;
+	if (!gspca_dev->present) {
+		ret = -ENODEV;
+		goto out;
+	}
 	strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
 	if (gspca_dev->dev->product != NULL) {
 		strncpy(cap->card, gspca_dev->dev->product,
@@ -969,13 +978,15 @@
 			le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
 			le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
 	}
-	strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
-		sizeof cap->bus_info);
+	usb_make_path(gspca_dev->dev, cap->bus_info, sizeof(cap->bus_info));
 	cap->version = DRIVER_VERSION_NUMBER;
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
 			  | V4L2_CAP_STREAMING
 			  | V4L2_CAP_READWRITE;
-	return 0;
+	ret = 0;
+out:
+	mutex_unlock(&gspca_dev->usb_lock);
+	return ret;
 }
 
 static int vidioc_queryctrl(struct file *file, void *priv,
@@ -1038,7 +1049,10 @@
 		PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		ret = ctrls->set(gspca_dev, ctrl->value);
+		if (gspca_dev->present)
+			ret = ctrls->set(gspca_dev, ctrl->value);
+		else
+			ret = -ENODEV;
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1062,7 +1076,10 @@
 			return -EINVAL;
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		ret = ctrls->get(gspca_dev, &ctrl->value);
+		if (gspca_dev->present)
+			ret = ctrls->get(gspca_dev, &ctrl->value);
+		else
+			ret = -ENODEV;
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1081,7 +1098,6 @@
 static int vidioc_g_audio(struct file *file, void *priv,
 			 struct v4l2_audio *audio)
 {
-	memset(audio, 0, sizeof *audio);
 	strcpy(audio->name, "Microphone");
 	return 0;
 }
@@ -1115,7 +1131,6 @@
 
 	if (input->index != 0)
 		return -EINVAL;
-	memset(input, 0, sizeof *input);
 	input->type = V4L2_INPUT_TYPE_CAMERA;
 	strncpy(input->name, gspca_dev->sd_desc->name,
 		sizeof input->name);
@@ -1224,10 +1239,7 @@
 		return -EINVAL;
 	if (mutex_lock_interruptible(&gspca_dev->queue_lock))
 		return -ERESTARTSYS;
-	if (!gspca_dev->present) {
-		ret = -ENODEV;
-		goto out;
-	}
+
 	if (gspca_dev->nframes == 0
 	    || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
 		ret = -EINVAL;
@@ -1295,7 +1307,10 @@
 		return -EINVAL;
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
-	ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
+	if (gspca_dev->present)
+		ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
+	else
+		ret = -ENODEV;
 	mutex_unlock(&gspca_dev->usb_lock);
 	return ret;
 }
@@ -1310,7 +1325,10 @@
 		return -EINVAL;
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
-	ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
+	if (gspca_dev->present)
+		ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
+	else
+		ret = -ENODEV;
 	mutex_unlock(&gspca_dev->usb_lock);
 	return ret;
 }
@@ -1320,8 +1338,6 @@
 {
 	struct gspca_dev *gspca_dev = priv;
 
-	memset(parm, 0, sizeof *parm);
-	parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	parm->parm.capture.readbuffers = gspca_dev->nbufread;
 
 	if (gspca_dev->sd_desc->get_streamparm) {
@@ -1329,7 +1345,11 @@
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
+		if (gspca_dev->present)
+			ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
+								 parm);
+		else
+			ret = -ENODEV;
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1354,7 +1374,11 @@
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
-		ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
+		if (gspca_dev->present)
+			ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
+								 parm);
+		else
+			ret = -ENODEV;
 		mutex_unlock(&gspca_dev->usb_lock);
 		return ret;
 	}
@@ -1382,7 +1406,6 @@
 		{
 			struct v4l2_format fmt;
 
-			memset(&fmt, 0, sizeof fmt);
 			fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 			i = gspca_dev->cam.nmodes - 1;	/* highest mode */
 			fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
@@ -1528,7 +1551,8 @@
 
 	if (gspca_dev->sd_desc->dq_callback) {
 		mutex_lock(&gspca_dev->usb_lock);
-		gspca_dev->sd_desc->dq_callback(gspca_dev);
+		if (gspca_dev->present)
+			gspca_dev->sd_desc->dq_callback(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
 	}
 	return j;
@@ -1550,6 +1574,9 @@
 	if (v4l2_buf->memory != gspca_dev->memory)
 		return -EINVAL;
 
+	if (!gspca_dev->present)
+		return -ENODEV;
+
 	/* if not streaming, be sure the application will not loop forever */
 	if (!(file->f_flags & O_NONBLOCK)
 	    && !gspca_dev->streaming && gspca_dev->users == 1)
@@ -1700,8 +1727,6 @@
 	PDEBUG(D_FRAM, "poll");
 
 	poll_wait(file, &gspca_dev->wq, wait);
-	if (!gspca_dev->present)
-		return POLLERR;
 
 	/* if reqbufs is not done, the user would use read() */
 	if (gspca_dev->nframes == 0) {
@@ -1714,10 +1739,6 @@
 
 	if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
 		return POLLERR;
-	if (!gspca_dev->present) {
-		ret = POLLERR;
-		goto out;
-	}
 
 	/* check the next incoming buffer */
 	i = gspca_dev->fr_o;
@@ -1726,8 +1747,9 @@
 		ret = POLLIN | POLLRDNORM;	/* something to read */
 	else
 		ret = 0;
-out:
 	mutex_unlock(&gspca_dev->queue_lock);
+	if (!gspca_dev->present)
+		return POLLHUP;
 	return ret;
 }
 
@@ -1925,7 +1947,7 @@
 	gspca_dev->present = 1;
 	ret = video_register_device(&gspca_dev->vdev,
 				  VFL_TYPE_GRABBER,
-				  video_nr);
+				  -1);
 	if (ret < 0) {
 		err("video_register_device err %d", ret);
 		goto out;
@@ -1953,10 +1975,16 @@
 
 	mutex_lock(&gspca_dev->usb_lock);
 	gspca_dev->present = 0;
+
+	if (gspca_dev->streaming) {
+		destroy_urbs(gspca_dev);
+		wake_up_interruptible(&gspca_dev->wq);
+	}
+
+	/* the device is freed at exit of this function */
+	gspca_dev->dev = NULL;
 	mutex_unlock(&gspca_dev->usb_lock);
 
-	destroy_urbs(gspca_dev);
-	gspca_dev->dev = NULL;
 	usb_set_intfdata(intf, NULL);
 
 	/* release the device */
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index c90af9c..e4d4cf6 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -33,19 +33,13 @@
 #endif
 #undef err
 #define err(fmt, args...) \
-	do {\
-		printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args); \
-	} while (0)
+	printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args)
 #undef info
 #define info(fmt, args...) \
-	do {\
-		printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
-	} while (0)
+	printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args)
 #undef warn
 #define warn(fmt, args...) \
-	do {\
-		printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args); \
-	} while (0)
+	printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args)
 
 #define GSPCA_MAX_FRAMES 16	/* maximum number of video frame buffers */
 /* image transfers */
@@ -62,7 +56,6 @@
 				 * - cannot be > MAX_NURBS
 				 * - when 0 and bulk_size != 0 means
 				 *   1 URB and submit done by subdriver */
-	__u8 epaddr;
 };
 
 struct gspca_dev;
@@ -174,6 +167,7 @@
 	__u8 iface;			/* USB interface number */
 	__u8 alt;			/* USB alternate setting */
 	__u8 nbalt;			/* number of USB alternate settings */
+	u8 bulk;			/* image transfer by 0:isoc / 1:bulk */
 };
 
 int gspca_dev_probe(struct usb_interface *intf,
diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h
index d823b47..de63c36 100644
--- a/drivers/media/video/gspca/jpeg.h
+++ b/drivers/media/video/gspca/jpeg.h
@@ -24,171 +24,39 @@
  *
  */
 
-/* start of jpeg frame + quantization table */
-static const unsigned char quant[][0x88] = {
-/* index 0 - Q40*/
-    {
-	0xff, 0xd8,			/* jpeg */
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,					/* quantization table part 1 */
-     20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50,
-     33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64,
-     70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101,
-     109,
-     119, 123, 129, 130, 129, 78, 96, 141, 151, 140, 125, 150, 115,
-     126, 129, 124,
-1,					/* quantization table part 2 */
-     21, 23, 23, 30, 26, 30, 59, 33, 33, 59, 124, 83, 70, 83, 124, 124,
-     124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
-     124, 124, 124,
-     124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
-     124, 124, 124,
-     124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
-     124, 124, 124},
-/* index 1 - Q50 */
-    {
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-     16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
-     26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
-     56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87,
-     95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101,
-     103, 99,
-1,
-    17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
-     99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-     99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-     99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
-/* index 2 Q60 */
-    {
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-     13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32,
-     21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41,
-     45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70,
-     76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79,
-1,
-     14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79,
-     79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
-     79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
-     79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
-/* index 3 - Q70 */
-    {
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-     10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24,
-     16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31,
-     34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52,
-     57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59,
-1,
-     10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59,
-     59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-     59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-     59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
-/* index 4 - Q80 */
-    {
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-      6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16,
-     10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20,
-     22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35,
-     38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40,
-1,
-      7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40,
-     40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
-     40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
-     40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
-/* index 5 - Q85 */
-    {
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-     5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12,
-     8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15,
-     17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26,
-     29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30,
-1,
-     5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30,
-     30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-     30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-     30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
-/* index 6 - 86 */
-{
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-	0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04,
-	0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B,
-	0x07, 0x07, 0x06, 0x06, 0x07, 0x0E, 0x0A, 0x0A,
-	0x08, 0x0B, 0x10, 0x0E, 0x11, 0x11, 0x10, 0x0E,
-	0x10, 0x0F, 0x12, 0x14, 0x1A, 0x16, 0x12, 0x13,
-	0x18, 0x13, 0x0F, 0x10, 0x16, 0x1F, 0x17, 0x18,
-	0x1B, 0x1B, 0x1D, 0x1D, 0x1D, 0x11, 0x16, 0x20,
-	0x22, 0x1F, 0x1C, 0x22, 0x1A, 0x1C, 0x1D, 0x1C,
-1,
-	0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07,
-	0x07, 0x0D, 0x1C, 0x12, 0x10, 0x12, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
-	0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
- },
-/* index 7 - 88 */
-{
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-	0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03,
-	0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0A,
-	0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09,
-	0x07, 0x0A, 0x0E, 0x0C, 0x0F, 0x0E, 0x0E, 0x0C,
-	0x0D, 0x0D, 0x0F, 0x11, 0x16, 0x13, 0x0F, 0x10,
-	0x15, 0x11, 0x0D, 0x0D, 0x13, 0x1A, 0x13, 0x15,
-	0x17, 0x18, 0x19, 0x19, 0x19, 0x0F, 0x12, 0x1B,
-	0x1D, 0x1B, 0x18, 0x1D, 0x16, 0x18, 0x19, 0x18,
-1,
-	0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06,
-	0x06, 0x0B, 0x18, 0x10, 0x0D, 0x10, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-	0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-},
-/* index 8 - ?? */
-{
-	0xff, 0xd8,
-	0xff, 0xdb, 0x00, 0x84,		/* DQT */
-0,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05,
-	0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05,
-	0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06,
-	0x07, 0x07, 0x08, 0x09, 0x0C, 0x0A, 0x08, 0x09,
-	0x0B, 0x09, 0x07, 0x07, 0x0A, 0x0E, 0x0A, 0x0B,
-	0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x08, 0x0A, 0x0E,
-	0x0F, 0x0E, 0x0D, 0x0F, 0x0C, 0x0D, 0x0D, 0x0C,
-1,
-	0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03,
-	0x03, 0x06, 0x0C, 0x08, 0x07, 0x08, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
-	0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C
-}
-};
+/*
+ * generation options
+ *	CONEX_CAM	Conexant if present
+ */
 
-/* huffman table + start of SOF0 */
-static unsigned char huffman[] = {
+/* JPEG header */
+static const u8 jpeg_head[] = {
+	0xff, 0xd8,			/* jpeg */
+
+/* quantization table quality 50% */
+	0xff, 0xdb, 0x00, 0x84,		/* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+	0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+	0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+	0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+	0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+	0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+	0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+	0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+	0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+	0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+	0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+/* huffman table */
 	0xff, 0xc4, 0x01, 0xa2,
 	0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
 	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -244,58 +112,57 @@
 	0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
 #ifdef CONEX_CAM
 /* the Conexant frames start with SOF0 */
+#define JPEG_HDR_SZ 556
 #else
 	0xff, 0xc0, 0x00, 0x11,		/* SOF0 (start of frame 0 */
 	0x08,				/* data precision */
-#endif
-};
-
-#ifndef CONEX_CAM
-/* variable part:
- *	0x01, 0xe0,			 height
- *	0x02, 0x80,			 width
- *	0x03,				 component number
- *		0x01,
- *			0x21,			samples Y
- */
-
-/* end of header */
-static unsigned char eoh[] = {
+#define JPEG_HEIGHT_OFFSET 561
+	0x01, 0xe0,			/* height */
+	0x02, 0x80,			/* width */
+	0x03,				/* component number */
+		0x01,
+			0x21,		/* samples Y */
 			0x00,		/* quant Y */
 		0x02, 0x11, 0x01,	/* samples CbCr - quant CbCr */
 		0x03, 0x11, 0x01,
 
 	0xff, 0xda, 0x00, 0x0c,		/* SOS (start of scan) */
 	0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 589
+#endif
 };
-#endif
 
-/* -- output the JPEG header -- */
-static void jpeg_put_header(struct gspca_dev *gspca_dev,
-			    struct gspca_frame *frame,
-			    int qindex,
-			    int samplesY)
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+			int height,
+			int width,
+			int samplesY)
 {
+	memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
 #ifndef CONEX_CAM
-	unsigned char tmpbuf[8];
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height & 0xff;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width & 0xff;
+	jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY;
 #endif
+}
 
-	gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-			(unsigned char *) quant[qindex], sizeof quant[0]);
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-			(unsigned char *) huffman, sizeof huffman);
-#ifndef CONEX_CAM
-	tmpbuf[0] = gspca_dev->height >> 8;
-	tmpbuf[1] = gspca_dev->height & 0xff;
-	tmpbuf[2] = gspca_dev->width >> 8;
-	tmpbuf[3] = gspca_dev->width & 0xff;
-	tmpbuf[4] = 0x03;		/* component number */
-	tmpbuf[5] = 0x01;		/* first component */
-	tmpbuf[6] = samplesY;
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-			tmpbuf, 7);
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-			eoh, sizeof eoh);
-#endif
+/* set the JPEG quality */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+			  int quality)
+{
+	int i, sc;
+
+	if (quality < 50)
+		sc = 5000 / quality;
+	else
+		sc = 200 - quality * 2;
+	for (i = 0; i < 64; i++) {
+		jpeg_hdr[JPEG_QT0_OFFSET + i] =
+			(jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+		jpeg_hdr[JPEG_QT1_OFFSET + i] =
+			(jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+	}
 }
 #endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index ed906fe..b35e483 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -332,7 +332,6 @@
 	int err;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = M5602_ISOC_ENDPOINT_ADDR;
 	sd->desc = &sd_desc;
 
 	if (dump_bridge)
@@ -374,8 +373,10 @@
 /* -- module insert / remove -- */
 static int __init mod_m5602_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 3d2090e..75e8d14 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -32,17 +32,91 @@
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	char qindex;
+	u8 brightness;
+	u8 colors;
+	u8 gamma;
+	u8 sharpness;
+	u8 quality;
+#define QUALITY_MIN 40
+#define QUALITY_MAX 70
+#define QUALITY_DEF 50
+
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
+static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
+
 static struct ctrl sd_ctrls[] = {
+	{
+	    {
+		.id      = V4L2_CID_BRIGHTNESS,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Brightness",
+		.minimum = 0,
+		.maximum = 30,
+		.step    = 1,
+#define BRIGHTNESS_DEF 15
+		.default_value = BRIGHTNESS_DEF,
+	    },
+	    .set = sd_setbrightness,
+	    .get = sd_getbrightness,
+	},
+	{
+	    {
+		.id      = V4L2_CID_SATURATION,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Color",
+		.minimum = 1,
+		.maximum = 255,
+		.step    = 1,
+#define COLOR_DEF 200
+		.default_value = COLOR_DEF,
+	    },
+	    .set = sd_setcolors,
+	    .get = sd_getcolors,
+	},
+	{
+	    {
+		.id      = V4L2_CID_GAMMA,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gamma",
+		.minimum = 0,
+		.maximum = 3,
+		.step    = 1,
+#define GAMMA_DEF 1
+		.default_value = GAMMA_DEF,
+	    },
+	    .set = sd_setgamma,
+	    .get = sd_getgamma,
+	},
+	{
+	    {
+		.id	 = V4L2_CID_SHARPNESS,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Sharpness",
+		.minimum = 0,
+		.maximum = 2,
+		.step    = 1,
+#define SHARPNESS_DEF 1
+		.default_value = SHARPNESS_DEF,
+	    },
+	    .set = sd_setsharpness,
+	    .get = sd_getsharpness,
+	},
 };
 
 static const struct v4l2_pix_format vga_mode[] = {
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240 * 3 / 8 + 589,
+		.sizeimage = 320 * 240 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = 2},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -52,65 +126,45 @@
 		.priv = 1},
 };
 
-/* MI Register table //elvis */
-enum {
-	REG_HW_MI_0,
-	REG_HW_MI_1,
-	REG_HW_MI_2,
-	REG_HW_MI_3,
-	REG_HW_MI_4,
-	REG_HW_MI_5,
-	REG_HW_MI_6,
-	REG_HW_MI_7,
-	REG_HW_MI_9 = 0x09,
-	REG_HW_MI_B = 0x0B,
-	REG_HW_MI_C,
-	REG_HW_MI_D,
-	REG_HW_MI_1E = 0x1E,
-	REG_HW_MI_20 = 0x20,
-	REG_HW_MI_2B = 0x2B,
-	REG_HW_MI_2C,
-	REG_HW_MI_2D,
-	REG_HW_MI_2E,
-	REG_HW_MI_35 = 0x35,
-	REG_HW_MI_5F = 0x5f,
-	REG_HW_MI_60,
-	REG_HW_MI_61,
-	REG_HW_MI_62,
-	REG_HW_MI_63,
-	REG_HW_MI_64,
-	REG_HW_MI_F1 = 0xf1,
-	ATTR_TOTAL_MI_REG = 0xf2
+static const __u8 mi_data[0x20] = {
+/*	 01    02   03     04    05    06    07    08 */
+	0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
+/*	 09    0a   0b     0c    0d    0e    0f    10 */
+	0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
+/*	 11    12   13     14    15    16    17    18 */
+	0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
+/*	 19    1a   1b     1c    1d    1e    1f    20 */
+	0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
 };
 
-/* the bytes to write are in gspca_dev->usb_buf */
+/* write <len> bytes from gspca_dev->usb_buf */
 static int reg_w(struct gspca_dev *gspca_dev,
-		 __u16 index, int len)
+		 int len)
 {
-	int rc;
+	int alen, ret;
 
-	rc = usb_control_msg(gspca_dev->dev,
-			 usb_sndbulkpipe(gspca_dev->dev, 4),
-			 0x12,
-			 0xc8,		/* ?? */
-			 0,		/* value */
-			 index, gspca_dev->usb_buf, len, 500);
-	if (rc < 0)
-		PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
-	return rc;
+	ret = usb_bulk_msg(gspca_dev->dev,
+			usb_sndbulkpipe(gspca_dev->dev, 4),
+			gspca_dev->usb_buf,
+			len,
+			&alen,
+			500);	/* timeout in milliseconds */
+	if (ret < 0)
+		PDEBUG(D_ERR, "reg write [%02x] error %d",
+			gspca_dev->usb_buf[0], ret);
+	return ret;
 }
 
-static void bulk_w(struct gspca_dev *gspca_dev,
-		   __u16 *pch,
-		   __u16 Address)
+static void mi_w(struct gspca_dev *gspca_dev,
+		 u8 addr,
+		 u8 value)
 {
 	gspca_dev->usb_buf[0] = 0x1f;
 	gspca_dev->usb_buf[1] = 0;			/* control byte */
-	gspca_dev->usb_buf[2] = Address;
-	gspca_dev->usb_buf[3] = *pch >> 8;		/* high byte */
-	gspca_dev->usb_buf[4] = *pch;			/* low byte */
+	gspca_dev->usb_buf[2] = addr;
+	gspca_dev->usb_buf[3] = value;
 
-	reg_w(gspca_dev, Address, 5);
+	reg_w(gspca_dev, 4);
 }
 
 /* this function is called at probe time */
@@ -121,10 +175,14 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = ARRAY_SIZE(vga_mode);
-	sd->qindex = 1;			/* set the quantization table */
+	sd->brightness = BRIGHTNESS_DEF;
+	sd->colors = COLOR_DEF;
+	sd->gamma = GAMMA_DEF;
+	sd->sharpness = SHARPNESS_DEF;
+	sd->quality = QUALITY_DEF;
+	gspca_dev->nbalt = 9;		/* use the altsetting 08 */
 	return 0;
 }
 
@@ -136,24 +194,22 @@
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	int err_code;
-	__u8 *data;
-	__u16 *MI_buf;
-	int h_size, v_size;
-	int intpipe;
+	u8 *data;
+	int i;
 
-	PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
-	err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8);
-	if (err_code < 0) {
-		PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
-		return err_code;
-	}
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x21);		/* JPEG 422 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 
 	data = gspca_dev->usb_buf;
+
 	data[0] = 0x01;		/* address */
 	data[1] = 0x01;
-
-	err_code = reg_w(gspca_dev, data[0], 2);
+	err_code = reg_w(gspca_dev, 2);
 	if (err_code < 0)
 		return err_code;
 
@@ -163,30 +219,28 @@
 	data[0] = 0x00;		/* address */
 	data[1] = 0x0c | 0x01;	/* reg 0 */
 	data[2] = 0x01;		/* reg 1 */
-	h_size = gspca_dev->width;
-	v_size = gspca_dev->height;
-	data[3] = h_size / 8;	/* h_size , reg 2 */
-	data[4] = v_size / 8;	/* v_size , reg 3 */
+	data[3] = gspca_dev->width / 8;		/* h_size , reg 2 */
+	data[4] = gspca_dev->height / 8;	/* v_size , reg 3 */
 	data[5] = 0x30;		/* reg 4, MI, PAS5101 :
 				 *	0x30 for 24mhz , 0x28 for 12mhz */
-	data[6] = 4;		/* reg 5, H start */
-	data[7] = 0xc0;		/* reg 6, gamma 1.5 */
-	data[8] = 3;		/* reg 7, V start */
+	data[6] = 0x02;		/* reg 5, H start - was 0x04 */
+	data[7] = sd->gamma * 0x40;	/* reg 0x06: gamma */
+	data[8] = 0x01;		/* reg 7, V start - was 0x03 */
 /*	if (h_size == 320 ) */
 /*		data[9]= 0x56;	 * reg 8, 24MHz, 2:1 scale down */
 /*	else */
 	data[9] = 0x52;		/* reg 8, 24MHz, no scale down */
-	data[10] = 0x5d;	/* reg 9, I2C device address
-				 *	[for PAS5101 (0x40)] [for MI (0x5d)] */
+/*jfm: from win trace*/
+	data[10] = 0x18;
 
-	err_code = reg_w(gspca_dev, data[0], 11);
+	err_code = reg_w(gspca_dev, 11);
 	if (err_code < 0)
 		return err_code;
 
 	data[0] = 0x23;		/* address */
 	data[1] = 0x09;		/* reg 35, append frame header */
 
-	err_code = reg_w(gspca_dev, data[0], 2);
+	err_code = reg_w(gspca_dev, 2);
 	if (err_code < 0)
 		return err_code;
 
@@ -197,137 +251,57 @@
 /*	else */
 	data[1] = 50;		/* 50 reg 60, pc-cam frame size
 				 *	(unit: 4KB) 200KB */
-	err_code = reg_w(gspca_dev, data[0], 2);
+	err_code = reg_w(gspca_dev, 2);
 	if (err_code < 0)
 		return err_code;
 
-	if (0) {			/* fixed dark-gain */
-		data[1] = 0;		/* reg 94, Y Gain (1.75) */
-		data[2] = 0;		/* reg 95, UV Gain (1.75) */
-		data[3] = 0x3f;		/* reg 96, Y Gain/UV Gain/disable
-					 *	auto dark-gain */
-		data[4] = 0;		/* reg 97, set fixed dark level */
-		data[5] = 0;		/* reg 98, don't care */
-	} else {			/* auto dark-gain */
-		data[1] = 0;		/* reg 94, Y Gain (auto) */
-		data[2] = 0;		/* reg 95, UV Gain (1.75) */
-		data[3] = 0x78;		/* reg 96, Y Gain/UV Gain/disable
-					 *	auto dark-gain */
-		switch (gspca_dev->width) {
-/*		case 1280: */
-/*			data[4] = 154;
-				 * reg 97, %3 shadow point (unit: 256 pixel) */
-/*			data[5] = 51;
-				 * reg 98, %1 highlight point
-				 *	(uint: 256 pixel) */
-/*			break; */
-		default:
-/*		case 640: */
-			data[4] = 36;	/* reg 97, %3 shadow point
-					 *	(unit: 256 pixel) */
-			data[5] = 12;	/* reg 98, %1 highlight point
-					 *	(uint: 256 pixel) */
-			break;
-		case 320:
-			data[4] = 9;	/* reg 97, %3 shadow point
-					 *	(unit: 256 pixel) */
-			data[5] = 3;	/* reg 98, %1 highlight point
-					 *	(uint: 256 pixel) */
-			break;
-		}
-	}
 	/* auto dark-gain */
 	data[0] = 0x5e;		/* address */
+	data[1] = 0;		/* reg 94, Y Gain (auto) */
+/*jfm: from win trace*/
+				/* reg 0x5f/0x60 (LE) = saturation */
+				/* h (60): xxxx x100
+				 * l (5f): xxxx x000 */
+	data[2] = sd->colors << 3;
+	data[3] = ((sd->colors >> 2) & 0xf8) | 0x04;
+	data[4] = sd->brightness; /* reg 0x61 = brightness */
+	data[5] = 0x00;
 
-	err_code = reg_w(gspca_dev, data[0], 6);
+	err_code = reg_w(gspca_dev, 6);
 	if (err_code < 0)
 		return err_code;
 
 	data[0] = 0x67;
-	data[1] = 0x13;		/* reg 103, first pixel B, disable sharpness */
-	err_code = reg_w(gspca_dev, data[0], 2);
+/*jfm: from win trace*/
+	data[1] = sd->sharpness * 4 + 3;
+	data[2] = 0x14;
+	err_code = reg_w(gspca_dev, 3);
 	if (err_code < 0)
 		return err_code;
 
-	/*
-	 * initialize the value of MI sensor...
-	 */
-	MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL);
-	MI_buf[REG_HW_MI_1] = 0x000a;
-	MI_buf[REG_HW_MI_2] = 0x000c;
-	MI_buf[REG_HW_MI_3] = 0x0405;
-	MI_buf[REG_HW_MI_4] = 0x0507;
-	/* mi_Attr_Reg_[REG_HW_MI_5]	 = 0x01ff;//13 */
-	MI_buf[REG_HW_MI_5] = 0x0013;	/* 13 */
-	MI_buf[REG_HW_MI_6] = 0x001f;	/* vertical blanking */
-	/* mi_Attr_Reg_[REG_HW_MI_6]	 = 0x0400;  // vertical blanking */
-	MI_buf[REG_HW_MI_7] = 0x0002;
-	/* mi_Attr_Reg_[REG_HW_MI_9]	 = 0x015f; */
-	/* mi_Attr_Reg_[REG_HW_MI_9]	 = 0x030f; */
-	MI_buf[REG_HW_MI_9] = 0x0374;
-	MI_buf[REG_HW_MI_B] = 0x0000;
-	MI_buf[REG_HW_MI_C] = 0x0000;
-	MI_buf[REG_HW_MI_D] = 0x0000;
-	MI_buf[REG_HW_MI_1E] = 0x8000;
-/* mi_Attr_Reg_[REG_HW_MI_20]	  = 0x1104; */
-	MI_buf[REG_HW_MI_20] = 0x1104;	/* 0x111c; */
-	MI_buf[REG_HW_MI_2B] = 0x0008;
-/* mi_Attr_Reg_[REG_HW_MI_2C]	  = 0x000f; */
-	MI_buf[REG_HW_MI_2C] = 0x001f;	/* lita suggest */
-	MI_buf[REG_HW_MI_2D] = 0x0008;
-	MI_buf[REG_HW_MI_2E] = 0x0008;
-	MI_buf[REG_HW_MI_35] = 0x0051;
-	MI_buf[REG_HW_MI_5F] = 0x0904;	/* fail to write */
-	MI_buf[REG_HW_MI_60] = 0x0000;
-	MI_buf[REG_HW_MI_61] = 0x0000;
-	MI_buf[REG_HW_MI_62] = 0x0498;
-	MI_buf[REG_HW_MI_63] = 0x0000;
-	MI_buf[REG_HW_MI_64] = 0x0000;
-	MI_buf[REG_HW_MI_F1] = 0x0001;
-	/* changing while setting up the different value of dx/dy */
+	data[0] = 0x69;
+	data[1] = 0x2f;
+	data[2] = 0x28;
+	data[3] = 0x42;
+	err_code = reg_w(gspca_dev, 4);
+	if (err_code < 0)
+		return err_code;
 
-	if (gspca_dev->width != 1280) {
-		MI_buf[0x01] = 0x010a;
-		MI_buf[0x02] = 0x014c;
-		MI_buf[0x03] = 0x01e5;
-		MI_buf[0x04] = 0x0287;
-	}
-	MI_buf[0x20] = 0x1104;
+	data[0] = 0x63;
+	data[1] = 0x07;
+	err_code = reg_w(gspca_dev, 2);
+/*jfm: win trace - many writes here to reg 0x64*/
+	if (err_code < 0)
+		return err_code;
 
-	bulk_w(gspca_dev, MI_buf + 1, 1);
-	bulk_w(gspca_dev, MI_buf + 2, 2);
-	bulk_w(gspca_dev, MI_buf + 3, 3);
-	bulk_w(gspca_dev, MI_buf + 4, 4);
-	bulk_w(gspca_dev, MI_buf + 5, 5);
-	bulk_w(gspca_dev, MI_buf + 6, 6);
-	bulk_w(gspca_dev, MI_buf + 7, 7);
-	bulk_w(gspca_dev, MI_buf + 9, 9);
-	bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b);
-	bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c);
-	bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d);
-	bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e);
-	bulk_w(gspca_dev, MI_buf + 0x20, 0x20);
-	bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b);
-	bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c);
-	bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d);
-	bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e);
-	bulk_w(gspca_dev, MI_buf + 0x35, 0x35);
-	bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f);
-	bulk_w(gspca_dev, MI_buf + 0x60, 0x60);
-	bulk_w(gspca_dev, MI_buf + 0x61, 0x61);
-	bulk_w(gspca_dev, MI_buf + 0x62, 0x62);
-	bulk_w(gspca_dev, MI_buf + 0x63, 0x63);
-	bulk_w(gspca_dev, MI_buf + 0x64, 0x64);
-	bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1);
-	kfree(MI_buf);
-
-	intpipe = usb_sndintpipe(gspca_dev->dev, 0);
-	err_code = usb_clear_halt(gspca_dev->dev, intpipe);
+	/* initialize the MI sensor */
+	for (i = 0; i < sizeof mi_data; i++)
+		mi_w(gspca_dev, i + 1, mi_data[i]);
 
 	data[0] = 0x00;
 	data[1] = 0x4d;		/* ISOC transfering enable... */
-	reg_w(gspca_dev, data[0], 2);
-	return err_code;
+	reg_w(gspca_dev, 2);
+	return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -336,11 +310,18 @@
 
 	gspca_dev->usb_buf[0] = 1;
 	gspca_dev->usb_buf[1] = 0;
-	result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2);
+	result = reg_w(gspca_dev, 2);
 	if (result < 0)
 		PDEBUG(D_ERR, "Camera Stop failed");
 }
 
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	kfree(sd->jpeg_hdr);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
@@ -363,16 +344,16 @@
 			    || data[5 + p] == 0x65
 			    || data[5 + p] == 0x66
 			    || data[5 + p] == 0x67) {
-				PDEBUG(D_PACK, "sof offset: %d leng: %d",
+				PDEBUG(D_PACK, "sof offset: %d len: %d",
 					p, len);
 				frame = gspca_frame_add(gspca_dev, LAST_PACKET,
-							frame, data, 0);
+							frame, data, p);
 
 				/* put the JPEG header */
-				jpeg_put_header(gspca_dev, frame,
-						sd->qindex, 0x21);
-				data += 16;
-				len -= 16;
+				gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+					sd->jpeg_hdr, JPEG_HDR_SZ);
+				data += p + 16;
+				len -= p + 16;
 				break;
 			}
 		}
@@ -380,6 +361,121 @@
 	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
+static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->brightness = val;
+	if (gspca_dev->streaming) {
+		gspca_dev->usb_buf[0] = 0x61;
+		gspca_dev->usb_buf[1] = val;
+		reg_w(gspca_dev, 2);
+	}
+	return 0;
+}
+
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->brightness;
+	return 0;
+}
+
+static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->colors = val;
+	if (gspca_dev->streaming) {
+
+		/* see sd_start */
+		gspca_dev->usb_buf[0] = 0x5f;
+		gspca_dev->usb_buf[1] = sd->colors << 3;
+		gspca_dev->usb_buf[2] = ((sd->colors >> 2) & 0xf8) | 0x04;
+		reg_w(gspca_dev, 3);
+	}
+	return 0;
+}
+
+static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->colors;
+	return 0;
+}
+
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->gamma = val;
+	if (gspca_dev->streaming) {
+		gspca_dev->usb_buf[0] = 0x06;
+		gspca_dev->usb_buf[1] = val * 0x40;
+		reg_w(gspca_dev, 2);
+	}
+	return 0;
+}
+
+static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->gamma;
+	return 0;
+}
+
+static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->sharpness = val;
+	if (gspca_dev->streaming) {
+		gspca_dev->usb_buf[0] = 0x67;
+		gspca_dev->usb_buf[1] = val * 4 + 3;
+		reg_w(gspca_dev, 2);
+	}
+	return 0;
+}
+
+static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->sharpness;
+	return 0;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -389,7 +485,10 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -421,8 +520,11 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
new file mode 100644
index 0000000..2a901a4
--- /dev/null
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -0,0 +1,362 @@
+/*
+ * Mars MR97310A library
+ *
+ * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.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
+ * 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 MODULE_NAME "mr97310a"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>");
+MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+	struct gspca_dev gspca_dev;  /* !! must be the first item */
+	u8 sof_read;
+};
+
+/* V4L2 controls supported by the driver */
+static struct ctrl sd_ctrls[] = {
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+	{160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 4},
+	{176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+		.bytesperline = 176,
+		.sizeimage = 176 * 144,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 3},
+	{320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2},
+	{352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+		.bytesperline = 352,
+		.sizeimage = 352 * 288,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1},
+	{640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+};
+
+/* the bytes to write are in gspca_dev->usb_buf */
+static int reg_w(struct gspca_dev *gspca_dev, int len)
+{
+	int rc;
+
+	rc = usb_bulk_msg(gspca_dev->dev,
+			  usb_sndbulkpipe(gspca_dev->dev, 4),
+			  gspca_dev->usb_buf, len, NULL, 500);
+	if (rc < 0)
+		PDEBUG(D_ERR, "reg write [%02x] error %d",
+		       gspca_dev->usb_buf[0], rc);
+	return rc;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+		     const struct usb_device_id *id)
+{
+	struct cam *cam;
+
+	cam = &gspca_dev->cam;
+	cam->cam_mode = vga_mode;
+	cam->nmodes = ARRAY_SIZE(vga_mode);
+	return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	__u8 *data = gspca_dev->usb_buf;
+	int err_code;
+
+	sd->sof_read = 0;
+
+	/* Note:  register descriptions guessed from MR97113A driver */
+
+	data[0] = 0x01;
+	data[1] = 0x01;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x00;
+	data[1] = 0x0d;
+	data[2] = 0x01;
+	data[5] = 0x2b;
+	data[7] = 0x00;
+	data[9] = 0x50;  /* reg 8, no scale down */
+	data[10] = 0xc0;
+
+	switch (gspca_dev->width) {
+	case 160:
+		data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
+		/* fall thru */
+	case 320:
+		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
+		/* fall thru */
+	case 640:
+	default:
+		data[3] = 0x50;  /* reg 2, H size */
+		data[4] = 0x78;  /* reg 3, V size */
+		data[6] = 0x04;  /* reg 5, H start */
+		data[8] = 0x03;  /* reg 7, V start */
+		break;
+
+	case 176:
+		data[9] |= 0x04;  /* reg 8, 2:1 scale down */
+		/* fall thru */
+	case 352:
+		data[3] = 0x2c;  /* reg 2, H size */
+		data[4] = 0x48;  /* reg 3, V size */
+		data[6] = 0x94;  /* reg 5, H start */
+		data[8] = 0x63;  /* reg 7, V start */
+		break;
+	}
+
+	err_code = reg_w(gspca_dev, 11);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x0a;
+	data[1] = 0x80;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x14;
+	data[1] = 0x0a;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1b;
+	data[1] = 0x00;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x15;
+	data[1] = 0x16;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x16;
+	data[1] = 0x10;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x17;
+	data[1] = 0x3a;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x18;
+	data[1] = 0x68;
+	err_code = reg_w(gspca_dev, 2);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x00;
+	data[2] = 0x02;
+	data[3] = 0x06;
+	data[4] = 0x59;
+	data[5] = 0x0c;
+	data[6] = 0x16;
+	data[7] = 0x00;
+	data[8] = 0x07;
+	data[9] = 0x00;
+	data[10] = 0x01;
+	err_code = reg_w(gspca_dev, 11);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x04;
+	data[2] = 0x11;
+	data[3] = 0x01;
+	err_code = reg_w(gspca_dev, 4);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x00;
+	data[2] = 0x0a;
+	data[3] = 0x00;
+	data[4] = 0x01;
+	data[5] = 0x00;
+	data[6] = 0x00;
+	data[7] = 0x01;
+	data[8] = 0x00;
+	data[9] = 0x0a;
+	err_code = reg_w(gspca_dev, 10);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x04;
+	data[2] = 0x11;
+	data[3] = 0x01;
+	err_code = reg_w(gspca_dev, 4);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x00;
+	data[2] = 0x12;
+	data[3] = 0x00;
+	data[4] = 0x63;
+	data[5] = 0x00;
+	data[6] = 0x70;
+	data[7] = 0x00;
+	data[8] = 0x00;
+	err_code = reg_w(gspca_dev, 9);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x1f;
+	data[1] = 0x04;
+	data[2] = 0x11;
+	data[3] = 0x01;
+	err_code = reg_w(gspca_dev, 4);
+	if (err_code < 0)
+		return err_code;
+
+	data[0] = 0x00;
+	data[1] = 0x4d;  /* ISOC transfering enable... */
+	err_code = reg_w(gspca_dev, 2);
+	return err_code;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	int result;
+
+	gspca_dev->usb_buf[0] = 1;
+	gspca_dev->usb_buf[1] = 0;
+	result = reg_w(gspca_dev, 2);
+	if (result < 0)
+		PDEBUG(D_ERR, "Camera Stop failed");
+}
+
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			struct gspca_frame *frame,    /* target */
+			__u8 *data,                   /* isoc packet */
+			int len)                      /* iso packet length */
+{
+	unsigned char *sof;
+
+	sof = pac_find_sof(gspca_dev, data, len);
+	if (sof) {
+		int n;
+
+		/* finish decoding current frame */
+		n = sof - data;
+		if (n > sizeof pac_sof_marker)
+			n -= sizeof pac_sof_marker;
+		else
+			n = 0;
+		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+					data, n);
+		/* Start next frame. */
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			pac_sof_marker, sizeof pac_sof_marker);
+		len -= sof - data;
+		data = sof;
+	}
+	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+	.name = MODULE_NAME,
+	.ctrls = sd_ctrls,
+	.nctrls = ARRAY_SIZE(sd_ctrls),
+	.config = sd_config,
+	.init = sd_init,
+	.start = sd_start,
+	.stopN = sd_stopN,
+	.pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x08ca, 0x0111)},
+	{}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id)
+{
+	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+			       THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name = MODULE_NAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	if (usb_register(&sd_driver) < 0)
+		return -1;
+	PDEBUG(D_PROBE, "registered");
+	return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+	PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index ee23295..1fff37b 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -1360,7 +1360,6 @@
 	}
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = OV511_ENDPOINT_ADDRESS;
 	if (!sd->sif) {
 		cam->cam_mode = vga_mode;
 		cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -2177,8 +2176,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
index 3bf15e4..19e0bc6 100644
--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -1,7 +1,8 @@
 /*
- * ov534/ov772x gspca driver
+ * ov534 gspca driver
  * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
  * Copyright (C) 2008 Jim Paris <jim@jtan.com>
+ * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
  *
  * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
  * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
@@ -26,7 +27,7 @@
 
 #include "gspca.h"
 
-#define OV534_REG_ADDRESS	0xf1	/* ? */
+#define OV534_REG_ADDRESS	0xf1	/* sensor address */
 #define OV534_REG_SUBADDR	0xf2
 #define OV534_REG_WRITE		0xf3
 #define OV534_REG_READ		0xf4
@@ -46,9 +47,13 @@
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
-	__u32 last_fid;
 	__u32 last_pts;
-	int frame_rate;
+	u16 last_fid;
+	u8 frame_rate;
+
+	u8 sensor;
+#define SENSOR_OV772X 0
+#define SENSOR_OV965X 1
 };
 
 /* V4L2 controls supported by the driver */
@@ -63,114 +68,7 @@
 	 .priv = 0},
 };
 
-static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
-{
-	struct usb_device *udev = gspca_dev->dev;
-	int ret;
-
-	PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val);
-	gspca_dev->usb_buf[0] = val;
-	ret = usb_control_msg(udev,
-			      usb_sndctrlpipe(udev, 0),
-			      0x1,
-			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-	if (ret < 0)
-		PDEBUG(D_ERR, "write failed");
-}
-
-static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
-{
-	struct usb_device *udev = gspca_dev->dev;
-	int ret;
-
-	ret = usb_control_msg(udev,
-			      usb_rcvctrlpipe(udev, 0),
-			      0x1,
-			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x0, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-	PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]);
-	if (ret < 0)
-		PDEBUG(D_ERR, "read failed");
-	return gspca_dev->usb_buf[0];
-}
-
-/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
- * (direction and output)? */
-static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
-{
-	u8 data;
-
-	PDEBUG(D_CONF, "led status: %d", status);
-
-	data = ov534_reg_read(gspca_dev, 0x21);
-	data |= 0x80;
-	ov534_reg_write(gspca_dev, 0x21, data);
-
-	data = ov534_reg_read(gspca_dev, 0x23);
-	if (status)
-		data |= 0x80;
-	else
-		data &= ~(0x80);
-
-	ov534_reg_write(gspca_dev, 0x23, data);
-}
-
-static int sccb_check_status(struct gspca_dev *gspca_dev)
-{
-	u8 data;
-	int i;
-
-	for (i = 0; i < 5; i++) {
-		data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
-
-		switch (data) {
-		case 0x00:
-			return 1;
-		case 0x04:
-			return 0;
-		case 0x03:
-			break;
-		default:
-			PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
-			       data, i + 1);
-		}
-	}
-	return 0;
-}
-
-static void sccb_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
-{
-	PDEBUG(D_USBO, "reg: 0x%04x, val: 0x%02x", reg, val);
-	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
-	ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
-	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
-
-	if (!sccb_check_status(gspca_dev))
-		PDEBUG(D_ERR, "sccb_reg_write failed");
-}
-
-#ifdef GSPCA_DEBUG
-static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
-{
-	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
-	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
-	if (!sccb_check_status(gspca_dev))
-		PDEBUG(D_ERR, "sccb_reg_read failed 1");
-
-	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
-	if (!sccb_check_status(gspca_dev))
-		PDEBUG(D_ERR, "sccb_reg_read failed 2");
-
-	return ov534_reg_read(gspca_dev, OV534_REG_READ);
-}
-#endif
-
-static const __u8 ov534_reg_initdata[][2] = {
-	{ 0xe7, 0x3a },
-
-	{ OV534_REG_ADDRESS, 0x42 }, /* select OV772x sensor */
-
+static const u8 bridge_init_ov722x[][2] = {
 	{ 0xc2, 0x0c },
 	{ 0x88, 0xf8 },
 	{ 0xc3, 0x69 },
@@ -228,7 +126,7 @@
 	{ 0xc2, 0x0c },
 };
 
-static const __u8 ov772x_reg_initdata[][2] = {
+static const u8 sensor_init_ov722x[][2] = {
 	{ 0x12, 0x80 },
 	{ 0x11, 0x01 },
 
@@ -311,6 +209,456 @@
 	{ 0x0c, 0xd0 }
 };
 
+static const u8 bridge_init_ov965x[][2] = {
+	{0x88, 0xf8},
+	{0x89, 0xff},
+	{0x76, 0x03},
+	{0x92, 0x03},
+	{0x95, 0x10},
+	{0xe2, 0x00},
+	{0xe7, 0x3e},
+	{0x8d, 0x1c},
+	{0x8e, 0x00},
+	{0x8f, 0x00},
+	{0x1f, 0x00},
+	{0xc3, 0xf9},
+	{0x89, 0xff},
+	{0x88, 0xf8},
+	{0x76, 0x03},
+	{0x92, 0x01},
+	{0x93, 0x18},
+	{0x1c, 0x0a},
+	{0x1d, 0x48},
+	{0xc0, 0x50},
+	{0xc1, 0x3c},
+	{0x34, 0x05},
+	{0xc2, 0x0c},
+	{0xc3, 0xf9},
+	{0x34, 0x05},
+	{0xe7, 0x2e},
+	{0x31, 0xf9},
+	{0x35, 0x02},
+	{0xd9, 0x10},
+	{0x25, 0x42},
+	{0x94, 0x11},
+};
+
+static const u8 sensor_init_ov965x[][2] = {
+	{0x12, 0x80},	/* com7 - reset */
+	{0x00, 0x00},	/* gain */
+	{0x01, 0x80},	/* blue */
+	{0x02, 0x80},	/* red */
+	{0x03, 0x1b},	/* vref */
+	{0x04, 0x03},	/* com1 - exposure low bits */
+	{0x0b, 0x57},	/* ver */
+	{0x0e, 0x61},	/* com5 */
+	{0x0f, 0x42},	/* com6 */
+	{0x11, 0x00},	/* clkrc */
+	{0x12, 0x02},	/* com7 */
+	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
+	{0x14, 0x28},	/* com9 */
+	{0x16, 0x24},	/* rsvd16 */
+	{0x17, 0x1d},	/* hstart*/
+	{0x18, 0xbd},	/* hstop */
+	{0x19, 0x01},	/* vstrt */
+	{0x1a, 0x81},	/* vstop*/
+	{0x1e, 0x04},	/* mvfp */
+	{0x24, 0x3c},	/* aew */
+	{0x25, 0x36},	/* aeb */
+	{0x26, 0x71},	/* vpt */
+	{0x27, 0x08},	/* bbias */
+	{0x28, 0x08},	/* gbbias */
+	{0x29, 0x15},	/* gr com */
+	{0x2a, 0x00},
+	{0x2b, 0x00},
+	{0x2c, 0x08},	/* rbias */
+	{0x32, 0xff},	/* href */
+	{0x33, 0x00},	/* chlf */
+	{0x34, 0x3f},	/* arblm */
+	{0x35, 0x00},	/* rsvd35 */
+	{0x36, 0xf8},	/* rsvd36 */
+	{0x38, 0x72},	/* acom38 */
+	{0x39, 0x57},	/* ofon */
+	{0x3a, 0x80},	/* tslb */
+	{0x3b, 0xc4},
+	{0x3d, 0x99},	/* com13 */
+	{0x3f, 0xc1},
+	{0x40, 0xc0},	/* com15 */
+	{0x41, 0x40},	/* com16 */
+	{0x42, 0xc0},
+	{0x43, 0x0a},
+	{0x44, 0xf0},
+	{0x45, 0x46},
+	{0x46, 0x62},
+	{0x47, 0x2a},
+	{0x48, 0x3c},
+	{0x4a, 0xfc},
+	{0x4b, 0xfc},
+	{0x4c, 0x7f},
+	{0x4d, 0x7f},
+	{0x4e, 0x7f},
+	{0x4f, 0x98},
+	{0x50, 0x98},
+	{0x51, 0x00},
+	{0x52, 0x28},
+	{0x53, 0x70},
+	{0x54, 0x98},
+	{0x58, 0x1a},
+	{0x59, 0x85},
+	{0x5a, 0xa9},
+	{0x5b, 0x64},
+	{0x5c, 0x84},
+	{0x5d, 0x53},
+	{0x5e, 0x0e},
+	{0x5f, 0xf0},
+	{0x60, 0xf0},
+	{0x61, 0xf0},
+	{0x62, 0x00},	/* lcc1 */
+	{0x63, 0x00},	/* lcc2 */
+	{0x64, 0x02},	/* lcc3 */
+	{0x65, 0x16},	/* lcc4 */
+	{0x66, 0x01},	/* lcc5 */
+	{0x69, 0x02},	/* hv */
+	{0x6b, 0x5a},	/* dbvl */
+	{0x6c, 0x04},
+	{0x6d, 0x55},
+	{0x6e, 0x00},
+	{0x6f, 0x9d},
+	{0x70, 0x21},
+	{0x71, 0x78},
+	{0x72, 0x00},
+	{0x73, 0x01},
+	{0x74, 0x3a},
+	{0x75, 0x35},
+	{0x76, 0x01},
+	{0x77, 0x02},
+	{0x7a, 0x12},
+	{0x7b, 0x08},
+	{0x7c, 0x16},
+	{0x7d, 0x30},
+	{0x7e, 0x5e},
+	{0x7f, 0x72},
+	{0x80, 0x82},
+	{0x81, 0x8e},
+	{0x82, 0x9a},
+	{0x83, 0xa4},
+	{0x84, 0xac},
+	{0x85, 0xb8},
+	{0x86, 0xc3},
+	{0x87, 0xd6},
+	{0x88, 0xe6},
+	{0x89, 0xf2},
+	{0x8a, 0x03},
+	{0x8c, 0x89},
+	{0x14, 0x28},	/* com9 */
+	{0x90, 0x7d},
+	{0x91, 0x7b},
+	{0x9d, 0x03},
+	{0x9e, 0x04},
+	{0x9f, 0x7a},
+	{0xa0, 0x79},
+	{0xa1, 0x40},	/* aechm */
+	{0xa4, 0x50},
+	{0xa5, 0x68},	/* com26 */
+	{0xa6, 0x4a},
+	{0xa8, 0xc1},	/* acoma8 */
+	{0xa9, 0xef},	/* acoma9 */
+	{0xaa, 0x92},
+	{0xab, 0x04},
+	{0xac, 0x80},
+	{0xad, 0x80},
+	{0xae, 0x80},
+	{0xaf, 0x80},
+	{0xb2, 0xf2},
+	{0xb3, 0x20},
+	{0xb4, 0x20},
+	{0xb5, 0x00},
+	{0xb6, 0xaf},
+	{0xbb, 0xae},
+	{0xbc, 0x7f},
+	{0xdb, 0x7f},
+	{0xbe, 0x7f},
+	{0xbf, 0x7f},
+	{0xc0, 0xe2},
+	{0xc1, 0xc0},
+	{0xc2, 0x01},
+	{0xc3, 0x4e},
+	{0xc6, 0x85},
+	{0xc7, 0x80},
+	{0xc9, 0xe0},
+	{0xca, 0xe8},
+	{0xcb, 0xf0},
+	{0xcc, 0xd8},
+	{0xcd, 0xf1},
+	{0x4f, 0x98},
+	{0x50, 0x98},
+	{0x51, 0x00},
+	{0x52, 0x28},
+	{0x53, 0x70},
+	{0x54, 0x98},
+	{0x58, 0x1a},
+	{0xff, 0x41},	/* read 41, write ff 00 */
+	{0x41, 0x40},	/* com16 */
+	{0xc5, 0x03},
+	{0x6a, 0x02},
+
+	{0x12, 0x62},	/* com7 - VGA + CIF */
+	{0x36, 0xfa},	/* rsvd36 */
+	{0x69, 0x0a},	/* hv */
+	{0x8c, 0x89},	/* com22 */
+	{0x14, 0x28},	/* com9 */
+	{0x3e, 0x0c},
+	{0x41, 0x40},	/* com16 */
+	{0x72, 0x00},
+	{0x73, 0x00},
+	{0x74, 0x3a},
+	{0x75, 0x35},
+	{0x76, 0x01},
+	{0xc7, 0x80},
+	{0x03, 0x12},	/* vref */
+	{0x17, 0x16},	/* hstart */
+	{0x18, 0x02},	/* hstop */
+	{0x19, 0x01},	/* vstrt */
+	{0x1a, 0x3d},	/* vstop */
+	{0x32, 0xff},	/* href */
+	{0xc0, 0xaa},
+};
+
+static const u8 bridge_init_ov965x_2[][2] = {
+	{0x94, 0xaa},
+	{0xf1, 0x60},
+	{0xe5, 0x04},
+	{0xc0, 0x50},
+	{0xc1, 0x3c},
+	{0x8c, 0x00},
+	{0x8d, 0x1c},
+	{0x34, 0x05},
+
+	{0xc2, 0x0c},
+	{0xc3, 0xf9},
+	{0xda, 0x01},
+	{0x50, 0x00},
+	{0x51, 0xa0},
+	{0x52, 0x3c},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x57, 0x00},
+	{0x5c, 0x00},
+	{0x5a, 0xa0},
+	{0x5b, 0x78},
+	{0x35, 0x02},
+	{0xd9, 0x10},
+	{0x94, 0x11},
+};
+
+static const u8 sensor_init_ov965x_2[][2] = {
+	{0x3b, 0xc4},
+	{0x1e, 0x04},	/* mvfp */
+	{0x13, 0xe0},	/* com8 */
+	{0x00, 0x00},	/* gain */
+	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
+	{0x11, 0x03},	/* clkrc */
+	{0x6b, 0x5a},	/* dblv */
+	{0x6a, 0x05},
+	{0xc5, 0x07},
+	{0xa2, 0x4b},
+	{0xa3, 0x3e},
+	{0x2d, 0x00},
+	{0xff, 0x42},	/* read 42, write ff 00 */
+	{0x42, 0xc0},
+	{0x2d, 0x00},
+	{0xff, 0x42},	/* read 42, write ff 00 */
+	{0x42, 0xc1},
+	{0x3f, 0x01},
+	{0xff, 0x42},	/* read 42, write ff 00 */
+	{0x42, 0xc1},
+	{0x4f, 0x98},
+	{0x50, 0x98},
+	{0x51, 0x00},
+	{0x52, 0x28},
+	{0x53, 0x70},
+	{0x54, 0x98},
+	{0x58, 0x1a},
+	{0xff, 0x41},	/* read 41, write ff 00 */
+	{0x41, 0x40},	/* com16 */
+	{0x56, 0x40},
+	{0x55, 0x8f},
+	{0x10, 0x25},	/* aech - exposure high bits */
+	{0xff, 0x13},	/* read 13, write ff 00 */
+	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
+};
+
+static const u8 bridge_start_ov965x[][2] = {
+	{0xc2, 0x4c},
+	{0xc3, 0xf9},
+	{0x50, 0x00},
+	{0x51, 0xa0},
+	{0x52, 0x78},
+	{0x53, 0x00},
+	{0x54, 0x00},
+	{0x55, 0x00},
+	{0x57, 0x00},
+	{0x5c, 0x00},
+	{0x5a, 0x28},
+	{0x5b, 0x1e},
+	{0x35, 0x00},
+	{0xd9, 0x21},
+	{0x94, 0x11},
+};
+
+static const u8 sensor_start_ov965x[][2] = {
+	{0x3b, 0xe4},
+	{0x1e, 0x04},	/* mvfp */
+	{0x13, 0xe0},	/* com8 */
+	{0x00, 0x00},
+	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
+	{0x11, 0x01},	/* clkrc */
+	{0x6b, 0x5a},	/* dblv */
+	{0x6a, 0x02},
+	{0xc5, 0x03},
+	{0xa2, 0x96},
+	{0xa3, 0x7d},
+	{0xff, 0x13},	/* read 13, write ff 00 */
+	{0x13, 0xe7},
+	{0x3a, 0x80},
+	{0xff, 0x42},	/* read 42, write ff 00 */
+	{0x42, 0xc1},
+};
+
+
+static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
+{
+	struct usb_device *udev = gspca_dev->dev;
+	int ret;
+
+	PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val);
+	gspca_dev->usb_buf[0] = val;
+	ret = usb_control_msg(udev,
+			      usb_sndctrlpipe(udev, 0),
+			      0x01,
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+	if (ret < 0)
+		PDEBUG(D_ERR, "write failed");
+}
+
+static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
+{
+	struct usb_device *udev = gspca_dev->dev;
+	int ret;
+
+	ret = usb_control_msg(udev,
+			      usb_rcvctrlpipe(udev, 0),
+			      0x01,
+			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+	PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]);
+	if (ret < 0)
+		PDEBUG(D_ERR, "read failed");
+	return gspca_dev->usb_buf[0];
+}
+
+/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
+ * (direction and output)? */
+static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
+{
+	u8 data;
+
+	PDEBUG(D_CONF, "led status: %d", status);
+
+	data = ov534_reg_read(gspca_dev, 0x21);
+	data |= 0x80;
+	ov534_reg_write(gspca_dev, 0x21, data);
+
+	data = ov534_reg_read(gspca_dev, 0x23);
+	if (status)
+		data |= 0x80;
+	else
+		data &= ~0x80;
+
+	ov534_reg_write(gspca_dev, 0x23, data);
+
+	if (!status) {
+		data = ov534_reg_read(gspca_dev, 0x21);
+		data &= ~0x80;
+		ov534_reg_write(gspca_dev, 0x21, data);
+	}
+}
+
+static int sccb_check_status(struct gspca_dev *gspca_dev)
+{
+	u8 data;
+	int i;
+
+	for (i = 0; i < 5; i++) {
+		data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
+
+		switch (data) {
+		case 0x00:
+			return 1;
+		case 0x04:
+			return 0;
+		case 0x03:
+			break;
+		default:
+			PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
+			       data, i + 1);
+		}
+	}
+	return 0;
+}
+
+static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+	PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val);
+	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+	ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
+	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
+
+	if (!sccb_check_status(gspca_dev))
+		PDEBUG(D_ERR, "sccb_reg_write failed");
+}
+
+static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
+{
+	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
+	if (!sccb_check_status(gspca_dev))
+		PDEBUG(D_ERR, "sccb_reg_read failed 1");
+
+	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
+	if (!sccb_check_status(gspca_dev))
+		PDEBUG(D_ERR, "sccb_reg_read failed 2");
+
+	return ov534_reg_read(gspca_dev, OV534_REG_READ);
+}
+
+/* output a bridge sequence (reg - val) */
+static void reg_w_array(struct gspca_dev *gspca_dev,
+			const u8 (*data)[2], int len)
+{
+	while (--len >= 0) {
+		ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
+		data++;
+	}
+}
+
+/* output a sensor sequence (reg - val) */
+static void sccb_w_array(struct gspca_dev *gspca_dev,
+			const u8 (*data)[2], int len)
+{
+	while (--len >= 0) {
+		if ((*data)[0] != 0xff) {
+			sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
+		} else {
+			sccb_reg_read(gspca_dev, (*data)[1]);
+			sccb_reg_write(gspca_dev, 0xff, 0x00);
+		}
+		data++;
+	}
+}
+
 /* set framerate */
 static void ov534_set_frame_rate(struct gspca_dev *gspca_dev)
 {
@@ -346,40 +694,17 @@
 	PDEBUG(D_PROBE, "frame_rate: %d", fr);
 }
 
-/* setup method */
-static void ov534_setup(struct gspca_dev *gspca_dev)
-{
-	int i;
-
-	/* Initialize bridge chip */
-	for (i = 0; i < ARRAY_SIZE(ov534_reg_initdata); i++)
-		ov534_reg_write(gspca_dev, ov534_reg_initdata[i][0],
-				ov534_reg_initdata[i][1]);
-
-	PDEBUG(D_PROBE, "sensor is ov%02x%02x",
-		sccb_reg_read(gspca_dev, 0x0a),
-		sccb_reg_read(gspca_dev, 0x0b));
-
-	ov534_set_led(gspca_dev, 1);
-
-	/* Initialize sensor */
-	for (i = 0; i < ARRAY_SIZE(ov772x_reg_initdata); i++)
-		sccb_reg_write(gspca_dev, ov772x_reg_initdata[i][0],
-			       ov772x_reg_initdata[i][1]);
-
-	ov534_reg_write(gspca_dev, 0xe0, 0x09);
-	ov534_set_led(gspca_dev, 0);
-}
-
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
 		     const struct usb_device_id *id)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
 
+	sd->sensor = id->driver_info;
+
 	cam = &gspca_dev->cam;
 
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = ARRAY_SIZE(vga_mode);
 
@@ -392,26 +717,102 @@
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	ov534_setup(gspca_dev);
-	ov534_set_frame_rate(gspca_dev);
+	struct sd *sd = (struct sd *) gspca_dev;
+	u16 sensor_id;
+	static const u8 sensor_addr[2] = {
+		0x42,			/* 0 SENSOR_OV772X */
+		0x60,			/* 1 SENSOR_OV965X */
+	};
+
+	/* reset bridge */
+	ov534_reg_write(gspca_dev, 0xe7, 0x3a);
+	ov534_reg_write(gspca_dev, 0xe0, 0x08);
+	msleep(100);
+
+	/* initialize the sensor address */
+	ov534_reg_write(gspca_dev, OV534_REG_ADDRESS,
+				sensor_addr[sd->sensor]);
+
+	/* reset sensor */
+	sccb_reg_write(gspca_dev, 0x12, 0x80);
+	msleep(10);
+
+	/* probe the sensor */
+	sccb_reg_read(gspca_dev, 0x0a);
+	sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
+	sccb_reg_read(gspca_dev, 0x0b);
+	sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
+	PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
+
+	/* initialize */
+	switch (sd->sensor) {
+	case SENSOR_OV772X:
+		reg_w_array(gspca_dev, bridge_init_ov722x,
+				ARRAY_SIZE(bridge_init_ov722x));
+		ov534_set_led(gspca_dev, 1);
+		sccb_w_array(gspca_dev, sensor_init_ov722x,
+				ARRAY_SIZE(sensor_init_ov722x));
+		ov534_reg_write(gspca_dev, 0xe0, 0x09);
+		ov534_set_led(gspca_dev, 0);
+		ov534_set_frame_rate(gspca_dev);
+		break;
+	default:
+/*	case SENSOR_OV965X: */
+		reg_w_array(gspca_dev, bridge_init_ov965x,
+				ARRAY_SIZE(bridge_init_ov965x));
+		sccb_w_array(gspca_dev, sensor_init_ov965x,
+				ARRAY_SIZE(sensor_init_ov965x));
+		reg_w_array(gspca_dev, bridge_init_ov965x_2,
+				ARRAY_SIZE(bridge_init_ov965x_2));
+		sccb_w_array(gspca_dev, sensor_init_ov965x_2,
+				ARRAY_SIZE(sensor_init_ov965x_2));
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
+		ov534_reg_write(gspca_dev, 0xe0, 0x01);
+		ov534_set_led(gspca_dev, 0);
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
+	}
 
 	return 0;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
-	/* start streaming data */
-	ov534_set_led(gspca_dev, 1);
-	ov534_reg_write(gspca_dev, 0xe0, 0x00);
+	struct sd *sd = (struct sd *) gspca_dev;
 
+	switch (sd->sensor) {
+	case SENSOR_OV772X:
+		ov534_set_led(gspca_dev, 1);
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
+		break;
+	default:
+/*	case SENSOR_OV965X: */
+		reg_w_array(gspca_dev, bridge_start_ov965x,
+				ARRAY_SIZE(bridge_start_ov965x));
+		sccb_w_array(gspca_dev, sensor_start_ov965x,
+				ARRAY_SIZE(sensor_start_ov965x));
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
+		ov534_set_led(gspca_dev, 1);
+/*fixme: other sensor start omitted*/
+	}
 	return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-	/* stop streaming data */
-	ov534_reg_write(gspca_dev, 0xe0, 0x09);
-	ov534_set_led(gspca_dev, 0);
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	switch (sd->sensor) {
+	case SENSOR_OV772X:
+		ov534_reg_write(gspca_dev, 0xe0, 0x09);
+		ov534_set_led(gspca_dev, 0);
+		break;
+	default:
+/*	case SENSOR_OV965X: */
+		ov534_reg_write(gspca_dev, 0xe0, 0x01);
+		ov534_set_led(gspca_dev, 0);
+		ov534_reg_write(gspca_dev, 0xe0, 0x00);
+		break;
+	}
 }
 
 /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
@@ -429,75 +830,75 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	__u32 this_pts;
-	int this_fid;
+	u16 this_fid;
 	int remaining_len = len;
-	__u8 *next_data = data;
 
-scan_next:
-	if (remaining_len <= 0)
-		return;
+	do {
+		len = min(remaining_len, 2040);		/*fixme: was 2048*/
 
-	data = next_data;
-	len = min(remaining_len, 2048);
-	remaining_len -= len;
-	next_data += len;
+		/* Payloads are prefixed with a UVC-style header.  We
+		   consider a frame to start when the FID toggles, or the PTS
+		   changes.  A frame ends when EOF is set, and we've received
+		   the correct number of bytes. */
 
-	/* Payloads are prefixed with a UVC-style header.  We
-	   consider a frame to start when the FID toggles, or the PTS
-	   changes.  A frame ends when EOF is set, and we've received
-	   the correct number of bytes. */
-
-	/* Verify UVC header.  Header length is always 12 */
-	if (data[0] != 12 || len < 12) {
-		PDEBUG(D_PACK, "bad header");
-		goto discard;
-	}
-
-	/* Check errors */
-	if (data[1] & UVC_STREAM_ERR) {
-		PDEBUG(D_PACK, "payload error");
-		goto discard;
-	}
-
-	/* Extract PTS and FID */
-	if (!(data[1] & UVC_STREAM_PTS)) {
-		PDEBUG(D_PACK, "PTS not present");
-		goto discard;
-	}
-	this_pts = (data[5] << 24) | (data[4] << 16) | (data[3] << 8) | data[2];
-	this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
-
-	/* If PTS or FID has changed, start a new frame. */
-	if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
-		gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
-		sd->last_pts = this_pts;
-		sd->last_fid = this_fid;
-	}
-
-	/* Add the data from this payload */
-	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
-				data + 12, len - 12);
-
-	/* If this packet is marked as EOF, end the frame */
-	if (data[1] & UVC_STREAM_EOF) {
-		sd->last_pts = 0;
-
-		if ((frame->data_end - frame->data) !=
-		    (gspca_dev->width * gspca_dev->height * 2)) {
-			PDEBUG(D_PACK, "short frame");
+		/* Verify UVC header.  Header length is always 12 */
+		if (data[0] != 12 || len < 12) {
+			PDEBUG(D_PACK, "bad header");
 			goto discard;
 		}
 
-		gspca_frame_add(gspca_dev, LAST_PACKET, frame, NULL, 0);
-	}
+		/* Check errors */
+		if (data[1] & UVC_STREAM_ERR) {
+			PDEBUG(D_PACK, "payload error");
+			goto discard;
+		}
 
-	/* Done this payload */
-	goto scan_next;
+		/* Extract PTS and FID */
+		if (!(data[1] & UVC_STREAM_PTS)) {
+			PDEBUG(D_PACK, "PTS not present");
+			goto discard;
+		}
+		this_pts = (data[5] << 24) | (data[4] << 16)
+						| (data[3] << 8) | data[2];
+		this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
+
+		/* If PTS or FID has changed, start a new frame. */
+		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
+			gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+					NULL, 0);
+			sd->last_pts = this_pts;
+			sd->last_fid = this_fid;
+		}
+
+		/* Add the data from this payload */
+		gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+					data + 12, len - 12);
+
+		/* If this packet is marked as EOF, end the frame */
+		if (data[1] & UVC_STREAM_EOF) {
+			sd->last_pts = 0;
+
+			if (frame->data_end - frame->data !=
+			    gspca_dev->width * gspca_dev->height * 2) {
+				PDEBUG(D_PACK, "short frame");
+				goto discard;
+			}
+
+			frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+						NULL, 0);
+		}
+
+		/* Done this payload */
+		goto scan_next;
 
 discard:
-	/* Discard data until a new frame starts. */
-	gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0);
-	goto scan_next;
+		/* Discard data until a new frame starts. */
+		gspca_frame_add(gspca_dev, DISCARD_PACKET, frame, NULL, 0);
+
+scan_next:
+		remaining_len -= len;
+		data += len;
+	} while (remaining_len > 0);
 }
 
 /* get stream parameters (framerate) */
@@ -556,9 +957,8 @@
 
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
-	{USB_DEVICE(0x06f8, 0x3002)},	/* Hercules Blog Webcam */
-	{USB_DEVICE(0x06f8, 0x3003)},	/* Hercules Dualpix HD Weblog */
-	{USB_DEVICE(0x1415, 0x2000)},	/* Sony HD Eye for PS3 (SLEH 00201) */
+	{USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X},
+	{USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X},
 	{}
 };
 
@@ -585,8 +985,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index c90ac85..95a97ab 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -256,7 +256,6 @@
 		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x05;
 	cam->cam_mode = sif_mode;
 	cam->nmodes = ARRAY_SIZE(sif_mode);
 	sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
@@ -536,6 +535,7 @@
 	{USB_DEVICE(0x093a, 0x2470)},
 	{USB_DEVICE(0x093a, 0x2471)},
 	{USB_DEVICE(0x093a, 0x2472)},
+	{USB_DEVICE(0x093a, 0x2474)},
 	{USB_DEVICE(0x093a, 0x2476)},
 	{USB_DEVICE(0x145f, 0x013a)},
 	{USB_DEVICE(0x2001, 0xf115)},
@@ -565,8 +565,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index a9c95cb..e1e3a3a 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -498,7 +498,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x05;
 
 	sd->sensor = id->driver_info;
 	if (sd->sensor == SENSOR_PAC7302) {
@@ -1097,8 +1096,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index b3e4e06..153d0a9 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -870,7 +870,6 @@
 	gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	if (!(sensor_data[sd->sensor].flags & F_SIF)) {
 		cam->cam_mode = vga_mode;
 		cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -1272,8 +1271,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 3373b8d..c72e19d 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -35,36 +35,47 @@
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
 	atomic_t avg_lum;
-	unsigned int exposure;
+	u32 exposure;
 
-	__u16 brightness;
-	__u8 contrast;
-	__u8 colors;
-	__u8 autogain;
-	__u8 blue;
-	__u8 red;
-	__u8 vflip;			/* ov7630 only */
-	__u8 infrared;			/* mi0360 only */
+	u16 brightness;
+	u8 contrast;
+	u8 colors;
+	u8 autogain;
+	u8 blue;
+	u8 red;
+	u8 gamma;
+	u8 vflip;			/* ov7630/ov7648 only */
+	u8 infrared;			/* mt9v111 only */
+	u8 quality;			/* image quality */
+#define QUALITY_MIN 60
+#define QUALITY_MAX 95
+#define QUALITY_DEF 80
+	u8 jpegqual;			/* webcam quality */
 
-	__s8 ag_cnt;
+	u8 reg18;
+
+	s8 ag_cnt;
 #define AG_CNT_START 13
 
-	__u8 qindex;
-	__u8 bridge;
+	u8 bridge;
 #define BRIDGE_SN9C102P 0
 #define BRIDGE_SN9C105 1
 #define BRIDGE_SN9C110 2
 #define BRIDGE_SN9C120 3
 #define BRIDGE_SN9C325 4
-	__u8 sensor;			/* Type of image sensor chip */
+	u8 sensor;			/* Type of image sensor chip */
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
 #define SENSOR_MO4000 2
-#define SENSOR_OM6802 3
-#define SENSOR_OV7630 4
-#define SENSOR_OV7648 5
-#define SENSOR_OV7660 6
-	__u8 i2c_base;
+#define SENSOR_MT9V111 3
+#define SENSOR_OM6802 4
+#define SENSOR_OV7630 5
+#define SENSOR_OV7648 6
+#define SENSOR_OV7660 7
+#define SENSOR_SP80708 8
+	u8 i2c_base;
+
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -78,6 +89,8 @@
 static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -158,6 +171,20 @@
 	    .set = sd_setred_balance,
 	    .get = sd_getred_balance,
 	},
+	{
+	    {
+		.id      = V4L2_CID_GAMMA,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gamma",
+		.minimum = 0,
+		.maximum = 40,
+		.step    = 1,
+#define GAMMA_DEF 20
+		.default_value = GAMMA_DEF,
+	    },
+	    .set = sd_setgamma,
+	    .get = sd_getgamma,
+	},
 #define AUTOGAIN_IDX 5
 	{
 	    {
@@ -173,7 +200,7 @@
 	    .set = sd_setautogain,
 	    .get = sd_getautogain,
 	},
-/* ov7630 only */
+/* ov7630/ov7648 only */
 #define VFLIP_IDX 6
 	{
 	    {
@@ -183,13 +210,13 @@
 		.minimum = 0,
 		.maximum = 1,
 		.step    = 1,
-#define VFLIP_DEF 1
+#define VFLIP_DEF 0			/* vflip def = 1 for ov7630 */
 		.default_value = VFLIP_DEF,
 	    },
 	    .set = sd_setvflip,
 	    .get = sd_getvflip,
 	},
-/* mi0360 only */
+/* mt9v111 only */
 #define INFRARED_IDX 7
 	{
 	    {
@@ -211,18 +238,22 @@
 static __u32 ctrl_dis[] = {
 	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
 						/* SENSOR_HV7131R 0 */
-	(1 << VFLIP_IDX),
+	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
 						/* SENSOR_MI0360 1 */
 	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
 						/* SENSOR_MO4000 2 */
+	(1 << VFLIP_IDX),
+						/* SENSOR_MT9V111 3 */
 	(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
-						/* SENSOR_OM6802 3 */
+						/* SENSOR_OM6802 4 */
 	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
-						/* SENSOR_OV7630 4 */
+						/* SENSOR_OV7630 5 */
+	(1 << INFRARED_IDX),
+						/* SENSOR_OV7648 6 */
 	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
-						/* SENSOR_OV7648 5 */
+						/* SENSOR_OV7660 7 */
 	(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
-						/* SENSOR_OV7660 6 */
+						/* SENSOR_SP80708 8 */
 };
 
 static const struct v4l2_pix_format vga_mode[] = {
@@ -243,196 +274,228 @@
 		.priv = 0},
 };
 
-/*Data from sn9c102p+hv71331r */
-static const __u8 sn_hv7131[] = {
+/*Data from sn9c102p+hv7131r */
+static const u8 sn_hv7131[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x03,	0x64,	0x00,	0x1a,	0x20,	0x20,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0xa1,	0x11,	0x02,	0x09,	0x00,	0x00,	0x00,	0x10,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x00,	0x01,	0x03,	0x28,	0x1e,	0x41,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x0a,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00
+/*	reg18	reg19	reg1a	reg1b */
+	0x0a,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_mi0360[] = {
+static const u8 sn_mi0360[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x61,	0x44,	0x00,	0x1a,	0x20,	0x20,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0xb1,	0x5d,	0x07,	0x00,	0x00,	0x00,	0x00,	0x10,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x61,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x06,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00
+/*	reg18	reg19	reg1a	reg1b */
+	0x06,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_mo4000[] = {
+static const u8 sn_mo4000[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
-	0x12,	0x23,	0x60,	0x00,	0x1a,	0x00,	0x20,	0x18,
+	0x00,	0x23,	0x60,	0x00,	0x1a,	0x00,	0x20,	0x18,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	 0x00,	0x0b,	0x0f,	0x14,	0x28,	0x1e,	0x40,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x08,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00
+/*	reg18	reg19	reg1a	reg1b */
+	0x08,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_om6802[] = {
+static const u8 sn_mt9v111[0x1c] = {
+/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
+	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
+/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
+	0x81,	0x5c,	0x07,	0x00,	0x00,	0x00,	0x00,	0x00,
+/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
+	0x03,	0x00,	0x00,	0x02,	0x1c,	0x28,	0x1e,	0x40,
+/*	reg18	reg19	reg1a	reg1b */
+	0x06,	0x00,	0x00,	0x00
+};
+
+static const u8 sn_om6802[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x23,	0x72,	0x00,	0x1a,	0x34,	0x27,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0x80,	0x34,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x51,	0x01,	0x00,	0x28,	0x1e,	0x40,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x05,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
-	0x08,	0x22,	0x44,	0x63,	0x7d,	0x92,	0xa3,	0xaf,
-	0xbc,	0xc4,	0xcd,	0xd5,	0xdc,	0xe1,	0xe8,	0xef,
-	0xf7
+/*	reg18	reg19	reg1a	reg1b */
+	0x05,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_ov7630[] = {
+static const u8 sn_ov7630[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x21,	0x40,	0x00,	0x1a,	0x20,	0x1f,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0xa1,	0x21,	0x76,	0x21,	0x00,	0x00,	0x00,	0x10,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x04,	0x01,	0x0a,	0x28,	0x1e,	0xc2,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x0b,	0x00,	0x00,	0x00,	0x00,	0x00
+/*	reg18	reg19	reg1a	reg1b */
+	0x0b,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_ov7648[] = {
+static const u8 sn_ov7648[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x10,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x00,	0x01,	0x00,	0x28,	0x1e,	0x00,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x0b,	0x00,	0x00,	0x00,	0x00,	0x00
+/*	reg18	reg19	reg1a	reg1b */
+	0x0b,	0x00,	0x00,	0x00
 };
 
-static const __u8 sn_ov7660[]	= {
+static const u8 sn_ov7660[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
 	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0x81,	0x21,	0x07,	0x00,	0x00,	0x00,	0x00,	0x10,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
 	0x03,	0x00,	0x01,	0x01,	0x08,	0x28,	0x1e,	0x20,
-/*	reg18	reg19	reg1a	reg1b	reg1c	reg1d	reg1e	reg1f */
-	0x07,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
+/*	reg18	reg19	reg1a	reg1b */
+	0x07,	0x00,	0x00,	0x00
+};
+
+static const u8 sn_sp80708[0x1c] = {
+/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
+	0x00,	0x63,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
+/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
+	0x81,	0x18,	0x07,	0x00,	0x00,	0x00,	0x00,	0x00,
+/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
+	0x03,	0x00,	0x00,	0x03,	0x04,	0x28,	0x1e,	0x00,
+/*	reg18	reg19	reg1a	reg1b */
+	0x07,	0x00,	0x00,	0x00
 };
 
 /* sequence specific to the sensors - !! index = SENSOR_xxx */
-static const __u8 *sn_tb[] = {
+static const u8 *sn_tb[] = {
 	sn_hv7131,
 	sn_mi0360,
 	sn_mo4000,
+	sn_mt9v111,
 	sn_om6802,
 	sn_ov7630,
 	sn_ov7648,
-	sn_ov7660
+	sn_ov7660,
+	sn_sp80708
 };
 
-static const __u8 gamma_def[] = {
+/* default gamma table */
+static const u8 gamma_def[17] = {
 	0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
 	0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
 };
+/* gamma for sensors HV7131R and MT9V111 */
+static const u8 gamma_spec_1[17] = {
+	0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
+	0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
+};
+/* gamma for sensor SP80708 */
+static const u8 gamma_spec_2[17] = {
+	0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
+	0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
+};
 
 /* color matrix and offsets */
-static const __u8 reg84[] = {
+static const u8 reg84[] = {
 	0x14, 0x00, 0x27, 0x00, 0x07, 0x00,	/* YR YG YB gains */
 	0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,	/* UR UG UB */
 	0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,	/* VR VG VB */
 	0x00, 0x00, 0x00			/* YUV offsets */
 };
-static const __u8 hv7131r_sensor_init[][8] = {
-	{0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
-	{0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
-	{0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
-	{0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
-	{0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
+static const u8 hv7131r_sensor_init[][8] = {
+	{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
+	{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
+	{0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
+/*	{0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+	{0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
+/*	{0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
 
-	{0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-	{0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
-	{0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
-	{0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
-	{0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
-	{0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
-	{0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
+	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+	{0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
+	{0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
+	{0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
+	{0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
+	{0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
+	{0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
 
-	{0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
 
-	{0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
 	{}
 };
-static const __u8 mi0360_sensor_init[][8] = {
-	{0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
-	{0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
-	{0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
-	{0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
-	{0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
-	{0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
-	{0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
-	{0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
-	{0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
-	{0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
+static const u8 mi0360_sensor_init[][8] = {
+	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
+	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
+	{0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
+	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
+	{0xd1, 0x5d, 0x2f, 0xf7, 0xB0, 0x00, 0x04, 0x10},
+	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
+	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
+	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
+	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
+	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
 
-	{0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
-	{0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
-	{0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
+	{0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
+	{0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
+	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
 
-	{0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
-	{0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
-	{0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
+	{0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
+	{0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
+	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
 
-	{0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
-	{0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
-/*	{0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
-/*	{0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
-	{0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
-	{0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
+	{0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
+	{0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
+/*	{0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
+/*	{0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
+	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
+	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
 	{}
 };
-static const __u8 mo4000_sensor_init[][8] = {
+static const u8 mo4000_sensor_init[][8] = {
 	{0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
 	{0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
@@ -455,7 +518,49 @@
 	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
 	{}
 };
-static __u8 om6802_sensor_init[][8] = {
+static const u8 mt9v111_sensor_init[][8] = {
+	{0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
+	/* delay 20 ms */
+	{0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
+	{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
+	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
+	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x04, 0x02, 0x81, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
+	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x03, 0x01, 0xe6, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x04, 0x02, 0x86, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
+	{0xb1, 0x5c, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
+	{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
+	{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
+	{0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
+	{0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
+	{0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
+	{0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
+	{0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
+	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
+	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+	/*******/
+	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10},
+	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */
+	{0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */
+	/*******/
+	{0xb1, 0x5c, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x10}, /* vert blanking */
+	{0xb1, 0x5c, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, /* horiz blanking */
+	{0xd1, 0x5c, 0x2c, 0x00, 0xad, 0x00, 0xad, 0x10}, /* blue gain */
+	{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
+	{}
+};
+static const u8 om6802_sensor_init[][8] = {
 	{0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
 	{0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
 	{0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
@@ -489,7 +594,7 @@
 /*	{0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
 	{}
 };
-static const __u8 ov7630_sensor_init[][8] = {
+static const u8 ov7630_sensor_init[][8] = {
 	{0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
 	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
 /* win: delay 20ms */
@@ -543,7 +648,7 @@
 	{}
 };
 
-static const __u8 ov7648_sensor_init[][8] = {
+static const u8 ov7648_sensor_init[][8] = {
 	{0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},	/* reset */
 	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
@@ -572,7 +677,8 @@
 	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
 /*...*/
 /*	{0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
+							 * set by setvflip */
 	{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
 	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
 /*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
@@ -589,7 +695,7 @@
 	{}
 };
 
-static const __u8 ov7660_sensor_init[][8] = {
+static const u8 ov7660_sensor_init[][8] = {
 	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
 /*		(delay 20ms) */
 	{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
@@ -678,28 +784,92 @@
 	{}
 };
 
-static const __u8 qtable4[] = {
-	0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
-	0x06, 0x08, 0x0A, 0x11,
-	0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
-	0x19, 0x19, 0x17, 0x15,
-	0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
-	0x21, 0x2E, 0x21, 0x23,
-	0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
-	0x25, 0x29, 0x2C, 0x29,
-	0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
-	0x17, 0x1B, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
-	0x29, 0x29, 0x29, 0x29
+static const u8 sp80708_sensor_init[][8] = {
+	{0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
+	/********/
+	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
+	{0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
+	{0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
+	{}
 };
 
 /* read <len> bytes to gspca_dev->usb_buf */
 static void reg_r(struct gspca_dev *gspca_dev,
-		  __u16 value, int len)
+		  u16 value, int len)
 {
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
@@ -718,10 +888,10 @@
 }
 
 static void reg_w1(struct gspca_dev *gspca_dev,
-		   __u16 value,
-		   __u8 data)
+		   u16 value,
+		   u8 data)
 {
-	PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
+	PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
 	gspca_dev->usb_buf[0] = data;
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
@@ -733,11 +903,11 @@
 			500);
 }
 static void reg_w(struct gspca_dev *gspca_dev,
-			  __u16 value,
-			  const __u8 *buffer,
+			  u16 value,
+			  const u8 *buffer,
 			  int len)
 {
-	PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
+	PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
 		value, buffer[0], buffer[1]);
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
@@ -756,7 +926,7 @@
 }
 
 /* I2C write 1 byte */
-static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
+static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
@@ -781,7 +951,7 @@
 
 /* I2C write 8 bytes */
 static void i2c_w8(struct gspca_dev *gspca_dev,
-		   const __u8 *buffer)
+		   const u8 *buffer)
 {
 	memcpy(gspca_dev->usb_buf, buffer, 8);
 	usb_control_msg(gspca_dev->dev,
@@ -795,10 +965,10 @@
 }
 
 /* read 5 bytes in gspca_dev->usb_buf */
-static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
+static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 mode[8];
+	u8 mode[8];
 
 	mode[0] = 0x81 | 0x10;
 	mode[1] = sd->i2c_base;
@@ -817,7 +987,7 @@
 	reg_r(gspca_dev, 0x0a, 5);
 }
 
-static int probesensor(struct gspca_dev *gspca_dev)
+static int hv7131r_probe(struct gspca_dev *gspca_dev)
 {
 	i2c_w1(gspca_dev, 0x02, 0);			/* sensor wakeup */
 	msleep(10);
@@ -839,16 +1009,66 @@
 	return -ENODEV;
 }
 
-static int configure_gpio(struct gspca_dev *gspca_dev,
-			  const __u8 *sn9c1xx)
+static void mi0360_probe(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	const __u8 *reg9a;
-	static const __u8 reg9a_def[] =
+	int i, j;
+	u16 val = 0;
+	static const u8 probe_tb[][4][8] = {
+	    {					/* mi0360 */
+		{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
+		{0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+		{0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+		{0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
+	    },
+	    {					/* mt9v111 */
+		{0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
+		{0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
+		{0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+		{}
+	    },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
+		reg_w1(gspca_dev, 0x17, 0x62);
+		reg_w1(gspca_dev, 0x01, 0x08);
+		for (j = 0; j < 3; j++)
+			i2c_w8(gspca_dev, probe_tb[i][j]);
+		msleep(2);
+		reg_r(gspca_dev, 0x0a, 5);
+		val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+		if (probe_tb[i][3][0] != 0)
+			i2c_w8(gspca_dev, probe_tb[i][3]);
+		reg_w1(gspca_dev, 0x01, 0x29);
+		reg_w1(gspca_dev, 0x17, 0x42);
+		if (val != 0xffff)
+			break;
+	}
+	switch (val) {
+	case 0x823a:
+		PDEBUG(D_PROBE, "Sensor mt9v111");
+		sd->sensor = SENSOR_MT9V111;
+		sd->i2c_base = 0x5c;
+		break;
+	case 0x8243:
+		PDEBUG(D_PROBE, "Sensor mi0360");
+		break;
+	default:
+		PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
+		break;
+	}
+}
+
+static int configure_gpio(struct gspca_dev *gspca_dev,
+			  const u8 *sn9c1xx)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	const u8 *reg9a;
+	static const u8 reg9a_def[] =
 		{0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
-	static const __u8 reg9a_sn9c325[] =
+	static const u8 reg9a_sn9c325[] =
 		{0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
-	static const __u8 regd4[] = {0x60, 0x00, 0x00};
+	static const u8 regd4[] = {0x60, 0x00, 0x00};
 
 	reg_w1(gspca_dev, 0xf1, 0x00);
 	reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
@@ -872,6 +1092,12 @@
 	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
 
 	switch (sd->sensor) {
+	case SENSOR_MT9V111:
+		reg_w1(gspca_dev, 0x01, 0x61);
+		reg_w1(gspca_dev, 0x17, 0x61);
+		reg_w1(gspca_dev, 0x01, 0x60);
+		reg_w1(gspca_dev, 0x01, 0x40);
+		break;
 	case SENSOR_OM6802:
 		reg_w1(gspca_dev, 0x02, 0x71);
 		reg_w1(gspca_dev, 0x01, 0x42);
@@ -900,12 +1126,20 @@
 			break;
 		}
 		/* fall thru */
+	case SENSOR_SP80708:
+		reg_w1(gspca_dev, 0x01, 0x63);
+		reg_w1(gspca_dev, 0x17, 0x20);
+		reg_w1(gspca_dev, 0x01, 0x62);
+		reg_w1(gspca_dev, 0x01, 0x42);
+		mdelay(100);
+		reg_w1(gspca_dev, 0x02, 0x62);
+		break;
 	default:
 		reg_w1(gspca_dev, 0x01, 0x43);
 		reg_w1(gspca_dev, 0x17, 0x61);
 		reg_w1(gspca_dev, 0x01, 0x42);
 		if (sd->sensor == SENSOR_HV7131R) {
-			if (probesensor(gspca_dev) < 0)
+			if (hv7131r_probe(gspca_dev) < 0)
 				return -ENODEV;
 		}
 		break;
@@ -916,7 +1150,7 @@
 static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
 {
 	int i = 0;
-	static const __u8 SetSensorClk[] =	/* 0x08 Mclk */
+	static const u8 SetSensorClk[] =	/* 0x08 Mclk */
 		{ 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
 
 	while (hv7131r_sensor_init[i][0]) {
@@ -946,6 +1180,19 @@
 	}
 }
 
+static void mt9v111_InitSensor(struct gspca_dev *gspca_dev)
+{
+	int i = 0;
+
+	i2c_w8(gspca_dev, mt9v111_sensor_init[i]);
+	i++;
+	msleep(20);
+	while (mt9v111_sensor_init[i][0]) {
+		i2c_w8(gspca_dev, mt9v111_sensor_init[i]);
+		i++;
+	}
+}
+
 static void om6802_InitSensor(struct gspca_dev *gspca_dev)
 {
 	int i = 0;
@@ -1010,6 +1257,19 @@
 	}
 }
 
+static void sp80708_InitSensor(struct gspca_dev *gspca_dev)
+{
+	int i = 0;
+
+	i2c_w8(gspca_dev, sp80708_sensor_init[i]);	/* reset SCCB */
+	i++;
+	msleep(20);
+	while (sp80708_sensor_init[i][0]) {
+		i2c_w8(gspca_dev, sp80708_sensor_init[i]);
+		i++;
+	}
+}
+
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
 			const struct usb_device_id *id)
@@ -1018,7 +1278,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = ARRAY_SIZE(vga_mode);
 
@@ -1026,16 +1285,21 @@
 	sd->sensor = id->driver_info >> 8;
 	sd->i2c_base = id->driver_info;
 
-	sd->qindex = 4;			/* set the quantization table */
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->contrast = CONTRAST_DEF;
 	sd->colors = COLOR_DEF;
 	sd->blue = BLUE_BALANCE_DEF;
 	sd->red = RED_BALANCE_DEF;
+	sd->gamma = GAMMA_DEF;
 	sd->autogain = AUTOGAIN_DEF;
 	sd->ag_cnt = -1;
-	sd->vflip = VFLIP_DEF;
+	if (sd->sensor != SENSOR_OV7630)
+		sd->vflip = 0;
+	else
+		sd->vflip = 1;
 	sd->infrared = INFRARED_DEF;
+	sd->quality = QUALITY_DEF;
+	sd->jpegqual = 80;
 
 	gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
 	return 0;
@@ -1045,8 +1309,8 @@
 static int sd_init(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 regGpio[] = { 0x29, 0x74 };
-	__u8 regF1;
+	u8 regGpio[] = { 0x29, 0x74 };
+	u8 regF1;
 
 	/* setup a selector by bridge */
 	reg_w1(gspca_dev, 0xf1, 0x01);
@@ -1064,11 +1328,15 @@
 	case BRIDGE_SN9C105:
 		if (regF1 != 0x11)
 			return -ENODEV;
+		if (sd->sensor == SENSOR_MI0360)
+			mi0360_probe(gspca_dev);
 		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
 	case BRIDGE_SN9C120:
 		if (regF1 != 0x12)
 			return -ENODEV;
+		if (sd->sensor == SENSOR_MI0360)
+			mi0360_probe(gspca_dev);
 		regGpio[1] = 0x70;
 		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
@@ -1086,20 +1354,14 @@
 	return 0;
 }
 
-static unsigned int setexposure(struct gspca_dev *gspca_dev,
-				unsigned int expo)
+static u32 setexposure(struct gspca_dev *gspca_dev,
+			u32 expo)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	static const __u8 doit[] =		/* update sensor */
-		{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
-	static const __u8 sensorgo[] =		/* sensor on */
-		{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
-	static const __u8 gainMo[] =
-		{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
 
 	switch (sd->sensor) {
 	case SENSOR_HV7131R: {
-		__u8 Expodoit[] =
+		u8 Expodoit[] =
 			{ 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
 
 		Expodoit[3] = expo >> 16;
@@ -1109,8 +1371,12 @@
 		break;
 	    }
 	case SENSOR_MI0360: {
-		__u8 expoMi[] =	 /* exposure 0x0635 -> 4 fp/s 0x10 */
+		u8 expoMi[] =		/* exposure 0x0635 -> 4 fp/s 0x10 */
 			{ 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
+		static const u8 doit[] =		/* update sensor */
+			{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
+		static const u8 sensorgo[] =		/* sensor on */
+			{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
 
 		if (expo > 0x0635)
 			expo = 0x0635;
@@ -1124,10 +1390,12 @@
 		break;
 	    }
 	case SENSOR_MO4000: {
-		__u8 expoMof[] =
+		u8 expoMof[] =
 			{ 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
-		__u8 expoMo10[] =
+		u8 expoMo10[] =
 			{ 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
+		static const u8 gainMo[] =
+			{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
 
 		if (expo > 0x1fff)
 			expo = 0x1fff;
@@ -1139,14 +1407,27 @@
 				| ((expo & 0x0003) << 4);
 		i2c_w8(gspca_dev, expoMo10);
 		i2c_w8(gspca_dev, gainMo);
-		PDEBUG(D_CONF, "set exposure %d",
+		PDEBUG(D_FRAM, "set exposure %d",
 			((expoMo10[3] & 0x07) << 10)
 			| (expoMof[3] << 2)
 			| ((expoMo10[3] & 0x30) >> 4));
 		break;
 	    }
+	case SENSOR_MT9V111: {
+		u8 expo_c1[] =
+			{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
+
+		if (expo > 0x0280)
+			expo = 0x0280;
+		else if (expo < 0x0040)
+			expo = 0x0040;
+		expo_c1[3] = expo >> 8;
+		expo_c1[4] = expo;
+		i2c_w8(gspca_dev, expo_c1);
+		break;
+	    }
 	case SENSOR_OM6802: {
-		__u8 gainOm[] =
+		u8 gainOm[] =
 			{ 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
 
 		if (expo > 0x03ff)
@@ -1156,7 +1437,7 @@
 		gainOm[3] = expo >> 2;
 		i2c_w8(gspca_dev, gainOm);
 		reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
-		PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
+		PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
 		break;
 	    }
 	}
@@ -1167,7 +1448,7 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned int expo;
-	__u8 k2;
+	u8 k2;
 
 	k2 = ((int) sd->brightness - 0x8000) >> 10;
 	switch (sd->sensor) {
@@ -1184,6 +1465,10 @@
 		expo = sd->brightness >> 4;
 		sd->exposure = setexposure(gspca_dev, expo);
 		break;
+	case SENSOR_MT9V111:
+		expo = sd->brightness >> 8;
+		sd->exposure = setexposure(gspca_dev, expo);
+		break;
 	case SENSOR_OM6802:
 		expo = sd->brightness >> 6;
 		sd->exposure = setexposure(gspca_dev, expo);
@@ -1191,14 +1476,15 @@
 		break;
 	}
 
-	reg_w1(gspca_dev, 0x96, k2);		/* color matrix Y offset */
+	if (sd->sensor != SENSOR_MT9V111)
+		reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 k2;
-	__u8 contrast[6];
+	u8 k2;
+	u8 contrast[6];
 
 	k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10;	/* 10..40 */
 	contrast[0] = (k2 + 1) / 2;		/* red */
@@ -1214,8 +1500,8 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i, v;
-	__u8 reg8a[12];			/* U & V gains */
-	static __s16 uv[6] = {		/* same as reg84 in signed decimal */
+	u8 reg8a[12];			/* U & V gains */
+	static s16 uv[6] = {		/* same as reg84 in signed decimal */
 		-24, -38, 64,		/* UR UG UB */
 		 62, -51, -9		/* VR VG VB */
 	};
@@ -1236,22 +1522,75 @@
 	reg_w1(gspca_dev, 0x06, sd->blue);
 }
 
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i;
+	u8 gamma[17];
+	const u8 *gamma_base;
+	static const u8 delta[17] = {
+		0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
+		0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
+	};
+
+	switch (sd->sensor) {
+	case SENSOR_HV7131R:
+	case SENSOR_MT9V111:
+		gamma_base = gamma_spec_1;
+		break;
+	case SENSOR_SP80708:
+		gamma_base = gamma_spec_2;
+		break;
+	default:
+		gamma_base = gamma_def;
+		break;
+	}
+
+	for (i = 0; i < sizeof gamma; i++)
+		gamma[i] = gamma_base[i]
+			+ delta[i] * (sd->gamma - GAMMA_DEF) / 32;
+	reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
+}
+
 static void setautogain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
 		return;
+	switch (sd->sensor) {
+	case SENSOR_OV7630:
+	case SENSOR_OV7648: {
+		u8 comb;
+
+		if (sd->sensor == SENSOR_OV7630)
+			comb = 0xc0;
+		else
+			comb = 0xa0;
+		if (sd->autogain)
+			comb |= 0x02;
+		i2c_w1(&sd->gspca_dev, 0x13, comb);
+		return;
+	    }
+	}
 	if (sd->autogain)
 		sd->ag_cnt = AG_CNT_START;
 	else
 		sd->ag_cnt = -1;
 }
 
+/* ov7630/ov7648 only */
 static void setvflip(struct sd *sd)
 {
-	i2c_w1(&sd->gspca_dev, 0x75,			/* COMN */
-		sd->vflip ? 0x82 : 0x02);
+	u8 comn;
+
+	if (sd->sensor == SENSOR_OV7630)
+		comn = 0x02;
+	else
+		comn = 0x06;
+	if (sd->vflip)
+		comn |= 0x80;
+	i2c_w1(&sd->gspca_dev, 0x75, comn);
 }
 
 static void setinfrared(struct sd *sd)
@@ -1262,20 +1601,63 @@
 		sd->infrared ? 0x66 : 0x64);
 }
 
+static void setjpegqual(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i, sc;
+
+	if (sd->jpegqual < 50)
+		sc = 5000 / sd->jpegqual;
+	else
+		sc = 200 - sd->jpegqual * 2;
+#if USB_BUF_SZ < 64
+#error "No room enough in usb_buf for quantization table"
+#endif
+	for (i = 0; i < 64; i++)
+		gspca_dev->usb_buf[i] =
+			(jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+	usb_control_msg(gspca_dev->dev,
+			usb_sndctrlpipe(gspca_dev->dev, 0),
+			0x08,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			0x0100, 0,
+			gspca_dev->usb_buf, 64,
+			500);
+	for (i = 0; i < 64; i++)
+		gspca_dev->usb_buf[i] =
+			(jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+	usb_control_msg(gspca_dev->dev,
+			usb_sndctrlpipe(gspca_dev->dev, 0),
+			0x08,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+			0x0140, 0,
+			gspca_dev->usb_buf, 64,
+			500);
+
+	sd->reg18 ^= 0x40;
+	reg_w1(gspca_dev, 0x18, sd->reg18);
+}
+
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
-	__u8 reg1, reg17, reg18;
-	const __u8 *sn9c1xx;
+	u8 reg1, reg17;
+	const u8 *sn9c1xx;
 	int mode;
-	static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
-	static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
-	static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
-	static const __u8 CE_ov76xx[] =
+	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
+	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
+	static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
+	static const u8 CE_ov76xx[] =
 				{ 0x32, 0xdd, 0x32, 0xdd };
 
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x21);		/* JPEG 422 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	sn9c1xx = sn_tb[(int) sd->sensor];
 	configure_gpio(gspca_dev, sn9c1xx);
 
@@ -1292,6 +1674,9 @@
 	reg_w1(gspca_dev, 0xc9, 0x3c);
 	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
 	switch (sd->sensor) {
+	case SENSOR_MT9V111:
+		reg17 = 0xe0;
+		break;
 	case SENSOR_OV7630:
 		reg17 = 0xe2;
 		break;
@@ -1315,14 +1700,24 @@
 	reg_w1(gspca_dev, 0x07, sn9c1xx[7]);	/* green */
 	reg_w1(gspca_dev, 0x06, sn9c1xx[6]);	/* blue */
 	reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
-	reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
+
+	setgamma(gspca_dev);
+
 	for (i = 0; i < 8; i++)
 		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
 	switch (sd->sensor) {
+	case SENSOR_MT9V111:
+		reg_w1(gspca_dev, 0x9a, 0x07);
+		reg_w1(gspca_dev, 0x99, 0x59);
+		break;
 	case SENSOR_OV7648:
 		reg_w1(gspca_dev, 0x9a, 0x0a);
 		reg_w1(gspca_dev, 0x99, 0x60);
 		break;
+	case SENSOR_SP80708:
+		reg_w1(gspca_dev, 0x9a, 0x05);
+		reg_w1(gspca_dev, 0x99, 0x59);
+		break;
 	case SENSOR_OV7660:
 		if (sd->bridge == BRIDGE_SN9C120) {
 			reg_w1(gspca_dev, 0x9a, 0x05);
@@ -1358,6 +1753,15 @@
 /*			reg1 = 0x06;	 * 640 clk 24Mz (done) */
 		}
 		break;
+	case SENSOR_MT9V111:
+		mt9v111_InitSensor(gspca_dev);
+		if (mode) {
+			reg1 = 0x04;	/* 320 clk 48Mhz */
+		} else {
+/*			reg1 = 0x06;	 * 640 clk 24Mz (done) */
+			reg17 = 0xc2;
+		}
+		break;
 	case SENSOR_OM6802:
 		om6802_InitSensor(gspca_dev);
 		reg17 = 0x64;		/* 640 MCKSIZE */
@@ -1373,8 +1777,7 @@
 		reg17 = 0x21;
 /*		reg1 = 0x42;		 * 42 - 46? */
 		break;
-	default:
-/*	case SENSOR_OV7660: */
+	case SENSOR_OV7660:
 		ov7660_InitSensor(gspca_dev);
 		if (sd->bridge == BRIDGE_SN9C120) {
 			if (mode) {		/* 320x240 - 160x120 */
@@ -1387,6 +1790,16 @@
 					 * inverse power down */
 		}
 		break;
+	default:
+/*	case SENSOR_SP80708: */
+		sp80708_InitSensor(gspca_dev);
+		if (mode) {
+/*??			reg1 = 0x04;	 * 320 clk 48Mhz */
+		} else {
+			reg1 = 0x46;	 /* 640 clk 48Mz */
+			reg17 = 0xa2;
+		}
+		break;
 	}
 	reg_w(gspca_dev, 0xc0, C0, 6);
 	reg_w(gspca_dev, 0xca, CA, 4);
@@ -1403,20 +1816,13 @@
 	}
 
 	/* here change size mode 0 -> VGA; 1 -> CIF */
-	reg18 = sn9c1xx[0x18] | (mode << 4);
-	reg_w1(gspca_dev, 0x18, reg18 | 0x40);
-
-	reg_w(gspca_dev, 0x100, qtable4, 0x40);
-	reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
-
-	reg_w1(gspca_dev, 0x18, reg18);
+	sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
+	reg_w1(gspca_dev, 0x18, sd->reg18);
+	setjpegqual(gspca_dev);
 
 	reg_w1(gspca_dev, 0x17, reg17);
 	reg_w1(gspca_dev, 0x01, reg1);
 	switch (sd->sensor) {
-	case SENSOR_MI0360:
-		setinfrared(sd);
-		break;
 	case SENSOR_OV7630:
 		setvflip(sd);
 		break;
@@ -1430,14 +1836,14 @@
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	static const __u8 stophv7131[] =
+	static const u8 stophv7131[] =
 		{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
-	static const __u8 stopmi0360[] =
+	static const u8 stopmi0360[] =
 		{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
-	static const __u8 stopov7648[] =
+	static const u8 stopov7648[] =
 		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
-	__u8 data;
-	const __u8 *sn9c1xx;
+	u8 data;
+	const u8 *sn9c1xx;
 
 	data = 0x0b;
 	switch (sd->sensor) {
@@ -1452,6 +1858,7 @@
 	case SENSOR_OV7648:
 		i2c_w8(gspca_dev, stopov7648);
 		/* fall thru */
+	case SENSOR_MT9V111:
 	case SENSOR_OV7630:
 		data = 0x29;
 		break;
@@ -1468,13 +1875,20 @@
 	reg_w1(gspca_dev, 0xf1, 0x00);
 }
 
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	kfree(sd->jpeg_hdr);
+}
+
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int delta;
 	int expotimes;
-	__u8 luma_mean = 130;
-	__u8 luma_delta = 20;
+	u8 luma_mean = 130;
+	u8 luma_delta = 20;
 
 	/* Thanks S., without your advice, autobright should not work :) */
 	if (sd->ag_cnt < 0)
@@ -1499,6 +1913,7 @@
 		default:
 /*		case SENSOR_MO4000: */
 /*		case SENSOR_MI0360: */
+/*		case SENSOR_MT9V111: */
 /*		case SENSOR_OM6802: */
 			expotimes = sd->exposure;
 			expotimes += (luma_mean - delta) >> 6;
@@ -1516,7 +1931,7 @@
 /* This function is run at interrupt level. */
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
-			__u8 *data,			/* isoc packet */
+			u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1550,7 +1965,8 @@
 	if (gspca_dev->last_packet_type == LAST_PACKET) {
 
 		/* put the JPEG 422 header */
-		jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
 	}
 	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
@@ -1645,6 +2061,24 @@
 	return 0;
 }
 
+static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->gamma = val;
+	if (gspca_dev->streaming)
+		setgamma(gspca_dev);
+	return 0;
+}
+
+static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	*val = sd->gamma;
+	return 0;
+}
+
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1699,6 +2133,34 @@
 	return 0;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -1708,8 +2170,11 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
 	.dq_callback = do_autogain,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -1724,9 +2189,7 @@
 #endif
 	{USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
 	{USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
-#endif
 	{USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
 	{USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
 	{USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
@@ -1764,10 +2227,10 @@
 	{USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
 	{USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
+#endif
 	{USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
 /*	{USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
-#endif
-	{USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
+	{USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1794,8 +2257,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	info("registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 942f04c..6f38fa6 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -38,8 +38,11 @@
 	unsigned char brightness;
 	unsigned char contrast;
 	unsigned char colors;
+	u8 quality;
+#define QUALITY_MIN 70
+#define QUALITY_MAX 95
+#define QUALITY_DEF 85
 
-	char qindex;
 	char subtype;
 #define AgfaCl20 0
 #define AiptekPocketDV 1
@@ -56,6 +59,8 @@
 #define Optimedia 12
 #define PalmPixDC85 13
 #define ToptroIndus 14
+
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -629,7 +634,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	sd->subtype = id->driver_info;
 	if (sd->subtype != LogitechClickSmart310) {
 		cam->cam_mode = vga_mode;
@@ -638,10 +642,10 @@
 		cam->cam_mode = sif_mode;
 		cam->nmodes = ARRAY_SIZE(sif_mode);
 	}
-	sd->qindex = 5;
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->contrast = CONTRAST_DEF;
 	sd->colors = COLOR_DEF;
+	sd->quality = QUALITY_DEF;
 	return 0;
 }
 
@@ -667,6 +671,12 @@
 	__u8 Data;
 	__u8 xmult, ymult;
 
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x22);		/* JPEG 411 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	if (sd->subtype == LogitechClickSmart310) {
 		xmult = 0x16;
 		ymult = 0x12;
@@ -713,7 +723,8 @@
 		write_vector(gspca_dev, spca500_visual_defaults);
 		spca500_setmode(gspca_dev, xmult, ymult);
 		/* enable drop packet */
-		reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+		err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+		if (err < 0)
 			PDEBUG(D_ERR, "failed to enable drop packet");
 		reg_w(gspca_dev, 0x00, 0x8880, 3);
 		err = spca50x_setup_qtable(gspca_dev,
@@ -881,6 +892,13 @@
 		gspca_dev->usb_buf[0]);
 }
 
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	kfree(sd->jpeg_hdr);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
@@ -901,7 +919,8 @@
 					ffd9, 2);
 
 		/* put the JPEG header in the new frame */
-		jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
 
 		data += SPCA500_OFFSET_DATA;
 		len -= SPCA500_OFFSET_DATA;
@@ -937,16 +956,6 @@
 			(__u8) (sd->brightness - 128));
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int ret;
-
-	ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
-	if (ret >= 0)
-		sd->brightness = ret + 128;
-}
-
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -954,16 +963,6 @@
 	reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
 }
 
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int ret;
-
-	ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
-	if (ret >= 0)
-		sd->contrast = ret;
-}
-
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -971,16 +970,6 @@
 	reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
 }
 
-static void getcolors(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	int ret;
-
-	ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
-	if (ret >= 0)
-		sd->colors = ret;
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -995,7 +984,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -1014,7 +1002,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcontrast(gspca_dev);
 	*val = sd->contrast;
 	return 0;
 }
@@ -1033,11 +1020,38 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcolors(gspca_dev);
 	*val = sd->colors;
 	return 0;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -1047,7 +1061,10 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -1093,8 +1110,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
index 82e3e3e..d48b27c 100644
--- a/drivers/media/video/gspca/spca501.c
+++ b/drivers/media/video/gspca/spca501.c
@@ -1883,10 +1883,6 @@
 	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-}
-
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1897,10 +1893,6 @@
 				  sd->contrast & 0xff);
 }
 
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
-}
-
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1908,10 +1900,6 @@
 	reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
 }
 
-static void getcolors(struct gspca_dev *gspca_dev)
-{
-}
-
 static void setblue_balance(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1934,7 +1922,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
 	sd->subtype = id->driver_info;
@@ -2084,7 +2071,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -2103,7 +2089,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcontrast(gspca_dev);
 	*val = sd->contrast;
 	return 0;
 }
@@ -2122,7 +2107,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcolors(gspca_dev);
 	*val = sd->colors;
 	return 0;
 }
@@ -2211,8 +2195,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
index 2a33a29..2acec58 100644
--- a/drivers/media/video/gspca/spca505.c
+++ b/drivers/media/video/gspca/spca505.c
@@ -31,9 +31,9 @@
 struct sd {
 	struct gspca_dev gspca_dev;		/* !! must be the first item */
 
-	unsigned char brightness;
+	u8 brightness;
 
-	char subtype;
+	u8 subtype;
 #define IntelPCCameraPro 0
 #define Nxultra 1
 };
@@ -43,7 +43,6 @@
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
 	{
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
@@ -52,7 +51,8 @@
 		.minimum = 0,
 		.maximum = 255,
 		.step    = 1,
-		.default_value = 127,
+#define BRIGHTNESS_DEF 127
+		.default_value = BRIGHTNESS_DEF,
 	    },
 	    .set = sd_setbrightness,
 	    .get = sd_getbrightness,
@@ -64,12 +64,12 @@
 		.bytesperline = 160,
 		.sizeimage = 160 * 120 * 3 / 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 5},
+		.priv = 4},
 	{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
 		.bytesperline = 176,
 		.sizeimage = 176 * 144 * 3 / 2,
 		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 4},
+		.priv = 3},
 	{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
 		.bytesperline = 320,
 		.sizeimage = 320 * 240 * 3 / 2,
@@ -93,6 +93,7 @@
 
 #define SPCA50X_USB_CTRL 0x00	/* spca505 */
 #define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
+
 #define SPCA50X_REG_GLOBAL 0x03	/* spca505 */
 #define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
 #define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
@@ -101,230 +102,230 @@
 #define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
 #define SPCA50X_GMISC3_SAA7113RST 0x20	/* Not sure about this one spca505 */
 
+/* Image format and compression control */
+#define SPCA50X_REG_COMPRESS 0x04
+
 /*
  * Data to initialize a SPCA505. Common to the CCD and external modes
  */
-static const __u16 spca505_init_data[][3] = {
-	/* line	   bmRequest,value,index */
-	/* 1819 */
+static const u8 spca505_init_data[][3] = {
+	/* bmRequest,value,index */
 	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
 	/* Sensor reset */
-	/* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
-	/* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
+	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
+	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
 	/* Block USB reset */
-	/* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL,
-		SPCA50X_GLOBAL_MISC0},
+	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
 
-	/* 1831 */ {0x5, 0x01, 0x10},
+	{0x05, 0x01, 0x10},
 					/* Maybe power down some stuff */
-	/* 1834 */ {0x5, 0x0f, 0x11},
+	{0x05, 0x0f, 0x11},
 
 	/* Setup internal CCD  ? */
-	/* 1837 */ {0x6, 0x10, 0x08},
-	/* 1840 */ {0x6, 0x00, 0x09},
-	/* 1843 */ {0x6, 0x00, 0x0a},
-	/* 1846 */ {0x6, 0x00, 0x0b},
-	/* 1849 */ {0x6, 0x10, 0x0c},
-	/* 1852 */ {0x6, 0x00, 0x0d},
-	/* 1855 */ {0x6, 0x00, 0x0e},
-	/* 1858 */ {0x6, 0x00, 0x0f},
-	/* 1861 */ {0x6, 0x10, 0x10},
-	/* 1864 */ {0x6, 0x02, 0x11},
-	/* 1867 */ {0x6, 0x00, 0x12},
-	/* 1870 */ {0x6, 0x04, 0x13},
-	/* 1873 */ {0x6, 0x02, 0x14},
-	/* 1876 */ {0x6, 0x8a, 0x51},
-	/* 1879 */ {0x6, 0x40, 0x52},
-	/* 1882 */ {0x6, 0xb6, 0x53},
-	/* 1885 */ {0x6, 0x3d, 0x54},
+	{0x06, 0x10, 0x08},
+	{0x06, 0x00, 0x09},
+	{0x06, 0x00, 0x0a},
+	{0x06, 0x00, 0x0b},
+	{0x06, 0x10, 0x0c},
+	{0x06, 0x00, 0x0d},
+	{0x06, 0x00, 0x0e},
+	{0x06, 0x00, 0x0f},
+	{0x06, 0x10, 0x10},
+	{0x06, 0x02, 0x11},
+	{0x06, 0x00, 0x12},
+	{0x06, 0x04, 0x13},
+	{0x06, 0x02, 0x14},
+	{0x06, 0x8a, 0x51},
+	{0x06, 0x40, 0x52},
+	{0x06, 0xb6, 0x53},
+	{0x06, 0x3d, 0x54},
 	{}
 };
 
 /*
  * Data to initialize the camera using the internal CCD
  */
-static const __u16 spca505_open_data_ccd[][3] = {
-	/* line	   bmRequest,value,index */
+static const u8 spca505_open_data_ccd[][3] = {
+	/* bmRequest,value,index */
 	/* Internal CCD data set */
-	/* 1891 */ {0x3, 0x04, 0x01},
+	{0x03, 0x04, 0x01},
 	/* This could be a reset */
-	/* 1894 */ {0x3, 0x00, 0x01},
+	{0x03, 0x00, 0x01},
 
 	/* Setup compression and image registers. 0x6 and 0x7 seem to be
 	   related to H&V hold, and are resolution mode specific */
-		/* 1897 */ {0x4, 0x10, 0x01},
+		{0x04, 0x10, 0x01},
 		/* DIFF(0x50), was (0x10) */
-	/* 1900 */ {0x4, 0x00, 0x04},
-	/* 1903 */ {0x4, 0x00, 0x05},
-	/* 1906 */ {0x4, 0x20, 0x06},
-	/* 1909 */ {0x4, 0x20, 0x07},
+	{0x04, 0x00, 0x04},
+	{0x04, 0x00, 0x05},
+	{0x04, 0x20, 0x06},
+	{0x04, 0x20, 0x07},
 
-	/* 1912 */ {0x8, 0x0a, 0x00},
+	{0x08, 0x0a, 0x00},
 	/* DIFF (0x4a), was (0xa) */
 
-	/* 1915 */ {0x5, 0x00, 0x10},
-	/* 1918 */ {0x5, 0x00, 0x11},
-	/* 1921 */ {0x5, 0x00, 0x00},
+	{0x05, 0x00, 0x10},
+	{0x05, 0x00, 0x11},
+	{0x05, 0x00, 0x00},
 	/* DIFF not written */
-	/* 1924 */ {0x5, 0x00, 0x01},
+	{0x05, 0x00, 0x01},
 	/* DIFF not written */
-	/* 1927 */ {0x5, 0x00, 0x02},
+	{0x05, 0x00, 0x02},
 	/* DIFF not written */
-	/* 1930 */ {0x5, 0x00, 0x03},
+	{0x05, 0x00, 0x03},
 	/* DIFF not written */
-	/* 1933 */ {0x5, 0x00, 0x04},
+	{0x05, 0x00, 0x04},
 	/* DIFF not written */
-		/* 1936 */ {0x5, 0x80, 0x05},
+		{0x05, 0x80, 0x05},
 		/* DIFF not written */
-		/* 1939 */ {0x5, 0xe0, 0x06},
+		{0x05, 0xe0, 0x06},
 		/* DIFF not written */
-		/* 1942 */ {0x5, 0x20, 0x07},
+		{0x05, 0x20, 0x07},
 		/* DIFF not written */
-		/* 1945 */ {0x5, 0xa0, 0x08},
+		{0x05, 0xa0, 0x08},
 		/* DIFF not written */
-		/* 1948 */ {0x5, 0x0, 0x12},
+		{0x05, 0x0, 0x12},
 		/* DIFF not written */
-	/* 1951 */ {0x5, 0x02, 0x0f},
+	{0x05, 0x02, 0x0f},
 	/* DIFF not written */
-		/* 1954 */ {0x5, 0x10, 0x46},
+		{0x05, 0x10, 0x46},
 		/* DIFF not written */
-		/* 1957 */ {0x5, 0x8, 0x4a},
+		{0x05, 0x8, 0x4a},
 		/* DIFF not written */
 
-	/* 1960 */ {0x3, 0x08, 0x03},
+	{0x03, 0x08, 0x03},
 	/* DIFF (0x3,0x28,0x3) */
-	/* 1963 */ {0x3, 0x08, 0x01},
-	/* 1966 */ {0x3, 0x0c, 0x03},
+	{0x03, 0x08, 0x01},
+	{0x03, 0x0c, 0x03},
 	/* DIFF not written */
-		/* 1969 */ {0x3, 0x21, 0x00},
+		{0x03, 0x21, 0x00},
 		/* DIFF (0x39) */
 
 /* Extra block copied from init to hopefully ensure CCD is in a sane state */
-	/* 1837 */ {0x6, 0x10, 0x08},
-	/* 1840 */ {0x6, 0x00, 0x09},
-	/* 1843 */ {0x6, 0x00, 0x0a},
-	/* 1846 */ {0x6, 0x00, 0x0b},
-	/* 1849 */ {0x6, 0x10, 0x0c},
-	/* 1852 */ {0x6, 0x00, 0x0d},
-	/* 1855 */ {0x6, 0x00, 0x0e},
-	/* 1858 */ {0x6, 0x00, 0x0f},
-	/* 1861 */ {0x6, 0x10, 0x10},
-	/* 1864 */ {0x6, 0x02, 0x11},
-	/* 1867 */ {0x6, 0x00, 0x12},
-	/* 1870 */ {0x6, 0x04, 0x13},
-	/* 1873 */ {0x6, 0x02, 0x14},
-	/* 1876 */ {0x6, 0x8a, 0x51},
-	/* 1879 */ {0x6, 0x40, 0x52},
-	/* 1882 */ {0x6, 0xb6, 0x53},
-	/* 1885 */ {0x6, 0x3d, 0x54},
+	{0x06, 0x10, 0x08},
+	{0x06, 0x00, 0x09},
+	{0x06, 0x00, 0x0a},
+	{0x06, 0x00, 0x0b},
+	{0x06, 0x10, 0x0c},
+	{0x06, 0x00, 0x0d},
+	{0x06, 0x00, 0x0e},
+	{0x06, 0x00, 0x0f},
+	{0x06, 0x10, 0x10},
+	{0x06, 0x02, 0x11},
+	{0x06, 0x00, 0x12},
+	{0x06, 0x04, 0x13},
+	{0x06, 0x02, 0x14},
+	{0x06, 0x8a, 0x51},
+	{0x06, 0x40, 0x52},
+	{0x06, 0xb6, 0x53},
+	{0x06, 0x3d, 0x54},
 	/* End of extra block */
 
-		/* 1972 */ {0x6, 0x3f, 0x1},
+		{0x06, 0x3f, 0x1},
 		/* Block skipped */
-	/* 1975 */ {0x6, 0x10, 0x02},
-	/* 1978 */ {0x6, 0x64, 0x07},
-	/* 1981 */ {0x6, 0x10, 0x08},
-	/* 1984 */ {0x6, 0x00, 0x09},
-	/* 1987 */ {0x6, 0x00, 0x0a},
-	/* 1990 */ {0x6, 0x00, 0x0b},
-	/* 1993 */ {0x6, 0x10, 0x0c},
-	/* 1996 */ {0x6, 0x00, 0x0d},
-	/* 1999 */ {0x6, 0x00, 0x0e},
-	/* 2002 */ {0x6, 0x00, 0x0f},
-	/* 2005 */ {0x6, 0x10, 0x10},
-	/* 2008 */ {0x6, 0x02, 0x11},
-	/* 2011 */ {0x6, 0x00, 0x12},
-	/* 2014 */ {0x6, 0x04, 0x13},
-	/* 2017 */ {0x6, 0x02, 0x14},
-	/* 2020 */ {0x6, 0x8a, 0x51},
-	/* 2023 */ {0x6, 0x40, 0x52},
-	/* 2026 */ {0x6, 0xb6, 0x53},
-	/* 2029 */ {0x6, 0x3d, 0x54},
-	/* 2032 */ {0x6, 0x60, 0x57},
-	/* 2035 */ {0x6, 0x20, 0x58},
-	/* 2038 */ {0x6, 0x15, 0x59},
-	/* 2041 */ {0x6, 0x05, 0x5a},
+	{0x06, 0x10, 0x02},
+	{0x06, 0x64, 0x07},
+	{0x06, 0x10, 0x08},
+	{0x06, 0x00, 0x09},
+	{0x06, 0x00, 0x0a},
+	{0x06, 0x00, 0x0b},
+	{0x06, 0x10, 0x0c},
+	{0x06, 0x00, 0x0d},
+	{0x06, 0x00, 0x0e},
+	{0x06, 0x00, 0x0f},
+	{0x06, 0x10, 0x10},
+	{0x06, 0x02, 0x11},
+	{0x06, 0x00, 0x12},
+	{0x06, 0x04, 0x13},
+	{0x06, 0x02, 0x14},
+	{0x06, 0x8a, 0x51},
+	{0x06, 0x40, 0x52},
+	{0x06, 0xb6, 0x53},
+	{0x06, 0x3d, 0x54},
+	{0x06, 0x60, 0x57},
+	{0x06, 0x20, 0x58},
+	{0x06, 0x15, 0x59},
+	{0x06, 0x05, 0x5a},
 
-	/* 2044 */ {0x5, 0x01, 0xc0},
-	/* 2047 */ {0x5, 0x10, 0xcb},
-		/* 2050 */ {0x5, 0x80, 0xc1},
+	{0x05, 0x01, 0xc0},
+	{0x05, 0x10, 0xcb},
+		{0x05, 0x80, 0xc1},
 		/* */
-		/* 2053 */ {0x5, 0x0, 0xc2},
+		{0x05, 0x0, 0xc2},
 		/* 4 was 0 */
-	/* 2056 */ {0x5, 0x00, 0xca},
-		/* 2059 */ {0x5, 0x80, 0xc1},
+	{0x05, 0x00, 0xca},
+		{0x05, 0x80, 0xc1},
 		/*  */
-	/* 2062 */ {0x5, 0x04, 0xc2},
-	/* 2065 */ {0x5, 0x00, 0xca},
-		/* 2068 */ {0x5, 0x0, 0xc1},
+	{0x05, 0x04, 0xc2},
+	{0x05, 0x00, 0xca},
+		{0x05, 0x0, 0xc1},
 		/*  */
-	/* 2071 */ {0x5, 0x00, 0xc2},
-	/* 2074 */ {0x5, 0x00, 0xca},
-		/* 2077 */ {0x5, 0x40, 0xc1},
+	{0x05, 0x00, 0xc2},
+	{0x05, 0x00, 0xca},
+		{0x05, 0x40, 0xc1},
 		/* */
-	/* 2080 */ {0x5, 0x17, 0xc2},
-	/* 2083 */ {0x5, 0x00, 0xca},
-		/* 2086 */ {0x5, 0x80, 0xc1},
+	{0x05, 0x17, 0xc2},
+	{0x05, 0x00, 0xca},
+		{0x05, 0x80, 0xc1},
 		/* */
-	/* 2089 */ {0x5, 0x06, 0xc2},
-	/* 2092 */ {0x5, 0x00, 0xca},
-		/* 2095 */ {0x5, 0x80, 0xc1},
+	{0x05, 0x06, 0xc2},
+	{0x05, 0x00, 0xca},
+		{0x05, 0x80, 0xc1},
 		/* */
-	/* 2098 */ {0x5, 0x04, 0xc2},
-	/* 2101 */ {0x5, 0x00, 0xca},
+	{0x05, 0x04, 0xc2},
+	{0x05, 0x00, 0xca},
 
-	/* 2104 */ {0x3, 0x4c, 0x3},
-	/* 2107 */ {0x3, 0x18, 0x1},
+	{0x03, 0x4c, 0x3},
+	{0x03, 0x18, 0x1},
 
-	/* 2110 */ {0x6, 0x70, 0x51},
-	/* 2113 */ {0x6, 0xbe, 0x53},
-	/* 2116 */ {0x6, 0x71, 0x57},
-	/* 2119 */ {0x6, 0x20, 0x58},
-	/* 2122 */ {0x6, 0x05, 0x59},
-	/* 2125 */ {0x6, 0x15, 0x5a},
+	{0x06, 0x70, 0x51},
+	{0x06, 0xbe, 0x53},
+	{0x06, 0x71, 0x57},
+	{0x06, 0x20, 0x58},
+	{0x06, 0x05, 0x59},
+	{0x06, 0x15, 0x5a},
 
-	/* 2128 */ {0x4, 0x00, 0x08},
+	{0x04, 0x00, 0x08},
 	/* Compress = OFF (0x1 to turn on) */
-	/* 2131 */ {0x4, 0x12, 0x09},
-	/* 2134 */ {0x4, 0x21, 0x0a},
-	/* 2137 */ {0x4, 0x10, 0x0b},
-	/* 2140 */ {0x4, 0x21, 0x0c},
-	/* 2143 */ {0x4, 0x05, 0x00},
+	{0x04, 0x12, 0x09},
+	{0x04, 0x21, 0x0a},
+	{0x04, 0x10, 0x0b},
+	{0x04, 0x21, 0x0c},
+	{0x04, 0x05, 0x00},
 	/* was 5 (Image Type ? ) */
-	/* 2146 */ {0x4, 0x00, 0x01},
+	{0x04, 0x00, 0x01},
 
-	/* 2149 */ {0x6, 0x3f, 0x01},
+	{0x06, 0x3f, 0x01},
 
-	/* 2152 */ {0x4, 0x00, 0x04},
-	/* 2155 */ {0x4, 0x00, 0x05},
-	/* 2158 */ {0x4, 0x40, 0x06},
-	/* 2161 */ {0x4, 0x40, 0x07},
+	{0x04, 0x00, 0x04},
+	{0x04, 0x00, 0x05},
+	{0x04, 0x40, 0x06},
+	{0x04, 0x40, 0x07},
 
-	/* 2164 */ {0x6, 0x1c, 0x17},
-	/* 2167 */ {0x6, 0xe2, 0x19},
-	/* 2170 */ {0x6, 0x1c, 0x1b},
-	/* 2173 */ {0x6, 0xe2, 0x1d},
-	/* 2176 */ {0x6, 0xaa, 0x1f},
-	/* 2179 */ {0x6, 0x70, 0x20},
+	{0x06, 0x1c, 0x17},
+	{0x06, 0xe2, 0x19},
+	{0x06, 0x1c, 0x1b},
+	{0x06, 0xe2, 0x1d},
+	{0x06, 0xaa, 0x1f},
+	{0x06, 0x70, 0x20},
 
-	/* 2182 */ {0x5, 0x01, 0x10},
-	/* 2185 */ {0x5, 0x00, 0x11},
-	/* 2188 */ {0x5, 0x01, 0x00},
-	/* 2191 */ {0x5, 0x05, 0x01},
-		/* 2194 */ {0x5, 0x00, 0xc1},
+	{0x05, 0x01, 0x10},
+	{0x05, 0x00, 0x11},
+	{0x05, 0x01, 0x00},
+	{0x05, 0x05, 0x01},
+		{0x05, 0x00, 0xc1},
 		/* */
-	/* 2197 */ {0x5, 0x00, 0xc2},
-	/* 2200 */ {0x5, 0x00, 0xca},
+	{0x05, 0x00, 0xc2},
+	{0x05, 0x00, 0xca},
 
-	/* 2203 */ {0x6, 0x70, 0x51},
-	/* 2206 */ {0x6, 0xbe, 0x53},
+	{0x06, 0x70, 0x51},
+	{0x06, 0xbe, 0x53},
 	{}
 };
 
 /*
-   Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
+ * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
  * SPCA505b chip based cameras initialization data
- *
  */
 /* jfm */
 #define initial_brightness 0x7f	/* 0x0(white)-0xff(black) */
@@ -332,7 +333,7 @@
 /*
  * Data to initialize a SPCA505. Common to the CCD and external modes
  */
-static const __u16 spca505b_init_data[][3] = {
+static const u8 spca505b_init_data[][3] = {
 /* start */
 	{0x02, 0x00, 0x00},		/* init */
 	{0x02, 0x00, 0x01},
@@ -396,7 +397,7 @@
 /*
  * Data to initialize the camera using the internal CCD
  */
-static const __u16 spca505b_open_data_ccd[][3] = {
+static const u8 spca505b_open_data_ccd[][3] = {
 
 /* {0x02,0x00,0x00}, */
 	{0x03, 0x04, 0x01},		/* rst */
@@ -426,7 +427,7 @@
 	{0x05, 0x00, 0x12},
 	{0x05, 0x6f, 0x00},
 	{0x05, initial_brightness >> 6, 0x00},
-	{0x05, initial_brightness << 2, 0x01},
+	{0x05, (initial_brightness << 2) & 0xff, 0x01},
 	{0x05, 0x00, 0x02},
 	{0x05, 0x01, 0x03},
 	{0x05, 0x00, 0x04},
@@ -436,7 +437,7 @@
 	{0x05, 0xa0, 0x08},
 	{0x05, 0x00, 0x12},
 	{0x05, 0x02, 0x0f},
-	{0x05, 128, 0x14},		/* max exposure off (0=on) */
+	{0x05, 0x80, 0x14},		/* max exposure off (0=on) */
 	{0x05, 0x01, 0xb0},
 	{0x05, 0x01, 0xbf},
 	{0x03, 0x02, 0x06},
@@ -560,26 +561,26 @@
 	{0x06, 0x32, 0x20},
 
 	{0x05, initial_brightness >> 6, 0x00},
-	{0x05, initial_brightness << 2, 0x01},
+	{0x05, (initial_brightness << 2) & 0xff, 0x01},
 	{0x05, 0x06, 0xc1},
 	{0x05, 0x58, 0xc2},
-	{0x05, 0x0, 0xca},
-	{0x05, 0x0, 0x11},
+	{0x05, 0x00, 0xca},
+	{0x05, 0x00, 0x11},
 	{}
 };
 
 static int reg_write(struct usb_device *dev,
-		     __u16 reg, __u16 index, __u16 value)
+		     u16 req, u16 index, u16 value)
 {
 	int ret;
 
 	ret = usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
-			reg,
+			req,
 			USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
-	PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
-		reg, index, value, ret);
+	PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
+		req, index, value, ret);
 	if (ret < 0)
 		PDEBUG(D_ERR, "reg write: error %d", ret);
 	return ret;
@@ -587,42 +588,34 @@
 
 /* returns: negative is error, pos or zero is data */
 static int reg_read(struct gspca_dev *gspca_dev,
-			__u16 reg,	/* bRequest */
-			__u16 index,	/* wIndex */
-			__u16 length)	/* wLength (1 or 2 only) */
+			u16 req,	/* bRequest */
+			u16 index)	/* wIndex */
 {
 	int ret;
 
-	gspca_dev->usb_buf[1] = 0;
 	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
-			reg,
+			req,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			(__u16) 0,		/* value */
-			(__u16) index,
-			gspca_dev->usb_buf, length,
+			0,			/* value */
+			index,
+			gspca_dev->usb_buf, 2,
 			500);			/* timeout */
-	if (ret < 0) {
-		PDEBUG(D_ERR, "reg_read err %d", ret);
-		return -1;
-	}
+	if (ret < 0)
+		return ret;
 	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
 }
 
 static int write_vector(struct gspca_dev *gspca_dev,
-			const __u16 data[][3])
+			const u8 data[][3])
 {
 	struct usb_device *dev = gspca_dev->dev;
 	int ret, i = 0;
 
-	while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
+	while (data[i][0] != 0) {
 		ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
-		if (ret < 0) {
-			PDEBUG(D_ERR,
-				"Register write failed for 0x%x,0x%x,0x%x",
-				data[i][0], data[i][1], data[i][2]);
+		if (ret < 0)
 			return ret;
-		}
 		i++;
 	}
 	return 0;
@@ -636,14 +629,13 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	sd->subtype = id->driver_info;
 	if (sd->subtype != IntelPCCameraPro)
-		cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+		cam->nmodes = ARRAY_SIZE(vga_mode);
 	else			/* no 640x480 for IntelPCCameraPro */
-		cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1;
-	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
+		cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
+	sd->brightness = BRIGHTNESS_DEF;
 
 	if (sd->subtype == Nxultra) {
 		if (write_vector(gspca_dev, spca505b_init_data))
@@ -658,81 +650,71 @@
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	struct sd *sd = (struct sd *) gspca_dev;
-	int ret;
-
-	PDEBUG(D_STREAM, "Initializing SPCA505");
-	if (sd->subtype == Nxultra)
-		write_vector(gspca_dev, spca505b_open_data_ccd);
-	else
-		write_vector(gspca_dev, spca505_open_data_ccd);
-	ret = reg_read(gspca_dev, 6, 0x16, 2);
-
-	if (ret < 0) {
-		PDEBUG(D_ERR|D_STREAM,
-		       "register read failed for after vector read err = %d",
-		       ret);
-		return -EIO;
-	}
-	PDEBUG(D_STREAM,
-		"After vector read returns : 0x%x should be 0x0101",
-		ret & 0xffff);
-
-	ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a);
-	if (ret < 0) {
-		PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d",
-		       ret);
-		return -EIO;
-	}
-	reg_write(gspca_dev->dev, 5, 0xc2, 18);
 	return 0;
 }
 
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 brightness = sd->brightness;
+
+	reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
+	reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
+}
+
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	struct usb_device *dev = gspca_dev->dev;
-	int ret;
+	int ret, mode;
+	static u8 mode_tb[][3] = {
+	/*	  r00   r06   r07	*/
+		{0x00, 0x10, 0x10},	/* 640x480 */
+		{0x01, 0x1a, 0x1a},	/* 352x288 */
+		{0x02, 0x1c, 0x1d},	/* 320x240 */
+		{0x04, 0x34, 0x34},	/* 176x144 */
+		{0x05, 0x40, 0x40}	/* 160x120 */
+	};
+
+	if (sd->subtype == Nxultra)
+		write_vector(gspca_dev, spca505b_open_data_ccd);
+	else
+		write_vector(gspca_dev, spca505_open_data_ccd);
+	ret = reg_read(gspca_dev, 0x06, 0x16);
+
+	if (ret < 0) {
+		PDEBUG(D_ERR|D_CONF,
+		       "register read failed err: %d",
+		       ret);
+		return ret;
+	}
+	if (ret != 0x0101) {
+		PDEBUG(D_ERR|D_CONF,
+			"After vector read returns 0x%04x should be 0x0101",
+			ret);
+	}
+
+	ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
+	if (ret < 0)
+		return ret;
+	reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
 
 	/* necessary because without it we can see stream
 	 * only once after loading module */
 	/* stopping usb registers Tomasz change */
-	reg_write(dev, 0x02, 0x0, 0x0);
-	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-	case 0:
-		reg_write(dev, 0x04, 0x00, 0x00);
-		reg_write(dev, 0x04, 0x06, 0x10);
-		reg_write(dev, 0x04, 0x07, 0x10);
-		break;
-	case 1:
-		reg_write(dev, 0x04, 0x00, 0x01);
-		reg_write(dev, 0x04, 0x06, 0x1a);
-		reg_write(dev, 0x04, 0x07, 0x1a);
-		break;
-	case 2:
-		reg_write(dev, 0x04, 0x00, 0x02);
-		reg_write(dev, 0x04, 0x06, 0x1c);
-		reg_write(dev, 0x04, 0x07, 0x1d);
-		break;
-	case 4:
-		reg_write(dev, 0x04, 0x00, 0x04);
-		reg_write(dev, 0x04, 0x06, 0x34);
-		reg_write(dev, 0x04, 0x07, 0x34);
-		break;
-	default:
-/*	case 5: */
-		reg_write(dev, 0x04, 0x00, 0x05);
-		reg_write(dev, 0x04, 0x06, 0x40);
-		reg_write(dev, 0x04, 0x07, 0x40);
-		break;
-	}
-/* Enable ISO packet machine - should we do this here or in ISOC init ? */
+	reg_write(dev, 0x02, 0x00, 0x00);
+
+	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+	reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
+	reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
+	reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
+
 	ret = reg_write(dev, SPCA50X_REG_USB,
 			 SPCA50X_USB_CTRL,
 			 SPCA50X_CUSB_ENABLE);
 
-/*	reg_write(dev, 0x5, 0x0, 0x0); */
-/*	reg_write(dev, 0x5, 0x0, 0x1); */
-/*	reg_write(dev, 0x5, 0x11, 0x2); */
+	setbrightness(gspca_dev);
+
 	return ret;
 }
 
@@ -750,15 +732,15 @@
 
 	/* This maybe reset or power control */
 	reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
-	reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
-	reg_write(gspca_dev->dev, 0x03, 0x00, 0x1);
-	reg_write(gspca_dev->dev, 0x05, 0x10, 0x1);
-	reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
+	reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
+	reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
+	reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
+	reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
-			__u8 *data,			/* isoc packet */
+			u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
 	switch (data[0]) {
@@ -771,7 +753,6 @@
 				data, len);
 		break;
 	case 0xff:			/* drop */
-/*		gspca_dev->last_packet_type = DISCARD_PACKET; */
 		break;
 	default:
 		data += 1;
@@ -782,24 +763,6 @@
 	}
 }
 
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	__u8 brightness = sd->brightness;
-	reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6);
-	reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2);
-
-}
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->brightness = 255
-		- ((reg_read(gspca_dev, 5, 0x01, 1) >> 2)
-			+ (reg_read(gspca_dev, 5, 0x0, 1) << 6));
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -814,7 +777,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -863,8 +825,11 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index 96e2512..3a0c893 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -193,24 +193,6 @@
 	}
 }
 
-static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg)
-{
-	int retry = 60;
-
-	reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
-	reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
-	reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002);
-	while (--retry) {
-		reg_r(gspca_dev, 0x07, 0x0003, 2);
-		if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
-			break;
-	}
-	if (retry == 0)
-		return -1;
-	reg_r(gspca_dev, 0x07, 0x0000, 1);
-	return gspca_dev->usb_buf[0];
-}
-
 static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
 				 __u16 norme,
 				 __u16 channel)
@@ -303,7 +285,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = vga_mode;
 	cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
 	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
@@ -596,13 +577,6 @@
 	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright);
-}
-
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -612,13 +586,6 @@
 	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
 }
 
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast);
-}
-
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -628,13 +595,6 @@
 	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
 }
 
-static void getcolors(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation);
-}
-
 static void sethue(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -644,13 +604,6 @@
 	spca506_WriteI2c(gspca_dev, 0x01, 0x09);
 }
 
-static void gethue(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue);
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -665,7 +618,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -684,7 +636,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcontrast(gspca_dev);
 	*val = sd->contrast;
 	return 0;
 }
@@ -703,7 +654,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcolors(gspca_dev);
 	*val = sd->colors;
 	return 0;
 }
@@ -722,7 +672,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	gethue(gspca_dev);
 	*val = sd->hue;
 	return 0;
 }
@@ -772,8 +721,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index be5d740..adacf84 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -101,8 +101,7 @@
  * Initialization data: this is the first set-up data written to the
  * device (before the open data).
  */
-static const __u16 spca508_init_data[][3] =
-#define IGN(x)			/* nothing */
+static const u16 spca508_init_data[][2] =
 {
 	/*  line   URB      value, index */
 	/* 44274  1804 */ {0x0000, 0x870b},
@@ -589,11 +588,10 @@
 	{}
 };
 
-
 /*
  * Initialization data for Intel EasyPC Camera CS110
  */
-static const __u16 spca508cs110_init_data[][3] = {
+static const u16 spca508cs110_init_data[][2] = {
 	{0x0000, 0x870b}, /* Reset CTL3 */
 	{0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
 	{0x0000, 0x8111}, /* Normal operation on reset */
@@ -677,7 +675,7 @@
 	{}
 };
 
-static const __u16 spca508_sightcam_init_data[][3] = {
+static const u16 spca508_sightcam_init_data[][2] = {
 /* This line seems to setup the frame/canvas */
 	/*368  */ {0x000f, 0x8402},
 
@@ -760,7 +758,7 @@
 	{}
 };
 
-static const __u16 spca508_sightcam2_init_data[][3] = {
+static const u16 spca508_sightcam2_init_data[][2] = {
 /* 35 */ {0x0020, 0x8112},
 
 /* 36 */ {0x000f, 0x8402},
@@ -1107,7 +1105,7 @@
 /*
  * Initialization data for Creative Webcam Vista
  */
-static const __u16 spca508_vista_init_data[][3] = {
+static const u16 spca508_vista_init_data[][2] = {
 	{0x0008, 0x8200},	/* Clear register */
 	{0x0000, 0x870b},	/* Reset CTL3 */
 	{0x0020, 0x8112},	/* Video Drop packet enable */
@@ -1309,18 +1307,18 @@
 
 	{0x0050, 0x8703},
 	{0x0002, 0x8704},	/* External input CKIx1 */
-	{0x0001, 0x870C},	/* Select CKOx2 output */
-	{0x009A, 0x8600},	/* Line memory Read Counter (L) */
+	{0x0001, 0x870c},	/* Select CKOx2 output */
+	{0x009a, 0x8600},	/* Line memory Read Counter (L) */
 	{0x0001, 0x8606},  /* 1 Line memory Read Counter (H) Result: (d)410 */
 	{0x0023, 0x8601},
 	{0x0010, 0x8602},
-	{0x000A, 0x8603},
+	{0x000a, 0x8603},
 	{0x009A, 0x8600},
-	{0x0001, 0x865B},	/* 1 Horizontal Offset for Valid Pixel(L) */
-	{0x0003, 0x865C},	/* Vertical offset for valid lines (L) */
-	{0x0058, 0x865D},	/* Horizontal valid pixels window (L) */
-	{0x0048, 0x865E},	/* Vertical valid lines window (L) */
-	{0x0000, 0x865F},
+	{0x0001, 0x865b},	/* 1 Horizontal Offset for Valid Pixel(L) */
+	{0x0003, 0x865c},	/* Vertical offset for valid lines (L) */
+	{0x0058, 0x865d},	/* Horizontal valid pixels window (L) */
+	{0x0048, 0x865e},	/* Vertical valid lines window (L) */
+	{0x0000, 0x865f},
 
 	{0x0006, 0x8660},
 		    /* Enable nibble data input, select nibble input order */
@@ -1328,63 +1326,63 @@
 	{0x0013, 0x8608},	/* A11 Coeficients for color correction */
 	{0x0028, 0x8609},
 		    /* Note: these values are confirmed at the end of array */
-	{0x0005, 0x860A},	/* ... */
-	{0x0025, 0x860B},
-	{0x00E1, 0x860C},
-	{0x00FA, 0x860D},
-	{0x00F4, 0x860E},
-	{0x00E8, 0x860F},
+	{0x0005, 0x860a},	/* ... */
+	{0x0025, 0x860b},
+	{0x00e1, 0x860c},
+	{0x00fa, 0x860D},
+	{0x00f4, 0x860e},
+	{0x00e8, 0x860f},
 	{0x0025, 0x8610},	/* A33 Coef. */
-	{0x00FC, 0x8611},	/* White balance offset: R */
+	{0x00fc, 0x8611},	/* White balance offset: R */
 	{0x0001, 0x8612},	/* White balance offset: Gr */
-	{0x00FE, 0x8613},	/* White balance offset: B */
+	{0x00fe, 0x8613},	/* White balance offset: B */
 	{0x0000, 0x8614},	/* White balance offset: Gb */
 
 	{0x0064, 0x8651},	/* R gain for white balance (L) */
 	{0x0040, 0x8652},	/* Gr gain for white balance (L) */
 	{0x0066, 0x8653},	/* B gain for white balance (L) */
 	{0x0040, 0x8654},	/* Gb gain for white balance (L) */
-	{0x0001, 0x863F},	/* Enable fixed gamma correction */
+	{0x0001, 0x863f},	/* Enable fixed gamma correction */
 
-	{0x00A1, 0x8656},	/* Size - Window1: 256x256, Window2: 128x128 */
+	{0x00a1, 0x8656},	/* Size - Window1: 256x256, Window2: 128x128 */
 	/* UV division: UV no change, Enable New edge enhancement */
 	{0x0018, 0x8657},	/* Edge gain high threshold */
 	{0x0020, 0x8658},	/* Edge gain low threshold */
 	{0x000A, 0x8659},	/* Edge bandwidth high threshold */
-	{0x0005, 0x865A},	/* Edge bandwidth low threshold */
+	{0x0005, 0x865a},	/* Edge bandwidth low threshold */
 	{0x0064, 0x8607},	/* UV filter enable */
 
 	{0x0016, 0x8660},
-	{0x0000, 0x86B0},	/* Bad pixels compensation address */
-	{0x00DC, 0x86B1},	/* X coord for bad pixels compensation (L) */
-	{0x0000, 0x86B2},
-	{0x0009, 0x86B3},	/* Y coord for bad pixels compensation (L) */
-	{0x0000, 0x86B4},
+	{0x0000, 0x86b0},	/* Bad pixels compensation address */
+	{0x00dc, 0x86b1},	/* X coord for bad pixels compensation (L) */
+	{0x0000, 0x86b2},
+	{0x0009, 0x86b3},	/* Y coord for bad pixels compensation (L) */
+	{0x0000, 0x86b4},
 
-	{0x0001, 0x86B0},
-	{0x00F5, 0x86B1},
-	{0x0000, 0x86B2},
-	{0x00C6, 0x86B3},
-	{0x0000, 0x86B4},
+	{0x0001, 0x86b0},
+	{0x00f5, 0x86b1},
+	{0x0000, 0x86b2},
+	{0x00c6, 0x86b3},
+	{0x0000, 0x86b4},
 
-	{0x0002, 0x86B0},
-	{0x001C, 0x86B1},
-	{0x0001, 0x86B2},
-	{0x00D7, 0x86B3},
-	{0x0000, 0x86B4},
+	{0x0002, 0x86b0},
+	{0x001c, 0x86b1},
+	{0x0001, 0x86b2},
+	{0x00d7, 0x86b3},
+	{0x0000, 0x86b4},
 
-	{0x0003, 0x86B0},
-	{0x001C, 0x86B1},
-	{0x0001, 0x86B2},
-	{0x00D8, 0x86B3},
-	{0x0000, 0x86B4},
+	{0x0003, 0x86b0},
+	{0x001c, 0x86b1},
+	{0x0001, 0x86b2},
+	{0x00d8, 0x86b3},
+	{0x0000, 0x86b4},
 
-	{0x0004, 0x86B0},
-	{0x001D, 0x86B1},
-	{0x0001, 0x86B2},
-	{0x00D8, 0x86B3},
-	{0x0000, 0x86B4},
-	{0x001E, 0x8660},
+	{0x0004, 0x86b0},
+	{0x001d, 0x86b1},
+	{0x0001, 0x86b2},
+	{0x00d8, 0x86b3},
+	{0x0000, 0x86b4},
+	{0x001e, 0x8660},
 
 	/* READ { 0, 0x0000, 0x8608 } ->
 		0000: 13  */
@@ -1449,7 +1447,7 @@
 }
 
 static int write_vector(struct gspca_dev *gspca_dev,
-			const __u16 data[][3])
+			const u16 data[][2])
 {
 	struct usb_device *dev = gspca_dev->dev;
 	int ret, i = 0;
@@ -1487,7 +1485,6 @@
 	PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	cam->cam_mode = sif_mode;
 	cam->nmodes = ARRAY_SIZE(sif_mode);
 
@@ -1593,13 +1590,6 @@
 	reg_write(gspca_dev->dev, 0x8654, brightness);
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->brightness = reg_read(gspca_dev, 0x8651);
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1614,7 +1604,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -1666,8 +1655,11 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index 3c92880..c99c5e3 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -141,38 +141,38 @@
 #define SPCA561_OFFSET_WIN1GBAVE 14
 #define SPCA561_OFFSET_FREQ 15
 #define SPCA561_OFFSET_VSYNC 16
-#define SPCA561_OFFSET_DATA 1
 #define SPCA561_INDEX_I2C_BASE 0x8800
 #define SPCA561_SNAPBIT 0x20
 #define SPCA561_SNAPCTRL 0x40
 
-static const __u16 rev72a_init_data1[][2] = {
+static const u16 rev72a_reset[][2] = {
 	{0x0000, 0x8114},	/* Software GPIO output data */
 	{0x0001, 0x8114},	/* Software GPIO output data */
 	{0x0000, 0x8112},	/* Some kind of reset */
+	{}
+};
+static const __u16 rev72a_init_data1[][2] = {
 	{0x0003, 0x8701},	/* PCLK clock delay adjustment */
 	{0x0001, 0x8703},	/* HSYNC from cmos inverted */
 	{0x0011, 0x8118},	/* Enable and conf sensor */
 	{0x0001, 0x8118},	/* Conf sensor */
 	{0x0092, 0x8804},	/* I know nothing about these */
 	{0x0010, 0x8802},	/* 0x88xx registers, so I won't */
-	{0x000d, 0x8805},	/* sensor default setting */
 	{}
 };
-static const __u16 rev72a_init_sensor1[][2] = {
-				/* ms-win values */
-	{0x0001, 0x0018},	/* 0x01 <- 0x0d */
-	{0x0002, 0x0065},	/* 0x02 <- 0x18 */
-	{0x0004, 0x0121},	/* 0x04 <- 0x0165 */
-	{0x0005, 0x00aa},	/* 0x05 <- 0x21 */
-	{0x0007, 0x0004},	/* 0x07 <- 0xaa */
-	{0x0020, 0x1502},	/* 0x20 <- 0x1504 */
-	{0x0039, 0x0010},	/* 0x39 <- 0x02 */
-	{0x0035, 0x0049},	/* 0x35 <- 0x10 */
-	{0x0009, 0x100b},	/* 0x09 <- 0x1049 */
-	{0x0028, 0x000f},	/* 0x28 <- 0x0b */
-	{0x003b, 0x003c},	/* 0x3b <- 0x0f */
-	{0x003c, 0x0000},	/* 0x3c <- 0x00 */
+static const u16 rev72a_init_sensor1[][2] = {
+	{0x0001, 0x000d},
+	{0x0002, 0x0018},
+	{0x0004, 0x0165},
+	{0x0005, 0x0021},
+	{0x0007, 0x00aa},
+	{0x0020, 0x1504},
+	{0x0039, 0x0002},
+	{0x0035, 0x0010},
+	{0x0009, 0x1049},
+	{0x0028, 0x000b},
+	{0x003b, 0x000f},
+	{0x003c, 0x0000},
 	{}
 };
 static const __u16 rev72a_init_data2[][2] = {
@@ -190,15 +190,10 @@
 	{0x0002, 0x8201},	/* Output address for r/w serial EEPROM */
 	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */
 	{0x0001, 0x8200},	/* OprMode to be executed by hardware */
-	{0x0007, 0x8201},	/* Output address for r/w serial EEPROM */
-	{0x0008, 0x8200},	/* Clear valid bit for serial EEPROM */
-	{0x0001, 0x8200},	/* OprMode to be executed by hardware */
-	{0x0010, 0x8660},	/* Compensation memory stuff */
-	{0x0018, 0x8660},	/* Compensation memory stuff */
-
-	{0x0004, 0x8611},	/* R offset for white balance */
-	{0x0004, 0x8612},	/* Gr offset for white balance */
-	{0x0007, 0x8613},	/* B offset for white balance */
+/* from ms-win */
+	{0x0000, 0x8611},	/* R offset for white balance */
+	{0x00fd, 0x8612},	/* Gr offset for white balance */
+	{0x0003, 0x8613},	/* B offset for white balance */
 	{0x0000, 0x8614},	/* Gb offset for white balance */
 /* from ms-win */
 	{0x0035, 0x8651},	/* R gain for white balance */
@@ -206,8 +201,8 @@
 	{0x005f, 0x8653},	/* B gain for white balance */
 	{0x0040, 0x8654},	/* Gb gain for white balance */
 	{0x0002, 0x8502},	/* Maximum average bit rate stuff */
-
 	{0x0011, 0x8802},
+
 	{0x0087, 0x8700},	/* Set master clock (96Mhz????) */
 	{0x0081, 0x8702},	/* Master clock output enable */
 
@@ -218,104 +213,15 @@
 	{0x0003, 0x865c},	/* Vertical offset for valid lines */
 	{}
 };
-static const __u16 rev72a_init_sensor2[][2] = {
-				/* ms-win values */
-	{0x0003, 0x0121},	/* 0x03 <- 0x01 0x21 //289 */
-	{0x0004, 0x0165},	/* 0x04 <- 0x01 0x65 //357 */
-	{0x0005, 0x002f},	/* 0x05 <- 0x2f */
-	{0x0006, 0x0000},	/* 0x06 <- 0 */
-	{0x000a, 0x0002},	/* 0x0a <- 2 */
-	{0x0009, 0x1061},	/* 0x09 <- 0x1061 */
-	{0x0035, 0x0014},	/* 0x35 <- 0x14 */
-	{}
-};
-static const __u16 rev72a_init_data3[][2] = {
-	{0x0030, 0x8112},	/* ISO and drop packet enable */
-/*fixme: should stop here*/
-	{0x0000, 0x8112},	/* Some kind of reset ???? */
-	{0x0009, 0x8118},	/* Enable sensor and set standby */
-	{0x0000, 0x8114},	/* Software GPIO output data */
-	{0x0000, 0x8114},	/* Software GPIO output data */
-	{0x0001, 0x8114},	/* Software GPIO output data */
-	{0x0000, 0x8112},	/* Some kind of reset ??? */
-	{0x0003, 0x8701},
-	{0x0001, 0x8703},
-	{0x0011, 0x8118},
-	{0x0001, 0x8118},
-	/***************/
-	{0x0092, 0x8804},
-	{0x0010, 0x8802},
-	{0x000d, 0x8805},
-	{0x0001, 0x8801},
-	{0x0000, 0x8800},
-	{0x0018, 0x8805},
-	{0x0002, 0x8801},
-	{0x0000, 0x8800},
-	{0x0065, 0x8805},
-	{0x0004, 0x8801},
-	{0x0001, 0x8800},
-	{0x0021, 0x8805},
-	{0x0005, 0x8801},
-	{0x0000, 0x8800},
-	{0x00aa, 0x8805},
-	{0x0007, 0x8801},	/* mode 0xaa */
-	{0x0000, 0x8800},
-	{0x0004, 0x8805},
-	{0x0020, 0x8801},
-	{0x0015, 0x8800},	/* mode 0x0415 */
-	{0x0002, 0x8805},
-	{0x0039, 0x8801},
-	{0x0000, 0x8800},
-	{0x0010, 0x8805},
-	{0x0035, 0x8801},
-	{0x0000, 0x8800},
-	{0x0049, 0x8805},
-	{0x0009, 0x8801},
-	{0x0010, 0x8800},
-	{0x000b, 0x8805},
-	{0x0028, 0x8801},
-	{0x0000, 0x8800},
-	{0x000f, 0x8805},
-	{0x003b, 0x8801},
-	{0x0000, 0x8800},
-	{0x0000, 0x8805},
-	{0x003c, 0x8801},
-	{0x0000, 0x8800},
-	{0x0002, 0x8502},
-	{0x0039, 0x8801},
-	{0x0000, 0x8805},
-	{0x0000, 0x8800},
-
-	{0x0087, 0x8700},	/* overwrite by start */
-	{0x0081, 0x8702},
-	{0x0000, 0x8500},
-/*	{0x0010, 0x8500},  -- Previous line was this */
-	{0x0002, 0x865b},
-	{0x0003, 0x865c},
-	/***************/
-	{0x0003, 0x8801},	/* 0x121-> 289 */
-	{0x0021, 0x8805},
-	{0x0001, 0x8800},
-	{0x0004, 0x8801},	/* 0x165 -> 357 */
-	{0x0065, 0x8805},
-	{0x0001, 0x8800},
-	{0x0005, 0x8801},	/* 0x2f //blanking control colonne */
-	{0x002f, 0x8805},
-	{0x0000, 0x8800},
-	{0x0006, 0x8801},	/* 0x00 //blanking mode row */
-	{0x0000, 0x8805},
-	{0x0000, 0x8800},
-	{0x000a, 0x8801},	/* 0x01 //0x02 */
-	{0x0001, 0x8805},
-	{0x0000, 0x8800},
-	{0x0009, 0x8801},	/* 0x1061 - setexposure times && pixel clock
+static const u16 rev72a_init_sensor2[][2] = {
+	{0x0003, 0x0121},
+	{0x0004, 0x0165},
+	{0x0005, 0x002f},	/* blanking control column */
+	{0x0006, 0x0000},	/* blanking mode row*/
+	{0x000a, 0x0002},
+	{0x0009, 0x1061},	/* setexposure times && pixel clock
 				 * 0001 0 | 000 0110 0001 */
-	{0x0061, 0x8805},	/* 61 31 */
-	{0x0008, 0x8800},	/* 08 */
-	{0x0035, 0x8801},	/* 0x14 - set gain general */
-	{0x001f, 0x8805},	/* 0x14 */
-	{0x0000, 0x8800},
-	{0x000e, 0x8112},	/* white balance - was 30 */
+	{0x0035, 0x0014},
 	{}
 };
 
@@ -460,6 +366,7 @@
 		reg_r(gspca_dev, 0x8803, 1);
 		if (!gspca_dev->usb_buf[0])
 			return;
+		msleep(10);
 	} while (--retry);
 }
 
@@ -479,6 +386,7 @@
 			reg_r(gspca_dev, 0x8805, 1);
 			return ((int) value << 8) | gspca_dev->usb_buf[0];
 		}
+		msleep(10);
 	} while (--retry);
 	return -1;
 }
@@ -541,7 +449,6 @@
 	}
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 	gspca_dev->nbalt = 7 + 1;	/* choose alternate 7 first */
 
 	sd->chip_revision = id->driver_info;
@@ -572,11 +479,13 @@
 static int sd_init_72a(struct gspca_dev *gspca_dev)
 {
 	PDEBUG(D_STREAM, "Chip revision: 072a");
+	write_vector(gspca_dev, rev72a_reset);
+	msleep(200);
 	write_vector(gspca_dev, rev72a_init_data1);
 	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
 	write_vector(gspca_dev, rev72a_init_data2);
 	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
-	write_vector(gspca_dev, rev72a_init_data3);
+	reg_w_val(gspca_dev->dev, 0x8112, 0x30);
 	return 0;
 }
 
@@ -731,11 +640,18 @@
 	int Clck;
 	int mode;
 
+	write_vector(gspca_dev, rev72a_reset);
+	msleep(200);
+	write_vector(gspca_dev, rev72a_init_data1);
+	write_sensor_72a(gspca_dev, rev72a_init_sensor1);
+
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 	switch (mode) {
 	default:
-/*	case 0:
-	case 1: */
+	case 0:
+		Clck = 0x27;		/* ms-win 0x87 */
+		break;
+	case 1:
 		Clck = 0x25;
 		break;
 	case 2:
@@ -745,13 +661,14 @@
 		Clck = 0x21;
 		break;
 	}
-	reg_w_val(dev, 0x8500, mode);	/* mode */
 	reg_w_val(dev, 0x8700, Clck);	/* 0x27 clock */
-	reg_w_val(dev, 0x8112, 0x10 | 0x20);
+	reg_w_val(dev, 0x8702, 0x81);
+	reg_w_val(dev, 0x8500, mode);	/* mode */
+	write_sensor_72a(gspca_dev, rev72a_init_sensor2);
 	setcontrast(gspca_dev);
 /*	setbrightness(gspca_dev);	 * fixme: bad values */
-	setwhite(gspca_dev);
 	setautogain(gspca_dev);
+	reg_w_val(dev, 0x8112, 0x10 | 0x20);
 	return 0;
 }
 
@@ -867,12 +784,11 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	switch (data[0]) {			/* sequence number */
+	len--;
+	switch (*data++) {			/* sequence number */
 	case 0:					/* start of frame */
 		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 					data, 0);
-		data += SPCA561_OFFSET_DATA;
-		len -= SPCA561_OFFSET_DATA;
 		if (data[1] & 0x10) {
 			/* compressed bayer */
 			gspca_frame_add(gspca_dev, FIRST_PACKET,
@@ -893,8 +809,6 @@
 	case 0xff:			/* drop (empty mpackets) */
 		return;
 	}
-	data++;
-	len--;
 	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
@@ -1197,8 +1111,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
new file mode 100644
index 0000000..04e3ae5
--- /dev/null
+++ b/drivers/media/video/gspca/sq905.c
@@ -0,0 +1,456 @@
+/*
+ * SQ905 subdriver
+ *
+ * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the 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
+ */
+
+/*
+ * History and Acknowledgments
+ *
+ * The original Linux driver for SQ905 based cameras was written by
+ * Marcell Lengyel and furter developed by many other contributers
+ * and is available from http://sourceforge.net/projects/sqcam/
+ *
+ * This driver takes advantage of the reverse engineering work done for
+ * that driver and for libgphoto2 but shares no code with them.
+ *
+ * This driver has used as a base the finepix driver and other gspca
+ * based drivers and may still contain code fragments taken from those
+ * drivers.
+ */
+
+#define MODULE_NAME "sq905"
+
+#include <linux/workqueue.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
+		"Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905_CMD_TIMEOUT 500
+#define SQ905_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905_MAX_TRANSFER 0x8000
+#define FRAME_HEADER_LEN 64
+
+/* The known modes, or registers. These go in the "value" slot. */
+
+/* 00 is "none" obviously */
+
+#define SQ905_BULK_READ	0x03	/* precedes any bulk read */
+#define SQ905_COMMAND	0x06	/* precedes the command codes below */
+#define SQ905_PING	0x07	/* when reading an "idling" command */
+#define SQ905_READ_DONE 0xc0    /* ack bulk read completed */
+
+/* Any non-zero value in the bottom 2 bits of the 2nd byte of
+ * the ID appears to indicate the camera can do 640*480. If the
+ * LSB of that byte is set the image is just upside down, otherwise
+ * it is rotated 180 degrees. */
+#define SQ905_HIRES_MASK	0x00000300
+#define SQ905_ORIENTATION_MASK	0x00000100
+
+/* Some command codes. These go in the "index" slot. */
+
+#define SQ905_ID      0xf0	/* asks for model string */
+#define SQ905_CONFIG  0x20	/* gets photo alloc. table, not used here */
+#define SQ905_DATA    0x30	/* accesses photo data, not used here */
+#define SQ905_CLEAR   0xa0	/* clear everything */
+#define SQ905_CAPTURE_LOW  0x60	/* Starts capture at 160x120 */
+#define SQ905_CAPTURE_MED  0x61	/* Starts capture at 320x240 */
+#define SQ905_CAPTURE_HIGH 0x62	/* Starts capture at 640x480 (some cams only) */
+/* note that the capture command also controls the output dimensions */
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	/*
+	 * Driver stuff
+	 */
+	struct work_struct work_struct;
+	struct workqueue_struct *work_thread;
+};
+
+static struct v4l2_pix_format sq905_mode[] = {
+	{ 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 160,
+		.sizeimage = 160 * 120,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+	{ 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+	{ 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0}
+};
+
+/*
+ * Send a command to the camera.
+ */
+static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
+{
+	int ret;
+
+	gspca_dev->usb_buf[0] = '\0';
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      USB_REQ_SYNCH_FRAME,                /* request */
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
+			      SQ905_CMD_TIMEOUT);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      USB_REQ_SYNCH_FRAME,                /* request */
+			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      SQ905_PING, 0, gspca_dev->usb_buf, 1,
+			      SQ905_CMD_TIMEOUT);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "%s: usb_control_msg failed 2 (%d)",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Acknowledge the end of a frame - see warning on sq905_command.
+ */
+static int sq905_ack_frame(struct gspca_dev *gspca_dev)
+{
+	int ret;
+
+	gspca_dev->usb_buf[0] = '\0';
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      USB_REQ_SYNCH_FRAME,                /* request */
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
+			      SQ905_CMD_TIMEOUT);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ *  request and read a block of data - see warning on sq905_command.
+ */
+static int
+sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size)
+{
+	int ret;
+	int act_len;
+
+	gspca_dev->usb_buf[0] = '\0';
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      USB_REQ_SYNCH_FRAME,                /* request */
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      SQ905_BULK_READ, size, gspca_dev->usb_buf,
+			      1, SQ905_CMD_TIMEOUT);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
+		return ret;
+	}
+	ret = usb_bulk_msg(gspca_dev->dev,
+			   usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+			   data, size, &act_len, SQ905_DATA_TIMEOUT);
+
+	/* successful, it returns 0, otherwise  negative */
+	if (ret < 0 || act_len != size) {
+		PDEBUG(D_ERR, "bulk read fail (%d) len %d/%d",
+			ret, act_len, size);
+		return -EIO;
+	}
+	return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface we take the gspca
+ * usb_lock when performing USB operations. In practice the only thing we need
+ * to protect against is the usb_set_interface call that gspca makes during
+ * stream_off as the camera doesn't provide any controls that the user could try
+ * to change.
+ */
+static void sq905_dostream(struct work_struct *work)
+{
+	struct sd *dev = container_of(work, struct sd, work_struct);
+	struct gspca_dev *gspca_dev = &dev->gspca_dev;
+	struct gspca_frame *frame;
+	int bytes_left; /* bytes remaining in current frame. */
+	int data_len;   /* size to use for the next read. */
+	int header_read; /* true if we have already read the frame header. */
+	int discarding; /* true if we failed to get space for frame. */
+	int packet_type;
+	int frame_sz;
+	int ret;
+	u8 *data;
+	u8 *buffer;
+
+	buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+	mutex_lock(&gspca_dev->usb_lock);
+	if (!buffer) {
+		PDEBUG(D_ERR, "Couldn't allocate USB buffer");
+		goto quit_stream;
+	}
+
+	frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
+			+ FRAME_HEADER_LEN;
+
+	while (gspca_dev->present && gspca_dev->streaming) {
+		/* Need a short delay to ensure streaming flag was set by
+		 * gspca and to make sure gspca can grab the mutex. */
+		mutex_unlock(&gspca_dev->usb_lock);
+		msleep(1);
+
+		/* request some data and then read it until we have
+		 * a complete frame. */
+		bytes_left = frame_sz;
+		header_read = 0;
+		discarding = 0;
+
+		while (bytes_left > 0) {
+			data_len = bytes_left > SQ905_MAX_TRANSFER ?
+				SQ905_MAX_TRANSFER : bytes_left;
+			mutex_lock(&gspca_dev->usb_lock);
+			if (!gspca_dev->present)
+				goto quit_stream;
+			ret = sq905_read_data(gspca_dev, buffer, data_len);
+			if (ret < 0)
+				goto quit_stream;
+			mutex_unlock(&gspca_dev->usb_lock);
+			PDEBUG(D_STREAM,
+				"Got %d bytes out of %d for frame",
+				data_len, bytes_left);
+			bytes_left -= data_len;
+			data = buffer;
+			if (!header_read) {
+				packet_type = FIRST_PACKET;
+				/* The first 64 bytes of each frame are
+				 * a header full of FF 00 bytes */
+				data += FRAME_HEADER_LEN;
+				data_len -= FRAME_HEADER_LEN;
+				header_read = 1;
+			} else if (bytes_left == 0) {
+				packet_type = LAST_PACKET;
+			} else {
+				packet_type = INTER_PACKET;
+			}
+			frame = gspca_get_i_frame(gspca_dev);
+			if (frame && !discarding) {
+				frame = gspca_frame_add(gspca_dev, packet_type,
+						frame, data, data_len);
+				/* If entire frame fits in one packet we still
+				   need to add a LAST_PACKET */
+				if (packet_type == FIRST_PACKET &&
+				    bytes_left == 0)
+					frame = gspca_frame_add(gspca_dev,
+							LAST_PACKET,
+							frame, data, 0);
+			} else {
+				discarding = 1;
+			}
+		}
+		/* acknowledge the frame */
+		mutex_lock(&gspca_dev->usb_lock);
+		if (!gspca_dev->present)
+			goto quit_stream;
+		ret = sq905_ack_frame(gspca_dev);
+		if (ret < 0)
+			goto quit_stream;
+	}
+quit_stream:
+	/* the usb_lock is already acquired */
+	if (gspca_dev->present)
+		sq905_command(gspca_dev, SQ905_CLEAR);
+	mutex_unlock(&gspca_dev->usb_lock);
+	kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+		const struct usb_device_id *id)
+{
+	struct cam *cam = &gspca_dev->cam;
+	struct sd *dev = (struct sd *) gspca_dev;
+
+	/* We don't use the buffer gspca allocates so make it small. */
+	cam->bulk_size = 64;
+
+	INIT_WORK(&dev->work_struct, sq905_dostream);
+
+	return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *dev = (struct sd *) gspca_dev;
+
+	/* wait for the work queue to terminate */
+	mutex_unlock(&gspca_dev->usb_lock);
+	/* This waits for sq905_dostream to finish */
+	destroy_workqueue(dev->work_thread);
+	dev->work_thread = NULL;
+	mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	u32 ident;
+	int ret;
+
+	/* connect to the camera and read
+	 * the model ID and process that and put it away.
+	 */
+	ret = sq905_command(gspca_dev, SQ905_CLEAR);
+	if (ret < 0)
+		return ret;
+	ret = sq905_command(gspca_dev, SQ905_ID);
+	if (ret < 0)
+		return ret;
+	ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4);
+	if (ret < 0)
+		return ret;
+	/* usb_buf is allocated with kmalloc so is aligned.
+	 * Camera model number is the right way round if we assume this
+	 * reverse engineered ID is supposed to be big endian. */
+	ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
+	ret = sq905_command(gspca_dev, SQ905_CLEAR);
+	if (ret < 0)
+		return ret;
+	PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
+	gspca_dev->cam.cam_mode = sq905_mode;
+	gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
+	if (!(ident & SQ905_HIRES_MASK))
+		gspca_dev->cam.nmodes--;
+	return 0;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *dev = (struct sd *) gspca_dev;
+	int ret;
+
+	/* "Open the shutter" and set size, to start capture */
+	switch (gspca_dev->curr_mode) {
+	default:
+/*	case 2: */
+		PDEBUG(D_STREAM, "Start streaming at high resolution");
+		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
+		break;
+	case 1:
+		PDEBUG(D_STREAM, "Start streaming at medium resolution");
+		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
+		break;
+	case 0:
+		PDEBUG(D_STREAM, "Start streaming at low resolution");
+		ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
+	}
+
+	if (ret < 0) {
+		PDEBUG(D_ERR, "Start streaming command failed");
+		return ret;
+	}
+	/* Start the workqueue function to do the streaming */
+	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+	queue_work(dev->work_thread, &dev->work_struct);
+
+	return 0;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x2770, 0x9120)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+	.name   = MODULE_NAME,
+	.config = sd_config,
+	.init   = sd_init,
+	.start  = sd_start,
+	.stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return gspca_dev_probe(intf, id,
+			&sd_desc,
+			sizeof(struct sd),
+			THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name       = MODULE_NAME,
+	.id_table   = device_table,
+	.probe      = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume  = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
+	PDEBUG(D_PROBE, "registered");
+	return 0;
+}
+
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+	PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
new file mode 100644
index 0000000..0bcb74a
--- /dev/null
+++ b/drivers/media/video/gspca/sq905c.c
@@ -0,0 +1,328 @@
+/*
+ * SQ905C subdriver
+ *
+ * Copyright (C) 2009 Theodore Kilgore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the 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
+ */
+
+/*
+ *
+ * This driver uses work done in
+ * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
+ *
+ * This driver has also used as a base the sq905c driver
+ * and may contain code fragments from it.
+ */
+
+#define MODULE_NAME "sq905c"
+
+#include <linux/workqueue.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905C_CMD_TIMEOUT 500
+#define SQ905C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905C_MAX_TRANSFER 0x8000
+
+#define FRAME_HEADER_LEN 0x50
+
+/* Commands. These go in the "value" slot. */
+#define SQ905C_CLEAR   0xa0		/* clear everything */
+#define SQ905C_CAPTURE_LOW 0xa040	/* Starts capture at 160x120 */
+#define SQ905C_CAPTURE_MED 0x1440	/* Starts capture at 320x240 */
+#define SQ905C_CAPTURE_HI 0x2840	/* Starts capture at 320x240 */
+
+/* For capture, this must go in the "index" slot. */
+#define SQ905C_CAPTURE_INDEX 0x110f
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+	const struct v4l2_pix_format *cap_mode;
+	/* Driver stuff */
+	struct work_struct work_struct;
+	struct workqueue_struct *work_thread;
+};
+
+/*
+ * Most of these cameras will do 640x480 and 320x240. 160x120 works
+ * in theory but gives very poor output. Therefore, not supported.
+ * The 0x2770:0x9050 cameras have max resolution of 320x240.
+ */
+static struct v4l2_pix_format sq905c_mode[] = {
+	{ 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+	{ 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0}
+};
+
+/* Send a command to the camera. */
+static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
+{
+	int ret;
+
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      USB_REQ_SYNCH_FRAME,                /* request */
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      command, index, NULL, 0,
+			      SQ905C_CMD_TIMEOUT);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+static void sq905c_dostream(struct work_struct *work)
+{
+	struct sd *dev = container_of(work, struct sd, work_struct);
+	struct gspca_dev *gspca_dev = &dev->gspca_dev;
+	struct gspca_frame *frame;
+	int bytes_left; /* bytes remaining in current frame. */
+	int data_len;   /* size to use for the next read. */
+	int act_len;
+	int discarding = 0; /* true if we failed to get space for frame. */
+	int packet_type;
+	int ret;
+	u8 *buffer;
+
+	buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
+		PDEBUG(D_ERR, "Couldn't allocate USB buffer");
+		goto quit_stream;
+	}
+
+	while (gspca_dev->present && gspca_dev->streaming) {
+		if (!gspca_dev->present)
+			goto quit_stream;
+		/* Request the header, which tells the size to download */
+		ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+				buffer, FRAME_HEADER_LEN, &act_len,
+				SQ905C_DATA_TIMEOUT);
+		PDEBUG(D_STREAM,
+			"Got %d bytes out of %d for header",
+			act_len, FRAME_HEADER_LEN);
+		if (ret < 0 || act_len < FRAME_HEADER_LEN)
+			goto quit_stream;
+		/* size is read from 4 bytes starting 0x40, little endian */
+		bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
+					|(buffer[0x43]<<24);
+		PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
+		/* We keep the header. It has other information, too. */
+		packet_type = FIRST_PACKET;
+		frame = gspca_get_i_frame(gspca_dev);
+		if (frame && !discarding) {
+			gspca_frame_add(gspca_dev, packet_type,
+				frame, buffer, FRAME_HEADER_LEN);
+			} else
+				discarding = 1;
+		while (bytes_left > 0) {
+			data_len = bytes_left > SQ905C_MAX_TRANSFER ?
+				SQ905C_MAX_TRANSFER : bytes_left;
+			if (!gspca_dev->present)
+				goto quit_stream;
+			ret = usb_bulk_msg(gspca_dev->dev,
+				usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+				buffer, data_len, &act_len,
+				SQ905C_DATA_TIMEOUT);
+			if (ret < 0 || act_len < data_len)
+				goto quit_stream;
+			PDEBUG(D_STREAM,
+				"Got %d bytes out of %d for frame",
+				data_len, bytes_left);
+			bytes_left -= data_len;
+			if (bytes_left == 0)
+				packet_type = LAST_PACKET;
+			else
+				packet_type = INTER_PACKET;
+			frame = gspca_get_i_frame(gspca_dev);
+			if (frame && !discarding)
+				gspca_frame_add(gspca_dev, packet_type,
+						frame, buffer, data_len);
+			else
+				discarding = 1;
+		}
+	}
+quit_stream:
+	mutex_lock(&gspca_dev->usb_lock);
+	if (gspca_dev->present)
+		sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+	mutex_unlock(&gspca_dev->usb_lock);
+	kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+		const struct usb_device_id *id)
+{
+	struct cam *cam = &gspca_dev->cam;
+	struct sd *dev = (struct sd *) gspca_dev;
+
+	PDEBUG(D_PROBE,
+		"SQ9050 camera detected"
+		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+	cam->cam_mode = sq905c_mode;
+	cam->nmodes = 2;
+	if (id->idProduct == 0x9050)
+		cam->nmodes = 1;
+	/* We don't use the buffer gspca allocates so make it small. */
+	cam->bulk_size = 32;
+	INIT_WORK(&dev->work_struct, sq905c_dostream);
+	return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *dev = (struct sd *) gspca_dev;
+
+	/* wait for the work queue to terminate */
+	mutex_unlock(&gspca_dev->usb_lock);
+	/* This waits for sq905c_dostream to finish */
+	destroy_workqueue(dev->work_thread);
+	dev->work_thread = NULL;
+	mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	int ret;
+
+	/* connect to the camera and reset it. */
+	ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+	return ret;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *dev = (struct sd *) gspca_dev;
+	int ret;
+
+	dev->cap_mode = gspca_dev->cam.cam_mode;
+	/* "Open the shutter" and set size, to start capture */
+	switch (gspca_dev->width) {
+	case 640:
+		PDEBUG(D_STREAM, "Start streaming at high resolution");
+		dev->cap_mode++;
+		ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
+						SQ905C_CAPTURE_INDEX);
+		break;
+	default: /* 320 */
+	PDEBUG(D_STREAM, "Start streaming at medium resolution");
+		ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
+						SQ905C_CAPTURE_INDEX);
+	}
+
+	if (ret < 0) {
+		PDEBUG(D_ERR, "Start streaming command failed");
+		return ret;
+	}
+	/* Start the workqueue function to do the streaming */
+	dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+	queue_work(dev->work_thread, &dev->work_struct);
+
+	return 0;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x2770, 0x905c)},
+	{USB_DEVICE(0x2770, 0x9050)},
+	{USB_DEVICE(0x2770, 0x913d)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+	.name   = MODULE_NAME,
+	.config = sd_config,
+	.init   = sd_init,
+	.start  = sd_start,
+	.stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return gspca_dev_probe(intf, id,
+			&sd_desc,
+			sizeof(struct sd),
+			THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+	.name       = MODULE_NAME,
+	.id_table   = device_table,
+	.probe      = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume  = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
+	PDEBUG(D_PROBE, "registered");
+	return 0;
+}
+
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+	PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index 60de9af..f25be20 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -35,10 +35,13 @@
 	unsigned char contrast;
 	unsigned char colors;
 	unsigned char lightfreq;
-};
+	u8 quality;
+#define QUALITY_MIN 60
+#define QUALITY_MAX 95
+#define QUALITY_DEF 80
 
-/* global parameters */
-static int sd_quant = 7;		/* <= 4 KO - 7: good (enough!) */
+	u8 *jpeg_hdr;
+};
 
 /* V4L2 controls supported by the driver */
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
@@ -180,7 +183,7 @@
 	reg_w(gspca_dev, 0x63b, 0);
 	reg_w(gspca_dev, 0x630, 5);
 	ret = usb_bulk_msg(dev,
-			usb_rcvbulkpipe(dev, 5),
+			usb_rcvbulkpipe(dev, 0x05),
 			gspca_dev->usb_buf,
 			4,		/* length */
 			&alen,
@@ -294,15 +297,14 @@
 			const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam = &gspca_dev->cam;
 
-	cam->epaddr = 0x02;
 	gspca_dev->cam.cam_mode = vga_mode;
 	gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
 	sd->brightness = BRIGHTNESS_DEF;
 	sd->contrast = CONTRAST_DEF;
 	sd->colors = COLOR_DEF;
 	sd->lightfreq = FREQ_DEF;
+	sd->quality = QUALITY_DEF;
 	return 0;
 }
 
@@ -326,8 +328,15 @@
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	int ret, value;
 
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x22);		/* JPEG 411 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	/* work on alternate 1 */
 	usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 
@@ -399,11 +408,19 @@
 	PDEBUG(D_STREAM, "camera stopped");
 }
 
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	kfree(sd->jpeg_hdr);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	static unsigned char ffd9[] = {0xff, 0xd9};
 
 	/* a frame starts with:
@@ -420,7 +437,8 @@
 					ffd9, 2);
 
 		/* put the JPEG 411 header */
-		jpeg_put_header(gspca_dev, frame, sd_quant, 0x22);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
 
 		/* beginning of the frame */
 #define STKHDRSZ 12
@@ -520,6 +538,34 @@
 	return -EINVAL;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -529,8 +575,11 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
 	.querymenu = sd_querymenu,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -562,8 +611,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	info("registered");
 	return 0;
 }
@@ -575,6 +626,3 @@
 
 module_init(sd_mod_init);
 module_exit(sd_mod_exit);
-
-module_param_named(quant, sd_quant, int, 0644);
-MODULE_PARM_DESC(quant, "Quantization index (0..8)");
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index 13a021e..9dff2e6 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -429,7 +429,6 @@
 	PDEBUG(D_PROBE, "Configuring camera");
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = STV_ISOC_ENDPOINT_ADDR;
 	sd->desc = sd_desc;
 	gspca_dev->sd_desc = &sd->desc;
 
@@ -501,8 +500,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
index 14335a9..b169038 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -30,6 +30,66 @@
 
 #include "stv06xx_hdcs.h"
 
+static const struct ctrl hdcs1x00_ctrl[] = {
+	{
+		{
+			.id		= V4L2_CID_EXPOSURE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "exposure",
+			.minimum	= 0x00,
+			.maximum	= 0xffff,
+			.step		= 0x1,
+			.default_value 	= HDCS_DEFAULT_EXPOSURE,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = hdcs_set_exposure,
+		.get = hdcs_get_exposure
+	}, {
+		{
+			.id		= V4L2_CID_GAIN,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "gain",
+			.minimum	= 0x00,
+			.maximum	= 0xff,
+			.step		= 0x1,
+			.default_value 	= HDCS_DEFAULT_GAIN,
+			.flags         	= V4L2_CTRL_FLAG_SLIDER
+		},
+		.set = hdcs_set_gain,
+		.get = hdcs_get_gain
+	}
+};
+
+static struct v4l2_pix_format hdcs1x00_mode[] = {
+	{
+		HDCS_1X00_DEF_WIDTH,
+		HDCS_1X00_DEF_HEIGHT,
+		V4L2_PIX_FMT_SBGGR8,
+		V4L2_FIELD_NONE,
+		.sizeimage =
+			HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
+		.bytesperline = HDCS_1X00_DEF_WIDTH,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1
+	}
+};
+
+static const struct ctrl hdcs1020_ctrl[] = {};
+
+static struct v4l2_pix_format hdcs1020_mode[] = {
+	{
+		HDCS_1020_DEF_WIDTH,
+		HDCS_1020_DEF_HEIGHT,
+		V4L2_PIX_FMT_SBGGR8,
+		V4L2_FIELD_NONE,
+		.sizeimage =
+			HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
+		.bytesperline = HDCS_1020_DEF_WIDTH,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1
+	}
+};
+
 enum hdcs_power_state {
 	HDCS_STATE_SLEEP,
 	HDCS_STATE_IDLE,
@@ -353,10 +413,10 @@
 
 	info("HDCS-1000/1100 sensor detected");
 
-	sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1x00.modes;
-	sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1x00.nmodes;
-	sd->desc.ctrls = stv06xx_sensor_hdcs1x00.ctrls;
-	sd->desc.nctrls = stv06xx_sensor_hdcs1x00.nctrls;
+	sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
+	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
+	sd->desc.ctrls = hdcs1x00_ctrl;
+	sd->desc.nctrls = ARRAY_SIZE(hdcs1x00_ctrl);
 
 	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
 	if (!hdcs)
@@ -412,10 +472,10 @@
 
 	info("HDCS-1020 sensor detected");
 
-	sd->gspca_dev.cam.cam_mode = stv06xx_sensor_hdcs1020.modes;
-	sd->gspca_dev.cam.nmodes = stv06xx_sensor_hdcs1020.nmodes;
-	sd->desc.ctrls = stv06xx_sensor_hdcs1020.ctrls;
-	sd->desc.nctrls = stv06xx_sensor_hdcs1020.nctrls;
+	sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
+	sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
+	sd->desc.ctrls = hdcs1020_ctrl;
+	sd->desc.nctrls = ARRAY_SIZE(hdcs1020_ctrl);
 
 	hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
 	if (!hdcs)
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
index 9c7279a..412f06c 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
@@ -152,53 +152,6 @@
 	.stop = hdcs_stop,
 	.disconnect = hdcs_disconnect,
 	.dump = hdcs_dump,
-
-	.nctrls = 2,
-	.ctrls = {
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "exposure",
-			.minimum	= 0x00,
-			.maximum	= 0xffff,
-			.step		= 0x1,
-			.default_value 	= HDCS_DEFAULT_EXPOSURE,
-			.flags         	= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = hdcs_set_exposure,
-		.get = hdcs_get_exposure
-	},
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "gain",
-			.minimum	= 0x00,
-			.maximum	= 0xff,
-			.step		= 0x1,
-			.default_value 	= HDCS_DEFAULT_GAIN,
-			.flags         	= V4L2_CTRL_FLAG_SLIDER
-		},
-		.set = hdcs_set_gain,
-		.get = hdcs_get_gain
-	}
-	},
-
-	.nmodes = 1,
-	.modes = {
-	{
-		HDCS_1X00_DEF_WIDTH,
-		HDCS_1X00_DEF_HEIGHT,
-		V4L2_PIX_FMT_SBGGR8,
-		V4L2_FIELD_NONE,
-		.sizeimage =
-			HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
-		.bytesperline = HDCS_1X00_DEF_WIDTH,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1
-	}
-	}
 };
 
 const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
@@ -207,29 +160,11 @@
 	.i2c_addr = (0x55 << 1),
 	.i2c_len = 1,
 
-	.nctrls = 0,
-	.ctrls = {},
-
 	.init = hdcs_init,
 	.probe = hdcs_probe_1020,
 	.start = hdcs_start,
 	.stop = hdcs_stop,
 	.dump = hdcs_dump,
-
-	.nmodes = 1,
-	.modes = {
-	{
-		HDCS_1020_DEF_WIDTH,
-		HDCS_1020_DEF_HEIGHT,
-		V4L2_PIX_FMT_SBGGR8,
-		V4L2_FIELD_NONE,
-		.sizeimage =
-			HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
-		.bytesperline = HDCS_1020_DEF_WIDTH,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 1
-	}
-	}
 };
 
 static const u16 stv_bridge_init[][2] = {
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
index d0a0f85..285221e 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -46,6 +46,132 @@
 
 #include "stv06xx_pb0100.h"
 
+static const struct ctrl pb0100_ctrl[] = {
+#define GAIN_IDX 0
+	{
+		{
+			.id		= V4L2_CID_GAIN,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Gain",
+			.minimum	= 0,
+			.maximum	= 255,
+			.step		= 1,
+			.default_value  = 128
+		},
+		.set = pb0100_set_gain,
+		.get = pb0100_get_gain
+	},
+#define RED_BALANCE_IDX 1
+	{
+		{
+			.id		= V4L2_CID_RED_BALANCE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Red Balance",
+			.minimum	= -255,
+			.maximum	= 255,
+			.step		= 1,
+			.default_value  = 0
+		},
+		.set = pb0100_set_red_balance,
+		.get = pb0100_get_red_balance
+	},
+#define BLUE_BALANCE_IDX 2
+	{
+		{
+			.id		= V4L2_CID_BLUE_BALANCE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Blue Balance",
+			.minimum	= -255,
+			.maximum	= 255,
+			.step		= 1,
+			.default_value  = 0
+		},
+		.set = pb0100_set_blue_balance,
+		.get = pb0100_get_blue_balance
+	},
+#define EXPOSURE_IDX 3
+	{
+		{
+			.id		= V4L2_CID_EXPOSURE,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Exposure",
+			.minimum	= 0,
+			.maximum	= 511,
+			.step		= 1,
+			.default_value  = 12
+		},
+		.set = pb0100_set_exposure,
+		.get = pb0100_get_exposure
+	},
+#define AUTOGAIN_IDX 4
+	{
+		{
+			.id		= V4L2_CID_AUTOGAIN,
+			.type		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name		= "Automatic Gain and Exposure",
+			.minimum	= 0,
+			.maximum	= 1,
+			.step		= 1,
+			.default_value  = 1
+		},
+		.set = pb0100_set_autogain,
+		.get = pb0100_get_autogain
+	},
+#define AUTOGAIN_TARGET_IDX 5
+	{
+		{
+			.id		= V4L2_CTRL_CLASS_USER + 0x1000,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "Automatic Gain Target",
+			.minimum	= 0,
+			.maximum	= 255,
+			.step		= 1,
+			.default_value  = 128
+		},
+		.set = pb0100_set_autogain_target,
+		.get = pb0100_get_autogain_target
+	},
+#define NATURAL_IDX 6
+	{
+		{
+			.id		= V4L2_CTRL_CLASS_USER + 0x1001,
+			.type		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name		= "Natural Light Source",
+			.minimum	= 0,
+			.maximum	= 1,
+			.step		= 1,
+			.default_value  = 1
+		},
+		.set = pb0100_set_natural,
+		.get = pb0100_get_natural
+	}
+};
+
+static struct v4l2_pix_format pb0100_mode[] = {
+/* low res / subsample modes disabled as they are only half res horizontal,
+   halving the vertical resolution does not seem to work */
+	{
+		320,
+		240,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.sizeimage = 320 * 240,
+		.bytesperline = 320,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = PB0100_CROP_TO_VGA
+	},
+	{
+		352,
+		288,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.sizeimage = 352 * 288,
+		.bytesperline = 352,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0
+	}
+};
+
 static int pb0100_probe(struct sd *sd)
 {
 	u16 sensor;
@@ -59,20 +185,19 @@
 
 	if ((sensor >> 8) == 0x64) {
 		sensor_settings = kmalloc(
-				stv06xx_sensor_pb0100.nctrls * sizeof(s32),
+				ARRAY_SIZE(pb0100_ctrl) * sizeof(s32),
 				GFP_KERNEL);
 		if (!sensor_settings)
 			return -ENOMEM;
 
 		info("Photobit pb0100 sensor detected");
 
-		sd->gspca_dev.cam.cam_mode = stv06xx_sensor_pb0100.modes;
-		sd->gspca_dev.cam.nmodes = stv06xx_sensor_pb0100.nmodes;
-		sd->desc.ctrls = stv06xx_sensor_pb0100.ctrls;
-		sd->desc.nctrls = stv06xx_sensor_pb0100.nctrls;
-		for (i = 0; i < stv06xx_sensor_pb0100.nctrls; i++)
-			sensor_settings[i] = stv06xx_sensor_pb0100.
-					     ctrls[i].qctrl.default_value;
+		sd->gspca_dev.cam.cam_mode = pb0100_mode;
+		sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
+		sd->desc.ctrls = pb0100_ctrl;
+		sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl);
+		for (i = 0; i < sd->desc.nctrls; i++)
+			sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value;
 		sd->sensor_priv = sensor_settings;
 
 		return 0;
@@ -143,6 +268,12 @@
 	return (err < 0) ? err : 0;
 }
 
+static void pb0100_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
 /* FIXME: Sort the init commands out and put them into tables,
 	  this is only for getting the camera to work */
 /* FIXME: No error handling for now,
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
index 5ea21a1..4de4fa5 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
@@ -114,6 +114,7 @@
 static int pb0100_init(struct sd *sd);
 static int pb0100_stop(struct sd *sd);
 static int pb0100_dump(struct sd *sd);
+static void pb0100_disconnect(struct sd *sd);
 
 /* V4L2 controls supported by the driver */
 static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
@@ -137,139 +138,12 @@
 	.i2c_addr = 0xba,
 	.i2c_len = 2,
 
-	.nctrls = 7,
-	.ctrls = {
-#define GAIN_IDX 0
-	{
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Gain",
-			.minimum	= 0,
-			.maximum	= 255,
-			.step		= 1,
-			.default_value  = 128
-		},
-		.set = pb0100_set_gain,
-		.get = pb0100_get_gain
-	},
-#define RED_BALANCE_IDX 1
-	{
-		{
-			.id		= V4L2_CID_RED_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Red Balance",
-			.minimum	= -255,
-			.maximum	= 255,
-			.step		= 1,
-			.default_value  = 0
-		},
-		.set = pb0100_set_red_balance,
-		.get = pb0100_get_red_balance
-	},
-#define BLUE_BALANCE_IDX 2
-	{
-		{
-			.id		= V4L2_CID_BLUE_BALANCE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Blue Balance",
-			.minimum	= -255,
-			.maximum	= 255,
-			.step		= 1,
-			.default_value  = 0
-		},
-		.set = pb0100_set_blue_balance,
-		.get = pb0100_get_blue_balance
-	},
-#define EXPOSURE_IDX 3
-	{
-		{
-			.id		= V4L2_CID_EXPOSURE,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Exposure",
-			.minimum	= 0,
-			.maximum	= 511,
-			.step		= 1,
-			.default_value  = 12
-		},
-		.set = pb0100_set_exposure,
-		.get = pb0100_get_exposure
-	},
-#define AUTOGAIN_IDX 4
-	{
-		{
-			.id		= V4L2_CID_AUTOGAIN,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "Automatic Gain and Exposure",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value  = 1
-		},
-		.set = pb0100_set_autogain,
-		.get = pb0100_get_autogain
-	},
-#define AUTOGAIN_TARGET_IDX 5
-	{
-		{
-			.id		= V4L2_CTRL_CLASS_USER + 0x1000,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "Automatic Gain Target",
-			.minimum	= 0,
-			.maximum	= 255,
-			.step		= 1,
-			.default_value  = 128
-		},
-		.set = pb0100_set_autogain_target,
-		.get = pb0100_get_autogain_target
-	},
-#define NATURAL_IDX 6
-	{
-		{
-			.id		= V4L2_CTRL_CLASS_USER + 0x1001,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "Natural Light Source",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value  = 1
-		},
-		.set = pb0100_set_natural,
-		.get = pb0100_get_natural
-	},
-	},
-
 	.init = pb0100_init,
 	.probe = pb0100_probe,
 	.start = pb0100_start,
 	.stop = pb0100_stop,
 	.dump = pb0100_dump,
-
-	.nmodes = 2,
-	.modes = {
-/* low res / subsample modes disabled as they are only half res horizontal,
-   halving the vertical resolution does not seem to work */
-	{
-		320,
-		240,
-		V4L2_PIX_FMT_SGRBG8,
-		V4L2_FIELD_NONE,
-		.sizeimage = 320 * 240,
-		.bytesperline = 320,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = PB0100_CROP_TO_VGA
-	},
-	{
-		352,
-		288,
-		V4L2_PIX_FMT_SGRBG8,
-		V4L2_FIELD_NONE,
-		.sizeimage = 352 * 288,
-		.bytesperline = 352,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0
-	},
-	}
+	.disconnect = pb0100_disconnect,
 };
 
 #endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
index c726dac..e88c42f 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
@@ -41,8 +41,6 @@
 extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
 extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
 
-#define STV06XX_MAX_CTRLS		(V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
-
 struct stv06xx_sensor {
 	/* Defines the name of a sensor */
 	char name[32];
@@ -81,12 +79,6 @@
 
 	/* Instructs the sensor to dump all its contents */
 	int (*dump)(struct sd *sd);
-
-	int nctrls;
-	struct ctrl ctrls[STV06XX_MAX_CTRLS];
-
-	char nmodes;
-	struct v4l2_pix_format modes[];
 };
 
 #endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
index 1ca91f2..69c77c9 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
@@ -29,26 +29,92 @@
 
 #include "stv06xx_vv6410.h"
 
+static struct v4l2_pix_format vv6410_mode[] = {
+	{
+		356,
+		292,
+		V4L2_PIX_FMT_SGRBG8,
+		V4L2_FIELD_NONE,
+		.sizeimage = 356 * 292,
+		.bytesperline = 356,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0
+	}
+};
+
+static const struct ctrl vv6410_ctrl[] = {
+#define HFLIP_IDX 0
+	{
+		{
+			.id		= V4L2_CID_HFLIP,
+			.type		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name		= "horizontal flip",
+			.minimum	= 0,
+			.maximum	= 1,
+			.step		= 1,
+			.default_value	= 0
+		},
+		.set = vv6410_set_hflip,
+		.get = vv6410_get_hflip
+	},
+#define VFLIP_IDX 1
+	{
+		{
+			.id		= V4L2_CID_VFLIP,
+			.type		= V4L2_CTRL_TYPE_BOOLEAN,
+			.name		= "vertical flip",
+			.minimum	= 0,
+			.maximum	= 1,
+			.step		= 1,
+			.default_value 	= 0
+		},
+		.set = vv6410_set_vflip,
+		.get = vv6410_get_vflip
+	},
+#define GAIN_IDX 2
+	{
+		{
+			.id		= V4L2_CID_GAIN,
+			.type		= V4L2_CTRL_TYPE_INTEGER,
+			.name		= "analog gain",
+			.minimum	= 0,
+			.maximum	= 15,
+			.step		= 1,
+			.default_value  = 0
+		},
+		.set = vv6410_set_analog_gain,
+		.get = vv6410_get_analog_gain
+	}
+};
+
 static int vv6410_probe(struct sd *sd)
 {
 	u16 data;
-	int err;
+	int err, i;
+	s32 *sensor_settings;
 
 	err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
-
 	if (err < 0)
 		return -ENODEV;
 
 	if (data == 0x19) {
 		info("vv6410 sensor detected");
 
-		sd->gspca_dev.cam.cam_mode = stv06xx_sensor_vv6410.modes;
-		sd->gspca_dev.cam.nmodes = stv06xx_sensor_vv6410.nmodes;
-		sd->desc.ctrls = stv06xx_sensor_vv6410.ctrls;
-		sd->desc.nctrls = stv06xx_sensor_vv6410.nctrls;
+		sensor_settings = kmalloc(ARRAY_SIZE(vv6410_ctrl) * sizeof(s32),
+					  GFP_KERNEL);
+		if (!sensor_settings)
+			return -ENOMEM;
+
+		sd->gspca_dev.cam.cam_mode = vv6410_mode;
+		sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
+		sd->desc.ctrls = vv6410_ctrl;
+		sd->desc.nctrls = ARRAY_SIZE(vv6410_ctrl);
+
+		for (i = 0; i < sd->desc.nctrls; i++)
+			sensor_settings[i] = vv6410_ctrl[i].qctrl.default_value;
+		sd->sensor_priv = sensor_settings;
 		return 0;
 	}
-
 	return -ENODEV;
 }
 
@@ -80,6 +146,12 @@
 	return (err < 0) ? err : 0;
 }
 
+static void vv6410_disconnect(struct sd *sd)
+{
+	sd->sensor = NULL;
+	kfree(sd->sensor_priv);
+}
+
 static int vv6410_start(struct sd *sd)
 {
 	int err;
@@ -156,17 +228,13 @@
 
 static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u16 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
-
-	*val = (i2c_data & VV6410_HFLIP) ? 1 : 0;
-
+	*val = sensor_settings[HFLIP_IDX];
 	PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
-	return (err < 0) ? err : 0;
+	return 0;
 }
 
 static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -174,6 +242,9 @@
 	int err;
 	u16 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[HFLIP_IDX] = val;
 	err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
 	if (err < 0)
 		return err;
@@ -191,17 +262,13 @@
 
 static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u16 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
-
-	*val = (i2c_data & VV6410_VFLIP) ? 1 : 0;
-
+	*val = sensor_settings[VFLIP_IDX];
 	PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
-	return (err < 0) ? err : 0;
+	return 0;
 }
 
 static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -209,6 +276,9 @@
 	int err;
 	u16 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
+
+	sensor_settings[VFLIP_IDX] = val;
 	err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
 	if (err < 0)
 		return err;
@@ -226,24 +296,23 @@
 
 static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val)
 {
-	int err;
-	u16 i2c_data;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
-	err = stv06xx_read_sensor(sd, VV6410_ANALOGGAIN, &i2c_data);
-
-	*val = i2c_data & 0xf;
+	*val = sensor_settings[GAIN_IDX];
 
 	PDEBUG(D_V4L2, "Read analog gain %d", *val);
 
-	return (err < 0) ? err : 0;
+	return 0;
 }
 
 static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	int err;
 	struct sd *sd = (struct sd *) gspca_dev;
+	s32 *sensor_settings = sd->sensor_priv;
 
+	sensor_settings[GAIN_IDX] = val;
 	PDEBUG(D_V4L2, "Set analog gain to %d", val);
 	err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
 
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index 3ff8c4e..95ac558 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -178,6 +178,7 @@
 static int vv6410_init(struct sd *sd);
 static int vv6410_stop(struct sd *sd);
 static int vv6410_dump(struct sd *sd);
+static void vv6410_disconnect(struct sd *sd);
 
 /* V4L2 controls supported by the driver */
 static int vv6410_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
@@ -197,62 +198,7 @@
 	.start = vv6410_start,
 	.stop = vv6410_stop,
 	.dump = vv6410_dump,
-
-	.nctrls = 3,
-	.ctrls = {
-	{
-		{
-			.id		= V4L2_CID_HFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "horizontal flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value	= 0
-		},
-		.set = vv6410_set_hflip,
-		.get = vv6410_get_hflip
-	}, {
-		{
-			.id		= V4L2_CID_VFLIP,
-			.type		= V4L2_CTRL_TYPE_BOOLEAN,
-			.name		= "vertical flip",
-			.minimum	= 0,
-			.maximum	= 1,
-			.step		= 1,
-			.default_value 	= 0
-		},
-		.set = vv6410_set_vflip,
-		.get = vv6410_get_vflip
-	}, {
-		{
-			.id		= V4L2_CID_GAIN,
-			.type		= V4L2_CTRL_TYPE_INTEGER,
-			.name		= "analog gain",
-			.minimum	= 0,
-			.maximum	= 15,
-			.step		= 1,
-			.default_value  = 0
-		},
-		.set = vv6410_set_analog_gain,
-		.get = vv6410_get_analog_gain
-	}
-	},
-
-	.nmodes = 1,
-	.modes = {
-	{
-		356,
-		292,
-		V4L2_PIX_FMT_SGRBG8,
-		V4L2_FIELD_NONE,
-		.sizeimage =
-			356 * 292,
-		.bytesperline = 356,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-		.priv = 0
-	}
-	}
+	.disconnect = vv6410_disconnect,
 };
 
 /* If NULL, only single value to write, stored in len */
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index 6d904d5..c2b8c10 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -39,8 +39,11 @@
 	unsigned char contrast;
 	unsigned char colors;
 	unsigned char autogain;
+	u8 quality;
+#define QUALITY_MIN 70
+#define QUALITY_MAX 95
+#define QUALITY_DEF 85
 
-	char qindex;
 	char bridge;
 #define BRIDGE_SPCA504 0
 #define BRIDGE_SPCA504B 1
@@ -52,6 +55,8 @@
 #define LogitechClickSmart420 2
 #define LogitechClickSmart820 3
 #define MegapixV4 4
+
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -812,7 +817,6 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 
 	sd->bridge = id->driver_info >> 8;
 	sd->subtype = id->driver_info;
@@ -850,10 +854,10 @@
 		cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
 		break;
 	}
-	sd->qindex = 5;			/* set the quantization table */
 	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
 	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
 	sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+	sd->quality = QUALITY_DEF;
 	return 0;
 }
 
@@ -970,6 +974,12 @@
 	__u8 i;
 	__u8 info[6];
 
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x22);		/* JPEG 411 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	if (sd->bridge == BRIDGE_SPCA504B)
 		spca504B_setQtable(gspca_dev);
 	spca504B_SetSizeType(gspca_dev);
@@ -1079,6 +1089,13 @@
 	}
 }
 
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	kfree(sd->jpeg_hdr);
+}
+
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
 			__u8 *data,			/* isoc packet */
@@ -1155,9 +1172,8 @@
 					ffd9, 2);
 
 		/* put the JPEG header in the new frame */
-		jpeg_put_header(gspca_dev, frame,
-				((struct sd *) gspca_dev)->qindex,
-				0x22);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
 	}
 
 	/* add 0x00 after 0xff */
@@ -1198,26 +1214,6 @@
 	}
 }
 
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-	__u16 brightness = 0;
-
-	switch (sd->bridge) {
-	default:
-/*	case BRIDGE_SPCA533: */
-/*	case BRIDGE_SPCA504B: */
-/*	case BRIDGE_SPCA504: */
-/*	case BRIDGE_SPCA504C: */
-		brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
-		break;
-	case BRIDGE_SPCA536:
-		brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
-		break;
-	}
-	sd->brightness = ((brightness & 0xff) - 128) % 255;
-}
-
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1237,24 +1233,6 @@
 	}
 }
 
-static void getcontrast(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	switch (sd->bridge) {
-	default:
-/*	case BRIDGE_SPCA533: */
-/*	case BRIDGE_SPCA504B: */
-/*	case BRIDGE_SPCA504: */
-/*	case BRIDGE_SPCA504C: */
-		sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
-		break;
-	case BRIDGE_SPCA536:
-		sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
-		break;
-	}
-}
-
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1274,24 +1252,6 @@
 	}
 }
 
-static void getcolors(struct gspca_dev *gspca_dev)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	switch (sd->bridge) {
-	default:
-/*	case BRIDGE_SPCA533: */
-/*	case BRIDGE_SPCA504B: */
-/*	case BRIDGE_SPCA504: */
-/*	case BRIDGE_SPCA504C: */
-		sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
-		break;
-	case BRIDGE_SPCA536:
-		sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
-		break;
-	}
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -1306,7 +1266,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getbrightness(gspca_dev);
 	*val = sd->brightness;
 	return 0;
 }
@@ -1325,7 +1284,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcontrast(gspca_dev);
 	*val = sd->contrast;
 	return 0;
 }
@@ -1344,7 +1302,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	getcolors(gspca_dev);
 	*val = sd->colors;
 	return 0;
 }
@@ -1365,6 +1322,34 @@
 	return 0;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -1374,7 +1359,10 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
@@ -1465,8 +1453,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
index 6ee111a..f63e37e 100644
--- a/drivers/media/video/gspca/t613.c
+++ b/drivers/media/video/gspca/t613.c
@@ -37,20 +37,21 @@
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
-	unsigned char brightness;
-	unsigned char contrast;
-	unsigned char colors;
-	unsigned char autogain;
-	unsigned char gamma;
-	unsigned char sharpness;
-	unsigned char freq;
-	unsigned char whitebalance;
-	unsigned char mirror;
-	unsigned char effect;
+	u8 brightness;
+	u8 contrast;
+	u8 colors;
+	u8 autogain;
+	u8 gamma;
+	u8 sharpness;
+	u8 freq;
+	u8 whitebalance;
+	u8 mirror;
+	u8 effect;
 
-	__u8 sensor;
-#define SENSOR_TAS5130A 0
-#define SENSOR_OM6802 1
+	u8 sensor;
+#define SENSOR_OM6802 0
+#define SENSOR_OTHER 1
+#define SENSOR_TAS5130A 2
 };
 
 /* V4L2 controls supported by the driver */
@@ -78,7 +79,6 @@
 			struct v4l2_querymenu *menu);
 
 static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
 	{
 	 {
 	  .id = V4L2_CID_BRIGHTNESS,
@@ -87,12 +87,12 @@
 	  .minimum = 0,
 	  .maximum = 14,
 	  .step = 1,
-	  .default_value = 8,
+#define BRIGHTNESS_DEF 8
+	  .default_value = BRIGHTNESS_DEF,
 	  },
 	 .set = sd_setbrightness,
 	 .get = sd_getbrightness,
 	 },
-#define SD_CONTRAST 1
 	{
 	 {
 	  .id = V4L2_CID_CONTRAST,
@@ -101,12 +101,12 @@
 	  .minimum = 0,
 	  .maximum = 0x0d,
 	  .step = 1,
-	  .default_value = 0x07,
+#define CONTRAST_DEF 0x07
+	  .default_value = CONTRAST_DEF,
 	  },
 	 .set = sd_setcontrast,
 	 .get = sd_getcontrast,
 	 },
-#define SD_COLOR 2
 	{
 	 {
 	  .id = V4L2_CID_SATURATION,
@@ -115,7 +115,8 @@
 	  .minimum = 0,
 	  .maximum = 0x0f,
 	  .step = 1,
-	  .default_value = 0x05,
+#define COLORS_DEF 0x05
+	  .default_value = COLORS_DEF,
 	  },
 	 .set = sd_setcolors,
 	 .get = sd_getcolors,
@@ -135,7 +136,6 @@
 	 .set = sd_setgamma,
 	 .get = sd_getgamma,
 	 },
-#define SD_AUTOGAIN 4
 	{
 	 {
 	  .id = V4L2_CID_GAIN,	/* here, i activate only the lowlight,
@@ -146,12 +146,12 @@
 	  .minimum = 0,
 	  .maximum = 1,
 	  .step = 1,
-	  .default_value = 0x01,
+#define AUTOGAIN_DEF 0x01
+	  .default_value = AUTOGAIN_DEF,
 	  },
 	 .set = sd_setlowlight,
 	 .get = sd_getlowlight,
 	 },
-#define SD_MIRROR 5
 	{
 	 {
 	  .id = V4L2_CID_HFLIP,
@@ -160,12 +160,12 @@
 	  .minimum = 0,
 	  .maximum = 1,
 	  .step = 1,
-	  .default_value = 0,
+#define MIRROR_DEF 0
+	  .default_value = MIRROR_DEF,
 	  },
 	 .set = sd_setflip,
 	 .get = sd_getflip
 	},
-#define SD_LIGHTFREQ 6
 	{
 	 {
 	  .id = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -174,12 +174,12 @@
 	  .minimum = 1,		/* 1 -> 0x50, 2->0x60 */
 	  .maximum = 2,
 	  .step = 1,
-	  .default_value = 1,
+#define FREQ_DEF 1
+	  .default_value = FREQ_DEF,
 	  },
 	 .set = sd_setfreq,
 	 .get = sd_getfreq},
 
-#define SD_WHITE_BALANCE 7
 	{
 	 {
 	  .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
@@ -188,12 +188,12 @@
 	  .minimum = 0,
 	  .maximum = 1,
 	  .step = 1,
-	  .default_value = 0,
+#define WHITE_BALANCE_DEF 0
+	  .default_value = WHITE_BALANCE_DEF,
 	  },
 	 .set = sd_setwhitebalance,
 	 .get = sd_getwhitebalance
 	},
-#define SD_SHARPNESS 8		/* (aka definition on win) */
 	{
 	 {
 	  .id = V4L2_CID_SHARPNESS,
@@ -202,12 +202,12 @@
 	  .minimum = 0,
 	  .maximum = 15,
 	  .step = 1,
-	  .default_value = 0x06,
+#define SHARPNESS_DEF 0x06
+	  .default_value = SHARPNESS_DEF,
 	  },
 	 .set = sd_setsharpness,
 	 .get = sd_getsharpness,
 	 },
-#define SD_EFFECTS 9
 	{
 	 {
 	  .id = V4L2_CID_EFFECTS,
@@ -216,7 +216,8 @@
 	  .minimum = 0,
 	  .maximum = 4,
 	  .step = 1,
-	  .default_value = 0,
+#define EFFECTS_DEF 0
+	  .default_value = EFFECTS_DEF,
 	  },
 	 .set = sd_seteffect,
 	 .get = sd_geteffect
@@ -263,28 +264,50 @@
 
 /* sensor specific data */
 struct additional_sensor_data {
-	const __u8 data1[20];
-	const __u8 data2[18];
-	const __u8 data3[18];
-	const __u8 data4[4];
-	const __u8 data5[6];
-	const __u8 stream[4];
+	const u8 data1[10];
+	const u8 data2[9];
+	const u8 data3[9];
+	const u8 data4[4];
+	const u8 data5[6];
+	const u8 stream[4];
 };
 
-const static struct additional_sensor_data sensor_data[] = {
+static const struct additional_sensor_data sensor_data[] = {
+    {				/* OM6802 */
+	.data1 =
+		{0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
+		 0xb3, 0xfc},
+	.data2 =
+		{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
+		 0xff},
+	.data4 =	/*Freq (50/60Hz). Splitted for test purpose */
+		{0x66, 0xca, 0xa8, 0xf0},
+	.data5 =	/* this could be removed later */
+		{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
+	.stream =
+		{0x0b, 0x04, 0x0a, 0x78},
+    },
+    {				/* OTHER */
+	.data1 =
+		{0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
+		 0xe8, 0xfc},
+	.data2 =
+		{0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
+		 0xd9},
+	.data4 =
+		{0x66, 0x00, 0xa8, 0xa8},
+	.data5 =
+		{0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
+	.stream =
+		{0x0b, 0x04, 0x0a, 0x00},
+    },
     {				/* TAS5130A */
 	.data1 =
-		{0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10,
-		 0xd4, 0xbb, 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
-		 0xd8, 0xc8, 0xd9, 0xfc},
+		{0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
+		 0xc8, 0xfc},
 	.data2 =
-		{0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60,
-		 0xe4, 0xa8, 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
-		 0xe8, 0xe0},
-	.data3 =
-		{0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60,
-		 0xcb, 0xa8, 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
-		 0xcf, 0xe0},
+		{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
+		 0xe0},
 	.data4 =	/* Freq (50/60Hz). Splitted for test purpose */
 		{0x66, 0x00, 0xa8, 0xe8},
 	.data5 =
@@ -292,32 +315,12 @@
 	.stream =
 		{0x0b, 0x04, 0x0a, 0x40},
     },
-    {				/* OM6802 */
-	.data1 =
-		{0xd0, 0xc2, 0xd1, 0x28, 0xd2, 0x0f, 0xd3, 0x22,
-		 0xd4, 0xcd, 0xd5, 0x27, 0xd6, 0x2c, 0xd7, 0x06,
-		 0xd8, 0xb3, 0xd9, 0xfc},
-	.data2 =
-		{0xe0, 0x80, 0xe1, 0xff, 0xe2, 0xff, 0xe3, 0x80,
-		 0xe4, 0xff, 0xe5, 0xff, 0xe6, 0x80, 0xe7, 0xff,
-		 0xe8, 0xff},
-	.data3 =
-		{0xc7, 0x80, 0xc8, 0xff, 0xc9, 0xff, 0xca, 0x80,
-		 0xcb, 0xff, 0xcc, 0xff, 0xcd, 0x80, 0xce, 0xff,
-		 0xcf, 0xff},
-	.data4 =	/*Freq (50/60Hz). Splitted for test purpose */
-		{0x66, 0xca, 0xa8, 0xf0 },
-	.data5 =	/* this could be removed later */
-		{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
-	.stream =
-		{0x0b, 0x04, 0x0a, 0x78},
-    }
 };
 
 #define MAX_EFFECTS 7
 /* easily done by soft, this table could be removed,
  * i keep it here just in case */
-static const __u8 effects_table[MAX_EFFECTS][6] = {
+static const u8 effects_table[MAX_EFFECTS][6] = {
 	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},	/* Normal */
 	{0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},	/* Repujar */
 	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},	/* Monochrome */
@@ -327,90 +330,58 @@
 	{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},	/* Negative */
 };
 
-static const __u8 gamma_table[GAMMA_MAX][34] = {
-	{0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,	/* 0 */
-	 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
-	 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
-	 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75,	/* 1 */
-	 0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
-	 0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
-	 0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b,	/* 2 */
-	 0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
-	 0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
-	 0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,	/* 3 */
-	 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
-	 0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
-	 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55,	/* 4 */
-	 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
-	 0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
-	 0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48,	/* 5 */
-	 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
-	 0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
-	 0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,	/* 6 */
-	 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
-	 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
-	 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,	/* 7 */
-	 0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
-	 0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
-	 0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,	/* 8 */
-	 0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
-	 0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
-	 0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,	/* 9 */
-	 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
-	 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
-	 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44,	/* 10 */
-	 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
-	 0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
-	 0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52,	/* 11 */
-	 0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
-	 0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
-	 0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e,	/* 12 */
-	 0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
-	 0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
-	 0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83,	/* 13 */
-	 0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
-	 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
-	 0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a,	/* 14 */
-	 0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
-	 0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
-	 0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
-	 0xa0, 0xff},
-	{0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7,	/* 15 */
-	 0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
-	 0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
-	 0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
-	 0xa0, 0xff}
+static const u8 gamma_table[GAMMA_MAX][17] = {
+	{0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9,	/* 0 */
+	 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
+	 0xff},
+	{0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad,	/* 1 */
+	 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
+	 0xff},
+	{0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6,	/* 2 */
+	 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
+	 0xff},
+	{0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e,	/* 3 */
+	 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
+	 0xff},
+	{0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95,	/* 4 */
+	 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
+	 0xff},
+	{0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87,	/* 5 */
+	 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
+	 0xff},
+	{0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67,	/* 6 */
+	 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
+	 0xff},
+	{0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70,	/* 7 */
+	 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
+	 0xff},
+	{0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79,	/* 8 */
+	 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
+	 0xff},
+	{0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84,	/* 9 */
+	 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
+	 0xff},
+	{0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e,	/* 10 */
+	 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
+	 0xff},
+	{0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8D, 0x9B,	/* 11 */
+	 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
+	 0xff},
+	{0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,	/* 12 */
+	 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
+	 0xff},
+	{0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,	/* 13 */
+	 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
+	 0xff},
+	{0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,	/* 14 */
+	 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
+	 0xff},
+	{0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,	/* 15 */
+	 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
+	 0xff}
 };
 
-static const __u8 tas5130a_sensor_init[][8] = {
+static const u8 tas5130a_sensor_init[][8] = {
 	{0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
 	{0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
 	{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
@@ -418,11 +389,11 @@
 	{},
 };
 
-static __u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
+static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
 
 /* read 1 byte */
-static int reg_r(struct gspca_dev *gspca_dev,
-		   __u16 index)
+static u8 reg_r(struct gspca_dev *gspca_dev,
+		   u16 index)
 {
 	usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
@@ -435,7 +406,7 @@
 }
 
 static void reg_w(struct gspca_dev *gspca_dev,
-		  __u16 index)
+		  u16 index)
 {
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
@@ -446,7 +417,7 @@
 }
 
 static void reg_w_buf(struct gspca_dev *gspca_dev,
-		  const __u8 *buffer, __u16 len)
+		  const u8 *buffer, u16 len)
 {
 	if (len <= USB_BUF_SZ) {
 		memcpy(gspca_dev->usb_buf, buffer, len);
@@ -457,7 +428,7 @@
 				0x01, 0,
 				gspca_dev->usb_buf, len, 500);
 	} else {
-		__u8 *tmpbuf;
+		u8 *tmpbuf;
 
 		tmpbuf = kmalloc(len, GFP_KERNEL);
 		memcpy(tmpbuf, buffer, len);
@@ -471,14 +442,41 @@
 	}
 }
 
+/* write values to consecutive registers */
+static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
+			u8 reg,
+			const u8 *buffer, u16 len)
+{
+	int i;
+	u8 *p, *tmpbuf;
+
+	if (len * 2 <= USB_BUF_SZ)
+		p = tmpbuf = gspca_dev->usb_buf;
+	else
+		p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
+	i = len;
+	while (--i >= 0) {
+		*p++ = reg++;
+		*p++ = *buffer++;
+	}
+	usb_control_msg(gspca_dev->dev,
+			usb_sndctrlpipe(gspca_dev->dev, 0),
+			0,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0x01, 0,
+			tmpbuf, len * 2, 500);
+	if (len * 2 > USB_BUF_SZ)
+		kfree(tmpbuf);
+}
+
 /* Reported as OM6802*/
 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
 {
 	int i;
-	const __u8 *p;
-	__u8 byte;
-	__u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
-	static const __u8 sensor_init[] = {
+	const u8 *p;
+	u8 byte;
+	u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
+	static const u8 sensor_init[] = {
 		0xdf, 0x6d,
 		0xdd, 0x18,
 		0x5a, 0xe0,
@@ -497,7 +495,7 @@
 	};
 
 	reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
-	msleep(5);
+	msleep(100);
 	i = 4;
 	while (--i > 0) {
 		byte = reg_r(gspca_dev, 0x0060);
@@ -538,20 +536,20 @@
 	struct cam *cam;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 
 	cam->cam_mode = vga_mode_t16;
 	cam->nmodes = ARRAY_SIZE(vga_mode_t16);
 
-	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
-	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
-	sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+	sd->brightness = BRIGHTNESS_DEF;
+	sd->contrast = CONTRAST_DEF;
+	sd->colors = COLORS_DEF;
 	sd->gamma = GAMMA_DEF;
-	sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
-	sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
-	sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
-	sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
-	sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
+	sd->autogain = AUTOGAIN_DEF;
+	sd->mirror = MIRROR_DEF;
+	sd->freq = FREQ_DEF;
+	sd->whitebalance = WHITE_BALANCE_DEF;
+	sd->sharpness = SHARPNESS_DEF;
+	sd->effect = EFFECTS_DEF;
 	return 0;
 }
 
@@ -559,7 +557,7 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned int brightness;
-	__u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
+	u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
 
 	brightness = sd->brightness;
 	if (brightness < 7) {
@@ -576,7 +574,7 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	unsigned int contrast = sd->contrast;
-	__u16 reg_to_write;
+	u16 reg_to_write;
 
 	if (contrast < 7)
 		reg_to_write = 0x8ea9 - contrast * 0x200;
@@ -589,7 +587,7 @@
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u16 reg_to_write;
+	u16 reg_to_write;
 
 	reg_to_write = 0x80bb + sd->colors * 0x100;	/* was 0xc0 */
 	reg_w(gspca_dev, reg_to_write);
@@ -600,14 +598,15 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 
 	PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
-	reg_w_buf(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
+	reg_w_ixbuf(gspca_dev, 0x90,
+		gamma_table[sd->gamma], sizeof gamma_table[0]);
 }
 
 static void setwhitebalance(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	__u8 white_balance[8] =
+	u8 white_balance[8] =
 		{0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
 
 	if (sd->whitebalance)
@@ -619,7 +618,7 @@
 static void setsharpness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u16 reg_to_write;
+	u16 reg_to_write;
 
 	reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
 
@@ -635,18 +634,22 @@
 	 * to see the initial parameters.*/
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
-	__u8 byte, test_byte;
+	u16 sensor_id;
+	u8 test_byte = 0;
+	u16 reg80, reg8e;
 
-	static const __u8 read_indexs[] =
-		{ 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
-		  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
-	static const __u8 n1[] =
+	static const u8 read_indexs[] =
+		{ 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
+		  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
+	static const u8 n1[] =
 			{0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
-	static const __u8 n2[] =
+	static const u8 n2[] =
 			{0x08, 0x00};
-	static const __u8 n3[] =
+	static const u8 n3[6] =
 			{0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
-	static const __u8 n4[] =
+	static const u8 n3_other[6] =
+			{0x61, 0xc2, 0x65, 0x88, 0x60, 0x00};
+	static const u8 n4[] =
 		{0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
 		 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
 		 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
@@ -656,40 +659,61 @@
 		 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
 		 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
 		 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
-	static const __u8 nset9[4] =
-			{ 0x0b, 0x04, 0x0a, 0x78 };
-	static const __u8 nset8[6] =
+	static const u8 n4_other[] =
+		{0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
+		 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
+		 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
+		 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
+		 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
+		 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
+		 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
+		 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00};
+	static const u8 nset8[6] =
 			{ 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
+	static const u8 nset8_other[6] =
+			{ 0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00 };
+	static const u8 nset9[4] =
+			{ 0x0b, 0x04, 0x0a, 0x78 };
+	static const u8 nset9_other[4] =
+			{ 0x0b, 0x04, 0x0a, 0x00 };
 
-	byte = reg_r(gspca_dev, 0x06);
-	test_byte = reg_r(gspca_dev, 0x07);
-	if (byte == 0x08 && test_byte == 0x07) {
-		PDEBUG(D_CONF, "sensor om6802");
+	sensor_id = (reg_r(gspca_dev, 0x06) << 8)
+			| reg_r(gspca_dev, 0x07);
+	switch (sensor_id & 0xff0f) {
+	case 0x0801:
+		PDEBUG(D_PROBE, "sensor tas5130a");
+		sd->sensor = SENSOR_TAS5130A;
+		break;
+	case 0x0803:
+		PDEBUG(D_PROBE, "sensor 'other'");
+		sd->sensor = SENSOR_OTHER;
+		break;
+	case 0x0807:
+		PDEBUG(D_PROBE, "sensor om6802");
 		sd->sensor = SENSOR_OM6802;
-	} else if (byte == 0x08 && test_byte == 0x01) {
-		PDEBUG(D_CONF, "sensor tas5130a");
-		sd->sensor = SENSOR_TAS5130A;
-	} else {
-		PDEBUG(D_CONF, "unknown sensor %02x %02x", byte, test_byte);
-		sd->sensor = SENSOR_TAS5130A;
+		break;
+	default:
+		PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
+		return -EINVAL;
 	}
 
-	reg_w_buf(gspca_dev, n1, sizeof n1);
-	test_byte = 0;
-	i = 5;
-	while (--i >= 0) {
-		reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
-		test_byte = reg_r(gspca_dev, 0x0063);
-		msleep(100);
-		if (test_byte == 0x17)
-			break;		/* OK */
-	}
-	if (i < 0) {
-		err("Bad sensor reset %02x", test_byte);
-/*		return -EIO; */
+	if (sd->sensor != SENSOR_OTHER) {
+		reg_w_buf(gspca_dev, n1, sizeof n1);
+		i = 5;
+		while (--i >= 0) {
+			reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+			test_byte = reg_r(gspca_dev, 0x0063);
+			msleep(100);
+			if (test_byte == 0x17)
+				break;		/* OK */
+		}
+		if (i < 0) {
+			err("Bad sensor reset %02x", test_byte);
+/*			return -EIO; */
 /*fixme: test - continue */
+		}
+		reg_w_buf(gspca_dev, n2, sizeof n2);
 	}
-	reg_w_buf(gspca_dev, n2, sizeof n2);
 
 	i = 0;
 	while (read_indexs[i] != 0x00) {
@@ -699,21 +723,31 @@
 		i++;
 	}
 
-	reg_w_buf(gspca_dev, n3, sizeof n3);
-	reg_w_buf(gspca_dev, n4, sizeof n4);
-	reg_r(gspca_dev, 0x0080);
-	reg_w(gspca_dev, 0x2c80);
+	if (sd->sensor != SENSOR_OTHER) {
+		reg_w_buf(gspca_dev, n3, sizeof n3);
+		reg_w_buf(gspca_dev, n4, sizeof n4);
+		reg_r(gspca_dev, 0x0080);
+		reg_w(gspca_dev, 0x2c80);
+		reg80 = 0x3880;
+		reg8e = 0x338e;
+	} else {
+		reg_w_buf(gspca_dev, n3_other, sizeof n3_other);
+		reg_w_buf(gspca_dev, n4_other, sizeof n4_other);
+		sd->gamma = 5;
+		reg80 = 0xac80;
+		reg8e = 0xb88e;
+	}
 
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+	reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1,
 			sizeof sensor_data[sd->sensor].data1);
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
-			sizeof sensor_data[sd->sensor].data3);
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+	reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2,
+			sizeof sensor_data[sd->sensor].data2);
+	reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2,
 			sizeof sensor_data[sd->sensor].data2);
 
-	reg_w(gspca_dev, 0x3880);
-	reg_w(gspca_dev, 0x3880);
-	reg_w(gspca_dev, 0x338e);
+	reg_w(gspca_dev, reg80);
+	reg_w(gspca_dev, reg80);
+	reg_w(gspca_dev, reg8e);
 
 	setbrightness(gspca_dev);
 	setcontrast(gspca_dev);
@@ -730,16 +764,20 @@
 			sizeof sensor_data[sd->sensor].data4);
 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data5,
 			sizeof sensor_data[sd->sensor].data5);
-	reg_w_buf(gspca_dev, nset8, sizeof nset8);
-	reg_w_buf(gspca_dev, nset9, sizeof nset9);
+	if (sd->sensor != SENSOR_OTHER) {
+		reg_w_buf(gspca_dev, nset8, sizeof nset8);
+		reg_w_buf(gspca_dev, nset9, sizeof nset9);
+		reg_w(gspca_dev, 0x2880);
+	} else {
+		reg_w_buf(gspca_dev, nset8_other, sizeof nset8_other);
+		reg_w_buf(gspca_dev, nset9_other, sizeof nset9_other);
+	}
 
-	reg_w(gspca_dev, 0x2880);
-
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data1,
+	reg_w_ixbuf(gspca_dev, 0xd0, sensor_data[sd->sensor].data1,
 			sizeof sensor_data[sd->sensor].data1);
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data3,
-			sizeof sensor_data[sd->sensor].data3);
-	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data2,
+	reg_w_ixbuf(gspca_dev, 0xc7, sensor_data[sd->sensor].data2,
+			sizeof sensor_data[sd->sensor].data2);
+	reg_w_ixbuf(gspca_dev, 0xe0, sensor_data[sd->sensor].data2,
 			sizeof sensor_data[sd->sensor].data2);
 
 	return 0;
@@ -748,7 +786,7 @@
 static void setflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 flipcmd[8] =
+	u8 flipcmd[8] =
 		{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
 
 	if (sd->mirror)
@@ -778,7 +816,7 @@
 static void setlightfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	__u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
+	u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
 
 	if (sd->freq == 2)	/* 60hz */
 		freq[1] = 0x00;
@@ -791,22 +829,22 @@
 static void poll_sensor(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	static const __u8 poll1[] =
+	static const u8 poll1[] =
 		{0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
 		 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
 		 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
 		 0x60, 0x14};
-	static const __u8 poll2[] =
+	static const u8 poll2[] =
 		{0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
 		 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
-	static const __u8 poll3[] =
+	static const u8 poll3[] =
 		{0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
-	static const __u8 poll4[] =
+	static const u8 poll4[] =
 		{0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
 		 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
 		 0xc2, 0x80, 0xc3, 0x10};
 
-	if (sd->sensor != SENSOR_TAS5130A) {
+	if (sd->sensor == SENSOR_OM6802) {
 		PDEBUG(D_STREAM, "[Sensor requires polling]");
 		reg_w_buf(gspca_dev, poll1, sizeof poll1);
 		reg_w_buf(gspca_dev, poll2, sizeof poll2);
@@ -819,13 +857,14 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i, mode;
-	__u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
-	static const __u8 t3[] =
-		{ 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
-		  0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
+	u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
+	static const u8 t3[] =
+		{ 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
 
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
 	switch (mode) {
+	case 0:		/* 640x480 (0x00) */
+		break;
 	case 1:		/* 352x288 */
 		t2[1] = 0x40;
 		break;
@@ -835,14 +874,20 @@
 	case 3:		/* 176x144 */
 		t2[1] = 0x50;
 		break;
-	case 4:		/* 160x120 */
+	default:
+/*	case 4:		 * 160x120 */
 		t2[1] = 0x20;
 		break;
-	default:	/* 640x480 (0x00) */
-		break;
 	}
 
-	if (sd->sensor == SENSOR_TAS5130A) {
+	switch (sd->sensor) {
+	case SENSOR_OM6802:
+		om6802_sensor_init(gspca_dev);
+		break;
+	case SENSOR_OTHER:
+		break;
+	default:
+/*	case SENSOR_TAS5130A: */
 		i = 0;
 		while (tas5130a_sensor_init[i][0] != 0) {
 			reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
@@ -854,14 +899,13 @@
 		reg_w_buf(gspca_dev, tas5130a_sensor_init[3],
 				 sizeof tas5130a_sensor_init[0]);
 		reg_w(gspca_dev, 0x3c80);
-	} else {
-		om6802_sensor_init(gspca_dev);
+		break;
 	}
 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].data4,
 			sizeof sensor_data[sd->sensor].data4);
 	reg_r(gspca_dev, 0x0012);
 	reg_w_buf(gspca_dev, t2, sizeof t2);
-	reg_w_buf(gspca_dev, t3, sizeof t3);
+	reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
 	reg_w(gspca_dev, 0x0013);
 	msleep(15);
 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
@@ -885,16 +929,18 @@
 	msleep(20);
 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
 			sizeof sensor_data[sd->sensor].stream);
-	msleep(20);
-	reg_w(gspca_dev, 0x0309);
+	if (sd->sensor != SENSOR_OTHER) {
+		msleep(20);
+		reg_w(gspca_dev, 0x0309);
+	}
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 			struct gspca_frame *frame,	/* target */
-			__u8 *data,			/* isoc packet */
+			u8 *data,			/* isoc packet */
 			int len)			/* iso packet length */
 {
-	static __u8 ffd9[] = { 0xff, 0xd9 };
+	static u8 ffd9[] = { 0xff, 0xd9 };
 
 	if (data[0] == 0x5a) {
 		/* Control Packet, after this came the header again,
@@ -1172,8 +1218,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
index 94163cc..9f243d7 100644
--- a/drivers/media/video/gspca/tv8532.c
+++ b/drivers/media/video/gspca/tv8532.c
@@ -31,7 +31,6 @@
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
 
 	__u16 brightness;
-	__u16 contrast;
 
 	__u8 packet;
 };
@@ -39,38 +38,22 @@
 /* V4L2 controls supported by the driver */
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
 	{
 	 {
 	  .id = V4L2_CID_BRIGHTNESS,
 	  .type = V4L2_CTRL_TYPE_INTEGER,
 	  .name = "Brightness",
 	  .minimum = 1,
-	  .maximum = 0x2ff,
+	  .maximum = 0x15f,	/* = 352 - 1 */
 	  .step = 1,
-	  .default_value = 0x18f,
+#define BRIGHTNESS_DEF 0x14c
+	  .default_value = BRIGHTNESS_DEF,
 	  },
 	 .set = sd_setbrightness,
 	 .get = sd_getbrightness,
 	 },
-#define SD_CONTRAST 1
-	{
-	 {
-	  .id = V4L2_CID_CONTRAST,
-	  .type = V4L2_CTRL_TYPE_INTEGER,
-	  .name = "Contrast",
-	  .minimum = 0,
-	  .maximum = 0xffff,
-	  .step = 1,
-	  .default_value = 0x7fff,
-	  },
-	 .set = sd_setcontrast,
-	 .get = sd_getcontrast,
-	 },
 };
 
 static const struct v4l2_pix_format sif_mode[] = {
@@ -86,78 +69,64 @@
 		.priv = 0},
 };
 
-/*
- * Initialization data: this is the first set-up data written to the
- * device (before the open data).
- */
-#define TESTCLK 0x10		/* reg 0x2c -> 0x12 //10 */
-#define TESTCOMP 0x90		/* reg 0x28 -> 0x80 */
-#define TESTLINE 0x81		/* reg 0x29 -> 0x81 */
-#define QCIFLINE 0x41		/* reg 0x29 -> 0x81 */
-#define TESTPTL 0x14		/* reg 0x2D -> 0x14 */
-#define TESTPTH 0x01		/* reg 0x2E -> 0x01 */
-#define TESTPTBL 0x12		/* reg 0x2F -> 0x0a */
-#define TESTPTBH 0x01		/* reg 0x30 -> 0x01 */
-#define ADWIDTHL 0xe8		/* reg 0x0c -> 0xe8 */
-#define ADWIDTHH 0x03		/* reg 0x0d -> 0x03 */
-#define ADHEIGHL 0x90		/* reg 0x0e -> 0x91 //93 */
-#define ADHEIGHH 0x01		/* reg 0x0f -> 0x01 */
-#define EXPOL 0x8f		/* reg 0x1c -> 0x8f */
-#define EXPOH 0x01		/* reg 0x1d -> 0x01 */
-#define ADCBEGINL 0x44		/* reg 0x10 -> 0x46 //47 */
-#define ADCBEGINH 0x00		/* reg 0x11 -> 0x00 */
-#define ADRBEGINL 0x0a		/* reg 0x14 -> 0x0b //0x0c */
-#define ADRBEGINH 0x00		/* reg 0x15 -> 0x00 */
-#define TV8532_CMD_UPDATE 0x84
+/* TV-8532A (ICM532A) registers (LE) */
+#define R00_PART_CONTROL 0x00
+#define		LATENT_CHANGE	0x80
+#define		EXPO_CHANGE	0x04
+#define R01_TIMING_CONTROL_LOW 0x01
+#define		CMD_EEprom_Open 0x30
+#define		CMD_EEprom_Close 0x29
+#define R03_TABLE_ADDR 0x03
+#define R04_WTRAM_DATA_L 0x04
+#define R05_WTRAM_DATA_M 0x05
+#define R06_WTRAM_DATA_H 0x06
+#define R07_TABLE_LEN	0x07
+#define R08_RAM_WRITE_ACTION 0x08
+#define R0C_AD_WIDTHL	0x0c
+#define R0D_AD_WIDTHH	0x0d
+#define R0E_AD_HEIGHTL	0x0e
+#define R0F_AD_HEIGHTH	0x0f
+#define R10_AD_COL_BEGINL 0x10
+#define R11_AD_COL_BEGINH 0x11
+#define		MIRROR		0x04	/* [10] */
+#define R14_AD_ROW_BEGINL 0x14
+#define R15_AD_ROWBEGINH  0x15
+#define R1C_AD_EXPOSE_TIMEL 0x1c
+#define R28_QUANT	0x28
+#define R29_LINE	0x29
+#define R2C_POLARITY	0x2c
+#define R2D_POINT	0x2d
+#define R2E_POINTH	0x2e
+#define R2F_POINTB	0x2f
+#define R30_POINTBH	0x30
+#define R31_UPD		0x31
+#define R2A_HIGH_BUDGET 0x2a
+#define R2B_LOW_BUDGET	0x2b
+#define R34_VID		0x34
+#define R35_VIDH	0x35
+#define R36_PID		0x36
+#define R37_PIDH	0x37
+#define R39_Test1	0x39		/* GPIO */
+#define R3B_Test3	0x3B		/* GPIO */
+#define R83_AD_IDH	0x83
+#define R91_AD_SLOPEREG 0x91
+#define R94_AD_BITCONTROL 0x94
 
-#define TV8532_EEprom_Add 0x03
-#define TV8532_EEprom_DataL 0x04
-#define TV8532_EEprom_DataM 0x05
-#define TV8532_EEprom_DataH 0x06
-#define TV8532_EEprom_TableLength 0x07
-#define TV8532_EEprom_Write 0x08
-#define TV8532_PART_CTRL 0x00
-#define TV8532_CTRL 0x01
-#define TV8532_CMD_EEprom_Open 0x30
-#define TV8532_CMD_EEprom_Close 0x29
-#define TV8532_UDP_UPDATE 0x31
-#define TV8532_GPIO 0x39
-#define TV8532_GPIO_OE 0x3B
-#define TV8532_REQ_RegWrite 0x02
-#define TV8532_REQ_RegRead 0x03
-
-#define TV8532_ADWIDTH_L 0x0C
-#define TV8532_ADWIDTH_H 0x0D
-#define TV8532_ADHEIGHT_L 0x0E
-#define TV8532_ADHEIGHT_H 0x0F
-#define TV8532_EXPOSURE 0x1C
-#define TV8532_QUANT_COMP 0x28
-#define TV8532_MODE_PACKET 0x29
-#define TV8532_SETCLK 0x2C
-#define TV8532_POINT_L 0x2D
-#define TV8532_POINT_H 0x2E
-#define TV8532_POINTB_L 0x2F
-#define TV8532_POINTB_H 0x30
-#define TV8532_BUDGET_L 0x2A
-#define TV8532_BUDGET_H 0x2B
-#define TV8532_VID_L 0x34
-#define TV8532_VID_H 0x35
-#define TV8532_PID_L 0x36
-#define TV8532_PID_H 0x37
-#define TV8532_DeviceID 0x83
-#define TV8532_AD_SLOPE 0x91
-#define TV8532_AD_BITCTRL 0x94
-#define TV8532_AD_COLBEGIN_L 0x10
-#define TV8532_AD_COLBEGIN_H 0x11
-#define TV8532_AD_ROWBEGIN_L 0x14
-#define TV8532_AD_ROWBEGIN_H 0x15
-
-static const __u32 tv_8532_eeprom_data[] = {
-/*	add		dataL	   dataM	dataH */
-	0x00010001, 0x01018011, 0x02050014, 0x0305001c,
-	0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,
-	0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,
-	0x0c0509f1, 0
+static const u8 eeprom_data[][3] = {
+/*	dataH dataM dataL */
+	{0x01, 0x00, 0x01},
+	{0x01, 0x80, 0x11},
+	{0x05, 0x00, 0x14},
+	{0x05, 0x00, 0x1c},
+	{0x0d, 0x00, 0x1e},
+	{0x05, 0x00, 0x1f},
+	{0x05, 0x05, 0x19},
+	{0x05, 0x01, 0x1b},
+	{0x05, 0x09, 0x1e},
+	{0x0d, 0x89, 0x2e},
+	{0x05, 0x89, 0x2f},
+	{0x05, 0x0d, 0xd9},
+	{0x05, 0x09, 0xf1},
 };
 
 static int reg_r(struct gspca_dev *gspca_dev,
@@ -165,7 +134,7 @@
 {
 	usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
-			TV8532_REQ_RegRead,
+			0x03,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0,	/* value */
 			index, gspca_dev->usb_buf, 1,
@@ -174,27 +143,27 @@
 }
 
 /* write 1 byte */
-static void reg_w_1(struct gspca_dev *gspca_dev,
+static void reg_w1(struct gspca_dev *gspca_dev,
 		  __u16 index, __u8 value)
 {
 	gspca_dev->usb_buf[0] = value;
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
-			TV8532_REQ_RegWrite,
+			0x02,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0,	/* value */
 			index, gspca_dev->usb_buf, 1, 500);
 }
 
 /* write 2 bytes */
-static void reg_w_2(struct gspca_dev *gspca_dev,
-		  __u16 index, __u8 val1, __u8 val2)
+static void reg_w2(struct gspca_dev *gspca_dev,
+		  u16 index, u16 value)
 {
-	gspca_dev->usb_buf[0] = val1;
-	gspca_dev->usb_buf[1] = val2;
+	gspca_dev->usb_buf[0] = value;
+	gspca_dev->usb_buf[1] = value >> 8;
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
-			TV8532_REQ_RegWrite,
+			0x02,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0,	/* value */
 			index, gspca_dev->usb_buf, 2, 500);
@@ -202,32 +171,18 @@
 
 static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
 {
-	int i = 0;
-	__u8 reg, data0, data1, data2;
+	int i;
 
-	reg_w_1(gspca_dev, TV8532_GPIO, 0xb0);
-	reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open);
-/*	msleep(1); */
-	while (tv_8532_eeprom_data[i]) {
-		reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;
-		reg_w_1(gspca_dev, TV8532_EEprom_Add, reg);
-		/* msleep(1); */
-		data0 = (tv_8532_eeprom_data[i] & 0x000000ff);
-		reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0);
-		/* msleep(1); */
-		data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8;
-		reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1);
-		/* msleep(1); */
-		data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16;
-		reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2);
-		/* msleep(1); */
-		reg_w_1(gspca_dev, TV8532_EEprom_Write, 0);
-		/* msleep(10); */
-		i++;
+	reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open);
+	for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) {
+		reg_w1(gspca_dev, R03_TABLE_ADDR, i);
+		reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]);
+		reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]);
+		reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]);
+		reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0);
 	}
-	reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i);
-/*	msleep(1); */
-	reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close);
+	reg_w1(gspca_dev, R07_TABLE_LEN, i);
+	reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
 	msleep(10);
 }
 
@@ -238,79 +193,76 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
 
-	tv_8532WriteEEprom(gspca_dev);
-
 	cam = &gspca_dev->cam;
-	cam->epaddr = 1;
 	cam->cam_mode = sif_mode;
-	cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
+	cam->nmodes = ARRAY_SIZE(sif_mode);
 
-	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
-	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
+	sd->brightness = BRIGHTNESS_DEF;
 	return 0;
 }
 
 static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
 {
-	__u8 data;
+	int i;
+	static u8 reg_tb[] = {
+		R0C_AD_WIDTHL,
+		R0D_AD_WIDTHH,
+		R28_QUANT,
+		R29_LINE,
+		R2C_POLARITY,
+		R2D_POINT,
+		R2E_POINTH,
+		R2F_POINTB,
+		R30_POINTBH,
+		R2A_HIGH_BUDGET,
+		R2B_LOW_BUDGET,
+		R34_VID,
+		R35_VIDH,
+		R36_PID,
+		R37_PIDH,
+		R83_AD_IDH,
+		R10_AD_COL_BEGINL,
+		R11_AD_COL_BEGINH,
+		R14_AD_ROW_BEGINL,
+		R15_AD_ROWBEGINH,
+		0
+	};
 
-	data = reg_r(gspca_dev, 0x0001);
-	PDEBUG(D_USBI, "register 0x01-> %x", data);
-	data = reg_r(gspca_dev, 0x0002);
-	PDEBUG(D_USBI, "register 0x02-> %x", data);
-	reg_r(gspca_dev, TV8532_ADWIDTH_L);
-	reg_r(gspca_dev, TV8532_ADWIDTH_H);
-	reg_r(gspca_dev, TV8532_QUANT_COMP);
-	reg_r(gspca_dev, TV8532_MODE_PACKET);
-	reg_r(gspca_dev, TV8532_SETCLK);
-	reg_r(gspca_dev, TV8532_POINT_L);
-	reg_r(gspca_dev, TV8532_POINT_H);
-	reg_r(gspca_dev, TV8532_POINTB_L);
-	reg_r(gspca_dev, TV8532_POINTB_H);
-	reg_r(gspca_dev, TV8532_BUDGET_L);
-	reg_r(gspca_dev, TV8532_BUDGET_H);
-	reg_r(gspca_dev, TV8532_VID_L);
-	reg_r(gspca_dev, TV8532_VID_H);
-	reg_r(gspca_dev, TV8532_PID_L);
-	reg_r(gspca_dev, TV8532_PID_H);
-	reg_r(gspca_dev, TV8532_DeviceID);
-	reg_r(gspca_dev, TV8532_AD_COLBEGIN_L);
-	reg_r(gspca_dev, TV8532_AD_COLBEGIN_H);
-	reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L);
-	reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H);
+	i = 0;
+	do {
+		reg_r(gspca_dev, reg_tb[i]);
+		i++;
+	} while (reg_tb[i] != 0);
 }
 
 static void tv_8532_setReg(struct gspca_dev *gspca_dev)
 {
-	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
-			ADCBEGINL);			/* 0x10 */
-	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
-			ADCBEGINH);			/* also digital gain */
-	reg_w_1(gspca_dev, TV8532_PART_CTRL,
-			TV8532_CMD_UPDATE);		/* 0x00<-0x84 */
+	reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
+						/* begin active line */
+	reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
+						/* mirror and digital gain */
+	reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+						/* = 0x84 */
 
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a);
+	reg_w1(gspca_dev, R3B_Test3, 0x0a);	/* Test0Sel = 10 */
 	/******************************************************/
-	reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */
-	reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */
-	reg_w_2(gspca_dev, TV8532_EXPOSURE,
-			EXPOL, EXPOH);			/* 350d 0x014c; 1c */
-	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
-			ADCBEGINL);			/* 0x10 */
-	reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
-			ADCBEGINH);			/* also digital gain */
-	reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L,
-			ADRBEGINL);			/* 0x14 */
+	reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90);
+	reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01);
+	reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
+	reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
+						/* begin active line */
+	reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
+						/* mirror and digital gain */
+	reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a);
 
-	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00);	/* 0x91 */
-	reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02);	/* 0x94 */
+	reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
+	reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02);
 
-	reg_w_1(gspca_dev, TV8532_CTRL,
-			TV8532_CMD_EEprom_Close);	/* 0x01 */
+	reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
 
-	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00);	/* 0x91 */
-	reg_w_1(gspca_dev, TV8532_PART_CTRL,
-			TV8532_CMD_UPDATE);		/* 0x00<-0x84 */
+	reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
+	reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+						/* = 0x84 */
 }
 
 static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
@@ -319,54 +271,55 @@
 
 	/* strange polling from tgc */
 	for (i = 0; i < 10; i++) {
-		reg_w_1(gspca_dev, TV8532_SETCLK,
-			TESTCLK);		/* 0x48; //0x08; 0x2c */
-		reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
-		reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01);	/* 0x31 */
+		reg_w1(gspca_dev, R2C_POLARITY, 0x10);
+		reg_w1(gspca_dev, R00_PART_CONTROL,
+				LATENT_CHANGE | EXPO_CHANGE);
+		reg_w1(gspca_dev, R31_UPD, 0x01);
 	}
 }
 
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
-	reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
+	tv_8532WriteEEprom(gspca_dev);
+
+	reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32);	/* slope begin 1,7V,
+							 * slope rate 2 */
+	reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00);
 	tv_8532ReadRegisters(gspca_dev);
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
-	reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL,
-				ADHEIGHH);	/* 401d 0x0169; 0e */
-	reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL,
-				EXPOH);		/* 350d 0x014c; 1c */
-	reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL);	/* 0x20; 0x0c */
-	reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH);	/* 0x0d */
+	reg_w1(gspca_dev, R3B_Test3, 0x0b);
+	reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190);
+	reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
+	reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8);
+	reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
 
 	/*******************************************************************/
-	reg_w_1(gspca_dev, TV8532_QUANT_COMP,
-			TESTCOMP);	/* 0x72 compressed mode 0x28 */
-	reg_w_1(gspca_dev, TV8532_MODE_PACKET,
-			TESTLINE);	/* 0x84; // CIF | 4 packet 0x29 */
+	reg_w1(gspca_dev, R28_QUANT, 0x90);
+					/* no compress - fixed Q - quant 0 */
+	reg_w1(gspca_dev, R29_LINE, 0x81);
+					/* 0x84; // CIF | 4 packet 0x29 */
 
 	/************************************************/
-	reg_w_1(gspca_dev, TV8532_SETCLK,
-			TESTCLK);		/* 0x48; //0x08; 0x2c */
-	reg_w_1(gspca_dev, TV8532_POINT_L,
-			TESTPTL);		/* 0x38; 0x2d */
-	reg_w_1(gspca_dev, TV8532_POINT_H,
-			TESTPTH);		/* 0x04; 0x2e */
-	reg_w_1(gspca_dev, TV8532_POINTB_L,
-			TESTPTBL);		/* 0x04; 0x2f */
-	reg_w_1(gspca_dev, TV8532_POINTB_H,
-			TESTPTBH);		/* 0x04; 0x30 */
-	reg_w_1(gspca_dev, TV8532_PART_CTRL,
-			TV8532_CMD_UPDATE);	/* 0x00<-0x84 */
+	reg_w1(gspca_dev, R2C_POLARITY, 0x10);
+						/* 0x48; //0x08; 0x2c */
+	reg_w1(gspca_dev, R2D_POINT, 0x14);
+						/* 0x38; 0x2d */
+	reg_w1(gspca_dev, R2E_POINTH, 0x01);
+						/* 0x04; 0x2e */
+	reg_w1(gspca_dev, R2F_POINTB, 0x12);
+						/* 0x04; 0x2f */
+	reg_w1(gspca_dev, R30_POINTBH, 0x01);
+						/* 0x04; 0x30 */
+	reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+						/* 0x00<-0x84 */
 	/*************************************************/
-	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01);	/* 0x31 */
+	reg_w1(gspca_dev, R31_UPD, 0x01);	/* update registers */
 	msleep(200);
-	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00);	/* 0x31 */
+	reg_w1(gspca_dev, R31_UPD, 0x00);		/* end update */
 	/*************************************************/
 	tv_8532_setReg(gspca_dev);
 	/*************************************************/
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
+	reg_w1(gspca_dev, R3B_Test3, 0x0b);	/* Test0Sel = 11 = GPIO */
 	/*************************************************/
 	tv_8532_setReg(gspca_dev);
 	/*************************************************/
@@ -377,11 +330,10 @@
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int brightness = sd->brightness;
 
-	reg_w_2(gspca_dev, TV8532_EXPOSURE,
-		brightness >> 8, brightness);		/* 1c */
-	reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
+	reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, sd->brightness);
+	reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+						/* 0x84 */
 }
 
 /* -- start the camera -- */
@@ -389,57 +341,50 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
-	reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
+	reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x32);	/* slope begin 1,7V,
+							 * slope rate 2 */
+	reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x00);
 	tv_8532ReadRegisters(gspca_dev);
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
-	reg_w_2(gspca_dev, TV8532_ADHEIGHT_L,
-		ADHEIGHL, ADHEIGHH);	/* 401d 0x0169; 0e */
-/*	reg_w_2(gspca_dev, TV8532_EXPOSURE,
-		EXPOL, EXPOH);		 * 350d 0x014c; 1c */
+	reg_w1(gspca_dev, R3B_Test3, 0x0b);
+
+	reg_w2(gspca_dev, R0E_AD_HEIGHTL, 0x0190);
 	setbrightness(gspca_dev);
 
-	reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL);	/* 0x20; 0x0c */
-	reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH);	/* 0x0d */
+	reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8);		/* 0x20; 0x0c */
+	reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
 
 	/************************************************/
-	reg_w_1(gspca_dev, TV8532_QUANT_COMP,
-			TESTCOMP);	/* 0x72 compressed mode 0x28 */
+	reg_w1(gspca_dev, R28_QUANT, 0x90);
+					/* 0x72 compressed mode 0x28 */
 	if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
 		/* 176x144 */
-		reg_w_1(gspca_dev, TV8532_MODE_PACKET,
-			QCIFLINE);	/* 0x84; // CIF | 4 packet 0x29 */
+		reg_w1(gspca_dev, R29_LINE, 0x41);
+					/* CIF - 2 lines/packet */
 	} else {
 		/* 352x288 */
-		reg_w_1(gspca_dev, TV8532_MODE_PACKET,
-			TESTLINE);	/* 0x84; // CIF | 4 packet 0x29 */
+		reg_w1(gspca_dev, R29_LINE, 0x81);
+					/* CIF - 2 lines/packet */
 	}
 	/************************************************/
-	reg_w_1(gspca_dev, TV8532_SETCLK,
-			TESTCLK);		/* 0x48; //0x08; 0x2c */
-	reg_w_1(gspca_dev, TV8532_POINT_L,
-			TESTPTL);		/* 0x38; 0x2d */
-	reg_w_1(gspca_dev, TV8532_POINT_H,
-			TESTPTH);		/* 0x04; 0x2e */
-	reg_w_1(gspca_dev, TV8532_POINTB_L,
-			TESTPTBL);		/* 0x04; 0x2f */
-	reg_w_1(gspca_dev, TV8532_POINTB_H,
-			TESTPTBH);		/* 0x04; 0x30 */
-	reg_w_1(gspca_dev, TV8532_PART_CTRL,
-			TV8532_CMD_UPDATE);	/* 0x00<-0x84 */
+	reg_w1(gspca_dev, R2C_POLARITY, 0x10);		/* slow clock */
+	reg_w1(gspca_dev, R2D_POINT, 0x14);
+	reg_w1(gspca_dev, R2E_POINTH, 0x01);
+	reg_w1(gspca_dev, R2F_POINTB, 0x12);
+	reg_w1(gspca_dev, R30_POINTBH, 0x01);
+	reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
 	/************************************************/
-	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01);	/* 0x31 */
+	reg_w1(gspca_dev, R31_UPD, 0x01);	/* update registers */
 	msleep(200);
-	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00);	/* 0x31 */
+	reg_w1(gspca_dev, R31_UPD, 0x00);		/* end update */
 	/************************************************/
 	tv_8532_setReg(gspca_dev);
 	/************************************************/
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
+	reg_w1(gspca_dev, R3B_Test3, 0x0b);	/* Test0Sel = 11 = GPIO */
 	/************************************************/
 	tv_8532_setReg(gspca_dev);
 	/************************************************/
 	tv_8532_PollReg(gspca_dev);
-	reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00);	/* 0x31 */
+	reg_w1(gspca_dev, R31_UPD, 0x00);	/* end update */
 
 	gspca_dev->empty_packet = 0;		/* check the empty packets */
 	sd->packet = 0;				/* ignore the first packets */
@@ -449,7 +394,7 @@
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
-	reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
+	reg_w1(gspca_dev, R3B_Test3, 0x0b);	/* Test0Sel = 11 = GPIO */
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -473,9 +418,9 @@
 
 	/* each packet contains:
 	 * - header 2 bytes
-	 * - RG line
+	 * - RGRG line
 	 * - 4 bytes
-	 * - GB line
+	 * - GBGB line
 	 * - 4 bytes
 	 */
 	gspca_frame_add(gspca_dev, packet_type0,
@@ -484,10 +429,6 @@
 			frame, data + gspca_dev->width + 6, gspca_dev->width);
 }
 
-static void setcontrast(struct gspca_dev *gspca_dev)
-{
-}
-
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -506,24 +447,6 @@
 	return 0;
 }
 
-static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->contrast = val;
-	if (gspca_dev->streaming)
-		setcontrast(gspca_dev);
-	return 0;
-}
-
-static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->contrast;
-	return 0;
-}
-
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
@@ -570,8 +493,10 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
index 0525ea5..4c802fb 100644
--- a/drivers/media/video/gspca/vc032x.c
+++ b/drivers/media/video/gspca/vc032x.c
@@ -37,18 +37,21 @@
 	__u8 lightfreq;
 	__u8 sharpness;
 
+	u8 image_offset;
+
 	char bridge;
 #define BRIDGE_VC0321 0
 #define BRIDGE_VC0323 1
 	char sensor;
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
-#define SENSOR_MI1320 2
-#define SENSOR_MI1310_SOC 3
-#define SENSOR_OV7660 4
-#define SENSOR_OV7670 5
-#define SENSOR_PO1200 6
-#define SENSOR_PO3130NC 7
+#define SENSOR_MI1310_SOC 2
+#define SENSOR_MI1320 3
+#define SENSOR_MI1320_SOC 4
+#define SENSOR_OV7660 5
+#define SENSOR_OV7670 6
+#define SENSOR_PO1200 7
+#define SENSOR_PO3130NC 8
 };
 
 /* V4L2 controls supported by the driver */
@@ -149,8 +152,50 @@
 		.sizeimage = 640 * 480 * 3 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = 0},
+	{1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi13x0_soc only */
+		.bytesperline = 1280,
+		.sizeimage = 1280 * 1024 * 1 / 4 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 2},
 };
-
+static const struct v4l2_pix_format bi_mode[] = {
+/*fixme: jeg does not work
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 5},
+*/
+	{320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 2,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 4},
+/*
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 3},
+*/
+	{640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 2,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 2},
+/*
+	{1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 1280,
+		.sizeimage = 1280 * 1024 * 1 / 4 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG,
+		.priv = 1},
+*/
+	{1280, 1024, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+		.bytesperline = 1280,
+		.sizeimage = 1280 * 1024 * 2,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 0},
+};
 static const struct v4l2_pix_format svga_mode[] = {
 	{800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 800,
@@ -400,92 +445,208 @@
 static const __u8 mi1310_socinitVGA_JPG[][4] = {
 	{0xb0, 0x03, 0x19, 0xcc},
 	{0xb0, 0x04, 0x02, 0xcc},
-	{0xb3, 0x00, 0x64, 0xcc},
-	{0xb3, 0x00, 0x65, 0xcc},
-	{0xb3, 0x05, 0x00, 0xcc},
-	{0xb3, 0x06, 0x00, 0xcc},
+	{0xb3, 0x00, 0x24, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x03, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
 	{0xb3, 0x08, 0x01, 0xcc},
 	{0xb3, 0x09, 0x0c, 0xcc},
 	{0xb3, 0x34, 0x02, 0xcc},
 	{0xb3, 0x35, 0xdd, 0xcc},
-	{0xb3, 0x02, 0x00, 0xcc},
 	{0xb3, 0x03, 0x0a, 0xcc},
-	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x04, 0x0d, 0xcc},
 	{0xb3, 0x20, 0x00, 0xcc},
 	{0xb3, 0x21, 0x00, 0xcc},
-	{0xb3, 0x22, 0x03, 0xcc},
-	{0xb3, 0x23, 0xc0, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
 	{0xb3, 0x14, 0x00, 0xcc},
 	{0xb3, 0x15, 0x00, 0xcc},
-	{0xb3, 0x16, 0x04, 0xcc},
-	{0xb3, 0x17, 0xff, 0xcc},
-	{0xb3, 0x00, 0x65, 0xcc},
-	{0xb8, 0x00, 0x00, 0xcc},
-	{0xbc, 0x00, 0xd0, 0xcc},
-	{0xbc, 0x01, 0x01, 0xcc},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0xc8, 0x9f, 0x0b, 0xbb},
-	{0x5b, 0x00, 0x01, 0xbb},
-	{0x2f, 0xde, 0x20, 0xbb},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb8, 0x01, 0x7d, 0xcc},
+	{0xb8, 0x81, 0x09, 0xcc},
+	{0xb8, 0x27, 0x20, 0xcc},
+	{0xb8, 0x26, 0x80, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb8, 0x00, 0x13, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xb8, 0x81, 0x01, 0xcc},
+	{0xb8, 0x2c, 0x5a, 0xcc},
+	{0xb8, 0x2d, 0xff, 0xcc},
+	{0xb8, 0x2e, 0xee, 0xcc},
+	{0xb8, 0x2f, 0xfb, 0xcc},
+	{0xb8, 0x30, 0x52, 0xcc},
+	{0xb8, 0x31, 0xf8, 0xcc},
+	{0xb8, 0x32, 0xf1, 0xcc},
+	{0xb8, 0x33, 0xff, 0xcc},
+	{0xb8, 0x34, 0x54, 0xcc},
+	{0xb8, 0x35, 0x00, 0xcc},
+	{0xb8, 0x36, 0x00, 0xcc},
+	{0xb8, 0x37, 0x00, 0xcc},
 	{0xf0, 0x00, 0x00, 0xbb},
-	{0x20, 0x03, 0x02, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x0d, 0x00, 0x09, 0xbb},
+	{0x0d, 0x00, 0x08, 0xbb},
 	{0xf0, 0x00, 0x01, 0xbb},
-	{0x05, 0x00, 0x07, 0xbb},
-	{0x34, 0x00, 0x00, 0xbb},
-	{0x35, 0xff, 0x00, 0xbb},
-	{0xdc, 0x07, 0x02, 0xbb},
-	{0xdd, 0x3c, 0x18, 0xbb},
-	{0xde, 0x92, 0x6d, 0xbb},
-	{0xdf, 0xcd, 0xb1, 0xbb},
-	{0xe0, 0xff, 0xe7, 0xbb},
-	{0x06, 0xf0, 0x0d, 0xbb},
-	{0x06, 0x70, 0x0e, 0xbb},
-	{0x4c, 0x00, 0x01, 0xbb},
-	{0x4d, 0x00, 0x01, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0x2e, 0x0c, 0x55, 0xbb},
-	{0x21, 0xb6, 0x6e, 0xbb},
-	{0x36, 0x30, 0x10, 0xbb},
-	{0x37, 0x00, 0xc1, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x06, 0x00, 0x14, 0xbb},
+	{0x3a, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x9b, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
 	{0xf0, 0x00, 0x00, 0xbb},
-	{0x07, 0x00, 0x84, 0xbb},
-	{0x08, 0x02, 0x4a, 0xbb},
-	{0x05, 0x01, 0x10, 0xbb},
-	{0x06, 0x00, 0x39, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0x58, 0x02, 0x67, 0xbb},
-	{0x57, 0x02, 0x00, 0xbb},
-	{0x5a, 0x02, 0x67, 0xbb},
-	{0x59, 0x02, 0x00, 0xbb},
-	{0x5c, 0x12, 0x0d, 0xbb},
-	{0x5d, 0x16, 0x11, 0xbb},
-	{0x39, 0x06, 0x18, 0xbb},
-	{0x3a, 0x06, 0x18, 0xbb},
-	{0x3b, 0x06, 0x18, 0xbb},
-	{0x3c, 0x06, 0x18, 0xbb},
-	{0x64, 0x7b, 0x5b, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0x36, 0x30, 0x10, 0xbb},
-	{0x37, 0x00, 0xc0, 0xbb},
-	{0xbc, 0x0e, 0x00, 0xcc},
-	{0xbc, 0x0f, 0x05, 0xcc},
-	{0xbc, 0x10, 0xc0, 0xcc},
-	{0xbc, 0x11, 0x03, 0xcc},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x2b, 0x00, 0x28, 0xbb},
+	{0x2c, 0x00, 0x30, 0xbb},
+	{0x2d, 0x00, 0x30, 0xbb},
+	{0x2e, 0x00, 0x28, 0xbb},
+	{0x41, 0x00, 0xd7, 0xbb},
+	{0x09, 0x02, 0x3a, 0xbb},
+	{0x0c, 0x00, 0x00, 0xbb},
+	{0x20, 0x00, 0x00, 0xbb},
+	{0x05, 0x00, 0x8c, 0xbb},
+	{0x06, 0x00, 0x32, 0xbb},
+	{0x07, 0x00, 0xc6, 0xbb},
+	{0x08, 0x00, 0x19, 0xbb},
+	{0x24, 0x80, 0x6f, 0xbb},
+	{0xc8, 0x00, 0x0f, 0xbb},
+	{0x20, 0x00, 0x0f, 0xbb},
 	{0xb6, 0x00, 0x00, 0xcc},
 	{0xb6, 0x03, 0x02, 0xcc},
 	{0xb6, 0x02, 0x80, 0xcc},
 	{0xb6, 0x05, 0x01, 0xcc},
 	{0xb6, 0x04, 0xe0, 0xcc},
-	{0xb6, 0x12, 0xf8, 0xcc},
-	{0xb6, 0x13, 0x25, 0xcc},
+	{0xb6, 0x12, 0x78, 0xcc},
 	{0xb6, 0x18, 0x02, 0xcc},
 	{0xb6, 0x17, 0x58, 0xcc},
 	{0xb6, 0x16, 0x00, 0xcc},
 	{0xb6, 0x22, 0x12, 0xcc},
 	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xb3, 0x02, 0x02, 0xcc},
 	{0xbf, 0xc0, 0x39, 0xcc},
 	{0xbf, 0xc1, 0x04, 0xcc},
-	{0xbf, 0xcc, 0x00, 0xcc},
+	{0xbf, 0xcc, 0x10, 0xcc},
+	{0xb9, 0x12, 0x00, 0xcc},
+	{0xb9, 0x13, 0x0a, 0xcc},
+	{0xb9, 0x14, 0x0a, 0xcc},
+	{0xb9, 0x15, 0x0a, 0xcc},
+	{0xb9, 0x16, 0x0a, 0xcc},
+	{0xb9, 0x18, 0x00, 0xcc},
+	{0xb9, 0x19, 0x0f, 0xcc},
+	{0xb9, 0x1a, 0x0f, 0xcc},
+	{0xb9, 0x1b, 0x0f, 0xcc},
+	{0xb9, 0x1c, 0x0f, 0xcc},
+	{0xb8, 0x8e, 0x00, 0xcc},
+	{0xb8, 0x8f, 0xff, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0x03, 0x03, 0xc0, 0xbb},
+	{0x06, 0x00, 0x10, 0xbb},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb8, 0x0c, 0x20, 0xcc},
+	{0xb8, 0x0d, 0x70, 0xcc},
+	{0xb6, 0x13, 0x13, 0xcc},
+	{0x2f, 0x00, 0xC0, 0xbb},
+	{0xb8, 0xa0, 0x12, 0xcc},
+	{},
+};
+static const __u8 mi1310_socinitQVGA_JPG[][4] = {
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0xb3, 0x00, 0x24, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x03, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xdd, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x0d, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb8, 0x01, 0x7d, 0xcc},
+	{0xb8, 0x81, 0x09, 0xcc},
+	{0xb8, 0x27, 0x20, 0xcc},
+	{0xb8, 0x26, 0x80, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb8, 0x00, 0x13, 0xcc},
+	{0xbc, 0x00, 0xd1, 0xcc},
+	{0xb8, 0x81, 0x01, 0xcc},
+	{0xb8, 0x2c, 0x5a, 0xcc},
+	{0xb8, 0x2d, 0xff, 0xcc},
+	{0xb8, 0x2e, 0xee, 0xcc},
+	{0xb8, 0x2f, 0xfb, 0xcc},
+	{0xb8, 0x30, 0x52, 0xcc},
+	{0xb8, 0x31, 0xf8, 0xcc},
+	{0xb8, 0x32, 0xf1, 0xcc},
+	{0xb8, 0x33, 0xff, 0xcc},
+	{0xb8, 0x34, 0x54, 0xcc},
+	{0xb8, 0x35, 0x00, 0xcc},
+	{0xb8, 0x36, 0x00, 0xcc},
+	{0xb8, 0x37, 0x00, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x0d, 0x00, 0x09, 0xbb},
+	{0x0d, 0x00, 0x08, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x06, 0x00, 0x14, 0xbb},
+	{0x3a, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x9b, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x2b, 0x00, 0x28, 0xbb},
+	{0x2c, 0x00, 0x30, 0xbb},
+	{0x2d, 0x00, 0x30, 0xbb},
+	{0x2e, 0x00, 0x28, 0xbb},
+	{0x41, 0x00, 0xd7, 0xbb},
+	{0x09, 0x02, 0x3a, 0xbb},
+	{0x0c, 0x00, 0x00, 0xbb},
+	{0x20, 0x00, 0x00, 0xbb},
+	{0x05, 0x00, 0x8c, 0xbb},
+	{0x06, 0x00, 0x32, 0xbb},
+	{0x07, 0x00, 0xc6, 0xbb},
+	{0x08, 0x00, 0x19, 0xbb},
+	{0x24, 0x80, 0x6f, 0xbb},
+	{0xc8, 0x00, 0x0f, 0xbb},
+	{0x20, 0x00, 0x0f, 0xbb},
+	{0xb6, 0x00, 0x00, 0xcc},
+	{0xb6, 0x03, 0x01, 0xcc},
+	{0xb6, 0x02, 0x40, 0xcc},
+	{0xb6, 0x05, 0x00, 0xcc},
+	{0xb6, 0x04, 0xf0, 0xcc},
+	{0xb6, 0x12, 0x78, 0xcc},
+	{0xb6, 0x18, 0x00, 0xcc},
+	{0xb6, 0x17, 0x96, 0xcc},
+	{0xb6, 0x16, 0x00, 0xcc},
+	{0xb6, 0x22, 0x12, 0xcc},
+	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xb3, 0x02, 0x02, 0xcc},
+	{0xbf, 0xc0, 0x39, 0xcc},
+	{0xbf, 0xc1, 0x04, 0xcc},
+	{0xbf, 0xcc, 0x10, 0xcc},
+	{0xb9, 0x12, 0x00, 0xcc},
+	{0xb9, 0x13, 0x0a, 0xcc},
+	{0xb9, 0x14, 0x0a, 0xcc},
+	{0xb9, 0x15, 0x0a, 0xcc},
+	{0xb9, 0x16, 0x0a, 0xcc},
+	{0xb9, 0x18, 0x00, 0xcc},
+	{0xb9, 0x19, 0x0f, 0xcc},
+	{0xb9, 0x1a, 0x0f, 0xcc},
+	{0xb9, 0x1b, 0x0f, 0xcc},
+	{0xb9, 0x1c, 0x0f, 0xcc},
+	{0xb8, 0x8e, 0x00, 0xcc},
+	{0xb8, 0x8f, 0xff, 0xcc},
 	{0xbc, 0x02, 0x18, 0xcc},
 	{0xbc, 0x03, 0x50, 0xcc},
 	{0xbc, 0x04, 0x18, 0xcc},
@@ -496,131 +657,123 @@
 	{0xbc, 0x0a, 0x10, 0xcc},
 	{0xbc, 0x0b, 0x00, 0xcc},
 	{0xbc, 0x0c, 0x00, 0xcc},
-	{0xb3, 0x5c, 0x01, 0xcc},
-	{0xf0, 0x00, 0x01, 0xbb},
-	{0x80, 0x00, 0x03, 0xbb},
-	{0x81, 0xc7, 0x14, 0xbb},
-	{0x82, 0xeb, 0xe8, 0xbb},
-	{0x83, 0xfe, 0xf4, 0xbb},
-	{0x84, 0xcd, 0x10, 0xbb},
-	{0x85, 0xf3, 0xee, 0xbb},
-	{0x86, 0xff, 0xf1, 0xbb},
-	{0x87, 0xcd, 0x10, 0xbb},
-	{0x88, 0xf3, 0xee, 0xbb},
-	{0x89, 0x01, 0xf1, 0xbb},
-	{0x8a, 0xe5, 0x17, 0xbb},
-	{0x8b, 0xe8, 0xe2, 0xbb},
-	{0x8c, 0xf7, 0xed, 0xbb},
-	{0x8d, 0x00, 0xff, 0xbb},
-	{0x8e, 0xec, 0x10, 0xbb},
-	{0x8f, 0xf0, 0xed, 0xbb},
-	{0x90, 0xf9, 0xf2, 0xbb},
-	{0x91, 0x00, 0x00, 0xbb},
-	{0x92, 0xe9, 0x0d, 0xbb},
-	{0x93, 0xf4, 0xf2, 0xbb},
-	{0x94, 0xfb, 0xf5, 0xbb},
-	{0x95, 0x00, 0xff, 0xbb},
-	{0xb6, 0x0f, 0x08, 0xbb},
-	{0xb7, 0x3d, 0x16, 0xbb},
-	{0xb8, 0x0c, 0x04, 0xbb},
-	{0xb9, 0x1c, 0x07, 0xbb},
-	{0xba, 0x0a, 0x03, 0xbb},
-	{0xbb, 0x1b, 0x09, 0xbb},
-	{0xbc, 0x17, 0x0d, 0xbb},
-	{0xbd, 0x23, 0x1d, 0xbb},
-	{0xbe, 0x00, 0x28, 0xbb},
-	{0xbf, 0x11, 0x09, 0xbb},
-	{0xc0, 0x16, 0x15, 0xbb},
-	{0xc1, 0x00, 0x1b, 0xbb},
-	{0xc2, 0x0e, 0x07, 0xbb},
-	{0xc3, 0x14, 0x10, 0xbb},
-	{0xc4, 0x00, 0x17, 0xbb},
-	{0x06, 0x74, 0x8e, 0xbb},
-	{0xf0, 0x00, 0x01, 0xbb},
-	{0x06, 0xf4, 0x8e, 0xbb},
-	{0x00, 0x00, 0x50, 0xdd},
-	{0x06, 0x74, 0x8e, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0x24, 0x50, 0x20, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},
-	{0x34, 0x0c, 0x50, 0xbb},
 	{0xb3, 0x01, 0x41, 0xcc},
-	{0xf0, 0x00, 0x00, 0xbb},
 	{0x03, 0x03, 0xc0, 0xbb},
+	{0x06, 0x00, 0x10, 0xbb},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb8, 0x0c, 0x20, 0xcc},
+	{0xb8, 0x0d, 0x70, 0xcc},
+	{0xb6, 0x13, 0x13, 0xcc},
+	{0x2f, 0x00, 0xC0, 0xbb},
+	{0xb8, 0xa0, 0x12, 0xcc},
 	{},
 };
-static const __u8 mi1310_socinitQVGA_JPG[][4] = {
-	{0xb0, 0x03, 0x19, 0xcc},	{0xb0, 0x04, 0x02, 0xcc},
-	{0xb3, 0x00, 0x64, 0xcc},	{0xb3, 0x00, 0x65, 0xcc},
-	{0xb3, 0x05, 0x00, 0xcc},	{0xb3, 0x06, 0x00, 0xcc},
-	{0xb3, 0x08, 0x01, 0xcc},	{0xb3, 0x09, 0x0c, 0xcc},
-	{0xb3, 0x34, 0x02, 0xcc},	{0xb3, 0x35, 0xdd, 0xcc},
-	{0xb3, 0x02, 0x00, 0xcc},	{0xb3, 0x03, 0x0a, 0xcc},
-	{0xb3, 0x04, 0x05, 0xcc},	{0xb3, 0x20, 0x00, 0xcc},
-	{0xb3, 0x21, 0x00, 0xcc},	{0xb3, 0x22, 0x03, 0xcc},
-	{0xb3, 0x23, 0xc0, 0xcc},	{0xb3, 0x14, 0x00, 0xcc},
-	{0xb3, 0x15, 0x00, 0xcc},	{0xb3, 0x16, 0x04, 0xcc},
-	{0xb3, 0x17, 0xff, 0xcc},	{0xb3, 0x00, 0x65, 0xcc},
-	{0xb8, 0x00, 0x00, 0xcc},	{0xbc, 0x00, 0xf0, 0xcc},
-	{0xbc, 0x01, 0x01, 0xcc},	{0xf0, 0x00, 0x02, 0xbb},
-	{0xc8, 0x9f, 0x0b, 0xbb},	{0x5b, 0x00, 0x01, 0xbb},
-	{0x2f, 0xde, 0x20, 0xbb},	{0xf0, 0x00, 0x00, 0xbb},
-	{0x20, 0x03, 0x02, 0xbb},	{0xf0, 0x00, 0x01, 0xbb},
-	{0x05, 0x00, 0x07, 0xbb},	{0x34, 0x00, 0x00, 0xbb},
-	{0x35, 0xff, 0x00, 0xbb},	{0xdc, 0x07, 0x02, 0xbb},
-	{0xdd, 0x3c, 0x18, 0xbb},	{0xde, 0x92, 0x6d, 0xbb},
-	{0xdf, 0xcd, 0xb1, 0xbb},	{0xe0, 0xff, 0xe7, 0xbb},
-	{0x06, 0xf0, 0x0d, 0xbb},	{0x06, 0x70, 0x0e, 0xbb},
-	{0x4c, 0x00, 0x01, 0xbb},	{0x4d, 0x00, 0x01, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},	{0x2e, 0x0c, 0x55, 0xbb},
-	{0x21, 0xb6, 0x6e, 0xbb},	{0x36, 0x30, 0x10, 0xbb},
-	{0x37, 0x00, 0xc1, 0xbb},	{0xf0, 0x00, 0x00, 0xbb},
-	{0x07, 0x00, 0x84, 0xbb},	{0x08, 0x02, 0x4a, 0xbb},
-	{0x05, 0x01, 0x10, 0xbb},	{0x06, 0x00, 0x39, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},	{0x58, 0x02, 0x67, 0xbb},
-	{0x57, 0x02, 0x00, 0xbb},	{0x5a, 0x02, 0x67, 0xbb},
-	{0x59, 0x02, 0x00, 0xbb},	{0x5c, 0x12, 0x0d, 0xbb},
-	{0x5d, 0x16, 0x11, 0xbb},	{0x39, 0x06, 0x18, 0xbb},
-	{0x3a, 0x06, 0x18, 0xbb},	{0x3b, 0x06, 0x18, 0xbb},
-	{0x3c, 0x06, 0x18, 0xbb},	{0x64, 0x7b, 0x5b, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},	{0x36, 0x30, 0x10, 0xbb},
-	{0x37, 0x00, 0xc0, 0xbb},	{0xbc, 0x0e, 0x00, 0xcc},
-	{0xbc, 0x0f, 0x05, 0xcc},	{0xbc, 0x10, 0xc0, 0xcc},
-	{0xbc, 0x11, 0x03, 0xcc},	{0xb6, 0x00, 0x00, 0xcc},
-	{0xb6, 0x03, 0x01, 0xcc},	{0xb6, 0x02, 0x40, 0xcc},
-	{0xb6, 0x05, 0x00, 0xcc},	{0xb6, 0x04, 0xf0, 0xcc},
-	{0xb6, 0x12, 0xf8, 0xcc},	{0xb6, 0x13, 0x25, 0xcc},
-	{0xb6, 0x18, 0x00, 0xcc},	{0xb6, 0x17, 0x96, 0xcc},
-	{0xb6, 0x16, 0x00, 0xcc},	{0xb6, 0x22, 0x12, 0xcc},
-	{0xb6, 0x23, 0x0b, 0xcc},	{0xbf, 0xc0, 0x39, 0xcc},
-	{0xbf, 0xc1, 0x04, 0xcc},	{0xbf, 0xcc, 0x00, 0xcc},
-	{0xb3, 0x5c, 0x01, 0xcc},	{0xf0, 0x00, 0x01, 0xbb},
-	{0x80, 0x00, 0x03, 0xbb},	{0x81, 0xc7, 0x14, 0xbb},
-	{0x82, 0xeb, 0xe8, 0xbb},	{0x83, 0xfe, 0xf4, 0xbb},
-	{0x84, 0xcd, 0x10, 0xbb},	{0x85, 0xf3, 0xee, 0xbb},
-	{0x86, 0xff, 0xf1, 0xbb},	{0x87, 0xcd, 0x10, 0xbb},
-	{0x88, 0xf3, 0xee, 0xbb},	{0x89, 0x01, 0xf1, 0xbb},
-	{0x8a, 0xe5, 0x17, 0xbb},	{0x8b, 0xe8, 0xe2, 0xbb},
-	{0x8c, 0xf7, 0xed, 0xbb},	{0x8d, 0x00, 0xff, 0xbb},
-	{0x8e, 0xec, 0x10, 0xbb},	{0x8f, 0xf0, 0xed, 0xbb},
-	{0x90, 0xf9, 0xf2, 0xbb},	{0x91, 0x00, 0x00, 0xbb},
-	{0x92, 0xe9, 0x0d, 0xbb},	{0x93, 0xf4, 0xf2, 0xbb},
-	{0x94, 0xfb, 0xf5, 0xbb},	{0x95, 0x00, 0xff, 0xbb},
-	{0xb6, 0x0f, 0x08, 0xbb},	{0xb7, 0x3d, 0x16, 0xbb},
-	{0xb8, 0x0c, 0x04, 0xbb},	{0xb9, 0x1c, 0x07, 0xbb},
-	{0xba, 0x0a, 0x03, 0xbb},	{0xbb, 0x1b, 0x09, 0xbb},
-	{0xbc, 0x17, 0x0d, 0xbb},	{0xbd, 0x23, 0x1d, 0xbb},
-	{0xbe, 0x00, 0x28, 0xbb},	{0xbf, 0x11, 0x09, 0xbb},
-	{0xc0, 0x16, 0x15, 0xbb},	{0xc1, 0x00, 0x1b, 0xbb},
-	{0xc2, 0x0e, 0x07, 0xbb},	{0xc3, 0x14, 0x10, 0xbb},
-	{0xc4, 0x00, 0x17, 0xbb},	{0x06, 0x74, 0x8e, 0xbb},
-	{0xf0, 0x00, 0x01, 0xbb},	{0x06, 0xf4, 0x8e, 0xbb},
-	{0x00, 0x00, 0x50, 0xdd},	{0x06, 0x74, 0x8e, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},	{0x24, 0x50, 0x20, 0xbb},
-	{0xf0, 0x00, 0x02, 0xbb},	{0x34, 0x0c, 0x50, 0xbb},
-	{0xb3, 0x01, 0x41, 0xcc},	{0xf0, 0x00, 0x00, 0xbb},
-	{0x03, 0x03, 0xc0, 0xbb},
-	{},
+static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0xb3, 0x00, 0x24, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb3, 0x05, 0x00, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xdd, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x0d, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x04, 0xcc},
+	{0xb3, 0x23, 0x00, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x04, 0xcc},
+	{0xb3, 0x17, 0xff, 0xcc},
+	{0xb8, 0x01, 0x7d, 0xcc},
+	{0xb8, 0x81, 0x09, 0xcc},
+	{0xb8, 0x27, 0x20, 0xcc},
+	{0xb8, 0x26, 0x80, 0xcc},
+	{0xb8, 0x06, 0x00, 0xcc},
+	{0xb8, 0x07, 0x05, 0xcc},
+	{0xb8, 0x08, 0x00, 0xcc},
+	{0xb8, 0x09, 0x04, 0xcc},
+	{0xb3, 0x00, 0x25, 0xcc},
+	{0xb8, 0x00, 0x11, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xb8, 0x81, 0x01, 0xcc},
+	{0xb8, 0x2c, 0x5a, 0xcc},
+	{0xb8, 0x2d, 0xff, 0xcc},
+	{0xb8, 0x2e, 0xee, 0xcc},
+	{0xb8, 0x2f, 0xfb, 0xcc},
+	{0xb8, 0x30, 0x52, 0xcc},
+	{0xb8, 0x31, 0xf8, 0xcc},
+	{0xb8, 0x32, 0xf1, 0xcc},
+	{0xb8, 0x33, 0xff, 0xcc},
+	{0xb8, 0x34, 0x54, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x0d, 0x00, 0x09, 0xbb},
+	{0x0d, 0x00, 0x08, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x06, 0x00, 0x14, 0xbb},
+	{0x3a, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x9b, 0x10, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x01, 0x00, 0xdd},
+	{0x2b, 0x00, 0x28, 0xbb},
+	{0x2c, 0x00, 0x30, 0xbb},
+	{0x2d, 0x00, 0x30, 0xbb},
+	{0x2e, 0x00, 0x28, 0xbb},
+	{0x41, 0x00, 0xd7, 0xbb},
+	{0x09, 0x02, 0x3a, 0xbb},
+	{0x0c, 0x00, 0x00, 0xbb},
+	{0x20, 0x00, 0x00, 0xbb},
+	{0x05, 0x00, 0x8c, 0xbb},
+	{0x06, 0x00, 0x32, 0xbb},
+	{0x07, 0x00, 0xc6, 0xbb},
+	{0x08, 0x00, 0x19, 0xbb},
+	{0x24, 0x80, 0x6f, 0xbb},
+	{0xc8, 0x00, 0x0f, 0xbb},
+	{0x20, 0x00, 0x03, 0xbb},
+	{0xb6, 0x00, 0x00, 0xcc},
+	{0xb6, 0x03, 0x05, 0xcc},
+	{0xb6, 0x02, 0x00, 0xcc},
+	{0xb6, 0x05, 0x04, 0xcc},
+	{0xb6, 0x04, 0x00, 0xcc},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb6, 0x18, 0x0a, 0xcc},
+	{0xb6, 0x17, 0x00, 0xcc},
+	{0xb6, 0x16, 0x00, 0xcc},
+	{0xb6, 0x22, 0x12, 0xcc},
+	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xb3, 0x02, 0x02, 0xcc},
+	{0xbf, 0xc0, 0x39, 0xcc},
+	{0xbf, 0xc1, 0x04, 0xcc},
+	{0xbf, 0xcc, 0x10, 0xcc},
+	{0xb9, 0x12, 0x00, 0xcc},
+	{0xb9, 0x13, 0x14, 0xcc},
+	{0xb9, 0x14, 0x14, 0xcc},
+	{0xb9, 0x15, 0x14, 0xcc},
+	{0xb9, 0x16, 0x14, 0xcc},
+	{0xb9, 0x18, 0x00, 0xcc},
+	{0xb9, 0x19, 0x1e, 0xcc},
+	{0xb9, 0x1a, 0x1e, 0xcc},
+	{0xb9, 0x1b, 0x1e, 0xcc},
+	{0xb9, 0x1c, 0x1e, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xb8, 0x8e, 0x00, 0xcc},
+	{0xb8, 0x8f, 0xff, 0xcc},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb8, 0x0c, 0x20, 0xcc},
+	{0xb8, 0x0d, 0x70, 0xcc},
+	{0xb6, 0x13, 0x13, 0xcc},
+	{0x2f, 0x00, 0xC0, 0xbb},
+	{0xb8, 0xa0, 0x12, 0xcc},
+	{}
 };
 
 static const __u8 mi1320_gamma[17] = {
@@ -778,6 +931,722 @@
 	{}
 };
 
+static const u8 mi1320_soc_InitVGA[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb8, 0x00, 0x00, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xc8, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x07, 0x00, 0xe0, 0xbb},
+	{0x08, 0x00, 0x0b, 0xbb},
+	{0x21, 0x00, 0x0c, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0xbf, 0xc0, 0x26, 0xcc},
+	{0xbf, 0xc1, 0x02, 0xcc},
+	{0xbf, 0xcc, 0x04, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{}
+};
+static const u8 mi1320_soc_InitVGA_JPG[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb8, 0x00, 0x00, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xc8, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x07, 0x00, 0xe0, 0xbb},
+	{0x08, 0x00, 0x0b, 0xbb},
+	{0x21, 0x00, 0x0c, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0xb6, 0x00, 0x00, 0xcc},
+	{0xb6, 0x03, 0x02, 0xcc},
+	{0xb6, 0x02, 0x80, 0xcc},
+	{0xb6, 0x05, 0x01, 0xcc},
+	{0xb6, 0x04, 0xe0, 0xcc},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb6, 0x13, 0x05, 0xcc},
+	{0xb6, 0x18, 0x02, 0xcc},
+	{0xb6, 0x17, 0x58, 0xcc},
+	{0xb6, 0x16, 0x00, 0xcc},
+	{0xb6, 0x22, 0x12, 0xcc},
+	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xbf, 0xc0, 0x39, 0xcc},
+	{0xbf, 0xc1, 0x04, 0xcc},
+	{0xbf, 0xcc, 0x00, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{}
+};
+static const u8 mi1320_soc_InitQVGA[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb8, 0x00, 0x00, 0xcc},
+	{0xbc, 0x00, 0xd1, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xc8, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x07, 0x00, 0xe0, 0xbb},
+	{0x08, 0x00, 0x0b, 0xbb},
+	{0x21, 0x00, 0x0c, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0xbf, 0xc0, 0x26, 0xcc},
+	{0xbf, 0xc1, 0x02, 0xcc},
+	{0xbf, 0xcc, 0x04, 0xcc},
+	{0xbc, 0x02, 0x18, 0xcc},
+	{0xbc, 0x03, 0x50, 0xcc},
+	{0xbc, 0x04, 0x18, 0xcc},
+	{0xbc, 0x05, 0x00, 0xcc},
+	{0xbc, 0x06, 0x00, 0xcc},
+	{0xbc, 0x08, 0x30, 0xcc},
+	{0xbc, 0x09, 0x40, 0xcc},
+	{0xbc, 0x0a, 0x10, 0xcc},
+	{0xbc, 0x0b, 0x00, 0xcc},
+	{0xbc, 0x0c, 0x00, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{}
+};
+static const u8 mi1320_soc_InitQVGA_JPG[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x01, 0xcc},
+	{0xb3, 0x23, 0xe0, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x02, 0xcc},
+	{0xb3, 0x17, 0x7f, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb8, 0x00, 0x00, 0xcc},
+	{0xbc, 0x00, 0xd1, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0xc8, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x10, 0xdd},
+	{0x07, 0x00, 0xe0, 0xbb},
+	{0x08, 0x00, 0x0b, 0xbb},
+	{0x21, 0x00, 0x0c, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0xb6, 0x00, 0x00, 0xcc},
+	{0xb6, 0x03, 0x01, 0xcc},
+	{0xb6, 0x02, 0x40, 0xcc},
+	{0xb6, 0x05, 0x00, 0xcc},
+	{0xb6, 0x04, 0xf0, 0xcc},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb6, 0x13, 0x05, 0xcc},
+	{0xb6, 0x18, 0x00, 0xcc},
+	{0xb6, 0x17, 0x96, 0xcc},
+	{0xb6, 0x16, 0x00, 0xcc},
+	{0xb6, 0x22, 0x12, 0xcc},
+	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xbf, 0xc0, 0x39, 0xcc},
+	{0xbf, 0xc1, 0x04, 0xcc},
+	{0xbf, 0xcc, 0x00, 0xcc},
+	{0xbc, 0x02, 0x18, 0xcc},
+	{0xbc, 0x03, 0x50, 0xcc},
+	{0xbc, 0x04, 0x18, 0xcc},
+	{0xbc, 0x05, 0x00, 0xcc},
+	{0xbc, 0x06, 0x00, 0xcc},
+	{0xbc, 0x08, 0x30, 0xcc},
+	{0xbc, 0x09, 0x40, 0xcc},
+	{0xbc, 0x0a, 0x10, 0xcc},
+	{0xbc, 0x0b, 0x00, 0xcc},
+	{0xbc, 0x0c, 0x00, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{}
+};
+static const u8 mi1320_soc_InitSXGA_JPG[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0xb0, 0x04, 0x02, 0xcc},
+	{0x00, 0x00, 0x33, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x00, 0xcc},
+	{0xb3, 0x06, 0x00, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x04, 0xcc},
+	{0xb3, 0x23, 0x00, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x04, 0xcc},
+	{0xb3, 0x17, 0xff, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xc8, 0x9f, 0x0b, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0x5b, 0x00, 0x01, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0xb6, 0x00, 0x00, 0xcc},
+	{0xb6, 0x03, 0x05, 0xcc},
+	{0xb6, 0x02, 0x00, 0xcc},
+	{0xb6, 0x05, 0x04, 0xcc},
+	{0xb6, 0x04, 0x00, 0xcc},
+	{0xb6, 0x12, 0xf8, 0xcc},
+	{0xb6, 0x13, 0x29, 0xcc},
+	{0xb6, 0x18, 0x0a, 0xcc},
+	{0xb6, 0x17, 0x00, 0xcc},
+	{0xb6, 0x16, 0x00, 0xcc},
+	{0xb6, 0x22, 0x12, 0xcc},
+	{0xb6, 0x23, 0x0b, 0xcc},
+	{0xbf, 0xc0, 0x39, 0xcc},
+	{0xbf, 0xc1, 0x04, 0xcc},
+	{0xbf, 0xcc, 0x00, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x13, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x00, 0x85, 0xbb},
+	{0x08, 0x00, 0x27, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0x0d, 0xbb},
+	{0x3a, 0x06, 0x1b, 0xbb},
+	{0x3b, 0x00, 0x95, 0xbb},
+	{0x3c, 0x04, 0xdb, 0xbb},
+	{0x57, 0x02, 0x00, 0xbb},
+	{0x58, 0x02, 0x66, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0x5a, 0x01, 0x33, 0xbb},
+	{0x5c, 0x12, 0x0d, 0xbb},
+	{0x5d, 0x16, 0x11, 0xbb},
+	{0x64, 0x5e, 0x1c, 0xbb},
+	{0x2f, 0x90, 0x00, 0xbb},
+	{}
+};
+static const u8 mi1320_soc_InitSXGA[][4] = {
+	{0xb3, 0x01, 0x01, 0xcc},
+	{0xb0, 0x03, 0x19, 0xcc},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xb3, 0x00, 0x64, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xb3, 0x05, 0x01, 0xcc},
+	{0xb3, 0x06, 0x01, 0xcc},
+	{0xb3, 0x08, 0x01, 0xcc},
+	{0xb3, 0x09, 0x0c, 0xcc},
+	{0xb3, 0x34, 0x02, 0xcc},
+	{0xb3, 0x35, 0xc8, 0xcc},
+	{0xb3, 0x02, 0x00, 0xcc},
+	{0xb3, 0x03, 0x0a, 0xcc},
+	{0xb3, 0x04, 0x05, 0xcc},
+	{0xb3, 0x20, 0x00, 0xcc},
+	{0xb3, 0x21, 0x00, 0xcc},
+	{0xb3, 0x22, 0x04, 0xcc},
+	{0xb3, 0x23, 0x00, 0xcc},
+	{0xb3, 0x14, 0x00, 0xcc},
+	{0xb3, 0x15, 0x00, 0xcc},
+	{0xb3, 0x16, 0x04, 0xcc},
+	{0xb3, 0x17, 0xff, 0xcc},
+	{0xb3, 0x00, 0x67, 0xcc},
+	{0xbc, 0x00, 0x71, 0xcc},
+	{0xbc, 0x01, 0x01, 0xcc},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0xc8, 0x9f, 0x0b, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0x5b, 0x00, 0x01, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x00, 0x00, 0x30, 0xdd},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x00, 0x00, 0x20, 0xdd},
+	{0xbf, 0xc0, 0x26, 0xcc},
+	{0xbf, 0xc1, 0x02, 0xcc},
+	{0xbf, 0xcc, 0x04, 0xcc},
+	{0xb3, 0x01, 0x41, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x78, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x01, 0x42, 0xbb},
+	{0x08, 0x00, 0x11, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0xca, 0xbb},
+	{0x3a, 0x06, 0x80, 0xbb},
+	{0x3b, 0x01, 0x52, 0xbb},
+	{0x3c, 0x05, 0x40, 0xbb},
+	{0x57, 0x01, 0x9c, 0xbb},
+	{0x58, 0x01, 0xee, 0xbb},
+	{0x59, 0x00, 0xf0, 0xbb},
+	{0x5a, 0x01, 0x20, 0xbb},
+	{0x5c, 0x1d, 0x17, 0xbb},
+	{0x5d, 0x22, 0x1c, 0xbb},
+	{0x64, 0x1e, 0x1c, 0xbb},
+	{0x5b, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x22, 0xa0, 0x78, 0xbb},
+	{0x23, 0xa0, 0x78, 0xbb},
+	{0x24, 0x7f, 0x00, 0xbb},
+	{0x28, 0xea, 0x02, 0xbb},
+	{0x29, 0x86, 0x7a, 0xbb},
+	{0x5e, 0x52, 0x4c, 0xbb},
+	{0x5f, 0x20, 0x24, 0xbb},
+	{0x60, 0x00, 0x02, 0xbb},
+	{0x02, 0x00, 0xee, 0xbb},
+	{0x03, 0x39, 0x23, 0xbb},
+	{0x04, 0x07, 0x24, 0xbb},
+	{0x09, 0x00, 0xc0, 0xbb},
+	{0x0a, 0x00, 0x79, 0xbb},
+	{0x0b, 0x00, 0x04, 0xbb},
+	{0x0c, 0x00, 0x5c, 0xbb},
+	{0x0d, 0x00, 0xd9, 0xbb},
+	{0x0e, 0x00, 0x53, 0xbb},
+	{0x0f, 0x00, 0x21, 0xbb},
+	{0x10, 0x00, 0xa4, 0xbb},
+	{0x11, 0x00, 0xe5, 0xbb},
+	{0x15, 0x00, 0x00, 0xbb},
+	{0x16, 0x00, 0x00, 0xbb},
+	{0x17, 0x00, 0x00, 0xbb},
+	{0x18, 0x00, 0x00, 0xbb},
+	{0x19, 0x00, 0x00, 0xbb},
+	{0x1a, 0x00, 0x00, 0xbb},
+	{0x1b, 0x00, 0x00, 0xbb},
+	{0x1c, 0x00, 0x00, 0xbb},
+	{0x1d, 0x00, 0x00, 0xbb},
+	{0x1e, 0x00, 0x00, 0xbb},
+	{0xf0, 0x00, 0x01, 0xbb},
+	{0x06, 0xe0, 0x0e, 0xbb},
+	{0x06, 0x60, 0x0e, 0xbb},
+	{0xb3, 0x5c, 0x01, 0xcc},
+	{0xf0, 0x00, 0x00, 0xbb},
+	{0x05, 0x01, 0x13, 0xbb},
+	{0x06, 0x00, 0x11, 0xbb},
+	{0x07, 0x00, 0x85, 0xbb},
+	{0x08, 0x00, 0x27, 0xbb},
+	{0x20, 0x01, 0x03, 0xbb},
+	{0x21, 0x80, 0x00, 0xbb},
+	{0x22, 0x0d, 0x0f, 0xbb},
+	{0x24, 0x80, 0x00, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0xf0, 0x00, 0x02, 0xbb},
+	{0x39, 0x03, 0x0d, 0xbb},
+	{0x3a, 0x06, 0x1b, 0xbb},
+	{0x3b, 0x00, 0x95, 0xbb},
+	{0x3c, 0x04, 0xdb, 0xbb},
+	{0x57, 0x02, 0x00, 0xbb},
+	{0x58, 0x02, 0x66, 0xbb},
+	{0x59, 0x00, 0xff, 0xbb},
+	{0x5a, 0x01, 0x33, 0xbb},
+	{0x5c, 0x12, 0x0d, 0xbb},
+	{0x5d, 0x16, 0x11, 0xbb},
+	{0x64, 0x5e, 0x1c, 0xbb},
+	{}
+};
 static const __u8 po3130_gamma[17] = {
 	0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
 	0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
@@ -1764,26 +2633,43 @@
 };
 
 struct sensor_info {
-	int sensorId;
-	__u8 I2cAdd;
-	__u8 IdAdd;
-	__u16 VpId;
-	__u8 m1;
-	__u8 m2;
-	__u8 op;
-	};
+	s8 sensorId;
+	u8 I2cAdd;
+	u8 IdAdd;
+	u16 VpId;
+	u8 m1;
+	u8 m2;
+	u8 op;
+};
 
 static const struct sensor_info sensor_info_data[] = {
 /*      sensorId,         I2cAdd,	IdAdd,  VpId,  m1,    m2,  op */
-	{SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
-	{SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
+	{-1,		    0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
+	{-1,		    0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
+/* (tested in vc032x_probe_sensor) */
+/*	{-1,		    0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */
 	{SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01},
-	{SENSOR_MI1320,     0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01},
-	{SENSOR_OV7670,     0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
 	{SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
 /* (tested in vc032x_probe_sensor) */
 /*	{SENSOR_MI0360,	    0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
+	{SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
+	{-1,		    0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
+	{-1,		    0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
+	{SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
+/*	{SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */
+	{-1,		    0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/*	{SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */
+/*	{-1,		    0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */
+	{-1,		    0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
 	{SENSOR_PO1200,     0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
+	{-1,		    0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
+	{-1,		    0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+	{-1,		    0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
+	{SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
+/*fixme: previously detected?*/
+	{SENSOR_MI1320,     0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
+/*fixme: not in the ms-win probe - may be found before?*/
+	{SENSOR_OV7670,     0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
 };
 
 /* read 'len' bytes in gspca_dev->usb_buf */
@@ -1814,51 +2700,49 @@
 			500);
 }
 
-static void read_sensor_register(struct gspca_dev *gspca_dev,
-				__u16 address, __u16 *value)
+static u16 read_sensor_register(struct gspca_dev *gspca_dev,
+				u16 address)
 {
 	struct usb_device *dev = gspca_dev->dev;
-	__u8 ldata, mdata, hdata;
+	u8 ldata, mdata, hdata;
 	int retry = 50;
 
-	*value = 0;
-
 	reg_r(gspca_dev, 0xa1, 0xb33f, 1);
-	/*PDEBUG(D_PROBE, " I2c Bus Busy Wait  0x%02X ", tmpvalue); */
 	if (!(gspca_dev->usb_buf[0] & 0x02)) {
-		PDEBUG(D_ERR, "I2c Bus Busy Wait %d",
-			gspca_dev->usb_buf[0] & 0x02);
-		return;
+		PDEBUG(D_ERR, "I2c Bus Busy Wait %02x",
+			gspca_dev->usb_buf[0]);
+		return 0;
 	}
 	reg_w(dev, 0xa0, address, 0xb33a);
 	reg_w(dev, 0xa0, 0x02, 0xb339);
 
-	reg_r(gspca_dev, 0xa1, 0xb33b, 1);
-	while (retry-- && gspca_dev->usb_buf[0]) {
+	do {
 		reg_r(gspca_dev, 0xa1, 0xb33b, 1);
-/*		PDEBUG(D_PROBE, "Read again 0xb33b %d", tmpvalue); */
-		msleep(1);
-	}
+		if (gspca_dev->usb_buf[0] == 0x00)
+			break;
+		msleep(40);
+	} while (--retry >= 0);
+
 	reg_r(gspca_dev, 0xa1, 0xb33e, 1);
 	ldata = gspca_dev->usb_buf[0];
 	reg_r(gspca_dev, 0xa1, 0xb33d, 1);
 	mdata = gspca_dev->usb_buf[0];
 	reg_r(gspca_dev, 0xa1, 0xb33c, 1);
 	hdata = gspca_dev->usb_buf[0];
-	PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
-		hdata, mdata, ldata);
+	if (hdata != 0 && mdata != 0 && ldata != 0)
+		PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
+			hdata, mdata, ldata);
 	reg_r(gspca_dev, 0xa1, 0xb334, 1);
 	if (gspca_dev->usb_buf[0] == 0x02)
-		*value = (hdata << 8) + mdata;
-	else
-		*value = hdata;
+		return (hdata << 8) + mdata;
+	return hdata;
 }
 
 static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
 {
 	struct usb_device *dev = gspca_dev->dev;
 	int i;
-	__u16 value;
+	u16 value;
 	const struct sensor_info *ptsensor_info;
 
 	reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
@@ -1872,48 +2756,51 @@
 		reg_w(dev, 0xa0, 0x0c, 0xb309);
 		reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
 		reg_w(dev, 0xa0, ptsensor_info->op, 0xb301);
-		read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value);
-		if (value == ptsensor_info->VpId)
-			return ptsensor_info->sensorId;
+		value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
+		if (value == 0 && ptsensor_info->IdAdd == 0x82)
+			value = read_sensor_register(gspca_dev, 0x83);
+		if (value != 0) {
+			PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
+				value, i);
+			if (value == ptsensor_info->VpId)
+				return ptsensor_info->sensorId;
 
-		/* special case for MI0360 */
-		if (ptsensor_info->sensorId == SENSOR_MI1310_SOC
-		    && value == 0x8243)
-			return SENSOR_MI0360;
+			switch (value) {
+			case 0x7673:
+				return SENSOR_OV7670;
+			case 0x8243:
+				return SENSOR_MI0360;
+			}
+/*fixme: should return here*/
+		}
 	}
 	return -1;
 }
 
-static __u8 i2c_write(struct gspca_dev *gspca_dev,
-			__u8 reg, const __u8 *val, __u8 size)
+static void i2c_write(struct gspca_dev *gspca_dev,
+			u8 reg, const u8 *val,
+			u8 size)		/* 1 or 2 */
 {
 	struct usb_device *dev = gspca_dev->dev;
+	int retry;
 
-	if (size > 3 || size < 1)
-		return -EINVAL;
 	reg_r(gspca_dev, 0xa1, 0xb33f, 1);
+/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
 	reg_w(dev, 0xa0, size, 0xb334);
 	reg_w(dev, 0xa0, reg, 0xb33a);
-	switch (size) {
-	case 1:
-		reg_w(dev, 0xa0, val[0], 0xb336);
-		break;
-	case 2:
-		reg_w(dev, 0xa0, val[0], 0xb336);
+	reg_w(dev, 0xa0, val[0], 0xb336);
+	if (size > 1)
 		reg_w(dev, 0xa0, val[1], 0xb337);
-		break;
-	case 3:
-		reg_w(dev, 0xa0, val[0], 0xb336);
-		reg_w(dev, 0xa0, val[1], 0xb337);
-		reg_w(dev, 0xa0, val[2], 0xb338);
-		break;
-	default:
-		reg_w(dev, 0xa0, 0x01, 0xb334);
-		return -EINVAL;
-	}
 	reg_w(dev, 0xa0, 0x01, 0xb339);
-	reg_r(gspca_dev, 0xa1, 0xb33b, 1);
-	return gspca_dev->usb_buf[0] == 0;
+	retry = 4;
+	do {
+		reg_r(gspca_dev, 0xa1, 0xb33b, 1);
+		if (gspca_dev->usb_buf[0] == 0)
+			break;
+		msleep(20);
+	} while (--retry > 0);
+	if (retry <= 0)
+		PDEBUG(D_ERR, "i2c_write failed");
 }
 
 static void put_tab_to_reg(struct gspca_dev *gspca_dev,
@@ -1938,7 +2825,7 @@
 			return;
 		case 0xcc:			/* normal write */
 			reg_w(dev, 0xa0, data[i][2],
-					((data[i][0])<<8) | data[i][1]);
+					(data[i][0]) << 8 | data[i][1]);
 			break;
 		case 0xaa:			/* i2c op */
 			i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
@@ -1955,19 +2842,6 @@
 	/*not reached*/
 }
 
-/*
- "GammaT"=hex:04,17,31,4f,6a,83,99,ad,bf,ce,da,e5,ee,f5,fb,ff,ff
- "MatrixT"=hex:60,f9,e5,e7,50,05,f3,e6,66
- */
-
-static void vc0321_reset(struct gspca_dev *gspca_dev)
-{
-	reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d);
-	reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb301);
-	msleep(100);
-	reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003);
-	msleep(100);
-}
 
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
@@ -1979,10 +2853,7 @@
 	int sensor;
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x02;
 	sd->bridge = id->driver_info;
-
-	vc0321_reset(gspca_dev);
 	sensor = vc032x_probe_sensor(gspca_dev);
 	switch (sensor) {
 	case -1:
@@ -2001,6 +2872,9 @@
 	case SENSOR_MI1320:
 		PDEBUG(D_PROBE, "Find Sensor MI1320");
 		break;
+	case SENSOR_MI1320_SOC:
+		PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
+		break;
 	case SENSOR_OV7660:
 		PDEBUG(D_PROBE, "Find Sensor OV7660");
 		break;
@@ -2020,12 +2894,23 @@
 		cam->cam_mode = vc0321_mode;
 		cam->nmodes = ARRAY_SIZE(vc0321_mode);
 	} else {
-		if (sensor != SENSOR_PO1200) {
-			cam->cam_mode = vc0323_mode;
-			cam->nmodes = ARRAY_SIZE(vc0323_mode);
-		} else {
+		switch (sensor) {
+		case SENSOR_PO1200:
 			cam->cam_mode = svga_mode;
 			cam->nmodes = ARRAY_SIZE(svga_mode);
+			break;
+		case SENSOR_MI1310_SOC:
+			cam->cam_mode = vc0323_mode;
+			cam->nmodes = ARRAY_SIZE(vc0323_mode);
+			break;
+		case SENSOR_MI1320_SOC:
+			cam->cam_mode = bi_mode;
+			cam->nmodes = ARRAY_SIZE(bi_mode);
+			break;
+		default:
+			cam->cam_mode = vc0323_mode;
+			cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
+			break;
 		}
 	}
 
@@ -2061,7 +2946,7 @@
 	return 0;
 }
 
-/* this function is called at probe and time */
+/* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
 	return 0;
@@ -2124,9 +3009,18 @@
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	const __u8 (*init)[4];
 	const __u8 *GammaT = NULL;
 	const __u8 *MatrixT = NULL;
 	int mode;
+	static const u8 (*mi1320_soc_init[])[4] = {
+		mi1320_soc_InitSXGA,
+		mi1320_soc_InitSXGA_JPG,
+		mi1320_soc_InitVGA,
+		mi1320_soc_InitVGA_JPG,
+		mi1320_soc_InitQVGA,
+		mi1320_soc_InitQVGA_JPG
+	};
 
 	/* Assume start use the good resolution from gspca_dev->mode */
 	if (sd->bridge == BRIDGE_VC0321) {
@@ -2134,6 +3028,13 @@
 		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed);
 		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee);
 		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef);
+		sd->image_offset = 46;
+	} else {
+		if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
+				== V4L2_PIX_FMT_JPEG)
+			sd->image_offset = 0;
+		else
+			sd->image_offset = 32;
 	}
 
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
@@ -2141,115 +3042,87 @@
 	case SENSOR_HV7131R:
 		GammaT = hv7131r_gamma;
 		MatrixT = hv7131r_matrix;
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, hv7131r_initQVGA_data);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, hv7131r_initVGA_data);
-		}
+		if (mode)
+			init = hv7131r_initQVGA_data;	/* 320x240 */
+		else
+			init = hv7131r_initVGA_data;	/* 640x480 */
 		break;
 	case SENSOR_OV7660:
 		GammaT = ov7660_gamma;
 		MatrixT = ov7660_matrix;
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, ov7660_initQVGA_data);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, ov7660_initVGA_data);
-		}
+		if (mode)
+			init = ov7660_initQVGA_data;	/* 320x240 */
+		else
+			init = ov7660_initVGA_data;	/* 640x480 */
 		break;
 	case SENSOR_OV7670:
 		/*GammaT = ov7660_gamma; */
 		/*MatrixT = ov7660_matrix; */
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, ov7670_initQVGA_JPG);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, ov7670_initVGA_JPG);
-		}
+		if (mode)
+			init = ov7670_initQVGA_JPG;	/* 320x240 */
+		else
+			init = ov7670_initVGA_JPG;	/* 640x480 */
 		break;
 	case SENSOR_MI0360:
 		GammaT = mi1320_gamma;
 		MatrixT = mi0360_matrix;
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, mi0360_initQVGA_JPG);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, mi0360_initVGA_JPG);
-		}
+		if (mode)
+			init = mi0360_initQVGA_JPG;	/* 320x240 */
+		else
+			init = mi0360_initVGA_JPG;	/* 640x480 */
 		break;
 	case SENSOR_MI1310_SOC:
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, mi1310_socinitVGA_JPG);
+		GammaT = mi1320_gamma;
+		MatrixT = mi1320_matrix;
+		switch (mode) {
+		case 1:
+			init = mi1310_socinitQVGA_JPG;	/* 320x240 */
+			break;
+		case 0:
+			init = mi1310_socinitVGA_JPG;	/* 640x480 */
+			break;
+		default:
+			init = mi1310_soc_InitSXGA_JPG;	/* 1280x1024 */
+			break;
 		}
 		break;
 	case SENSOR_MI1320:
 		GammaT = mi1320_gamma;
 		MatrixT = mi1320_matrix;
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, mi1320_initQVGA_data);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, mi1320_initVGA_data);
-		}
+		if (mode)
+			init = mi1320_initQVGA_data;	/* 320x240 */
+		else
+			init = mi1320_initVGA_data;	/* 640x480 */
+		break;
+	case SENSOR_MI1320_SOC:
+		GammaT = mi1320_gamma;
+		MatrixT = mi1320_matrix;
+		init = mi1320_soc_init[mode];
 		break;
 	case SENSOR_PO3130NC:
 		GammaT = po3130_gamma;
 		MatrixT = po3130_matrix;
-		if (mode) {
-			/* 320x240 */
-			usb_exchange(gspca_dev, po3130_initQVGA_data);
-		} else {
-			/* 640x480 */
-			usb_exchange(gspca_dev, po3130_initVGA_data);
-		}
-		usb_exchange(gspca_dev, po3130_rundata);
-		break;
-	case SENSOR_PO1200:
-		GammaT = po1200_gamma;
-		MatrixT = po1200_matrix;
-		usb_exchange(gspca_dev, po1200_initVGA_data);
+		if (mode)
+			init = po3130_initQVGA_data;	/* 320x240 */
+		else
+			init = po3130_initVGA_data;	/* 640x480 */
+		usb_exchange(gspca_dev, init);
+		init = po3130_rundata;
 		break;
 	default:
-		PDEBUG(D_PROBE, "Damned !! no sensor found Bye");
-		return -EMEDIUMTYPE;
+/*	case SENSOR_PO1200: */
+		GammaT = po1200_gamma;
+		MatrixT = po1200_matrix;
+		init = po1200_initVGA_data;
+		break;
 	}
+	usb_exchange(gspca_dev, init);
 	if (GammaT && MatrixT) {
 		put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
 		put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
 		put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
 		put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
 
-		/* Seem SHARPNESS */
-		/*
-		reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80b);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80e);
-		*/
-		/* all 0x40 ??? do nothing
-		reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb822);
-		reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb823);
-		reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb824);
-		*/
-		/* Only works for HV7131R ??
-		reg_r (gspca_dev, 0xa1, 0xb881, 1);
-		reg_w(gspca_dev->dev, 0xa0, 0xfe01, 0xb881);
-		reg_w(gspca_dev->dev, 0xa0, 0x79, 0xb801);
-		*/
-		/* only hv7131r et ov7660
-		reg_w(gspca_dev->dev, 0xa0, 0x20, 0xb827);
-		reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb826); * ISP_GAIN 80
-		reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS
-		*/
 		/* set the led on 0x0892 0x0896 */
 		if (sd->sensor != SENSOR_PO1200) {
 			reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
@@ -2296,12 +3169,8 @@
 			"vc032x header packet found len %d", len);
 		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 						data, 0);
-		if (sd->bridge == BRIDGE_VC0321) {
-#define VCHDRSZ 46
-			data += VCHDRSZ;
-			len -= VCHDRSZ;
-#undef VCHDRSZ
-		}
+		data += sd->image_offset;
+		len -= sd->image_offset;
 		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
 				data, len);
 		return;
@@ -2399,7 +3268,8 @@
 		case 1:		/* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
 			strcpy((char *) menu->name, "50 Hz");
 			return 0;
-		case 2:		/* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+		default:
+/*		case 2:		 * V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
 			strcpy((char *) menu->name, "60 Hz");
 			return 0;
 		}
@@ -2424,6 +3294,7 @@
 
 /* -- module initialisation -- */
 static const __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0323},
 	{USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321},
 	{USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321},
 	{USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321},
@@ -2432,6 +3303,7 @@
 	{USB_DEVICE(0x0ac8, 0x0328), .driver_info = BRIDGE_VC0321},
 	{USB_DEVICE(0x0ac8, 0xc001), .driver_info = BRIDGE_VC0321},
 	{USB_DEVICE(0x0ac8, 0xc002), .driver_info = BRIDGE_VC0321},
+	{USB_DEVICE(0x15b8, 0x6001), .driver_info = BRIDGE_VC0323},
 	{USB_DEVICE(0x15b8, 0x6002), .driver_info = BRIDGE_VC0323},
 	{USB_DEVICE(0x17ef, 0x4802), .driver_info = BRIDGE_VC0323},
 	{}
@@ -2460,8 +3332,11 @@
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index ec2a53d..4fe01d8 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -23,6 +23,7 @@
 #define MODULE_NAME "zc3xx"
 
 #include "gspca.h"
+#include "jpeg.h"
 
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, "
 		"Serge A. Suchkov <Serge.A.S@tochka.ru>");
@@ -31,7 +32,7 @@
 
 static int force_sensor = -1;
 
-#include "jpeg.h"
+#define QUANT_VAL 1		/* quantization table */
 #include "zc3xx-reg.h"
 
 /* specific webcam descriptor */
@@ -44,30 +45,36 @@
 	__u8 autogain;
 	__u8 lightfreq;
 	__u8 sharpness;
+	u8 quality;			/* image quality */
+#define QUALITY_MIN 40
+#define QUALITY_MAX 60
+#define QUALITY_DEF 50
 
-	char qindex;
 	signed char sensor;		/* Type of image sensor chip */
 /* !! values used in different tables */
-#define SENSOR_CS2102 0
-#define SENSOR_CS2102K 1
-#define SENSOR_GC0305 2
-#define SENSOR_HDCS2020b 3
-#define SENSOR_HV7131B 4
-#define SENSOR_HV7131C 5
-#define SENSOR_ICM105A 6
-#define SENSOR_MC501CB 7
-#define SENSOR_OV7620 8
-/*#define SENSOR_OV7648 8 - same values */
-#define SENSOR_OV7630C 9
-#define SENSOR_PAS106 10
-#define SENSOR_PAS202B 11
-#define SENSOR_PB0330 12
-#define SENSOR_PO2030 13
-#define SENSOR_TAS5130CK 14
-#define SENSOR_TAS5130CXX 15
-#define SENSOR_TAS5130C_VF0250 16
-#define SENSOR_MAX 17
+#define SENSOR_ADCM2700 0
+#define SENSOR_CS2102 1
+#define SENSOR_CS2102K 2
+#define SENSOR_GC0305 3
+#define SENSOR_HDCS2020b 4
+#define SENSOR_HV7131B 5
+#define SENSOR_HV7131C 6
+#define SENSOR_ICM105A 7
+#define SENSOR_MC501CB 8
+#define SENSOR_OV7620 9
+/*#define SENSOR_OV7648 9 - same values */
+#define SENSOR_OV7630C 10
+#define SENSOR_PAS106 11
+#define SENSOR_PAS202B 12
+#define SENSOR_PB0330 13
+#define SENSOR_PO2030 14
+#define SENSOR_TAS5130CK 15
+#define SENSOR_TAS5130CXX 16
+#define SENSOR_TAS5130C_VF0250 17
+#define SENSOR_MAX 18
 	unsigned short chip_revision;
+
+	u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -206,6 +213,213 @@
 	__u16	idx;
 };
 
+static const struct usb_action adcm2700_Initial[] = {
+	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},		/* 00,00,01,cc */
+	{0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},		/* 00,02,04,cc */
+	{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},		/* 00,08,03,cc */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},		/* 00,8b,d3,cc */
+	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},	/* 00,03,02,cc */
+	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},		/* 00,04,80,cc */
+	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},	/* 00,05,01,cc */
+	{0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW},	/* 00,06,d8,cc */
+	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},	/* 00,01,01,cc */
+	{0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,03,cc */
+	{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,01,cc */
+	{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,05,cc */
+	{0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},		/* 00,98,00,cc */
+	{0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},		/* 00,9a,00,cc */
+	{0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},		/* 01,1a,00,cc */
+	{0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},		/* 01,1c,00,cc */
+	{0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW},		/* 00,9c,de,cc */
+	{0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},		/* 00,9e,86,cc */
+	{0xbb, 0x00, 0x0400},				/* 04,00,00,bb */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x0f, 0x140f},				/* 14,0f,0f,bb */
+	{0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},	/* 01,01,37,cc */
+	{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},		/* 01,00,0d,cc */
+	{0xa0, 0x06, ZC3XX_R189_AWBSTATUS},		/* 01,89,06,cc */
+	{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},		/* 01,c5,03,cc */
+	{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},		/* 01,cb,13,cc */
+	{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},	/* 02,50,08,cc */
+	{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},		/* 03,01,08,cc */
+	{0xa0, 0x58, ZC3XX_R116_RGAIN},			/* 01,16,58,cc */
+	{0xa0, 0x5a, ZC3XX_R118_BGAIN},			/* 01,18,5a,cc */
+	{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},	/* 01,80,02,cc */
+	{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},		/* 00,8b,d3,cc */
+	{0xbb, 0x00, 0x0408},				/* 04,00,08,bb */
+	{0xdd, 0x00, 0x0200},				/* 00,02,00,dd */
+	{0xbb, 0x00, 0x0400},				/* 04,00,00,bb */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x0f, 0x140f},				/* 14,0f,0f,bb */
+	{0xbb, 0xe0, 0x0c2e},				/* 0c,e0,2e,bb */
+	{0xbb, 0x01, 0x2000},				/* 20,01,00,bb */
+	{0xbb, 0x96, 0x2400},				/* 24,96,00,bb */
+	{0xbb, 0x06, 0x1006},				/* 10,06,06,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x5f, 0x2090},				/* 20,5f,90,bb */
+	{0xbb, 0x01, 0x8000},				/* 80,01,00,bb */
+	{0xbb, 0x09, 0x8400},				/* 84,09,00,bb */
+	{0xbb, 0x86, 0x0002},				/* 00,86,02,bb */
+	{0xbb, 0xe6, 0x0401},				/* 04,e6,01,bb */
+	{0xbb, 0x86, 0x0802},				/* 08,86,02,bb */
+	{0xbb, 0xe6, 0x0c01},				/* 0c,e6,01,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0000},				/* 00,fe,00,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0020},				/* 00,fe,20,aa */
+/*mswin+*/
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
+	{0xaa, 0xfe, 0x0002},
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+	{0xaa, 0xb4, 0xcd37},
+	{0xaa, 0xa4, 0x0004},
+	{0xaa, 0xa8, 0x0007},
+	{0xaa, 0xac, 0x0004},
+/*mswin-*/
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0000},				/* 00,fe,00,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x04, 0x0400},				/* 04,04,00,bb */
+	{0xdd, 0x00, 0x0100},				/* 00,01,00,dd */
+	{0xbb, 0x01, 0x0400},				/* 04,01,00,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xbb, 0x41, 0x2803},				/* 28,41,03,bb */
+	{0xbb, 0x40, 0x2c03},				/* 2c,40,03,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0010},				/* 00,fe,10,aa */
+	{}
+};
+static const struct usb_action adcm2700_InitialScale[] = {
+	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},		/* 00,00,01,cc */
+	{0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},		/* 00,02,10,cc */
+	{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},		/* 00,08,03,cc */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},		/* 00,8b,d3,cc */
+	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},	/* 00,03,02,cc */
+	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},		/* 00,04,80,cc */
+	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},	/* 00,05,01,cc */
+	{0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW},	/* 00,06,d0,cc */
+	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},	/* 00,01,01,cc */
+	{0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,03,cc */
+	{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,01,cc */
+	{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},	/* 00,12,05,cc */
+	{0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},		/* 00,98,00,cc */
+	{0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},		/* 00,9a,00,cc */
+	{0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},		/* 01,1a,00,cc */
+	{0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},		/* 01,1c,00,cc */
+	{0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},		/* 00,9c,d8,cc */
+	{0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},		/* 00,9e,88,cc */
+	{0xbb, 0x00, 0x0400},				/* 04,00,00,bb */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x0f, 0x140f},				/* 14,0f,0f,bb */
+	{0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},	/* 01,01,37,cc */
+	{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},		/* 01,00,0d,cc */
+	{0xa0, 0x06, ZC3XX_R189_AWBSTATUS},		/* 01,89,06,cc */
+	{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},		/* 01,c5,03,cc */
+	{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},		/* 01,cb,13,cc */
+	{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},	/* 02,50,08,cc */
+	{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},		/* 03,01,08,cc */
+	{0xa0, 0x58, ZC3XX_R116_RGAIN},			/* 01,16,58,cc */
+	{0xa0, 0x5a, ZC3XX_R118_BGAIN},			/* 01,18,5a,cc */
+	{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},	/* 01,80,02,cc */
+	{0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},		/* 00,8b,d3,cc */
+	{0xbb, 0x00, 0x0408},				/* 04,00,08,bb */
+	{0xdd, 0x00, 0x0200},				/* 00,02,00,dd */
+	{0xbb, 0x00, 0x0400},				/* 04,00,00,bb */
+	{0xdd, 0x00, 0x0050},				/* 00,00,50,dd */
+	{0xbb, 0x0f, 0x140f},				/* 14,0f,0f,bb */
+	{0xbb, 0xe0, 0x0c2e},				/* 0c,e0,2e,bb */
+	{0xbb, 0x01, 0x2000},				/* 20,01,00,bb */
+	{0xbb, 0x96, 0x2400},				/* 24,96,00,bb */
+	{0xbb, 0x06, 0x1006},				/* 10,06,06,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x5f, 0x2090},				/* 20,5f,90,bb */
+	{0xbb, 0x01, 0x8000},				/* 80,01,00,bb */
+	{0xbb, 0x09, 0x8400},				/* 84,09,00,bb */
+	{0xbb, 0x86, 0x0002},				/* 00,88,02,bb */
+	{0xbb, 0xe6, 0x0401},				/* 04,e6,01,bb */
+	{0xbb, 0x86, 0x0802},				/* 08,88,02,bb */
+	{0xbb, 0xe6, 0x0c01},				/* 0c,e6,01,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0000},				/* 00,fe,00,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0020},				/* 00,fe,20,aa */
+	/*******/
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xaa, 0xfe, 0x0000},				/* 00,fe,00,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xdd, 0x00, 0x0010},				/* 00,00,10,dd */
+	{0xbb, 0x04, 0x0400},				/* 04,04,00,bb */
+	{0xdd, 0x00, 0x0100},				/* 00,01,00,dd */
+	{0xbb, 0x01, 0x0400},				/* 04,01,00,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xbb, 0x41, 0x2803},				/* 28,41,03,bb */
+	{0xbb, 0x40, 0x2c03},				/* 2c,40,03,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0010},				/* 00,fe,10,aa */
+	{}
+};
+static const struct usb_action adcm2700_50HZ[] = {
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xbb, 0x05, 0x8400},				/* 84,05,00,bb */
+	{0xbb, 0xd0, 0xb007},				/* b0,d0,07,bb */
+	{0xbb, 0xa0, 0xb80f},				/* b8,a0,0f,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0010},				/* 00,fe,10,aa */
+	{0xaa, 0x26, 0x00d0},				/* 00,26,d0,aa */
+	{0xaa, 0x28, 0x0002},				/* 00,28,02,aa */
+	{}
+};
+static const struct usb_action adcm2700_60HZ[] = {
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xbb, 0x07, 0x8400},				/* 84,07,00,bb */
+	{0xbb, 0x82, 0xb006},				/* b0,82,06,bb */
+	{0xbb, 0x04, 0xb80d},				/* b8,04,0d,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0010},				/* 00,fe,10,aa */
+	{0xaa, 0x26, 0x0057},				/* 00,26,57,aa */
+	{0xaa, 0x28, 0x0002},				/* 00,28,02,aa */
+	{}
+};
+static const struct usb_action adcm2700_NoFliker[] = {
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0002},				/* 00,fe,02,aa */
+	{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,0a,cc */
+	{0xbb, 0x07, 0x8400},				/* 84,07,00,bb */
+	{0xbb, 0x05, 0xb000},				/* b0,05,00,bb */
+	{0xbb, 0xa0, 0xb801},				/* b8,a0,01,bb */
+	{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},	/* 00,10,01,cc */
+	{0xaa, 0xfe, 0x0010},				/* 00,fe,10,aa */
+	{}
+};
 static const struct usb_action cs2102_Initial[] = {
 	{0xa1, 0x01, 0x0008},
 	{0xa1, 0x01, 0x0008},
@@ -877,7 +1091,7 @@
 };
 
 static const struct usb_action cs2102K_InitialScale[] = {
-	{0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
+	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
 	{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
 	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
 	{0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
@@ -894,6 +1108,7 @@
 	{0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
 	{0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
 	{0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+/*fixme: next sequence = i2c exchanges*/
 	{0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
 	{0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
 	{0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
@@ -1077,207 +1292,6 @@
 	{0xa0, 0x60, ZC3XX_R116_RGAIN},
 	{0xa0, 0x40, ZC3XX_R117_GGAIN},
 	{0xa0, 0x4c, ZC3XX_R118_BGAIN},
-	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-	{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-	{0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
-	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-	{0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-	{0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-	{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-	{0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-	{0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-	{0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-	{0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-	{0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-	{0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-	{0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
-	{0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0A, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0B, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0C, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0D, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0xA3, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0E, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x0C, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
-	{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-	{0xa0, 0x78, ZC3XX_R18D_YTARGET},
-	{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-	{0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-	{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-	{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-	{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
-	{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
-	{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-	{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-	{0xa0, 0x00, 0x01ad},
-	{0xa0, 0x01, 0x01b1},
-	{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-	{0xa0, 0x60, ZC3XX_R116_RGAIN},
-	{0xa0, 0x40, ZC3XX_R117_GGAIN},
-	{0xa0, 0x4c, ZC3XX_R118_BGAIN},
-	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},	/* clock ? */
-	{0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},	/* sharpness+ */
-	{0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},	/* sharpness- */
-	{0xa0, 0x13, ZC3XX_R120_GAMMA00},	/* gamma 4 */
-	{0xa0, 0x38, ZC3XX_R121_GAMMA01},
-	{0xa0, 0x59, ZC3XX_R122_GAMMA02},
-	{0xa0, 0x79, ZC3XX_R123_GAMMA03},
-	{0xa0, 0x92, ZC3XX_R124_GAMMA04},
-	{0xa0, 0xa7, ZC3XX_R125_GAMMA05},
-	{0xa0, 0xb9, ZC3XX_R126_GAMMA06},
-	{0xa0, 0xc8, ZC3XX_R127_GAMMA07},
-	{0xa0, 0xd4, ZC3XX_R128_GAMMA08},
-	{0xa0, 0xdf, ZC3XX_R129_GAMMA09},
-	{0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
-	{0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
-	{0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
-	{0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
-	{0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
-	{0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-	{0xa0, 0x26, ZC3XX_R130_GAMMA10},
-	{0xa0, 0x22, ZC3XX_R131_GAMMA11},
-	{0xa0, 0x20, ZC3XX_R132_GAMMA12},
-	{0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-	{0xa0, 0x16, ZC3XX_R134_GAMMA14},
-	{0xa0, 0x13, ZC3XX_R135_GAMMA15},
-	{0xa0, 0x10, ZC3XX_R136_GAMMA16},
-	{0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-	{0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-	{0xa0, 0x09, ZC3XX_R139_GAMMA19},
-	{0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-	{0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-	{0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-	{0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-	{0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
-	{0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
-	{0xa0, 0x58, ZC3XX_R10A_RGB00},	/* matrix */
-	{0xa0, 0xf4, ZC3XX_R10B_RGB01},
-	{0xa0, 0xf4, ZC3XX_R10C_RGB02},
-	{0xa0, 0xf4, ZC3XX_R10D_RGB10},
-	{0xa0, 0x58, ZC3XX_R10E_RGB11},
-	{0xa0, 0xf4, ZC3XX_R10F_RGB12},
-	{0xa0, 0xf4, ZC3XX_R110_RGB20},
-	{0xa0, 0xf4, ZC3XX_R111_RGB21},
-	{0xa0, 0x58, ZC3XX_R112_RGB22},
-	{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-	{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-	{0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-	{0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-	{0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-	{0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-	{0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
-	{0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
-	{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-	{0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-	{0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
-	{0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-	{0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-	{0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
-	{0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-	{0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-	{0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-	{0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
-	{0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
-	{0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
-	{0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
-	{0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
-	{0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-	{0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-	{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-	{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-	{0xa0, 0x60, ZC3XX_R116_RGAIN},
-	{0xa0, 0x40, ZC3XX_R117_GGAIN},
-	{0xa0, 0x4c, ZC3XX_R118_BGAIN},
 	{0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
 	{0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
 	{0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
@@ -1334,6 +1348,7 @@
 	{0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
 	{0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
 	{0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+/*fixme:what does the next sequence?*/
 	{0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
 	{0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
 	{0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
@@ -6237,7 +6252,7 @@
 	{}
 };
 
-static int reg_r_i(struct gspca_dev *gspca_dev,
+static u8 reg_r_i(struct gspca_dev *gspca_dev,
 		__u16 index)
 {
 	usb_control_msg(gspca_dev->dev,
@@ -6250,10 +6265,10 @@
 	return gspca_dev->usb_buf[0];
 }
 
-static int reg_r(struct gspca_dev *gspca_dev,
+static u8 reg_r(struct gspca_dev *gspca_dev,
 		__u16 index)
 {
-	int ret;
+	u8 ret;
 
 	ret = reg_r_i(gspca_dev, index);
 	PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret);
@@ -6286,8 +6301,8 @@
 	__u8 retbyte;
 	__u16 retval;
 
-	reg_w_i(gspca_dev->dev, reg, 0x92);
-	reg_w_i(gspca_dev->dev, 0x02, 0x90);		/* <- read command */
+	reg_w_i(gspca_dev->dev, reg, 0x0092);
+	reg_w_i(gspca_dev->dev, 0x02, 0x0090);		/* <- read command */
 	msleep(25);
 	retbyte = reg_r_i(gspca_dev, 0x0091);		/* read status */
 	retval = reg_r_i(gspca_dev, 0x0095);		/* read Lowbyte */
@@ -6332,6 +6347,12 @@
 				  action->idx & 0xff,		/* valL */
 				  action->idx >> 8);		/* valH */
 			break;
+		case 0xbb:
+			i2c_write(gspca_dev,
+				  action->idx >> 8,		/* reg */
+				  action->idx & 0xff,		/* valL */
+				  action->val);			/* valH */
+			break;
 		default:
 /*		case 0xdd:	 * delay */
 			msleep(action->val / 64 + 10);
@@ -6347,6 +6368,10 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	int i;
 	const __u8 *matrix;
+	static const u8 adcm2700_matrix[9] =
+/*		{0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
+/*ms-win*/
+		{0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
 	static const __u8 gc0305_matrix[9] =
 		{0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
 	static const __u8 ov7620_matrix[9] =
@@ -6358,23 +6383,24 @@
 	static const __u8 vf0250_matrix[9] =
 		{0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b};
 	static const __u8 *matrix_tb[SENSOR_MAX] = {
-		NULL,		/* SENSOR_CS2102 0 */
-		NULL,		/* SENSOR_CS2102K 1 */
-		gc0305_matrix,	/* SENSOR_GC0305 2 */
-		NULL,		/* SENSOR_HDCS2020b 3 */
-		NULL,		/* SENSOR_HV7131B 4 */
-		NULL,		/* SENSOR_HV7131C 5 */
-		NULL,		/* SENSOR_ICM105A 6 */
-		NULL,		/* SENSOR_MC501CB 7 */
-		ov7620_matrix,	/* SENSOR_OV7620 8 */
-		NULL,		/* SENSOR_OV7630C 9 */
-		NULL,		/* SENSOR_PAS106 10 */
-		pas202b_matrix,	/* SENSOR_PAS202B 11 */
-		NULL,		/* SENSOR_PB0330 12 */
-		po2030_matrix,	/* SENSOR_PO2030 13 */
-		NULL,		/* SENSOR_TAS5130CK 14 */
-		NULL,		/* SENSOR_TAS5130CXX 15 */
-		vf0250_matrix,	/* SENSOR_TAS5130C_VF0250 16 */
+		adcm2700_matrix, /* SENSOR_ADCM2700 0 */
+		NULL,		/* SENSOR_CS2102 1 */
+		NULL,		/* SENSOR_CS2102K 2 */
+		gc0305_matrix,	/* SENSOR_GC0305 3 */
+		NULL,		/* SENSOR_HDCS2020b 4 */
+		NULL,		/* SENSOR_HV7131B 5 */
+		NULL,		/* SENSOR_HV7131C 6 */
+		NULL,		/* SENSOR_ICM105A 7 */
+		NULL,		/* SENSOR_MC501CB 8 */
+		ov7620_matrix,	/* SENSOR_OV7620 9 */
+		NULL,		/* SENSOR_OV7630C 10 */
+		NULL,		/* SENSOR_PAS106 11 */
+		pas202b_matrix,	/* SENSOR_PAS202B 12 */
+		NULL,		/* SENSOR_PB0330 13 */
+		po2030_matrix,	/* SENSOR_PO2030 14 */
+		NULL,		/* SENSOR_TAS5130CK 15 */
+		NULL,		/* SENSOR_TAS5130CXX 16 */
+		vf0250_matrix,	/* SENSOR_TAS5130C_VF0250 17 */
 	};
 
 	matrix = matrix_tb[sd->sensor];
@@ -6398,8 +6424,11 @@
 /*fixme: is it really write to 011d and 018d for all other sensors? */
 	brightness = sd->brightness;
 	reg_w(gspca_dev->dev, brightness, 0x011d);
-	if (sd->sensor == SENSOR_HV7131B)
+	switch (sd->sensor) {
+	case SENSOR_ADCM2700:
+	case SENSOR_HV7131B:
 		return;
+	}
 	if (brightness < 0x70)
 		brightness += 0x10;
 	else
@@ -6536,10 +6565,10 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct usb_device *dev = gspca_dev->dev;
-	__u8 quality;
 	__u8 frxt;
 
 	switch (sd->sensor) {
+	case SENSOR_ADCM2700:
 	case SENSOR_GC0305:
 	case SENSOR_HV7131B:
 	case SENSOR_OV7620:
@@ -6547,26 +6576,18 @@
 		return;
 	}
 /*fixme: is it really 0008 0007 0018 for all other sensors? */
-	quality = sd->qindex;
-	reg_w(dev, quality, 0x0008);
+	reg_w(dev, QUANT_VAL, 0x0008);
 	frxt = 0x30;
 	reg_w(dev, frxt, 0x0007);
-	switch (quality) {
-	case 0:
-	case 1:
-	case 2:
-		frxt = 0xff;
-		break;
-	case 3:
-		frxt = 0xf0;
-		break;
-	case 4:
-		frxt = 0xe0;
-		break;
-	case 5:
-		frxt = 0x20;
-		break;
-	}
+#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2
+	frxt = 0xff;
+#elif QUANT_VAL == 3
+	frxt = 0xf0;
+#elif QUANT_VAL == 4
+	frxt = 0xe0;
+#else
+	frxt = 0x20;
+#endif
 	reg_w(dev, frxt, 0x0018);
 }
 
@@ -6583,71 +6604,75 @@
 	int i, mode;
 	const struct usb_action *zc3_freq;
 	static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
-/* SENSOR_CS2102 0 */
+/* SENSOR_ADCM2700 0 */
+		{adcm2700_NoFliker, adcm2700_NoFliker,
+		 adcm2700_50HZ, adcm2700_50HZ,
+		 adcm2700_60HZ, adcm2700_60HZ},
+/* SENSOR_CS2102 1 */
 		{cs2102_NoFliker, cs2102_NoFlikerScale,
 		 cs2102_50HZ, cs2102_50HZScale,
 		 cs2102_60HZ, cs2102_60HZScale},
-/* SENSOR_CS2102K 1 */
+/* SENSOR_CS2102K 2 */
 		{cs2102_NoFliker, cs2102_NoFlikerScale,
 		 NULL, NULL, /* currently disabled */
 		 NULL, NULL},
-/* SENSOR_GC0305 2 */
+/* SENSOR_GC0305 3 */
 		{gc0305_NoFliker, gc0305_NoFliker,
 		 gc0305_50HZ, gc0305_50HZ,
 		 gc0305_60HZ, gc0305_60HZ},
-/* SENSOR_HDCS2020b 3 */
+/* SENSOR_HDCS2020b 4 */
 		{hdcs2020b_NoFliker, hdcs2020b_NoFliker,
 		 hdcs2020b_50HZ, hdcs2020b_50HZ,
 		 hdcs2020b_60HZ, hdcs2020b_60HZ},
-/* SENSOR_HV7131B 4 */
+/* SENSOR_HV7131B 5 */
 		{hv7131b_NoFlikerScale, hv7131b_NoFliker,
 		 hv7131b_50HZScale, hv7131b_50HZ,
 		 hv7131b_60HZScale, hv7131b_60HZ},
-/* SENSOR_HV7131C 5 */
+/* SENSOR_HV7131C 6 */
 		{NULL, NULL,
 		 NULL, NULL,
 		 NULL, NULL},
-/* SENSOR_ICM105A 6 */
+/* SENSOR_ICM105A 7 */
 		{icm105a_NoFliker, icm105a_NoFlikerScale,
 		 icm105a_50HZ, icm105a_50HZScale,
 		 icm105a_60HZ, icm105a_60HZScale},
-/* SENSOR_MC501CB 7 */
+/* SENSOR_MC501CB 8 */
 		{MC501CB_NoFliker, MC501CB_NoFlikerScale,
 		 MC501CB_50HZ, MC501CB_50HZScale,
 		 MC501CB_60HZ, MC501CB_60HZScale},
-/* SENSOR_OV7620 8 */
+/* SENSOR_OV7620 9 */
 		{OV7620_NoFliker, OV7620_NoFliker,
 		 OV7620_50HZ, OV7620_50HZ,
 		 OV7620_60HZ, OV7620_60HZ},
-/* SENSOR_OV7630C 9 */
+/* SENSOR_OV7630C 10 */
 		{NULL, NULL,
 		 NULL, NULL,
 		 NULL, NULL},
-/* SENSOR_PAS106 10 */
+/* SENSOR_PAS106 11 */
 		{pas106b_NoFliker, pas106b_NoFliker,
 		 pas106b_50HZ, pas106b_50HZ,
 		 pas106b_60HZ, pas106b_60HZ},
-/* SENSOR_PAS202B 11 */
+/* SENSOR_PAS202B 12 */
 		{pas202b_NoFlikerScale, pas202b_NoFliker,
 		 pas202b_50HZScale, pas202b_50HZ,
 		 pas202b_60HZScale, pas202b_60HZ},
-/* SENSOR_PB0330 12 */
+/* SENSOR_PB0330 13 */
 		{pb0330_NoFliker, pb0330_NoFlikerScale,
 		 pb0330_50HZ, pb0330_50HZScale,
 		 pb0330_60HZ, pb0330_60HZScale},
-/* SENSOR_PO2030 13 */
+/* SENSOR_PO2030 14 */
 		{PO2030_NoFliker, PO2030_NoFliker,
 		 PO2030_50HZ, PO2030_50HZ,
 		 PO2030_60HZ, PO2030_60HZ},
-/* SENSOR_TAS5130CK 14 */
+/* SENSOR_TAS5130CK 15 */
 		{tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
 		 tas5130cxx_50HZ, tas5130cxx_50HZScale,
 		 tas5130cxx_60HZ, tas5130cxx_60HZScale},
-/* SENSOR_TAS5130CXX 15 */
+/* SENSOR_TAS5130CXX 16 */
 		{tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
 		 tas5130cxx_50HZ, tas5130cxx_50HZScale,
 		 tas5130cxx_60HZ, tas5130cxx_60HZScale},
-/* SENSOR_TAS5130C_VF0250 16 */
+/* SENSOR_TAS5130C_VF0250 17 */
 		{tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
 		 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
 		 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale},
@@ -6701,6 +6726,7 @@
 		reg_w(dev, 0x0c, 0x003b);
 		reg_w(dev, 0x08, 0x0038);
 		break;
+	case SENSOR_ADCM2700:
 	case SENSOR_GC0305:
 	case SENSOR_OV7620:
 	case SENSOR_PB0330:
@@ -6743,26 +6769,25 @@
 static int vga_2wr_probe(struct gspca_dev *gspca_dev)
 {
 	struct usb_device *dev = gspca_dev->dev;
-	__u8 retbyte;
-	__u16 checkword;
+	u16 retword;
 
 	start_2wr_probe(dev, 0x00);		/* HV7131B */
 	i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x01);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x01);
+	if (retword != 0)
 		return 0x00;			/* HV7131B */
 
 	start_2wr_probe(dev, 0x04);		/* CS2102 */
 	i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x01);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x01);
+	if (retword != 0)
 		return 0x04;			/* CS2102 */
 
 	start_2wr_probe(dev, 0x06);		/* OmniVision */
 	reg_w(dev, 0x08, 0x008d);
 	i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x11);
-	if (retbyte != 0) {
+	retword = i2c_read(gspca_dev, 0x11);
+	if (retword != 0) {
 		/* (should have returned 0xaa) --> Omnivision? */
 		/* reg_r 0x10 -> 0x06 -->  */
 		goto ov_check;
@@ -6770,40 +6795,40 @@
 
 	start_2wr_probe(dev, 0x08);		/* HDCS2020 */
 	i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x15);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x15);
+	if (retword != 0)
 		return 0x08;			/* HDCS2020 */
 
 	start_2wr_probe(dev, 0x0a);		/* PB0330 */
 	i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
-	retbyte = i2c_read(gspca_dev, 0x07);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x07);
+	if (retword != 0)
 		return 0x0a;			/* PB0330 */
-	retbyte = i2c_read(gspca_dev, 0x03);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x03);
+	if (retword != 0)
 		return 0x0a;			/* PB0330 ?? */
-	retbyte = i2c_read(gspca_dev, 0x04);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x04);
+	if (retword != 0)
 		return 0x0a;			/* PB0330 ?? */
 
 	start_2wr_probe(dev, 0x0c);		/* ICM105A */
 	i2c_write(gspca_dev, 0x01, 0x11, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x01);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x01);
+	if (retword != 0)
 		return 0x0c;			/* ICM105A */
 
 	start_2wr_probe(dev, 0x0e);		/* PAS202BCB */
 	reg_w(dev, 0x08, 0x008d);
 	i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
 	msleep(500);
-	retbyte = i2c_read(gspca_dev, 0x03);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x03);
+	if (retword != 0)
 		return 0x0e;			/* PAS202BCB */
 
 	start_2wr_probe(dev, 0x02);		/* ?? */
 	i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-	retbyte = i2c_read(gspca_dev, 0x01);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x01);
+	if (retword != 0)
 		return 0x02;			/* ?? */
 ov_check:
 	reg_r(gspca_dev, 0x0010);		/* ?? */
@@ -6817,12 +6842,10 @@
 	msleep(500);
 	reg_w(dev, 0x01, 0x0012);
 	i2c_write(gspca_dev, 0x12, 0x80, 0x00);	/* sensor reset */
-	retbyte = i2c_read(gspca_dev, 0x0a);
-	checkword = retbyte << 8;
-	retbyte = i2c_read(gspca_dev, 0x0b);
-	checkword |= retbyte;
-	PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", checkword);
-	switch (checkword) {
+	retword = i2c_read(gspca_dev, 0x0a) << 8;
+	retword |= i2c_read(gspca_dev, 0x0b);
+	PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
+	switch (retword) {
 	case 0x7631:				/* OV7630C */
 		reg_w(dev, 0x06, 0x0010);
 		break;
@@ -6832,7 +6855,7 @@
 	default:
 		return -1;			/* not OmniVision */
 	}
-	return checkword;
+	return retword;
 }
 
 struct sensor_by_chipset_revision {
@@ -6845,6 +6868,7 @@
 	{0x8001, 0x13},
 	{0x8000, 0x14},		/* CS2102K */
 	{0x8400, 0x15},		/* TAS5130K */
+	{0x4001, 0x16},		/* ADCM2700 */
 };
 
 static int vga_3wr_probe(struct gspca_dev *gspca_dev)
@@ -6853,7 +6877,7 @@
 	struct usb_device *dev = gspca_dev->dev;
 	int i;
 	__u8 retbyte;
-	__u16 checkword;
+	u16 retword;
 
 /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
 	reg_w(dev, 0x02, 0x0010);
@@ -6865,27 +6889,25 @@
 	reg_w(dev, 0x03, 0x0012);
 	reg_w(dev, 0x01, 0x0012);
 	reg_w(dev, 0x05, 0x0012);
-	retbyte = i2c_read(gspca_dev, 0x14);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x14);
+	if (retword != 0)
 		return 0x11;			/* HV7131R */
-	retbyte = i2c_read(gspca_dev, 0x15);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x15);
+	if (retword != 0)
 		return 0x11;			/* HV7131R */
-	retbyte = i2c_read(gspca_dev, 0x16);
-	if (retbyte != 0)
+	retword = i2c_read(gspca_dev, 0x16);
+	if (retword != 0)
 		return 0x11;			/* HV7131R */
 
 	reg_w(dev, 0x02, 0x0010);
-	retbyte = reg_r(gspca_dev, 0x000b);
-	checkword = retbyte << 8;
-	retbyte = reg_r(gspca_dev, 0x000a);
-	checkword |= retbyte;
-	PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", checkword);
+	retword = reg_r(gspca_dev, 0x000b) << 8;
+	retword |= reg_r(gspca_dev, 0x000a);
+	PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
 	reg_r(gspca_dev, 0x0010);
 	/* this is tested only once anyway */
 	for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
-		if (chipset_revision_sensor[i].revision == checkword) {
-			sd->chip_revision = checkword;
+		if (chipset_revision_sensor[i].revision == retword) {
+			sd->chip_revision = retword;
 			send_unknown(dev, SENSOR_PB0330);
 			return chipset_revision_sensor[i].internal_sensor_id;
 		}
@@ -6897,8 +6919,8 @@
 	reg_w(dev, 0x0a, 0x0010);
 	reg_w(dev, 0x03, 0x0012);
 	reg_w(dev, 0x01, 0x0012);
-	retbyte = i2c_read(gspca_dev, 0x00);
-	if (retbyte != 0) {
+	retword = i2c_read(gspca_dev, 0x00);
+	if (retword != 0) {
 		PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
 		return 0x0a;			/* ?? */
 	}
@@ -6910,14 +6932,14 @@
 	reg_w(dev, 0x03, 0x0012);
 	msleep(2);
 	reg_w(dev, 0x01, 0x0012);
-	retbyte = i2c_read(gspca_dev, 0x00);
-	if (retbyte != 0) {
-		PDEBUG(D_PROBE, "probe 3wr vga type %02x", retbyte);
-		if (retbyte == 0x11)			/* VF0250 */
+	retword = i2c_read(gspca_dev, 0x00);
+	if (retword != 0) {
+		PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
+		if (retword == 0x0011)			/* VF0250 */
 			return 0x0250;
-		if (retbyte == 0x29)			/* gc0305 */
+		if (retword == 0x0029)			/* gc0305 */
 			send_unknown(dev, SENSOR_GC0305);
-		return retbyte;
+		return retword;
 	}
 
 	reg_w(dev, 0x01, 0x0000);	/* check OmniVision */
@@ -6927,8 +6949,8 @@
 	reg_w(dev, 0x06, 0x0010);
 	reg_w(dev, 0x01, 0x0012);
 	reg_w(dev, 0x05, 0x0012);
-	if (i2c_read(gspca_dev, 0x1c) == 0x7f	/* OV7610 - manufacturer ID */
-	    && i2c_read(gspca_dev, 0x1d) == 0xa2) {
+	if (i2c_read(gspca_dev, 0x1c) == 0x007f	/* OV7610 - manufacturer ID */
+	    && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
 		send_unknown(dev, SENSOR_OV7620);
 		return 0x06;		/* OmniVision confirm ? */
 	}
@@ -6942,16 +6964,14 @@
 /*	msleep(150); */
 	reg_w(dev, 0x01, 0x0012);
 	reg_w(dev, 0x05, 0x0012);
-	retbyte = i2c_read(gspca_dev, 0x0000);		/* ID 0 */
-	checkword = retbyte << 8;
-	retbyte = i2c_read(gspca_dev, 0x0001);		/* ID 1 */
-	checkword |= retbyte;
-	PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", checkword);
-	if (checkword == 0x2030) {
+	retword = i2c_read(gspca_dev, 0x00) << 8;	/* ID 0 */
+	retword |= i2c_read(gspca_dev, 0x01);		/* ID 1 */
+	PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
+	if (retword == 0x2030) {
 		retbyte = i2c_read(gspca_dev, 0x02);	/* revision number */
 		PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
 		send_unknown(dev, SENSOR_PO2030);
-		return checkword;
+		return retword;
 	}
 
 	reg_w(dev, 0x01, 0x0000);
@@ -6962,10 +6982,10 @@
 	reg_w(dev, 0x01, 0x0012);
 	reg_w(dev, 0x05, 0x0001);
 	reg_w(dev, 0xd3, 0x008b);
-	retbyte = i2c_read(gspca_dev, 0x01);
-	if (retbyte != 0) {
-		PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
-		return 0x0a;			/* ?? */
+	retword = i2c_read(gspca_dev, 0x01);
+	if (retword != 0) {
+		PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
+		return retword;
 	}
 	return -1;
 }
@@ -6973,7 +6993,7 @@
 static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int sensor, sensor2;
+	int sensor;
 
 	switch (sd->sensor) {
 	case SENSOR_MC501CB:
@@ -6988,16 +7008,9 @@
 		break;
 	}
 	sensor = vga_2wr_probe(gspca_dev);
-	if (sensor >= 0) {
-		if (sensor < 0x7600)
-			return sensor;
-		/* next probe is needed for OmniVision ? */
-	}
-	sensor2 = vga_3wr_probe(gspca_dev);
-	if (sensor2 >= 0
-	    && sensor >= 0)
+	if (sensor >= 0)
 		return sensor;
-	return sensor2;
+	return vga_3wr_probe(gspca_dev);
 }
 
 /* this function is called at probe time */
@@ -7009,23 +7022,24 @@
 	int sensor;
 	int vga = 1;		/* 1: vga, 0: sif */
 	static const __u8 gamma[SENSOR_MAX] = {
-		5,	/* SENSOR_CS2102 0 */
-		5,	/* SENSOR_CS2102K 1 */
-		4,	/* SENSOR_GC0305 2 */
-		4,	/* SENSOR_HDCS2020b 3 */
-		4,	/* SENSOR_HV7131B 4 */
-		4,	/* SENSOR_HV7131C 5 */
-		4,	/* SENSOR_ICM105A 6 */
-		4,	/* SENSOR_MC501CB 7 */
-		3,	/* SENSOR_OV7620 8 */
-		4,	/* SENSOR_OV7630C 9 */
-		4,	/* SENSOR_PAS106 10 */
-		4,	/* SENSOR_PAS202B 11 */
-		4,	/* SENSOR_PB0330 12 */
-		4,	/* SENSOR_PO2030 13 */
-		4,	/* SENSOR_TAS5130CK 14 */
-		4,	/* SENSOR_TAS5130CXX 15 */
-		3,	/* SENSOR_TAS5130C_VF0250 16 */
+		4,	/* SENSOR_ADCM2700 0 */
+		5,	/* SENSOR_CS2102 1 */
+		5,	/* SENSOR_CS2102K 2 */
+		4,	/* SENSOR_GC0305 3 */
+		4,	/* SENSOR_HDCS2020b 4 */
+		4,	/* SENSOR_HV7131B 5 */
+		4,	/* SENSOR_HV7131C 6 */
+		4,	/* SENSOR_ICM105A 7 */
+		4,	/* SENSOR_MC501CB 8 */
+		3,	/* SENSOR_OV7620 9 */
+		4,	/* SENSOR_OV7630C 10 */
+		4,	/* SENSOR_PAS106 11 */
+		4,	/* SENSOR_PAS202B 12 */
+		4,	/* SENSOR_PB0330 13 */
+		4,	/* SENSOR_PO2030 14 */
+		4,	/* SENSOR_TAS5130CK 15 */
+		4,	/* SENSOR_TAS5130CXX 16 */
+		3,	/* SENSOR_TAS5130C_VF0250 17 */
 	};
 
 	/* define some sensors from the vendor/product */
@@ -7033,7 +7047,7 @@
 	sd->sensor = id->driver_info;
 	sensor = zcxx_probeSensor(gspca_dev);
 	if (sensor >= 0)
-		PDEBUG(D_PROBE, "probe sensor -> %02x", sensor);
+		PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
 	if ((unsigned) force_sensor < SENSOR_MAX) {
 		sd->sensor = force_sensor;
 		PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
@@ -7112,6 +7126,10 @@
 				sd->chip_revision);
 			sd->sensor = SENSOR_TAS5130CK;
 			break;
+		case 0x16:
+			PDEBUG(D_PROBE, "Find Sensor ADCM2700");
+			sd->sensor = SENSOR_ADCM2700;
+			break;
 		case 0x29:
 			PDEBUG(D_PROBE, "Find Sensor GC0305");
 			sd->sensor = SENSOR_GC0305;
@@ -7129,12 +7147,16 @@
 			PDEBUG(D_PROBE, "Find Sensor OV7620");
 			sd->sensor = SENSOR_OV7620;
 			break;
+		case 0x7631:
+			PDEBUG(D_PROBE, "Find Sensor OV7630C");
+			sd->sensor = SENSOR_OV7630C;
+			break;
 		case 0x7648:
 			PDEBUG(D_PROBE, "Find Sensor OV7648");
 			sd->sensor = SENSOR_OV7620;	/* same sensor (?) */
 			break;
 		default:
-			PDEBUG(D_ERR|D_PROBE, "Unknown sensor %02x", sensor);
+			PDEBUG(D_ERR|D_PROBE, "Unknown sensor %04x", sensor);
 			return -EINVAL;
 		}
 	}
@@ -7147,7 +7169,6 @@
 	}
 
 	cam = &gspca_dev->cam;
-	cam->epaddr = 0x01;
 /*fixme:test*/
 	gspca_dev->nbalt--;
 	if (vga) {
@@ -7157,12 +7178,12 @@
 		cam->cam_mode = sif_mode;
 		cam->nmodes = ARRAY_SIZE(sif_mode);
 	}
-	sd->qindex = 1;
 	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
 	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
 	sd->gamma = gamma[(int) sd->sensor];
 	sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
 	sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
+	sd->quality = QUALITY_DEF;
 
 	switch (sd->sensor) {
 	case SENSOR_GC0305:
@@ -7196,27 +7217,34 @@
 	const struct usb_action *zc3_init;
 	int mode;
 	static const struct usb_action *init_tb[SENSOR_MAX][2] = {
-		{cs2102_InitialScale, cs2102_Initial},		/* 0 */
-		{cs2102K_InitialScale, cs2102K_Initial},	/* 1 */
-		{gc0305_Initial, gc0305_InitialScale},		/* 2 */
-		{hdcs2020xb_InitialScale, hdcs2020xb_Initial},	/* 3 */
-		{hv7131bxx_InitialScale, hv7131bxx_Initial},	/* 4 */
-		{hv7131cxx_InitialScale, hv7131cxx_Initial},	/* 5 */
-		{icm105axx_InitialScale, icm105axx_Initial},	/* 6 */
-		{MC501CB_InitialScale, MC501CB_Initial},	/* 7 */
-		{OV7620_mode0, OV7620_mode1},			/* 8 */
-		{ov7630c_InitialScale, ov7630c_Initial},	/* 9 */
-		{pas106b_InitialScale, pas106b_Initial},	/* 10 */
-		{pas202b_Initial, pas202b_InitialScale},	/* 11 */
-		{pb0330xx_InitialScale, pb0330xx_Initial},	/* 12 */
+		{adcm2700_Initial, adcm2700_InitialScale},	/* 0 */
+		{cs2102_InitialScale, cs2102_Initial},		/* 1 */
+		{cs2102K_InitialScale, cs2102K_Initial},	/* 2 */
+		{gc0305_Initial, gc0305_InitialScale},		/* 3 */
+		{hdcs2020xb_InitialScale, hdcs2020xb_Initial},	/* 4 */
+		{hv7131bxx_InitialScale, hv7131bxx_Initial},	/* 5 */
+		{hv7131cxx_InitialScale, hv7131cxx_Initial},	/* 6 */
+		{icm105axx_InitialScale, icm105axx_Initial},	/* 7 */
+		{MC501CB_InitialScale, MC501CB_Initial},	/* 8 */
+		{OV7620_mode0, OV7620_mode1},			/* 9 */
+		{ov7630c_InitialScale, ov7630c_Initial},	/* 10 */
+		{pas106b_InitialScale, pas106b_Initial},	/* 11 */
+		{pas202b_Initial, pas202b_InitialScale},	/* 12 */
+		{pb0330xx_InitialScale, pb0330xx_Initial},	/* 13 */
 /* or		{pb03303x_InitialScale, pb03303x_Initial}, */
-		{PO2030_mode0, PO2030_mode1},			/* 13 */
-		{tas5130CK_InitialScale, tas5130CK_Initial},	/* 14 */
-		{tas5130cxx_InitialScale, tas5130cxx_Initial},	/* 15 */
+		{PO2030_mode0, PO2030_mode1},			/* 14 */
+		{tas5130CK_InitialScale, tas5130CK_Initial},	/* 15 */
+		{tas5130cxx_InitialScale, tas5130cxx_Initial},	/* 16 */
 		{tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial},
-								/* 16 */
+								/* 17 */
 	};
 
+	/* create the JPEG header */
+	sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+			0x21);		/* JPEG 422 */
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
 	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
 	zc3_init = init_tb[(int) sd->sensor][mode];
 	switch (sd->sensor) {
@@ -7243,11 +7271,12 @@
 	usb_exchange(gspca_dev, zc3_init);
 
 	switch (sd->sensor) {
+	case SENSOR_ADCM2700:
 	case SENSOR_GC0305:
 	case SENSOR_OV7620:
 	case SENSOR_PO2030:
 	case SENSOR_TAS5130C_VF0250:
-		msleep(100);			/* ?? */
+/*		msleep(100);			 * ?? */
 		reg_r(gspca_dev, 0x0002);	/* --> 0x40 */
 		reg_w(dev, 0x09, 0x01ad);	/* (from win traces) */
 		reg_w(dev, 0x15, 0x01ae);
@@ -7260,6 +7289,7 @@
 	setmatrix(gspca_dev);
 	setbrightness(gspca_dev);
 	switch (sd->sensor) {
+	case SENSOR_ADCM2700:
 	case SENSOR_OV7620:
 		reg_r(gspca_dev, 0x0008);
 		reg_w(dev, 0x00, 0x0008);
@@ -7301,6 +7331,13 @@
 	setlightfreq(gspca_dev);
 
 	switch (sd->sensor) {
+	case SENSOR_ADCM2700:
+		reg_w(dev, 0x09, 0x01ad);	/* (from win traces) */
+		reg_w(dev, 0x15, 0x01ae);
+		reg_w(dev, 0x02, 0x0180);
+						/* ms-win + */
+		reg_w(dev, 0x40, 0x0117);
+		break;
 	case SENSOR_GC0305:
 		reg_w(dev, 0x09, 0x01ad);	/* (from win traces) */
 		reg_w(dev, 0x15, 0x01ae);
@@ -7323,19 +7360,16 @@
 
 	setautogain(gspca_dev);
 	switch (sd->sensor) {
-	case SENSOR_PAS202B:
-		reg_w(dev, 0x00, 0x0007);	/* (from win traces) */
-		break;
 	case SENSOR_PO2030:
 		msleep(500);
 		reg_r(gspca_dev, 0x0008);
 		reg_r(gspca_dev, 0x0007);
+		/*fall thru*/
+	case SENSOR_PAS202B:
 		reg_w(dev, 0x00, 0x0007);	/* (from win traces) */
-		reg_w(dev, 0x02, 0x0008);
+		reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
 		break;
 	}
-	if (sd->sensor == SENSOR_PAS202B)
-		reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
 	return 0;
 }
 
@@ -7344,6 +7378,7 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	kfree(sd->jpeg_hdr);
 	if (!gspca_dev->present)
 		return;
 	send_unknown(gspca_dev->dev, sd->sensor);
@@ -7354,14 +7389,15 @@
 			__u8 *data,
 			int len)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 
 	if (data[0] == 0xff && data[1] == 0xd8) {	/* start of frame */
 		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
 					data, 0);
 		/* put the JPEG header in the new frame */
-		jpeg_put_header(gspca_dev, frame,
-				((struct sd *) gspca_dev)->qindex,
-				0x21);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+			sd->jpeg_hdr, JPEG_HDR_SZ);
+
 		/* remove the webcam's header:
 		 * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
 		 *	- 'ss ss' is the frame sequence number (BE)
@@ -7503,6 +7539,34 @@
 	return -EINVAL;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (jcomp->quality < QUALITY_MIN)
+		sd->quality = QUALITY_MIN;
+	else if (jcomp->quality > QUALITY_MAX)
+		sd->quality = QUALITY_MAX;
+	else
+		sd->quality = jcomp->quality;
+	if (gspca_dev->streaming)
+		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+	return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+			struct v4l2_jpegcompression *jcomp)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	memset(jcomp, 0, sizeof *jcomp);
+	jcomp->quality = sd->quality;
+	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+			| V4L2_JPEG_MARKER_DQT;
+	return 0;
+}
+
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
 	.ctrls = sd_ctrls,
@@ -7513,6 +7577,8 @@
 	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
 	.querymenu = sd_querymenu,
+	.get_jcomp = sd_get_jcomp,
+	.set_jcomp = sd_set_jcomp,
 };
 
 static const __devinitdata struct usb_device_id device_table[] = {
@@ -7563,11 +7629,9 @@
 	{USB_DEVICE(0x055f, 0xd004)},
 	{USB_DEVICE(0x0698, 0x2003)},
 	{USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
-	{USB_DEVICE(0x0ac8, 0x0302)},
+	{USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
 	{USB_DEVICE(0x0ac8, 0x301b)},
-#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
 	{USB_DEVICE(0x0ac8, 0x303b)},
-#endif
 	{USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
 	{USB_DEVICE(0x0ac8, 0x307b)},
 	{USB_DEVICE(0x10fd, 0x0128)},
@@ -7600,8 +7664,10 @@
 
 static int __init sd_mod_init(void)
 {
-	if (usb_register(&sd_driver) < 0)
-		return -1;
+	int ret;
+	ret = usb_register(&sd_driver);
+	if (ret < 0)
+		return ret;
 	PDEBUG(D_PROBE, "registered");
 	return 0;
 }
diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/video/hdpvr/Kconfig
new file mode 100644
index 0000000..de247f3
--- /dev/null
+++ b/drivers/media/video/hdpvr/Kconfig
@@ -0,0 +1,10 @@
+
+config VIDEO_HDPVR
+	tristate "Hauppauge HD PVR support"
+	depends on VIDEO_DEV
+	---help---
+	  This is a video4linux driver for Hauppauge's HD PVR USB device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hdpvr
+
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
new file mode 100644
index 0000000..e0230fc
--- /dev/null
+++ b/drivers/media/video/hdpvr/Makefile
@@ -0,0 +1,9 @@
+hdpvr-objs	:= hdpvr-control.o hdpvr-core.o hdpvr-video.o
+
+hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o
+
+obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c
new file mode 100644
index 0000000..0679174
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-control.c
@@ -0,0 +1,201 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	This program is free software; 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
+{
+	int ret;
+	char request_type = 0x38, snd_request = 0x01;
+
+	msleep(10);
+
+	mutex_lock(&dev->usbc_mutex);
+	dev->usbc_buf[0] = valbuf;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      snd_request, 0x00 | request_type,
+			      value, CTRL_DEFAULT_INDEX,
+			      dev->usbc_buf, 1, 10000);
+
+	mutex_unlock(&dev->usbc_mutex);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "config call request for value 0x%x returned %d\n", value,
+		 ret);
+
+	return ret < 0 ? ret : 0;
+}
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
+{
+	struct hdpvr_video_info *vidinf = NULL;
+#ifdef HDPVR_DEBUG
+	char print_buf[15];
+#endif
+	int ret;
+
+	vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
+	if (!vidinf) {
+		v4l2_err(&dev->v4l2_dev, "out of memory\n");
+		goto err;
+	}
+
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1400, 0x0003,
+			      dev->usbc_buf, 5,
+			      1000);
+	if (ret == 5) {
+		vidinf->width	= dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+		vidinf->height	= dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
+		vidinf->fps	= dev->usbc_buf[4];
+	}
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO) {
+		hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf,
+				   sizeof(print_buf), 0);
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "get video info returned: %d, %s\n", ret, print_buf);
+	}
+#endif
+	mutex_unlock(&dev->usbc_mutex);
+
+	if (!vidinf->width || !vidinf->height || !vidinf->fps) {
+		kfree(vidinf);
+		vidinf = NULL;
+	}
+err:
+	return vidinf;
+}
+
+int get_input_lines_info(struct hdpvr_device *dev)
+{
+#ifdef HDPVR_DEBUG
+	char print_buf[9];
+#endif
+	int ret, lines;
+
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1800, 0x0003,
+			      dev->usbc_buf, 3,
+			      1000);
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO) {
+		hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf,
+				   sizeof(print_buf), 0);
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "get input lines info returned: %d, %s\n", ret,
+			 print_buf);
+	}
+#endif
+	lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+	mutex_unlock(&dev->usbc_mutex);
+	return lines;
+}
+
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev)
+{
+	int ret;
+
+	mutex_lock(&dev->usbc_mutex);
+	memset(dev->usbc_buf, 0, 4);
+	dev->usbc_buf[0] = dev->options.bitrate;
+	dev->usbc_buf[2] = dev->options.peak_bitrate;
+
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0x01, 0x38, CTRL_BITRATE_VALUE,
+			      CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000);
+	mutex_unlock(&dev->usbc_mutex);
+
+	return ret;
+}
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+		    enum v4l2_mpeg_audio_encoding codec)
+{
+	int ret = 0;
+
+	if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+		mutex_lock(&dev->usbc_mutex);
+		memset(dev->usbc_buf, 0, 2);
+		dev->usbc_buf[0] = input;
+		if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC)
+			dev->usbc_buf[1] = 0;
+		else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3)
+			dev->usbc_buf[1] = 1;
+		else {
+			mutex_unlock(&dev->usbc_mutex);
+			v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n",
+				 codec);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		ret = usb_control_msg(dev->udev,
+				      usb_sndctrlpipe(dev->udev, 0),
+				      0x01, 0x38, CTRL_AUDIO_INPUT_VALUE,
+				      CTRL_DEFAULT_INDEX, dev->usbc_buf, 2,
+				      1000);
+		mutex_unlock(&dev->usbc_mutex);
+		if (ret == 2)
+			ret = 0;
+	} else
+		ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE,
+					dev->options.audio_input+1);
+error:
+	return ret;
+}
+
+int hdpvr_set_options(struct hdpvr_device *dev)
+{
+       hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std);
+
+       hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE,
+			 dev->options.video_input+1);
+
+       hdpvr_set_audio(dev, dev->options.audio_input+1,
+		       dev->options.audio_codec);
+
+       hdpvr_set_bitrate(dev);
+       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+			 dev->options.bitrate_mode);
+       hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode);
+
+       hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness);
+       hdpvr_config_call(dev, CTRL_CONTRAST,   dev->options.contrast);
+       hdpvr_config_call(dev, CTRL_HUE,        dev->options.hue);
+       hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation);
+       hdpvr_config_call(dev, CTRL_SHARPNESS,  dev->options.sharpness);
+
+       return 0;
+}
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
new file mode 100644
index 0000000..188bd5a
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -0,0 +1,466 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ * Copyright (C) 2008      John Poet
+ *
+ *	This program is free software; 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET};
+module_param_array(video_nr, int, NULL, 0);
+MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
+
+/* holds the number of currently registered devices */
+static atomic_t dev_nr = ATOMIC_INIT(-1);
+
+int hdpvr_debug;
+module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hdpvr_debug, "enable debugging output");
+
+uint default_video_input = HDPVR_VIDEO_INPUTS;
+module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / "
+		 "1=S-Video / 2=Composite");
+
+uint default_audio_input = HDPVR_AUDIO_INPUTS;
+module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / "
+		 "1=RCA front / 2=S/PDIF");
+
+static int boost_audio;
+module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(boost_audio, "boost the audio signal");
+
+
+/* table of devices that work with this driver */
+static struct usb_device_id hdpvr_table[] = {
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) },
+	{ USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, hdpvr_table);
+
+
+void hdpvr_delete(struct hdpvr_device *dev)
+{
+	hdpvr_free_buffers(dev);
+
+	if (dev->video_dev)
+		video_device_release(dev->video_dev);
+
+	usb_put_dev(dev->udev);
+}
+
+static void challenge(u8 *bytes)
+{
+	u64 *i64P, tmp64;
+	uint i, idx;
+
+	for (idx = 0; idx < 32; ++idx) {
+
+		if (idx & 0x3)
+			bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3];
+
+		switch (idx & 0x3) {
+		case 0x3:
+			bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5];
+			bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9;
+			break;
+		case 0x1:
+			bytes[0] *= 8;
+			bytes[0] += 7*idx + 4;
+			bytes[6] += bytes[3] * 3;
+			break;
+		case 0x0:
+			bytes[3 - (idx >> 3)] = bytes[idx >> 2];
+			bytes[5] += bytes[6] * 3;
+			for (i = 0; i < 3; i++)
+				bytes[3] *= bytes[3] + 1;
+			break;
+		case 0x2:
+			for (i = 0; i < 3; i++)
+				bytes[1] *= bytes[6] + 1;
+			for (i = 0; i < 3; i++) {
+				i64P = (u64 *)bytes;
+				tmp64 = le64_to_cpup(i64P);
+				tmp64 <<= bytes[7] & 0x0f;
+				*i64P += cpu_to_le64(tmp64);
+			}
+			break;
+		}
+	}
+}
+
+/* try to init the device like the windows driver */
+static int device_authorization(struct hdpvr_device *dev)
+{
+
+	int ret, retval = -ENOMEM;
+	char request_type = 0x38, rcv_request = 0x81;
+	char *response;
+#ifdef HDPVR_DEBUG
+	size_t buf_size = 46;
+	char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL);
+	if (!print_buf) {
+		v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+		goto error;
+	}
+#endif
+
+	mutex_lock(&dev->usbc_mutex);
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      rcv_request, 0x80 | request_type,
+			      0x0400, 0x0003,
+			      dev->usbc_buf, 46,
+			      10000);
+	if (ret != 46) {
+		v4l2_err(&dev->v4l2_dev,
+			 "unexpected answer of status request, len %d\n", ret);
+		goto error;
+	}
+#ifdef HDPVR_DEBUG
+	else {
+		hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf,
+				   sizeof(print_buf), 0);
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "Status request returned, len %d: %s\n",
+			 ret, print_buf);
+	}
+#endif
+	if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION) {
+		dev->flags &= ~HDPVR_FLAG_AC3_CAP;
+	} else if (dev->usbc_buf[1] == HDPVR_FIRMWARE_VERSION_AC3) {
+		dev->flags |= HDPVR_FLAG_AC3_CAP;
+	} else if (dev->usbc_buf[1] > HDPVR_FIRMWARE_VERSION_AC3) {
+		v4l2_info(&dev->v4l2_dev, "untested firmware version 0x%x, "
+			  "the driver might not work\n", dev->usbc_buf[1]);
+		dev->flags |= HDPVR_FLAG_AC3_CAP;
+	} else {
+		v4l2_err(&dev->v4l2_dev, "unknown firmware version 0x%x\n",
+			dev->usbc_buf[1]);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	response = dev->usbc_buf+38;
+#ifdef HDPVR_DEBUG
+	hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n",
+		 print_buf);
+#endif
+	challenge(response);
+#ifdef HDPVR_DEBUG
+	hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
+		 print_buf);
+#endif
+
+	msleep(100);
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd1, 0x00 | request_type,
+			      0x0000, 0x0000,
+			      response, 8,
+			      10000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "magic request returned %d\n", ret);
+	mutex_unlock(&dev->usbc_mutex);
+
+	retval = ret != 8;
+error:
+	return retval;
+}
+
+static int hdpvr_device_init(struct hdpvr_device *dev)
+{
+	int ret;
+	u8 *buf;
+	struct hdpvr_video_info *vidinf;
+
+	if (device_authorization(dev))
+		return -EACCES;
+
+	/* default options for init */
+	hdpvr_set_options(dev);
+
+	/* set filter options */
+	mutex_lock(&dev->usbc_mutex);
+	buf = dev->usbc_buf;
+	buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0x01, 0x38,
+			      CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX,
+			      buf, 4,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+	mutex_unlock(&dev->usbc_mutex);
+
+	vidinf = get_video_info(dev);
+	if (!vidinf)
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			"no valid video signal or device init failed\n");
+	else
+		kfree(vidinf);
+
+	/* enable fan and bling leds */
+	mutex_lock(&dev->usbc_mutex);
+	buf[0] = 0x1;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd4, 0x38, 0, 0, buf, 1,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+
+	/* boost analog audio */
+	buf[0] = boost_audio;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      0xd5, 0x38, 0, 0, buf, 1,
+			      1000);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "control request returned %d\n", ret);
+	mutex_unlock(&dev->usbc_mutex);
+
+	dev->status = STATUS_IDLE;
+	return 0;
+}
+
+static const struct hdpvr_options hdpvr_default_options = {
+	.video_std	= HDPVR_60HZ,
+	.video_input	= HDPVR_COMPONENT,
+	.audio_input	= HDPVR_RCA_BACK,
+	.bitrate	= 65, /* 6 mbps */
+	.peak_bitrate	= 90, /* 9 mbps */
+	.bitrate_mode	= HDPVR_CONSTANT,
+	.gop_mode	= HDPVR_SIMPLE_IDR_GOP,
+	.audio_codec	= V4L2_MPEG_AUDIO_ENCODING_AAC,
+	.brightness	= 0x86,
+	.contrast	= 0x80,
+	.hue		= 0x80,
+	.saturation	= 0x80,
+	.sharpness	= 0x80,
+};
+
+static int hdpvr_probe(struct usb_interface *interface,
+		       const struct usb_device_id *id)
+{
+	struct hdpvr_device *dev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	size_t buffer_size;
+	int i;
+	int retval = -ENOMEM;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		err("Out of memory");
+		goto error;
+	}
+
+	/* register v4l2_device early so it can be used for printks */
+	if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
+		err("v4l2_device_register failed");
+		goto error;
+	}
+
+	mutex_init(&dev->io_mutex);
+	mutex_init(&dev->i2c_mutex);
+	mutex_init(&dev->usbc_mutex);
+	dev->usbc_buf = kmalloc(64, GFP_KERNEL);
+	if (!dev->usbc_buf) {
+		v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+		goto error;
+	}
+
+	init_waitqueue_head(&dev->wait_buffer);
+	init_waitqueue_head(&dev->wait_data);
+
+	dev->workqueue = create_singlethread_workqueue("hdpvr_buffer");
+	if (!dev->workqueue)
+		goto error;
+
+	/* init video transfer queues */
+	INIT_LIST_HEAD(&dev->free_buff_list);
+	INIT_LIST_HEAD(&dev->rec_buff_list);
+
+	dev->options = hdpvr_default_options;
+
+	if (default_video_input < HDPVR_VIDEO_INPUTS)
+		dev->options.video_input = default_video_input;
+
+	if (default_audio_input < HDPVR_AUDIO_INPUTS)
+		dev->options.audio_input = default_audio_input;
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* set up the endpoint information */
+	/* use only the first bulk-in and bulk-out endpoints */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (!dev->bulk_in_endpointAddr &&
+		    usb_endpoint_is_bulk_in(endpoint)) {
+			/* USB interface description is buggy, reported max
+			 * packet size is 512 bytes, windows driver uses 8192 */
+			buffer_size = 8192;
+			dev->bulk_in_size = buffer_size;
+			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+		}
+
+	}
+	if (!dev->bulk_in_endpointAddr) {
+		v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
+		goto error;
+	}
+
+	/* init the device */
+	if (hdpvr_device_init(dev)) {
+		v4l2_err(&dev->v4l2_dev, "device init failed\n");
+		goto error;
+	}
+
+	mutex_lock(&dev->io_mutex);
+	if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
+		v4l2_err(&dev->v4l2_dev,
+			 "allocating transfer buffers failed\n");
+		goto error;
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	if (hdpvr_register_videodev(dev, &interface->dev,
+				    video_nr[atomic_inc_return(&dev_nr)])) {
+		v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
+		goto error;
+	}
+
+#ifdef CONFIG_I2C
+	/* until i2c is working properly */
+	retval = 0; /* hdpvr_register_i2c_adapter(dev); */
+	if (retval < 0) {
+		v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n");
+		goto error;
+	}
+#endif /* CONFIG_I2C */
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* let the user know what node this device is now attached to */
+	v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n",
+		  dev->video_dev->minor);
+	return 0;
+
+error:
+	if (dev) {
+		mutex_unlock(&dev->io_mutex);
+		/* this frees allocated memory */
+		hdpvr_delete(dev);
+	}
+	return retval;
+}
+
+static void hdpvr_disconnect(struct usb_interface *interface)
+{
+	struct hdpvr_device *dev;
+	int minor;
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	minor = dev->video_dev->minor;
+
+	/* prevent more I/O from starting and stop any ongoing */
+	mutex_lock(&dev->io_mutex);
+	dev->status = STATUS_DISCONNECTED;
+	v4l2_device_disconnect(&dev->v4l2_dev);
+	video_unregister_device(dev->video_dev);
+	wake_up_interruptible(&dev->wait_data);
+	wake_up_interruptible(&dev->wait_buffer);
+	mutex_unlock(&dev->io_mutex);
+	msleep(100);
+	flush_workqueue(dev->workqueue);
+	mutex_lock(&dev->io_mutex);
+	hdpvr_cancel_queue(dev);
+	destroy_workqueue(dev->workqueue);
+	mutex_unlock(&dev->io_mutex);
+
+	/* deregister I2C adapter */
+#ifdef CONFIG_I2C
+	mutex_lock(&dev->i2c_mutex);
+	if (dev->i2c_adapter)
+		i2c_del_adapter(dev->i2c_adapter);
+	kfree(dev->i2c_adapter);
+	dev->i2c_adapter = NULL;
+	mutex_unlock(&dev->i2c_mutex);
+#endif /* CONFIG_I2C */
+
+	atomic_dec(&dev_nr);
+
+	v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	kfree(dev->usbc_buf);
+	kfree(dev);
+}
+
+
+static struct usb_driver hdpvr_usb_driver = {
+	.name =		"hdpvr",
+	.probe =	hdpvr_probe,
+	.disconnect =	hdpvr_disconnect,
+	.id_table =	hdpvr_table,
+};
+
+static int __init hdpvr_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&hdpvr_usb_driver);
+	if (result)
+		err("usb_register failed. Error number %d", result);
+
+	return result;
+}
+
+static void __exit hdpvr_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&hdpvr_usb_driver);
+}
+
+module_init(hdpvr_init);
+module_exit(hdpvr_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Janne Grunau");
+MODULE_DESCRIPTION("Hauppauge HD PVR driver");
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
new file mode 100644
index 0000000..c4b5d15
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -0,0 +1,145 @@
+
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	This program is free software; 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.
+ *
+ */
+
+#include <linux/i2c.h>
+
+#include "hdpvr.h"
+
+#define CTRL_READ_REQUEST	0xb8
+#define CTRL_WRITE_REQUEST	0x38
+
+#define REQTYPE_I2C_READ	0xb1
+#define REQTYPE_I2C_WRITE	0xb0
+#define REQTYPE_I2C_WRITE_STATT	0xd0
+
+static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
+			  char *data, int len)
+{
+	int ret;
+	char *buf = kmalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
+			      0x100|addr, 0, buf, len, 1000);
+
+	if (ret == len) {
+		memcpy(data, buf, len);
+		ret = 0;
+	} else if (ret >= 0)
+		ret = -EIO;
+
+	kfree(buf);
+
+	return ret;
+}
+
+static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
+			   char *data, int len)
+{
+	int ret;
+	char *buf = kmalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, data, len);
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+			      0x100|addr, 0, buf, len, 1000);
+
+	if (ret < 0)
+		goto error;
+
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
+			      0, 0, buf, 2, 1000);
+
+	if (ret == 2)
+		ret = 0;
+	else if (ret >= 0)
+		ret = -EIO;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
+			  int num)
+{
+	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
+	int retval = 0, i, addr;
+
+	if (num <= 0)
+		return 0;
+
+	mutex_lock(&dev->i2c_mutex);
+
+	for (i = 0; i < num && !retval; i++) {
+		addr = msgs[i].addr << 1;
+
+		if (msgs[i].flags & I2C_M_RD)
+			retval = hdpvr_i2c_read(dev, addr, msgs[i].buf,
+						msgs[i].len);
+		else
+			retval = hdpvr_i2c_write(dev, addr, msgs[i].buf,
+						 msgs[i].len);
+	}
+
+	mutex_unlock(&dev->i2c_mutex);
+
+	return retval ? retval : num;
+}
+
+static u32 hdpvr_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm hdpvr_algo = {
+	.master_xfer   = hdpvr_transfer,
+	.functionality = hdpvr_functionality,
+};
+
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
+{
+	struct i2c_adapter *i2c_adap;
+	int retval = -ENOMEM;
+
+	i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (i2c_adap == NULL)
+		goto error;
+
+	strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C",
+		sizeof(i2c_adap->name));
+	i2c_adap->algo  = &hdpvr_algo;
+	i2c_adap->class = I2C_CLASS_TV_ANALOG;
+	i2c_adap->id    = I2C_HW_B_HDPVR;
+	i2c_adap->owner = THIS_MODULE;
+	i2c_adap->dev.parent = &dev->udev->dev;
+
+	i2c_set_adapdata(i2c_adap, dev);
+
+	retval = i2c_add_adapter(i2c_adap);
+
+	if (!retval)
+		dev->i2c_adapter = i2c_adap;
+	else
+		kfree(i2c_adap);
+
+error:
+	return retval;
+}
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
new file mode 100644
index 0000000..3e6ffee
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -0,0 +1,1248 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	This program is free software; 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "hdpvr.h"
+
+#define BULK_URB_TIMEOUT 1250 /* 1.25 seconds */
+
+#define print_buffer_status() { \
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,	\
+			 "%s:%d buffer stat: %d free, %d proc\n",	\
+			 __func__, __LINE__,				\
+			 list_size(&dev->free_buff_list),		\
+			 list_size(&dev->rec_buff_list)); }
+
+struct hdpvr_fh {
+	struct hdpvr_device	*dev;
+};
+
+static uint list_size(struct list_head *list)
+{
+	struct list_head *tmp;
+	uint count = 0;
+
+	list_for_each(tmp, list) {
+		count++;
+	}
+
+	return count;
+}
+
+/*=========================================================================*/
+/* urb callback */
+static void hdpvr_read_bulk_callback(struct urb *urb)
+{
+	struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context;
+	struct hdpvr_device *dev = buf->dev;
+
+	/* marking buffer as received and wake waiting */
+	buf->status = BUFSTAT_READY;
+	wake_up_interruptible(&dev->wait_data);
+}
+
+/*=========================================================================*/
+/* bufffer bits */
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_cancel_queue(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+
+	list_for_each_entry(buf, &dev->rec_buff_list, buff_list) {
+		usb_kill_urb(buf->urb);
+		buf->status = BUFSTAT_AVAILABLE;
+	}
+
+	list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev);
+
+	return 0;
+}
+
+static int hdpvr_free_queue(struct list_head *q)
+{
+	struct list_head *tmp;
+	struct list_head *p;
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+
+	for (p = q->next; p != q;) {
+		buf = list_entry(p, struct hdpvr_buffer, buff_list);
+
+		urb = buf->urb;
+		usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+				urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		tmp = p->next;
+		list_del(p);
+		kfree(buf);
+		p = tmp;
+	}
+
+	return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_free_buffers(struct hdpvr_device *dev)
+{
+	hdpvr_cancel_queue(dev);
+
+	hdpvr_free_queue(&dev->free_buff_list);
+	hdpvr_free_queue(&dev->rec_buff_list);
+
+	return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
+{
+	uint i;
+	int retval = -ENOMEM;
+	u8 *mem;
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "allocating %u buffers\n", count);
+
+	for (i = 0; i < count; i++) {
+
+		buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL);
+		if (!buf) {
+			v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n");
+			goto exit;
+		}
+		buf->dev = dev;
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n");
+			goto exit;
+		}
+		buf->urb = urb;
+
+		mem = usb_buffer_alloc(dev->udev, dev->bulk_in_size, GFP_KERNEL,
+				       &urb->transfer_dma);
+		if (!mem) {
+			v4l2_err(&dev->v4l2_dev,
+				 "cannot allocate usb transfer buffer\n");
+			goto exit;
+		}
+
+		usb_fill_bulk_urb(buf->urb, dev->udev,
+				  usb_rcvbulkpipe(dev->udev,
+						  dev->bulk_in_endpointAddr),
+				  mem, dev->bulk_in_size,
+				  hdpvr_read_bulk_callback, buf);
+
+		buf->status = BUFSTAT_AVAILABLE;
+		list_add_tail(&buf->buff_list, &dev->free_buff_list);
+	}
+	return 0;
+exit:
+	hdpvr_free_buffers(dev);
+	return retval;
+}
+
+static int hdpvr_submit_buffers(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+	struct urb *urb;
+	int ret = 0, err_count = 0;
+
+	mutex_lock(&dev->io_mutex);
+
+	while (dev->status == STATUS_STREAMING &&
+	       !list_empty(&dev->free_buff_list)) {
+
+		buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer,
+				 buff_list);
+		if (buf->status != BUFSTAT_AVAILABLE) {
+			v4l2_err(&dev->v4l2_dev,
+				 "buffer not marked as availbale\n");
+			ret = -EFAULT;
+			goto err;
+		}
+
+		urb = buf->urb;
+		urb->status = 0;
+		urb->actual_length = 0;
+		ret = usb_submit_urb(urb, GFP_KERNEL);
+		if (ret) {
+			v4l2_err(&dev->v4l2_dev,
+				 "usb_submit_urb in %s returned %d\n",
+				 __func__, ret);
+			if (++err_count > 2)
+				break;
+			continue;
+		}
+		buf->status = BUFSTAT_INPROGRESS;
+		list_move_tail(&buf->buff_list, &dev->rec_buff_list);
+	}
+err:
+	print_buffer_status();
+	mutex_unlock(&dev->io_mutex);
+	return ret;
+}
+
+static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev)
+{
+	struct hdpvr_buffer *buf;
+
+	mutex_lock(&dev->io_mutex);
+
+	if (list_empty(&dev->rec_buff_list)) {
+		mutex_unlock(&dev->io_mutex);
+		return NULL;
+	}
+
+	buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer,
+			 buff_list);
+	mutex_unlock(&dev->io_mutex);
+
+	return buf;
+}
+
+static void hdpvr_transmit_buffers(struct work_struct *work)
+{
+	struct hdpvr_device *dev = container_of(work, struct hdpvr_device,
+						worker);
+
+	while (dev->status == STATUS_STREAMING) {
+
+		if (hdpvr_submit_buffers(dev)) {
+			v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n");
+			goto error;
+		}
+		if (wait_event_interruptible(dev->wait_buffer,
+				!list_empty(&dev->free_buff_list) ||
+					     dev->status != STATUS_STREAMING))
+			goto error;
+	}
+
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "transmit worker exited\n");
+	return;
+error:
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "transmit buffers errored\n");
+	dev->status = STATUS_ERROR;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_start_streaming(struct hdpvr_device *dev)
+{
+	int ret;
+	struct hdpvr_video_info *vidinf;
+
+	if (dev->status == STATUS_STREAMING)
+		return 0;
+	else if (dev->status != STATUS_IDLE)
+		return -EAGAIN;
+
+	vidinf = get_video_info(dev);
+
+	if (vidinf) {
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			 "video signal: %dx%d@%dhz\n", vidinf->width,
+			 vidinf->height, vidinf->fps);
+		kfree(vidinf);
+
+		/* start streaming 2 request */
+		ret = usb_control_msg(dev->udev,
+				      usb_sndctrlpipe(dev->udev, 0),
+				      0xb8, 0x38, 0x1, 0, NULL, 0, 8000);
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			 "encoder start control request returned %d\n", ret);
+
+		hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00);
+
+		INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
+		queue_work(dev->workqueue, &dev->worker);
+
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			 "streaming started\n");
+		dev->status = STATUS_STREAMING;
+
+		return 0;
+	}
+	msleep(250);
+	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+		 "no video signal at input %d\n", dev->options.video_input);
+	return -EAGAIN;
+}
+
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_stop_streaming(struct hdpvr_device *dev)
+{
+	uint actual_length, c = 0;
+	u8 *buf;
+
+	if (dev->status == STATUS_IDLE)
+		return 0;
+	else if (dev->status != STATUS_STREAMING)
+		return -EAGAIN;
+
+	buf = kmalloc(dev->bulk_in_size, GFP_KERNEL);
+	if (!buf)
+		v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer "
+			 "for emptying the internal device buffer. "
+			 "Next capture start will be slow\n");
+
+	dev->status = STATUS_SHUTTING_DOWN;
+	hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00);
+	mutex_unlock(&dev->io_mutex);
+
+	wake_up_interruptible(&dev->wait_buffer);
+	msleep(50);
+
+	flush_workqueue(dev->workqueue);
+
+	mutex_lock(&dev->io_mutex);
+	/* kill the still outstanding urbs */
+	hdpvr_cancel_queue(dev);
+
+	/* emptying the device buffer beforeshutting it down */
+	while (buf && ++c < 500 &&
+	       !usb_bulk_msg(dev->udev,
+			     usb_rcvbulkpipe(dev->udev,
+					     dev->bulk_in_endpointAddr),
+			     buf, dev->bulk_in_size, &actual_length,
+			     BULK_URB_TIMEOUT)) {
+		/* wait */
+		msleep(5);
+		v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+			 "%2d: got %d bytes\n", c, actual_length);
+	}
+	kfree(buf);
+	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+		 "used %d urbs to empty device buffers\n", c-1);
+	msleep(10);
+
+	dev->status = STATUS_IDLE;
+
+	return 0;
+}
+
+
+/*=======================================================================*/
+/*
+ * video 4 linux 2 file operations
+ */
+
+static int hdpvr_open(struct file *file)
+{
+	struct hdpvr_device *dev;
+	struct hdpvr_fh *fh;
+	int retval = -ENOMEM;
+
+	dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
+	if (!dev) {
+		v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n");
+		retval = -ENODEV;
+		goto err;
+	}
+
+	fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL);
+	if (!fh) {
+		v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+		goto err;
+	}
+	/* lock the device to allow correctly handling errors
+	 * in resumption */
+	mutex_lock(&dev->io_mutex);
+	dev->open_count++;
+
+	fh->dev = dev;
+
+	/* save our object in the file's private structure */
+	file->private_data = fh;
+
+	retval = 0;
+err:
+	mutex_unlock(&dev->io_mutex);
+	return retval;
+}
+
+static int hdpvr_release(struct file *file)
+{
+	struct hdpvr_fh		*fh  = (struct hdpvr_fh *)file->private_data;
+	struct hdpvr_device	*dev = fh->dev;
+
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->io_mutex);
+	if (!(--dev->open_count) && dev->status == STATUS_STREAMING)
+		hdpvr_stop_streaming(dev);
+
+	mutex_unlock(&dev->io_mutex);
+
+	return 0;
+}
+
+/*
+ * hdpvr_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
+			  loff_t *pos)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	struct hdpvr_buffer *buf = NULL;
+	struct urb *urb;
+	unsigned int ret = 0;
+	int rem, cnt;
+
+	if (*pos)
+		return -ESPIPE;
+
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->io_mutex);
+	if (dev->status == STATUS_IDLE) {
+		if (hdpvr_start_streaming(dev)) {
+			v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+				 "start_streaming failed\n");
+			ret = -EIO;
+			msleep(200);
+			dev->status = STATUS_IDLE;
+			mutex_unlock(&dev->io_mutex);
+			goto err;
+		}
+		print_buffer_status();
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	/* wait for the first buffer */
+	if (!(file->f_flags & O_NONBLOCK)) {
+		if (wait_event_interruptible(dev->wait_data,
+					     hdpvr_get_next_buffer(dev)))
+			return -ERESTARTSYS;
+	}
+
+	buf = hdpvr_get_next_buffer(dev);
+
+	while (count > 0 && buf) {
+
+		if (buf->status != BUFSTAT_READY &&
+		    dev->status != STATUS_DISCONNECTED) {
+			/* return nonblocking */
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				goto err;
+			}
+
+			if (wait_event_interruptible(dev->wait_data,
+					      buf->status == BUFSTAT_READY)) {
+				ret = -ERESTARTSYS;
+				goto err;
+			}
+		}
+
+		if (buf->status != BUFSTAT_READY)
+			break;
+
+		/* set remaining bytes to copy */
+		urb = buf->urb;
+		rem = urb->actual_length - buf->pos;
+		cnt = rem > count ? count : rem;
+
+		if (copy_to_user(buffer, urb->transfer_buffer + buf->pos,
+				 cnt)) {
+			v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n");
+			if (!ret)
+				ret = -EFAULT;
+			goto err;
+		}
+
+		buf->pos += cnt;
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+
+		/* finished, take next buffer */
+		if (buf->pos == urb->actual_length) {
+			mutex_lock(&dev->io_mutex);
+			buf->pos = 0;
+			buf->status = BUFSTAT_AVAILABLE;
+
+			list_move_tail(&buf->buff_list, &dev->free_buff_list);
+
+			print_buffer_status();
+
+			mutex_unlock(&dev->io_mutex);
+
+			wake_up_interruptible(&dev->wait_buffer);
+
+			buf = hdpvr_get_next_buffer(dev);
+		}
+	}
+err:
+	if (!ret && !buf)
+		ret = -EAGAIN;
+	return ret;
+}
+
+static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
+{
+	struct hdpvr_buffer *buf = NULL;
+	struct hdpvr_fh *fh = (struct hdpvr_fh *)filp->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	unsigned int mask = 0;
+
+	mutex_lock(&dev->io_mutex);
+
+	if (video_is_unregistered(dev->video_dev))
+		return -EIO;
+
+	if (dev->status == STATUS_IDLE) {
+		if (hdpvr_start_streaming(dev)) {
+			v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+				 "start_streaming failed\n");
+			dev->status = STATUS_IDLE;
+		}
+
+		print_buffer_status();
+	}
+	mutex_unlock(&dev->io_mutex);
+
+	buf = hdpvr_get_next_buffer(dev);
+	/* only wait if no data is available */
+	if (!buf || buf->status != BUFSTAT_READY) {
+		poll_wait(filp, &dev->wait_data, wait);
+		buf = hdpvr_get_next_buffer(dev);
+	}
+	if (buf && buf->status == BUFSTAT_READY)
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
+}
+
+
+static const struct v4l2_file_operations hdpvr_fops = {
+	.owner		= THIS_MODULE,
+	.open		= hdpvr_open,
+	.release	= hdpvr_release,
+	.read		= hdpvr_read,
+	.poll		= hdpvr_poll,
+	.unlocked_ioctl	= video_ioctl2,
+};
+
+/*=======================================================================*/
+/*
+ * V4L2 ioctl handling
+ */
+
+static int vidioc_querycap(struct file *file, void  *priv,
+			   struct v4l2_capability *cap)
+{
+	struct hdpvr_device *dev = video_drvdata(file);
+
+	strcpy(cap->driver, "hdpvr");
+	strcpy(cap->card, "Haupauge HD PVR");
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->version = HDPVR_VERSION;
+	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
+				V4L2_CAP_AUDIO         |
+				V4L2_CAP_READWRITE;
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *private_data,
+			v4l2_std_id *std)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	u8 std_type = 1;
+
+	if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
+		std_type = 0;
+
+	return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type);
+}
+
+static const char *iname[] = {
+	[HDPVR_COMPONENT] = "Component",
+	[HDPVR_SVIDEO]    = "S-Video",
+	[HDPVR_COMPOSITE] = "Composite",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	unsigned int n;
+
+	n = i->index;
+	if (n >= HDPVR_VIDEO_INPUTS)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+
+	strncpy(i->name, iname[n], sizeof(i->name) - 1);
+	i->name[sizeof(i->name) - 1] = '\0';
+
+	i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF;
+
+	i->std = dev->video_dev->tvnorms;
+
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *private_data,
+			  unsigned int index)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int retval;
+
+	if (index >= HDPVR_VIDEO_INPUTS)
+		return -EINVAL;
+
+	if (dev->status != STATUS_IDLE)
+		return -EAGAIN;
+
+	retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1);
+	if (!retval)
+		dev->options.video_input = index;
+
+	return retval;
+}
+
+static int vidioc_g_input(struct file *file, void *private_data,
+			  unsigned int *index)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+
+	*index = dev->options.video_input;
+	return 0;
+}
+
+
+static const char *audio_iname[] = {
+	[HDPVR_RCA_FRONT] = "RCA front",
+	[HDPVR_RCA_BACK]  = "RCA back",
+	[HDPVR_SPDIF]     = "SPDIF",
+};
+
+static int vidioc_enumaudio(struct file *file, void *priv,
+				struct v4l2_audio *audio)
+{
+	unsigned int n;
+
+	n = audio->index;
+	if (n >= HDPVR_AUDIO_INPUTS)
+		return -EINVAL;
+
+	audio->capability = V4L2_AUDCAP_STEREO;
+
+	strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1);
+	audio->name[sizeof(audio->name) - 1] = '\0';
+
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *private_data,
+			  struct v4l2_audio *audio)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int retval;
+
+	if (audio->index >= HDPVR_AUDIO_INPUTS)
+		return -EINVAL;
+
+	if (dev->status != STATUS_IDLE)
+		return -EAGAIN;
+
+	retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec);
+	if (!retval)
+		dev->options.audio_input = audio->index;
+
+	return retval;
+}
+
+static int vidioc_g_audio(struct file *file, void *private_data,
+			  struct v4l2_audio *audio)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+
+	audio->index = dev->options.audio_input;
+	audio->capability = V4L2_AUDCAP_STEREO;
+	strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
+	audio->name[sizeof(audio->name) - 1] = '\0';
+	return 0;
+}
+
+static const s32 supported_v4l2_ctrls[] = {
+	V4L2_CID_BRIGHTNESS,
+	V4L2_CID_CONTRAST,
+	V4L2_CID_SATURATION,
+	V4L2_CID_HUE,
+	V4L2_CID_SHARPNESS,
+	V4L2_CID_MPEG_AUDIO_ENCODING,
+	V4L2_CID_MPEG_VIDEO_ENCODING,
+	V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+	V4L2_CID_MPEG_VIDEO_BITRATE,
+	V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+};
+
+static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc,
+			  int ac3)
+{
+	int err;
+
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86);
+	case V4L2_CID_CONTRAST:
+		return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+	case V4L2_CID_SHARPNESS:
+		return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_fill(
+			qc, V4L2_MPEG_AUDIO_ENCODING_AAC,
+			ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3
+			: V4L2_MPEG_AUDIO_ENCODING_AAC,
+			1, V4L2_MPEG_AUDIO_ENCODING_AAC);
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		return v4l2_ctrl_query_fill(
+			qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
+
+/* 	case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */
+/* 		return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		return v4l2_ctrl_query_fill(
+			qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000,
+					    6500000);
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000,
+					   9000000);
+		if (!err && opt->bitrate_mode == HDPVR_CONSTANT)
+			qc->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int vidioc_queryctrl(struct file *file, void *private_data,
+			    struct v4l2_queryctrl *qc)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int i, next;
+	u32 id = qc->id;
+
+	memset(qc, 0, sizeof(*qc));
+
+	next = !!(id &  V4L2_CTRL_FLAG_NEXT_CTRL);
+	qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+
+	for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) {
+		if (next) {
+			if (qc->id < supported_v4l2_ctrls[i])
+				qc->id = supported_v4l2_ctrls[i];
+			else
+				continue;
+		}
+
+		if (qc->id == supported_v4l2_ctrls[i])
+			return fill_queryctrl(&dev->options, qc,
+					      dev->flags & HDPVR_FLAG_AC3_CAP);
+
+		if (qc->id < supported_v4l2_ctrls[i])
+			break;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *private_data,
+			 struct v4l2_control *ctrl)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = dev->options.brightness;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctrl->value = dev->options.contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctrl->value = dev->options.saturation;
+		break;
+	case V4L2_CID_HUE:
+		ctrl->value = dev->options.hue;
+		break;
+	case V4L2_CID_SHARPNESS:
+		ctrl->value = dev->options.sharpness;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *private_data,
+			 struct v4l2_control *ctrl)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int retval;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value);
+		if (!retval)
+			dev->options.brightness = ctrl->value;
+		break;
+	case V4L2_CID_CONTRAST:
+		retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value);
+		if (!retval)
+			dev->options.contrast = ctrl->value;
+		break;
+	case V4L2_CID_SATURATION:
+		retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value);
+		if (!retval)
+			dev->options.saturation = ctrl->value;
+		break;
+	case V4L2_CID_HUE:
+		retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value);
+		if (!retval)
+			dev->options.hue = ctrl->value;
+		break;
+	case V4L2_CID_SHARPNESS:
+		retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value);
+		if (!retval)
+			dev->options.sharpness = ctrl->value;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return retval;
+}
+
+
+static int hdpvr_get_ctrl(struct hdpvr_options *opt,
+			  struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		ctrl->value = opt->audio_codec;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
+		break;
+/* 	case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/* 		ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */
+/* 		break; */
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT
+			? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
+			: V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctrl->value = opt->bitrate * 100000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		ctrl->value = opt->peak_bitrate * 100000;
+		break;
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+			      struct v4l2_ext_controls *ctrls)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int i, err = 0;
+
+	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+		for (i = 0; i < ctrls->count; i++) {
+			struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+			err = hdpvr_get_ctrl(&dev->options, ctrl);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+		}
+		return err;
+
+	}
+
+	return -EINVAL;
+}
+
+
+static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
+{
+	int ret = -EINVAL;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC ||
+		    (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3))
+			ret = 0;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
+			ret = 0;
+		break;
+/* 	case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/* 		if (ctrl->value == 0 || ctrl->value == 128) */
+/* 			ret = 0; */
+/* 		break; */
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR ||
+		    ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+			ret = 0;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+	{
+		uint bitrate = ctrl->value / 100000;
+		if (bitrate >= 10 && bitrate <= 135)
+			ret = 0;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+	{
+		uint peak_bitrate = ctrl->value / 100000;
+		if (peak_bitrate >= 10 && peak_bitrate <= 202)
+			ret = 0;
+		break;
+	}
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
+			ret = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+				struct v4l2_ext_controls *ctrls)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int i, err = 0;
+
+	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+		for (i = 0; i < ctrls->count; i++) {
+			struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+			err = hdpvr_try_ctrl(ctrl,
+					     dev->flags & HDPVR_FLAG_AC3_CAP);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+		}
+		return err;
+	}
+
+	return -EINVAL;
+}
+
+
+static int hdpvr_set_ctrl(struct hdpvr_device *dev,
+			  struct v4l2_ext_control *ctrl)
+{
+	struct hdpvr_options *opt = &dev->options;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+			opt->audio_codec = ctrl->value;
+			ret = hdpvr_set_audio(dev, opt->audio_input,
+					      opt->audio_codec);
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		break;
+/* 	case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/* 		if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */
+/* 			opt->gop_mode |= 0x2; */
+/* 			hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/* 					  opt->gop_mode); */
+/* 		} */
+/* 		if (ctrl->value == 128 && opt->gop_mode & 0x2) { */
+/* 			opt->gop_mode &= ~0x2; */
+/* 			hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/* 					  opt->gop_mode); */
+/* 		} */
+/* 		break; */
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR &&
+		    opt->bitrate_mode != HDPVR_CONSTANT) {
+			opt->bitrate_mode = HDPVR_CONSTANT;
+			hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+					  opt->bitrate_mode);
+		}
+		if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+		    opt->bitrate_mode == HDPVR_CONSTANT) {
+			opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE;
+			hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+					  opt->bitrate_mode);
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE: {
+		uint bitrate = ctrl->value / 100000;
+
+		opt->bitrate = bitrate;
+		if (bitrate >= opt->peak_bitrate)
+			opt->peak_bitrate = bitrate+1;
+
+		hdpvr_set_bitrate(dev);
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: {
+		uint peak_bitrate = ctrl->value / 100000;
+
+		if (opt->bitrate_mode == HDPVR_CONSTANT)
+			break;
+
+		if (opt->bitrate < peak_bitrate) {
+			opt->peak_bitrate = peak_bitrate;
+			hdpvr_set_bitrate(dev);
+		} else
+			ret = -EINVAL;
+		break;
+	}
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+			      struct v4l2_ext_controls *ctrls)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int i, err = 0;
+
+	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+		for (i = 0; i < ctrls->count; i++) {
+			struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+			err = hdpvr_try_ctrl(ctrl,
+					     dev->flags & HDPVR_FLAG_AC3_CAP);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+			err = hdpvr_set_ctrl(dev, ctrl);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+		}
+		return err;
+
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
+				    struct v4l2_fmtdesc *f)
+{
+
+	if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+	strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32);
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
+				struct v4l2_format *f)
+{
+	struct hdpvr_fh *fh = file->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	struct hdpvr_video_info *vid_info;
+
+	if (!dev)
+		return -ENODEV;
+
+	vid_info = get_video_info(dev);
+	if (!vid_info)
+		return -EFAULT;
+
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	f->fmt.pix.pixelformat	= V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.width	= vid_info->width;
+	f->fmt.pix.height	= vid_info->height;
+	f->fmt.pix.sizeimage	= dev->bulk_in_size;
+	f->fmt.pix.colorspace	= 0;
+	f->fmt.pix.bytesperline	= 0;
+	f->fmt.pix.field	= V4L2_FIELD_ANY;
+
+	kfree(vid_info);
+	return 0;
+}
+
+static int vidioc_encoder_cmd(struct file *filp, void *priv,
+			       struct v4l2_encoder_cmd *a)
+{
+	struct hdpvr_fh *fh = filp->private_data;
+	struct hdpvr_device *dev = fh->dev;
+	int res;
+
+	mutex_lock(&dev->io_mutex);
+
+	memset(&a->raw, 0, sizeof(a->raw));
+	switch (a->cmd) {
+	case V4L2_ENC_CMD_START:
+		a->flags = 0;
+		res = hdpvr_start_streaming(dev);
+		break;
+	case V4L2_ENC_CMD_STOP:
+		res = hdpvr_stop_streaming(dev);
+		break;
+	default:
+		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+			 "Unsupported encoder cmd %d\n", a->cmd);
+		res = -EINVAL;
+	}
+	mutex_unlock(&dev->io_mutex);
+	return res;
+}
+
+static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
+					struct v4l2_encoder_cmd *a)
+{
+	switch (a->cmd) {
+	case V4L2_ENC_CMD_START:
+	case V4L2_ENC_CMD_STOP:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
+	.vidioc_querycap	= vidioc_querycap,
+	.vidioc_s_std		= vidioc_s_std,
+	.vidioc_enum_input	= vidioc_enum_input,
+	.vidioc_g_input		= vidioc_g_input,
+	.vidioc_s_input		= vidioc_s_input,
+	.vidioc_enumaudio	= vidioc_enumaudio,
+	.vidioc_g_audio		= vidioc_g_audio,
+	.vidioc_s_audio		= vidioc_s_audio,
+	.vidioc_queryctrl	= vidioc_queryctrl,
+	.vidioc_g_ctrl		= vidioc_g_ctrl,
+	.vidioc_s_ctrl		= vidioc_s_ctrl,
+	.vidioc_g_ext_ctrls	= vidioc_g_ext_ctrls,
+	.vidioc_s_ext_ctrls	= vidioc_s_ext_ctrls,
+	.vidioc_try_ext_ctrls	= vidioc_try_ext_ctrls,
+	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
+	.vidioc_encoder_cmd	= vidioc_encoder_cmd,
+	.vidioc_try_encoder_cmd	= vidioc_try_encoder_cmd,
+};
+
+static void hdpvr_device_release(struct video_device *vdev)
+{
+	struct hdpvr_device *dev = video_get_drvdata(vdev);
+
+	hdpvr_delete(dev);
+}
+
+static const struct video_device hdpvr_video_template = {
+/* 	.type			= VFL_TYPE_GRABBER, */
+/* 	.type2			= VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */
+	.fops			= &hdpvr_fops,
+	.release		= hdpvr_device_release,
+	.ioctl_ops 		= &hdpvr_ioctl_ops,
+	.tvnorms 		=
+		V4L2_STD_NTSC  | V4L2_STD_SECAM | V4L2_STD_PAL_B |
+		V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I |
+		V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N |
+		V4L2_STD_PAL_60,
+};
+
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+			    int devnum)
+{
+	/* setup and register video device */
+	dev->video_dev = video_device_alloc();
+	if (!dev->video_dev) {
+		v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n");
+		goto error;
+	}
+
+	*(dev->video_dev) = hdpvr_video_template;
+	strcpy(dev->video_dev->name, "Hauppauge HD PVR");
+	dev->video_dev->parent = parent;
+	video_set_drvdata(dev->video_dev, dev);
+
+	if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) {
+		v4l2_err(&dev->v4l2_dev, "video_device registration failed\n");
+		goto error;
+	}
+
+	return 0;
+error:
+	return -ENOMEM;
+}
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h
new file mode 100644
index 0000000..1edd875
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr.h
@@ -0,0 +1,303 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *	This program is free software; 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.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+
+#define HDPVR_MAJOR_VERSION 0
+#define HDPVR_MINOR_VERSION 2
+#define HDPVR_RELEASE 0
+#define HDPVR_VERSION \
+	KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE)
+
+#define HDPVR_MAX 8
+
+/* Define these values to match your devices */
+#define HD_PVR_VENDOR_ID	0x2040
+#define HD_PVR_PRODUCT_ID	0x4900
+#define HD_PVR_PRODUCT_ID1	0x4901
+#define HD_PVR_PRODUCT_ID2	0x4902
+
+#define UNSET    (-1U)
+
+#define NUM_BUFFERS 64
+
+#define HDPVR_FIRMWARE_VERSION		0x8
+#define HDPVR_FIRMWARE_VERSION_AC3	0xd
+
+/* #define HDPVR_DEBUG */
+
+extern int hdpvr_debug;
+
+#define MSG_INFO	1
+#define MSG_BUFFER	2
+
+struct hdpvr_options {
+	u8	video_std;
+	u8	video_input;
+	u8	audio_input;
+	u8	bitrate;	/* in 100kbps */
+	u8	peak_bitrate;	/* in 100kbps */
+	u8	bitrate_mode;
+	u8	gop_mode;
+	enum v4l2_mpeg_audio_encoding	audio_codec;
+	u8	brightness;
+	u8	contrast;
+	u8	hue;
+	u8	saturation;
+	u8	sharpness;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct hdpvr_device {
+	/* the v4l device for this device */
+	struct video_device	*video_dev;
+	/* the usb device for this device */
+	struct usb_device	*udev;
+	/* v4l2-device unused */
+	struct v4l2_device	v4l2_dev;
+
+	/* the max packet size of the bulk endpoint */
+	size_t			bulk_in_size;
+	/* the address of the bulk in endpoint */
+	__u8			bulk_in_endpointAddr;
+
+	/* holds the current device status */
+	__u8			status;
+	/* count the number of openers */
+	uint			open_count;
+
+	/* holds the cureent set options */
+	struct hdpvr_options	options;
+
+	uint			flags;
+
+	/* synchronize I/O */
+	struct mutex		io_mutex;
+	/* available buffers */
+	struct list_head	free_buff_list;
+	/* in progress buffers */
+	struct list_head	rec_buff_list;
+	/* waitqueue for buffers */
+	wait_queue_head_t	wait_buffer;
+	/* waitqueue for data */
+	wait_queue_head_t	wait_data;
+	/**/
+	struct workqueue_struct	*workqueue;
+	/**/
+	struct work_struct	worker;
+
+	/* I2C adapter */
+	struct i2c_adapter	*i2c_adapter;
+	/* I2C lock */
+	struct mutex		i2c_mutex;
+
+	/* usb control transfer buffer and lock */
+	struct mutex		usbc_mutex;
+	u8			*usbc_buf;
+};
+
+
+/* buffer one bulk urb of data */
+struct hdpvr_buffer {
+	struct list_head	buff_list;
+
+	struct urb		*urb;
+
+	struct hdpvr_device	*dev;
+
+	uint			pos;
+
+	__u8			status;
+};
+
+/* */
+
+struct hdpvr_video_info {
+	u16	width;
+	u16	height;
+	u8	fps;
+};
+
+enum {
+	STATUS_UNINITIALIZED	= 0,
+	STATUS_IDLE,
+	STATUS_STARTING,
+	STATUS_SHUTTING_DOWN,
+	STATUS_STREAMING,
+	STATUS_ERROR,
+	STATUS_DISCONNECTED,
+};
+
+enum {
+	HDPVR_FLAG_AC3_CAP = 1,
+};
+
+enum {
+	BUFSTAT_UNINITIALIZED = 0,
+	BUFSTAT_AVAILABLE,
+	BUFSTAT_INPROGRESS,
+	BUFSTAT_READY,
+};
+
+#define CTRL_START_STREAMING_VALUE	0x0700
+#define CTRL_STOP_STREAMING_VALUE	0x0800
+#define CTRL_BITRATE_VALUE		0x1000
+#define CTRL_BITRATE_MODE_VALUE		0x1200
+#define CTRL_GOP_MODE_VALUE		0x1300
+#define CTRL_VIDEO_INPUT_VALUE		0x1500
+#define CTRL_VIDEO_STD_TYPE		0x1700
+#define CTRL_AUDIO_INPUT_VALUE		0x2500
+#define CTRL_BRIGHTNESS			0x2900
+#define CTRL_CONTRAST			0x2a00
+#define CTRL_HUE			0x2b00
+#define CTRL_SATURATION			0x2c00
+#define CTRL_SHARPNESS			0x2d00
+#define CTRL_LOW_PASS_FILTER_VALUE	0x3100
+
+#define CTRL_DEFAULT_INDEX		0x0003
+
+
+	/* :0 s 38 01 1000 0003 0004 4 = 0a00ca00
+	 * BITRATE SETTING
+	 *   1st and 2nd byte (little endian): average bitrate in 100 000 bit/s
+	 *                                     min: 1 mbit/s, max: 13.5 mbit/s
+	 *   3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s
+	 *                                     min: average + 100kbit/s,
+	 *                                      max: 20.2 mbit/s
+	 */
+
+	/* :0 s 38 01 1200 0003 0001 1 = 02
+	 * BIT RATE MODE
+	 *  constant = 1, variable (peak) = 2, variable (average) = 3
+	 */
+
+	/* :0 s 38 01 1300 0003 0001 1 = 03
+	 * GOP MODE (2 bit)
+	 *    low bit 0/1: advanced/simple GOP
+	 *   high bit 0/1: IDR(4/32/128) / no IDR (4/32/0)
+	 */
+
+	/* :0 s 38 01 1700 0003 0001 1 = 00
+	 * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz
+	 */
+
+	/* :0 s 38 01 3100 0003 0004 4 = 03030000
+	 * FILTER CONTROL
+	 *   1st byte luma low pass filter strength,
+	 *   2nd byte chroma low pass filter strength,
+	 *   3rd byte MF enable chroma, min=0, max=1
+	 *   4th byte n
+	 */
+
+
+	/* :0 s 38 b9 0001 0000 0000 0 */
+
+
+
+/* :0 s 38 d3 0000 0000 0001 1 = 00 */
+/* 		ret = usb_control_msg(dev->udev, */
+/* 				      usb_sndctrlpipe(dev->udev, 0), */
+/* 				      0xd3, 0x38, */
+/* 				      0, 0, */
+/* 				      "\0", 1, */
+/* 				      1000); */
+
+/* 		info("control request returned %d", ret); */
+/* 		msleep(5000); */
+
+
+	/* :0 s b8 81 1400 0003 0005 5 <
+	 * :0 0 5 = d0024002 19
+	 * QUERY FRAME SIZE AND RATE
+	 *   1st and 2nd byte (little endian): horizontal resolution
+	 *   3rd and 4th byte (little endian): vertical resolution
+	 *   5th byte: frame rate
+	 */
+
+	/* :0 s b8 81 1800 0003 0003 3 <
+	 * :0 0 3 = 030104
+	 * QUERY SIGNAL AND DETECTED LINES, maybe INPUT
+	 */
+
+enum hdpvr_video_std {
+	HDPVR_60HZ = 0,
+	HDPVR_50HZ,
+};
+
+enum hdpvr_video_input {
+	HDPVR_COMPONENT = 0,
+	HDPVR_SVIDEO,
+	HDPVR_COMPOSITE,
+	HDPVR_VIDEO_INPUTS
+};
+
+enum hdpvr_audio_inputs {
+	HDPVR_RCA_BACK = 0,
+	HDPVR_RCA_FRONT,
+	HDPVR_SPDIF,
+	HDPVR_AUDIO_INPUTS
+};
+
+enum hdpvr_bitrate_mode {
+	HDPVR_CONSTANT = 1,
+	HDPVR_VARIABLE_PEAK,
+	HDPVR_VARIABLE_AVERAGE,
+};
+
+enum hdpvr_gop_mode {
+	HDPVR_ADVANCED_IDR_GOP = 0,
+	HDPVR_SIMPLE_IDR_GOP,
+	HDPVR_ADVANCED_NOIDR_GOP,
+	HDPVR_SIMPLE_NOIDR_GOP,
+};
+
+void hdpvr_delete(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* hardware control functions */
+int hdpvr_set_options(struct hdpvr_device *dev);
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev);
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+		    enum v4l2_mpeg_audio_encoding codec);
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value,
+		      unsigned char valbuf);
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev);
+
+/* :0 s b8 81 1800 0003 0003 3 < */
+/* :0 0 3 = 0301ff */
+int get_input_lines_info(struct hdpvr_device *dev);
+
+
+/*========================================================================*/
+/* v4l2 registration */
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+			    int devnumber);
+
+int hdpvr_cancel_queue(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* i2c adapter registration */
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* buffer management */
+int hdpvr_free_buffers(struct hdpvr_device *dev);
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count);
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index 79393d1..8e1463e 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -56,17 +56,6 @@
 	u8 byte;
 };
 
-static struct saa7146_extension_ioctls ioctls[] = {
-	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_QUERYCTRL, 	SAA7146_BEFORE },
-	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_STD,		SAA7146_AFTER },
-	{ VIDIOC_G_CTRL,	SAA7146_BEFORE },
-	{ VIDIOC_S_CTRL,	SAA7146_BEFORE },
-	{ 0,			0 }
-};
-
 #define HEXIUM_CONTROLS	1
 static struct v4l2_queryctrl hexium_controls[] = {
 	{ V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
@@ -231,6 +220,132 @@
 	return 0;
 }
 
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+
+	if (i->index < 0 || i->index >= HEXIUM_INPUTS)
+		return -EINVAL;
+
+	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
+
+	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	*input = hexium->cur_input;
+
+	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+
+	if (input < 0 || input >= HEXIUM_INPUTS)
+		return -EINVAL;
+
+	hexium->cur_input = input;
+	hexium_set_input(hexium, input);
+	return 0;
+}
+
+/* the saa7146 provides some controls (brightness, contrast, saturation)
+   which gets registered *after* this function. because of this we have
+   to return with a value != 0 even if the function succeded.. */
+static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	int i;
+
+	for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+		if (hexium_controls[i].id == qc->id) {
+			*qc = hexium_controls[i];
+			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+			return 0;
+		}
+	}
+	return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	int i;
+
+	for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+		if (hexium_controls[i].id == vc->id)
+			break;
+	}
+
+	if (i < 0)
+		return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
+
+	if (vc->id == V4L2_CID_PRIVATE_BASE) {
+		vc->value = hexium->cur_bw;
+		DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	int i = 0;
+
+	for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+		if (hexium_controls[i].id == vc->id)
+			break;
+	}
+
+	if (i < 0)
+		return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
+
+	if (vc->id == V4L2_CID_PRIVATE_BASE)
+		hexium->cur_bw = vc->value;
+
+	DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
+
+	if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
+		hexium_set_standard(hexium, hexium_pal);
+		return 0;
+	}
+	if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
+		hexium_set_standard(hexium, hexium_ntsc);
+		return 0;
+	}
+	if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
+		hexium_set_standard(hexium, hexium_secam);
+		return 0;
+	}
+	if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
+		hexium_set_standard(hexium, hexium_pal_bw);
+		return 0;
+	}
+	if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
+		hexium_set_standard(hexium, hexium_ntsc_bw);
+		return 0;
+	}
+	if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std)
+		/* fixme: is there no bw secam mode? */
+		return -EINVAL;
+
+	return -EINVAL;
+}
+
+
 static struct saa7146_ext_vv vv_data;
 
 /* this function only gets called when the probing was successful */
@@ -279,6 +394,12 @@
 	hexium->cur_input = 0;
 
 	saa7146_vv_init(dev, &vv_data);
+	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
+	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
+	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
+	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
+	vv_data.ops.vidioc_g_input = vidioc_g_input;
+	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
 		printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
 		return -1;
@@ -306,153 +427,6 @@
 	return 0;
 }
 
-static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct hexium *hexium = (struct hexium *) dev->ext_priv;
-/*
-	struct saa7146_vv *vv = dev->vv_data;
-*/
-	switch (cmd) {
-	case VIDIOC_ENUMINPUT:
-		{
-			struct v4l2_input *i = arg;
-			DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
-
-			if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
-				return -EINVAL;
-			}
-
-			memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
-
-			DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
-			return 0;
-		}
-	case VIDIOC_G_INPUT:
-		{
-			int *input = (int *) arg;
-			*input = hexium->cur_input;
-
-			DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
-			return 0;
-		}
-	case VIDIOC_S_INPUT:
-		{
-			int input = *(int *) arg;
-
-			DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
-
-			if (input < 0 || input >= HEXIUM_INPUTS) {
-				return -EINVAL;
-			}
-
-			hexium->cur_input = input;
-			hexium_set_input(hexium, input);
-
-			return 0;
-		}
-		/* the saa7146 provides some controls (brightness, contrast, saturation)
-		   which gets registered *after* this function. because of this we have
-		   to return with a value != 0 even if the function succeded.. */
-	case VIDIOC_QUERYCTRL:
-		{
-			struct v4l2_queryctrl *qc = arg;
-			int i;
-
-			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
-				if (hexium_controls[i].id == qc->id) {
-					*qc = hexium_controls[i];
-					DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
-					return 0;
-				}
-			}
-			return -EAGAIN;
-		}
-	case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *vc = arg;
-			int i;
-
-			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
-				if (hexium_controls[i].id == vc->id) {
-					break;
-				}
-			}
-
-			if (i < 0) {
-				return -EAGAIN;
-			}
-
-			switch (vc->id) {
-			case V4L2_CID_PRIVATE_BASE:{
-					vc->value = hexium->cur_bw;
-					DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
-					return 0;
-				}
-			}
-			return -EINVAL;
-		}
-
-	case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *vc = arg;
-			int i = 0;
-
-			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
-				if (hexium_controls[i].id == vc->id) {
-					break;
-				}
-			}
-
-			if (i < 0) {
-				return -EAGAIN;
-			}
-
-			switch (vc->id) {
-			case V4L2_CID_PRIVATE_BASE:{
-					hexium->cur_bw = vc->value;
-					break;
-				}
-			}
-
-			DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
-
-			if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
-				hexium_set_standard(hexium, hexium_pal);
-				return 0;
-			}
-			if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
-				hexium_set_standard(hexium, hexium_ntsc);
-				return 0;
-			}
-			if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
-				hexium_set_standard(hexium, hexium_secam);
-				return 0;
-			}
-			if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
-				hexium_set_standard(hexium, hexium_pal_bw);
-				return 0;
-			}
-			if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
-				hexium_set_standard(hexium, hexium_ntsc_bw);
-				return 0;
-			}
-			if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
-				/* fixme: is there no bw secam mode? */
-				return -EINVAL;
-			}
-
-			return -EINVAL;
-		}
-	default:
-/*
-		DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
-*/
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
@@ -514,8 +488,6 @@
 	.stds = &hexium_standards[0],
 	.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
 	.std_callback = &std_callback,
-	.ioctls = &ioctls[0],
-	.ioctl = hexium_ioctl,
 };
 
 static struct saa7146_extension hexium_extension = {
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 074bec7..2bc39f6 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -57,14 +57,6 @@
 	u8 byte;
 };
 
-static struct saa7146_extension_ioctls ioctls[] = {
-	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_STD,		SAA7146_AFTER },
-	{ 0,			0 }
-};
-
 struct hexium
 {
 	int type;
@@ -329,6 +321,44 @@
 	return 0;
 }
 
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+
+	if (i->index < 0 || i->index >= HEXIUM_INPUTS)
+		return -EINVAL;
+
+	memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
+
+	DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	*input = hexium->cur_input;
+
+	DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	if (input < 0 || input >= HEXIUM_INPUTS)
+		return -EINVAL;
+
+	hexium->cur_input = input;
+	hexium_set_input(hexium, input);
+
+	return 0;
+}
+
 static struct saa7146_ext_vv vv_data;
 
 /* this function only gets called when the probing was successful */
@@ -339,6 +369,9 @@
 	DEB_EE((".\n"));
 
 	saa7146_vv_init(dev, &vv_data);
+	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
+	vv_data.ops.vidioc_g_input = vidioc_g_input;
+	vv_data.ops.vidioc_s_input = vidioc_s_input;
 	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
 		printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
 		return -1;
@@ -370,58 +403,6 @@
 	return 0;
 }
 
-static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct hexium *hexium = (struct hexium *) dev->ext_priv;
-/*
-	struct saa7146_vv *vv = dev->vv_data;
-*/
-	switch (cmd) {
-	case VIDIOC_ENUMINPUT:
-		{
-			struct v4l2_input *i = arg;
-			DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
-
-			if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
-				return -EINVAL;
-			}
-
-			memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
-
-			DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
-			return 0;
-		}
-	case VIDIOC_G_INPUT:
-		{
-			int *input = (int *) arg;
-			*input = hexium->cur_input;
-
-			DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
-			return 0;
-		}
-	case VIDIOC_S_INPUT:
-		{
-			int input = *(int *) arg;
-
-			if (input < 0 || input >= HEXIUM_INPUTS) {
-				return -EINVAL;
-			}
-
-			hexium->cur_input = input;
-			hexium_set_input(hexium, input);
-
-			return 0;
-		}
-	default:
-/*
-		DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
-*/
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
 {
 	return 0;
@@ -479,8 +460,6 @@
 	.stds = &hexium_standards[0],
 	.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
 	.std_callback = &std_callback,
-	.ioctls = &ioctls[0],
-	.ioctl = hexium_ioctl,
 };
 
 static struct saa7146_extension extension = {
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index 84b9e4f..3d69401 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -19,10 +19,12 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#include <linux/videodev.h>
 /* IndyCam decodes stream of photons into digital image representation ;-) */
-#include <linux/video_decoder.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 #include "indycam.h"
 
@@ -33,6 +35,7 @@
 MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
 MODULE_LICENSE("GPL");
 
+
 // #define INDYCAM_DEBUG
 
 #ifdef INDYCAM_DEBUG
@@ -44,11 +47,14 @@
 #endif
 
 struct indycam {
-	struct i2c_client *client;
+	struct v4l2_subdev sd;
 	u8 version;
 };
 
-static struct i2c_driver i2c_driver_indycam;
+static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct indycam, sd);
+}
 
 static const u8 initseq[] = {
 	INDYCAM_CONTROL_AGCENA,		/* INDYCAM_CONTROL */
@@ -63,8 +69,9 @@
 
 /* IndyCam register handling */
 
-static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value)
+static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret;
 
 	if (reg == INDYCAM_REG_RESET) {
@@ -87,12 +94,12 @@
 	return 0;
 }
 
-static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value)
+static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int err;
 
-	if ((reg == INDYCAM_REG_BRIGHTNESS)
-	    || (reg == INDYCAM_REG_VERSION)) {
+	if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
 		dprintk("indycam_write_reg(): "
 			"skipping read-only register %d\n", reg);
 		return 0;
@@ -108,13 +115,13 @@
 	return err;
 }
 
-static int indycam_write_block(struct i2c_client *client, u8 reg,
+static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
 			       u8 length, u8 *data)
 {
 	int i, err;
 
 	for (i = 0; i < length; i++) {
-		err = indycam_write_reg(client, reg + i, data[i]);
+		err = indycam_write_reg(sd, reg + i, data[i]);
 		if (err)
 			return err;
 	}
@@ -125,79 +132,78 @@
 /* Helper functions */
 
 #ifdef INDYCAM_DEBUG
-static void indycam_regdump_debug(struct i2c_client *client)
+static void indycam_regdump_debug(struct v4l2_subdev *sd)
 {
 	int i;
 	u8 val;
 
 	for (i = 0; i < 9; i++) {
-		indycam_read_reg(client, i, &val);
+		indycam_read_reg(sd, i, &val);
 		dprintk("Reg %d = 0x%02x\n", i, val);
 	}
 }
 #endif
 
-static int indycam_get_control(struct i2c_client *client,
-			       struct indycam_control *ctrl)
+static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	struct indycam *camera = i2c_get_clientdata(client);
+	struct indycam *camera = to_indycam(sd);
 	u8 reg;
 	int ret = 0;
 
-	switch (ctrl->type) {
-	case INDYCAM_CONTROL_AGC:
-	case INDYCAM_CONTROL_AWB:
-		ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
 		if (ret)
 			return -EIO;
-		if (ctrl->type == INDYCAM_CONTROL_AGC)
+		if (ctrl->id == V4L2_CID_AUTOGAIN)
 			ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
 				? 1 : 0;
 		else
 			ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
 				? 1 : 0;
 		break;
-	case INDYCAM_CONTROL_SHUTTER:
-		ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg);
+	case V4L2_CID_EXPOSURE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
 		break;
-	case INDYCAM_CONTROL_GAIN:
-		ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg);
+	case V4L2_CID_GAIN:
+		ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = (s32)reg;
 		break;
-	case INDYCAM_CONTROL_RED_BALANCE:
-		ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg);
+	case V4L2_CID_RED_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = (s32)reg;
 		break;
-	case INDYCAM_CONTROL_BLUE_BALANCE:
-		ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg);
+	case V4L2_CID_BLUE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = (s32)reg;
 		break;
 	case INDYCAM_CONTROL_RED_SATURATION:
-		ret = indycam_read_reg(client,
+		ret = indycam_read_reg(sd,
 				       INDYCAM_REG_RED_SATURATION, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = (s32)reg;
 		break;
 	case INDYCAM_CONTROL_BLUE_SATURATION:
-		ret = indycam_read_reg(client,
+		ret = indycam_read_reg(sd,
 				       INDYCAM_REG_BLUE_SATURATION, &reg);
 		if (ret)
 			return -EIO;
 		ctrl->value = (s32)reg;
 		break;
-	case INDYCAM_CONTROL_GAMMA:
+	case V4L2_CID_GAMMA:
 		if (camera->version == CAMERA_VERSION_MOOSE) {
-			ret = indycam_read_reg(client,
+			ret = indycam_read_reg(sd,
 					       INDYCAM_REG_GAMMA, &reg);
 			if (ret)
 				return -EIO;
@@ -213,21 +219,20 @@
 	return ret;
 }
 
-static int indycam_set_control(struct i2c_client *client,
-			       struct indycam_control *ctrl)
+static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	struct indycam *camera = i2c_get_clientdata(client);
+	struct indycam *camera = to_indycam(sd);
 	u8 reg;
 	int ret = 0;
 
-	switch (ctrl->type) {
-	case INDYCAM_CONTROL_AGC:
-	case INDYCAM_CONTROL_AWB:
-		ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
 		if (ret)
 			break;
 
-		if (ctrl->type == INDYCAM_CONTROL_AGC) {
+		if (ctrl->id == V4L2_CID_AUTOGAIN) {
 			if (ctrl->value)
 				reg |= INDYCAM_CONTROL_AGCENA;
 			else
@@ -239,34 +244,34 @@
 				reg &= ~INDYCAM_CONTROL_AWBCTL;
 		}
 
-		ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg);
+		ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
 		break;
-	case INDYCAM_CONTROL_SHUTTER:
+	case V4L2_CID_EXPOSURE:
 		reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
-		ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg);
+		ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
 		break;
-	case INDYCAM_CONTROL_GAIN:
-		ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value);
+	case V4L2_CID_GAIN:
+		ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
 		break;
-	case INDYCAM_CONTROL_RED_BALANCE:
-		ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE,
+	case V4L2_CID_RED_BALANCE:
+		ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
 					ctrl->value);
 		break;
-	case INDYCAM_CONTROL_BLUE_BALANCE:
-		ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE,
+	case V4L2_CID_BLUE_BALANCE:
+		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
 					ctrl->value);
 		break;
 	case INDYCAM_CONTROL_RED_SATURATION:
-		ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION,
+		ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
 					ctrl->value);
 		break;
 	case INDYCAM_CONTROL_BLUE_SATURATION:
-		ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION,
+		ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
 					ctrl->value);
 		break;
-	case INDYCAM_CONTROL_GAMMA:
+	case V4L2_CID_GAMMA:
 		if (camera->version == CAMERA_VERSION_MOOSE) {
-			ret = indycam_write_reg(client, INDYCAM_REG_GAMMA,
+			ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
 						ctrl->value);
 		}
 		break;
@@ -279,192 +284,103 @@
 
 /* I2C-interface */
 
-static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+static int indycam_g_chip_ident(struct v4l2_subdev *sd,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct indycam *camera = to_indycam(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM,
+		       camera->version);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops indycam_core_ops = {
+	.g_chip_ident = indycam_g_chip_ident,
+	.g_ctrl = indycam_g_ctrl,
+	.s_ctrl = indycam_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops indycam_ops = {
+	.core = &indycam_core_ops,
+};
+
+static int indycam_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	int err = 0;
 	struct indycam *camera;
-	struct i2c_client *client;
+	struct v4l2_subdev *sd;
 
-	printk(KERN_INFO "SGI IndyCam driver version %s\n",
-	       INDYCAM_MODULE_VERSION);
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
 	camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
-	if (!camera) {
-		err = -ENOMEM;
-		goto out_free_client;
-	}
+	if (!camera)
+		return -ENOMEM;
 
-	client->addr = addr;
-	client->adapter = adap;
-	client->driver = &i2c_driver_indycam;
-	client->flags = 0;
-	strcpy(client->name, "IndyCam client");
-	i2c_set_clientdata(client, camera);
-
-	camera->client = client;
-
-	err = i2c_attach_client(client);
-	if (err)
-		goto out_free_camera;
+	sd = &camera->sd;
+	v4l2_i2c_subdev_init(sd, client, &indycam_ops);
 
 	camera->version = i2c_smbus_read_byte_data(client,
 						   INDYCAM_REG_VERSION);
 	if (camera->version != CAMERA_VERSION_INDY &&
 	    camera->version != CAMERA_VERSION_MOOSE) {
-		err = -ENODEV;
-		goto out_detach_client;
+		kfree(camera);
+		return -ENODEV;
 	}
+
 	printk(KERN_INFO "IndyCam v%d.%d detected\n",
 	       INDYCAM_VERSION_MAJOR(camera->version),
 	       INDYCAM_VERSION_MINOR(camera->version));
 
-	indycam_regdump(client);
+	indycam_regdump(sd);
 
 	// initialize
-	err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq);
+	err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
 	if (err) {
 		printk(KERN_ERR "IndyCam initialization failed\n");
-		err = -EIO;
-		goto out_detach_client;
+		kfree(camera);
+		return -EIO;
 	}
 
-	indycam_regdump(client);
+	indycam_regdump(sd);
 
 	// white balance
-	err = indycam_write_reg(client, INDYCAM_REG_CONTROL,
+	err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
 			  INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
 	if (err) {
 		printk(KERN_ERR "IndyCam: White balancing camera failed\n");
-		err = -EIO;
-		goto out_detach_client;
+		kfree(camera);
+		return -EIO;
 	}
 
-	indycam_regdump(client);
+	indycam_regdump(sd);
 
 	printk(KERN_INFO "IndyCam initialized\n");
 
 	return 0;
-
-out_detach_client:
-	i2c_detach_client(client);
-out_free_camera:
-	kfree(camera);
-out_free_client:
-	kfree(client);
-	return err;
 }
 
-static int indycam_probe(struct i2c_adapter *adap)
+static int indycam_remove(struct i2c_client *client)
 {
-	/* Indy specific crap */
-	if (adap->id == I2C_HW_SGI_VINO)
-		return indycam_attach(adap, INDYCAM_ADDR, 0);
-	/* Feel free to add probe here :-) */
-	return -ENODEV;
-}
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
-static int indycam_detach(struct i2c_client *client)
-{
-	struct indycam *camera = i2c_get_clientdata(client);
-
-	i2c_detach_client(client);
-	kfree(camera);
-	kfree(client);
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_indycam(sd));
 	return 0;
 }
 
-static int indycam_command(struct i2c_client *client, unsigned int cmd,
-			   void *arg)
-{
-	// struct indycam *camera = i2c_get_clientdata(client);
-
-	/* The old video_decoder interface just isn't enough,
-	 * so we'll use some custom commands. */
-	switch (cmd) {
-	case DECODER_GET_CAPABILITIES: {
-		struct video_decoder_capability *cap = arg;
-
-		cap->flags  = VIDEO_DECODER_NTSC;
-		cap->inputs = 1;
-		cap->outputs = 1;
-		break;
-	}
-	case DECODER_GET_STATUS: {
-		int *iarg = arg;
-
-		*iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
-			DECODER_STATUS_COLOR;
-		break;
-	}
-	case DECODER_SET_NORM: {
-		int *iarg = arg;
-
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	}
-	case DECODER_SET_INPUT:	{
-		int *iarg = arg;
-
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-	case DECODER_SET_OUTPUT: {
-		int *iarg = arg;
-
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-	case DECODER_ENABLE_OUTPUT: {
-		/* Always enabled */
-		break;
-	}
-	case DECODER_SET_PICTURE: {
-		// struct video_picture *pic = arg;
-		/* TODO: convert values for indycam_set_controls() */
-		break;
-	}
-	case DECODER_INDYCAM_GET_CONTROL: {
-		return indycam_get_control(client, arg);
-	}
-	case DECODER_INDYCAM_SET_CONTROL: {
-		return indycam_set_control(client, arg);
-	}
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct i2c_driver i2c_driver_indycam = {
-	.driver = {
-		.name 	= "indycam",
-	},
-	.id		= I2C_DRIVERID_INDYCAM,
-	.attach_adapter = indycam_probe,
-	.detach_client	= indycam_detach,
-	.command	= indycam_command,
+static const struct i2c_device_id indycam_id[] = {
+	{ "indycam", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, indycam_id);
 
-static int __init indycam_init(void)
-{
-	return i2c_add_driver(&i2c_driver_indycam);
-}
-
-static void __exit indycam_exit(void)
-{
-	i2c_del_driver(&i2c_driver_indycam);
-}
-
-module_init(indycam_init);
-module_exit(indycam_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "indycam",
+	.probe = indycam_probe,
+	.remove = indycam_remove,
+	.id_table = indycam_id,
+};
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h
index e6ee820..881f21c 100644
--- a/drivers/media/video/indycam.h
+++ b/drivers/media/video/indycam.h
@@ -87,22 +87,7 @@
 
 /* Driver interface definitions */
 
-#define INDYCAM_CONTROL_AGC			0	/* boolean */
-#define INDYCAM_CONTROL_AWB			1	/* boolean */
-#define INDYCAM_CONTROL_SHUTTER			2
-#define INDYCAM_CONTROL_GAIN			3
-#define INDYCAM_CONTROL_RED_BALANCE		4
-#define INDYCAM_CONTROL_BLUE_BALANCE		5
-#define INDYCAM_CONTROL_RED_SATURATION		6
-#define INDYCAM_CONTROL_BLUE_SATURATION		7
-#define INDYCAM_CONTROL_GAMMA			8
-
-struct indycam_control {
-	u8 type;
-	s32 value;
-};
-
-#define	DECODER_INDYCAM_GET_CONTROL	_IOR('d', 193, struct indycam_control)
-#define	DECODER_INDYCAM_SET_CONTROL	_IOW('d', 194, struct indycam_control)
+#define INDYCAM_CONTROL_RED_SATURATION		(V4L2_CID_PRIVATE_BASE + 0)
+#define INDYCAM_CONTROL_BLUE_SATURATION		(V4L2_CID_PRIVATE_BASE + 1)
 
 #endif
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index d4658c5..092c7da 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -16,6 +16,8 @@
  *      Henry Wong <henry@stuffedcow.net>
  *      Mark Schultz <n9xmj@yahoo.com>
  *      Brian Rogers <brian_rogers@comcast.net>
+ * modified for AVerMedia Cardbus by
+ *      Oldrich Jedlicka <oldium.pro@seznam.cz>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -216,6 +218,46 @@
 	return 1;
 }
 
+static int get_key_avermedia_cardbus(struct IR_i2c *ir,
+				     u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char subaddr, key, keygroup;
+	struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+				   .buf = &subaddr, .len = 1},
+				 { .addr = ir->c.addr, .flags = I2C_M_RD,
+				  .buf = &key, .len = 1} };
+	subaddr = 0x0d;
+	if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+		dprintk(1, "read error\n");
+		return -EIO;
+	}
+
+	if (key == 0xff)
+		return 0;
+
+	subaddr = 0x0b;
+	msg[1].buf = &keygroup;
+	if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+		dprintk(1, "read error\n");
+		return -EIO;
+	}
+
+	if (keygroup == 0xff)
+		return 0;
+
+	dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
+	if (keygroup < 2 || keygroup > 3) {
+		/* Only a warning */
+		dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
+								keygroup, key);
+	}
+	key |= (keygroup & 1) << 6;
+
+	*ir_key = key;
+	*ir_raw = key;
+	return 1;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void ir_key_poll(struct IR_i2c *ir)
@@ -237,15 +279,9 @@
 	}
 }
 
-static void ir_timer(unsigned long data)
-{
-	struct IR_i2c *ir = (struct IR_i2c*)data;
-	schedule_work(&ir->work);
-}
-
 static void ir_work(struct work_struct *work)
 {
-	struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+	struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
 	int polling_interval = 100;
 
 	/* MSI TV@nywhere Plus requires more frequent polling
@@ -254,7 +290,7 @@
 		polling_interval = 50;
 
 	ir_key_poll(ir);
-	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval));
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(polling_interval));
 }
 
 /* ----------------------------------------------------------------------- */
@@ -360,6 +396,12 @@
 			ir_type     = IR_TYPE_OTHER;
 		}
 		break;
+	case 0x40:
+		name        = "AVerMedia Cardbus remote";
+		ir->get_key = get_key_avermedia_cardbus;
+		ir_type     = IR_TYPE_OTHER;
+		ir_codes    = ir_codes_avermedia_cardbus;
+		break;
 	default:
 		/* shouldn't happen */
 		printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
@@ -404,11 +446,8 @@
 	       ir->input->name, ir->input->phys, adap->name);
 
 	/* start polling via eventd */
-	INIT_WORK(&ir->work, ir_work);
-	init_timer(&ir->timer);
-	ir->timer.function = ir_timer;
-	ir->timer.data     = (unsigned long)ir;
-	schedule_work(&ir->work);
+	INIT_DELAYED_WORK(&ir->work, ir_work);
+	schedule_delayed_work(&ir->work, 0);
 
 	return 0;
 
@@ -425,8 +464,7 @@
 	struct IR_i2c *ir = i2c_get_clientdata(client);
 
 	/* kill outstanding polls */
-	del_timer_sync(&ir->timer);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister devices */
 	input_unregister_device(ir->input);
@@ -524,6 +562,22 @@
 			ir_attach(adap, msg.addr, 0, 0);
 	}
 
+	/* Special case for AVerMedia Cardbus remote */
+	if (adap->id == I2C_HW_SAA7134) {
+		unsigned char subaddr, data;
+		struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
+					   .buf = &subaddr, .len = 1},
+					 { .addr = 0x40, .flags = I2C_M_RD,
+					   .buf = &data, .len = 1} };
+		subaddr = 0x0d;
+		rc = i2c_transfer(adap, msg, 2);
+		dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
+			msg[0].addr, subaddr, adap->name,
+			(2 == rc) ? "yes" : "no");
+		if (2 == rc)
+			ir_attach(adap, msg[0].addr, 0, 0);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
index 62aa06f..84995bc 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -26,6 +26,7 @@
 #include "ivtv-mailbox.h"
 #include "ivtv-controls.h"
 
+/* Must be sorted from low to high control ID! */
 static const u32 user_ctrls[] = {
 	V4L2_CID_USER_CLASS,
 	V4L2_CID_BRIGHTNESS,
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index c46c990..eca8bf9 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -357,7 +357,7 @@
 static void ivtv_process_eeprom(struct ivtv *itv)
 {
 	struct tveeprom tv;
-	int pci_slot = PCI_SLOT(itv->dev->devfn);
+	int pci_slot = PCI_SLOT(itv->pdev->devfn);
 
 	ivtv_read_eeprom(itv, &tv);
 
@@ -604,7 +604,7 @@
 	itv->std = ivtv_parse_std(itv);
 	if (itv->std == 0 && tunertype >= 0)
 		itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
-	itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15);
+	itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15);
 	chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
 	if (itv->options.cardtype == -1) {
 		IVTV_INFO("Ignore card (detected %s based chip)\n", chipname);
@@ -617,9 +617,9 @@
 		IVTV_ERR("Unknown user specified type, trying to autodetect card\n");
 	}
 	if (itv->card == NULL) {
-		if (itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE ||
-		    itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 ||
-		    itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) {
+		if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE ||
+		    itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 ||
+		    itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) {
 			itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150);
 			IVTV_INFO("Autodetected Hauppauge card (%s based)\n",
 					chipname);
@@ -630,13 +630,13 @@
 			if (itv->card->pci_list == NULL)
 				continue;
 			for (j = 0; itv->card->pci_list[j].device; j++) {
-				if (itv->dev->device !=
+				if (itv->pdev->device !=
 				    itv->card->pci_list[j].device)
 					continue;
-				if (itv->dev->subsystem_vendor !=
+				if (itv->pdev->subsystem_vendor !=
 				    itv->card->pci_list[j].subsystem_vendor)
 					continue;
-				if (itv->dev->subsystem_device !=
+				if (itv->pdev->subsystem_device !=
 				    itv->card->pci_list[j].subsystem_device)
 					continue;
 				IVTV_INFO("Autodetected %s card (%s based)\n",
@@ -650,9 +650,9 @@
 	if (itv->card == NULL) {
 		itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
 		IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
-		     itv->dev->vendor, itv->dev->device);
+		     itv->pdev->vendor, itv->pdev->device);
 		IVTV_ERR("              subsystem vendor/device: [%04x:%04x]\n",
-		     itv->dev->subsystem_vendor, itv->dev->subsystem_device);
+		     itv->pdev->subsystem_vendor, itv->pdev->subsystem_device);
 		IVTV_ERR("              %s based\n", chipname);
 		IVTV_ERR("Defaulting to %s card\n", itv->card->name);
 		IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
@@ -671,7 +671,7 @@
  */
 static int __devinit ivtv_init_struct1(struct ivtv *itv)
 {
-	itv->base_addr = pci_resource_start(itv->dev, 0);
+	itv->base_addr = pci_resource_start(itv->pdev, 0);
 	itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
 	itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
 
@@ -682,7 +682,7 @@
 	spin_lock_init(&itv->lock);
 	spin_lock_init(&itv->dma_reg_lock);
 
-	itv->irq_work_queues = create_singlethread_workqueue(itv->device.name);
+	itv->irq_work_queues = create_singlethread_workqueue(itv->v4l2_dev.name);
 	if (itv->irq_work_queues == NULL) {
 		IVTV_ERR("Could not create ivtv workqueue\n");
 		return -1;
@@ -766,7 +766,7 @@
 	itv->audio_input = itv->card->video_inputs[i].audio_index;
 }
 
-static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
+static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
 			  const struct pci_device_id *pci_id)
 {
 	u16 cmd;
@@ -775,11 +775,11 @@
 
 	IVTV_DEBUG_INFO("Enabling pci device\n");
 
-	if (pci_enable_device(dev)) {
+	if (pci_enable_device(pdev)) {
 		IVTV_ERR("Can't enable device!\n");
 		return -EIO;
 	}
-	if (pci_set_dma_mask(dev, 0xffffffff)) {
+	if (pci_set_dma_mask(pdev, 0xffffffff)) {
 		IVTV_ERR("No suitable DMA available.\n");
 		return -EIO;
 	}
@@ -805,11 +805,11 @@
 	}
 
 	/* Check for bus mastering */
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
 	if (!(cmd & PCI_COMMAND_MASTER)) {
 		IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n");
-		pci_set_master(dev);
-		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		pci_set_master(pdev);
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
 		if (!(cmd & PCI_COMMAND_MASTER)) {
 			IVTV_ERR("Bus Mastering is not enabled\n");
 			return -ENXIO;
@@ -817,26 +817,26 @@
 	}
 	IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
 
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev);
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &card_rev);
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 
 	if (pci_latency < 64 && ivtv_pci_latency) {
 		IVTV_INFO("Unreasonably low latency timer, "
 			       "setting to 64 (was %d)\n", pci_latency);
-		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-		pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 	}
 	/* This config space value relates to DMA latencies. The
 	   default value 0x8080 is too low however and will lead
 	   to DMA errors. 0xffff is the max value which solves
 	   these problems. */
-	pci_write_config_dword(dev, 0x40, 0xffff);
+	pci_write_config_dword(pdev, 0x40, 0xffff);
 
 	IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
 		   "irq: %d, latency: %d, memory: 0x%lx\n",
-		   itv->dev->device, card_rev, dev->bus->number,
-		   PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
-		   itv->dev->irq, pci_latency, (unsigned long)itv->base_addr);
+		   pdev->device, card_rev, pdev->bus->number,
+		   PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+		   pdev->irq, pci_latency, (unsigned long)itv->base_addr);
 
 	return 0;
 }
@@ -935,7 +935,7 @@
 	}
 }
 
-static int __devinit ivtv_probe(struct pci_dev *dev,
+static int __devinit ivtv_probe(struct pci_dev *pdev,
 				const struct pci_device_id *pci_id)
 {
 	int retval = 0;
@@ -945,17 +945,17 @@
 	itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC);
 	if (itv == NULL)
 		return -ENOMEM;
-	itv->dev = dev;
+	itv->pdev = pdev;
 	itv->instance = atomic_inc_return(&ivtv_instance) - 1;
 
-	retval = v4l2_device_register(&dev->dev, &itv->device);
+	retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
 	if (retval) {
 		kfree(itv);
 		return retval;
 	}
 	/* "ivtv + PCI ID" is a bit of a mouthful, so use
 	   "ivtv + instance" instead. */
-	snprintf(itv->device.name, sizeof(itv->device.name),
+	snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name),
 			"ivtv%d", itv->instance);
 	IVTV_INFO("Initializing card %d\n", itv->instance);
 
@@ -972,12 +972,11 @@
 	IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr);
 
 	/* PCI Device Setup */
-	if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) {
-		if (retval == -EIO)
-			goto free_workqueue;
-		else if (retval == -ENXIO)
-			goto free_mem;
-	}
+	retval = ivtv_setup_pci(itv, pdev, pci_id);
+	if (retval == -EIO)
+		goto free_workqueue;
+	if (retval == -ENXIO)
+		goto free_mem;
 
 	/* map io memory */
 	IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
@@ -1154,8 +1153,8 @@
 	ivtv_set_irq_mask(itv, 0xffffffff);
 
 	/* Register IRQ */
-	retval = request_irq(itv->dev->irq, ivtv_irq_handler,
-	     IRQF_SHARED | IRQF_DISABLED, itv->device.name, (void *)itv);
+	retval = request_irq(itv->pdev->irq, ivtv_irq_handler,
+	     IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv);
 	if (retval) {
 		IVTV_ERR("Failed to register irq %d\n", retval);
 		goto free_i2c;
@@ -1177,7 +1176,7 @@
 free_streams:
 	ivtv_streams_cleanup(itv, 1);
 free_irq:
-	free_irq(itv->dev->irq, (void *)itv);
+	free_irq(itv->pdev->irq, (void *)itv);
 free_i2c:
 	exit_ivtv_i2c(itv);
 free_io:
@@ -1194,7 +1193,7 @@
 		retval = -ENODEV;
 	IVTV_ERR("Error %d on initialization\n", retval);
 
-	v4l2_device_unregister(&itv->device);
+	v4l2_device_unregister(&itv->v4l2_dev);
 	kfree(itv);
 	return retval;
 }
@@ -1292,10 +1291,10 @@
 	return 0;
 }
 
-static void ivtv_remove(struct pci_dev *pci_dev)
+static void ivtv_remove(struct pci_dev *pdev)
 {
-	struct v4l2_device *dev = dev_get_drvdata(&pci_dev->dev);
-	struct ivtv *itv = to_ivtv(dev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct ivtv *itv = to_ivtv(v4l2_dev);
 	int i;
 
 	IVTV_DEBUG_INFO("Removing card\n");
@@ -1336,11 +1335,9 @@
 	ivtv_streams_cleanup(itv, 1);
 	ivtv_udma_free(itv);
 
-	v4l2_device_unregister(&itv->device);
-
 	exit_ivtv_i2c(itv);
 
-	free_irq(itv->dev->irq, (void *)itv);
+	free_irq(itv->pdev->irq, (void *)itv);
 	ivtv_iounmap(itv);
 
 	release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
@@ -1348,11 +1345,13 @@
 	if (itv->has_cx23415)
 		release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
 
-	pci_disable_device(itv->dev);
+	pci_disable_device(itv->pdev);
 	for (i = 0; i < IVTV_VBI_FRAMES; i++)
 		kfree(itv->vbi.sliced_mpeg_data[i]);
 
 	printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name);
+
+	v4l2_device_unregister(&itv->v4l2_dev);
 	kfree(itv);
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index ce8d9b7..440f732 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -133,7 +133,7 @@
 #define IVTV_DEBUG(x, type, fmt, args...) \
 	do { \
 		if ((x) & ivtv_debug) \
-			v4l2_info(&itv->device, " " type ": " fmt , ##args);	\
+			v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);	\
 	} while (0)
 #define IVTV_DEBUG_WARN(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
 #define IVTV_DEBUG_INFO(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
@@ -149,7 +149,7 @@
 #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
 	do { \
 		if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) 	\
-			v4l2_info(&itv->device, " " type ": " fmt , ##args);	\
+			v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);	\
 	} while (0)
 #define IVTV_DEBUG_HI_WARN(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
 #define IVTV_DEBUG_HI_INFO(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
@@ -163,9 +163,9 @@
 #define IVTV_DEBUG_HI_YUV(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
 
 /* Standard kernel messages */
-#define IVTV_ERR(fmt, args...)      v4l2_err(&itv->device, fmt , ## args)
-#define IVTV_WARN(fmt, args...)     v4l2_warn(&itv->device, fmt , ## args)
-#define IVTV_INFO(fmt, args...)     v4l2_info(&itv->device, fmt , ## args)
+#define IVTV_ERR(fmt, args...)      v4l2_err(&itv->v4l2_dev, fmt , ## args)
+#define IVTV_WARN(fmt, args...)     v4l2_warn(&itv->v4l2_dev, fmt , ## args)
+#define IVTV_INFO(fmt, args...)     v4l2_info(&itv->v4l2_dev, fmt , ## args)
 
 /* output modes (cx23415 only) */
 #define OUT_NONE        0
@@ -315,7 +315,7 @@
 struct ivtv_stream {
 	/* These first four fields are always set, even if the stream
 	   is not actually created. */
-	struct video_device *v4l2dev;	/* NULL when stream not created */
+	struct video_device *vdev;	/* NULL when stream not created */
 	struct ivtv *itv; 		/* for ease of use */
 	const char *name;		/* name of the stream */
 	int type;			/* stream type */
@@ -592,7 +592,7 @@
 /* Struct to hold info about ivtv cards */
 struct ivtv {
 	/* General fixed card data */
-	struct pci_dev *dev;		/* PCI device */
+	struct pci_dev *pdev;		/* PCI device */
 	const struct ivtv_card *card;	/* card information */
 	const char *card_name;          /* full name of the card */
 	const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
@@ -612,7 +612,7 @@
 	volatile void __iomem *reg_mem; /* pointer to mapped registers */
 	struct ivtv_options options; 	/* user options */
 
-	struct v4l2_device device;
+	struct v4l2_device v4l2_dev;
 	struct v4l2_subdev sd_gpio;	/* GPIO sub-device */
 	u16 instance;
 
@@ -696,7 +696,7 @@
 	u64 vbi_data_inserted;          /* number of VBI bytes inserted into the MPEG stream */
 	u32 last_dec_timing[3];         /* cache last retrieved pts/scr/frame values */
 	unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */
-	u16 dualwatch_stereo_mode;      /* current detected dualwatch stereo mode */
+	u32 dualwatch_stereo_mode;      /* current detected dualwatch stereo mode */
 
 
 	/* VBI state info */
@@ -719,9 +719,9 @@
 	struct osd_info *osd_info;      /* ivtvfb private OSD info */
 };
 
-static inline struct ivtv *to_ivtv(struct v4l2_device *dev)
+static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
 {
-	return container_of(dev, struct ivtv, device);
+	return container_of(v4l2_dev, struct ivtv, v4l2_dev);
 }
 
 /* Globals */
@@ -788,7 +788,7 @@
 /* Call the specified callback for all subdevs matching hw (if 0, then
    match them all). Ignore any errors. */
 #define ivtv_call_hw(itv, hw, o, f, args...) 				\
-	__v4l2_device_call_subdevs(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
+	__v4l2_device_call_subdevs(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
 
 #define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
 
@@ -796,7 +796,7 @@
    match them all). If the callback returns an error other than 0 or
    -ENOIOCTLCMD, then return with that error code. */
 #define ivtv_call_hw_err(itv, hw, o, f, args...)  		\
-	__v4l2_device_call_subdevs_until_err(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
+	__v4l2_device_call_subdevs_until_err(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
 
 #define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args)
 
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index d594bc2..cfaacf6 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -148,10 +148,10 @@
 static void ivtv_dualwatch(struct ivtv *itv)
 {
 	struct v4l2_tuner vt;
-	u16 new_bitmap;
-	u16 new_stereo_mode;
-	const u16 stereo_mask = 0x0300;
-	const u16 dual = 0x0200;
+	u32 new_bitmap;
+	u32 new_stereo_mode;
+	const u32 stereo_mask = 0x0300;
+	const u32 dual = 0x0200;
 
 	new_stereo_mode = itv->params.audio_properties & stereo_mask;
 	memset(&vt, 0, sizeof(vt));
@@ -991,7 +991,7 @@
 	mutex_lock(&itv->serialize_lock);
 	if (ivtv_init_on_first_open(itv)) {
 		IVTV_ERR("Failed to initialize on minor %d\n",
-				s->v4l2dev->minor);
+				vdev->minor);
 		mutex_unlock(&itv->serialize_lock);
 		return -ENXIO;
 	}
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c
index 6dba55b..c1b7ec4 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.c
+++ b/drivers/media/video/ivtv/ivtv-firmware.c
@@ -52,7 +52,7 @@
 	int retries = 3;
 
 retry:
-	if (retries && request_firmware(&fw, fn, &itv->dev->dev) == 0) {
+	if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) {
 		int i;
 		volatile u32 __iomem *dst = (volatile u32 __iomem *)mem;
 		const u32 *src = (const u32 *)fw->data;
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index dc2850e..3321983 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -384,7 +384,7 @@
 	write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
 	write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
 	v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
-	snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name);
+	snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
 	itv->sd_gpio.grp_id = IVTV_HW_GPIO;
-	return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio);
+	return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
 }
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index ca1d955..e73a196 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -194,14 +194,14 @@
 	struct v4l2_subdev *result = NULL;
 	struct v4l2_subdev *sd;
 
-	spin_lock(&itv->device.lock);
-	v4l2_device_for_each_subdev(sd, &itv->device) {
+	spin_lock(&itv->v4l2_dev.lock);
+	v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) {
 		if (sd->grp_id == hw) {
 			result = sd;
 			break;
 		}
 	}
-	spin_unlock(&itv->device.lock);
+	spin_unlock(&itv->v4l2_dev.lock);
 	return result;
 }
 
@@ -472,8 +472,8 @@
    intervening stop condition */
 static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
-	struct v4l2_device *drv = i2c_get_adapdata(i2c_adap);
-	struct ivtv *itv = to_ivtv(drv);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+	struct ivtv *itv = to_ivtv(v4l2_dev);
 	int retval;
 	int i;
 
@@ -604,12 +604,12 @@
 
 	sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
 		itv->instance);
-	i2c_set_adapdata(&itv->i2c_adap, &itv->device);
+	i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
 
 	memcpy(&itv->i2c_client, &ivtv_i2c_client_template,
 	       sizeof(struct i2c_client));
 	itv->i2c_client.adapter = &itv->i2c_adap;
-	itv->i2c_adap.dev.parent = &itv->dev->dev;
+	itv->i2c_adap.dev.parent = &itv->pdev->dev;
 
 	IVTV_DEBUG_I2C("setting scl and sda to 1\n");
 	ivtv_setscl(itv, 1);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index c13bd2a..9a04242 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -345,10 +345,8 @@
 	pixfmt->priv = 0;
 	if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
-		/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
-		pixfmt->sizeimage =
-			pixfmt->height * pixfmt->width +
-			pixfmt->height * (pixfmt->width / 2);
+		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
+		pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
 		pixfmt->bytesperline = 720;
 	} else {
 		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -469,11 +467,17 @@
 	struct ivtv *itv = id->itv;
 	int w = fmt->fmt.pix.width;
 	int h = fmt->fmt.pix.height;
+	int min_h = 2;
 
 	w = min(w, 720);
 	w = max(w, 2);
+	if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
+		/* YUV height must be a multiple of 32 */
+		h &= ~0x1f;
+		min_h = 32;
+	}
 	h = min(h, itv->is_50hz ? 576 : 480);
-	h = max(h, 2);
+	h = max(h, min_h);
 	ivtv_g_fmt_vid_cap(file, fh, fmt);
 	fmt->fmt.pix.width = w;
 	fmt->fmt.pix.height = h;
@@ -766,7 +770,7 @@
 
 	strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
-	snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev));
+	snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
 	vcap->version = IVTV_DRIVER_VERSION; 	    /* version */
 	vcap->capabilities = itv->v4l2_cap; 	    /* capabilities */
 	return 0;
@@ -1513,12 +1517,12 @@
 	}
 	IVTV_INFO("Tuner:  %s\n",
 		test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
-	cx2341x_log_status(&itv->params, itv->device.name);
+	cx2341x_log_status(&itv->params, itv->v4l2_dev.name);
 	IVTV_INFO("Status flags:    0x%08lx\n", itv->i_flags);
 	for (i = 0; i < IVTV_MAX_STREAMS; i++) {
 		struct ivtv_stream *s = &itv->streams[i];
 
-		if (s->v4l2dev == NULL || s->buffers == 0)
+		if (s->vdev == NULL || s->buffers == 0)
 			continue;
 		IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
 				(s->buffers - s->q_free.buffers) * 100 / s->buffers,
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index f5d00ec..01c14d2 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -46,7 +46,7 @@
 
 	IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
 	if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
-			s->v4l2dev == NULL || !ivtv_use_pio(s)) {
+			s->vdev == NULL || !ivtv_use_pio(s)) {
 		itv->cur_pio_stream = -1;
 		/* trigger PIO complete user interrupt */
 		write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
@@ -109,7 +109,7 @@
 	int rc;
 
 	/* sanity checks */
-	if (s->v4l2dev == NULL) {
+	if (s->vdev == NULL) {
 		IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
 		return -1;
 	}
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index 71bd13e..ff7b7de 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -230,7 +230,7 @@
 		return -ENOMEM;
 	}
 	if (ivtv_might_use_dma(s)) {
-		s->sg_handle = pci_map_single(itv->dev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma);
+		s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma);
 		ivtv_stream_sync_for_cpu(s);
 	}
 
@@ -248,7 +248,7 @@
 		}
 		INIT_LIST_HEAD(&buf->list);
 		if (ivtv_might_use_dma(s)) {
-			buf->dma_handle = pci_map_single(s->itv->dev,
+			buf->dma_handle = pci_map_single(s->itv->pdev,
 				buf->buf, s->buf_size + 256, s->dma);
 			ivtv_buf_sync_for_cpu(s, buf);
 		}
@@ -271,7 +271,7 @@
 	/* empty q_free */
 	while ((buf = ivtv_dequeue(s, &s->q_free))) {
 		if (ivtv_might_use_dma(s))
-			pci_unmap_single(s->itv->dev, buf->dma_handle,
+			pci_unmap_single(s->itv->pdev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 		kfree(buf->buf);
 		kfree(buf);
@@ -280,7 +280,7 @@
 	/* Free SG Array/Lists */
 	if (s->sg_dma != NULL) {
 		if (s->sg_handle != IVTV_DMA_UNMAPPED) {
-			pci_unmap_single(s->itv->dev, s->sg_handle,
+			pci_unmap_single(s->itv->pdev, s->sg_handle,
 				 sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
 			s->sg_handle = IVTV_DMA_UNMAPPED;
 		}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
index 476556a..9123383 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -53,14 +53,14 @@
 static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
 {
 	if (ivtv_use_dma(s))
-		pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
+		pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 }
 
 static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
 {
 	if (ivtv_use_dma(s))
-		pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
+		pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle,
 				s->buf_size + 256, s->dma);
 }
 
@@ -82,14 +82,14 @@
 static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
 {
 	if (ivtv_use_dma(s))
-		pci_dma_sync_single_for_cpu(s->itv->dev, s->sg_handle,
+		pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle,
 			sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
 }
 
 static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
 {
 	if (ivtv_use_dma(s))
-		pci_dma_sync_single_for_device(s->itv->dev, s->sg_handle,
+		pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle,
 			sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 854a950..15da017 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -137,11 +137,11 @@
 static void ivtv_stream_init(struct ivtv *itv, int type)
 {
 	struct ivtv_stream *s = &itv->streams[type];
-	struct video_device *dev = s->v4l2dev;
+	struct video_device *vdev = s->vdev;
 
-	/* we need to keep v4l2dev, so restore it afterwards */
+	/* we need to keep vdev, so restore it afterwards */
 	memset(s, 0, sizeof(*s));
-	s->v4l2dev = dev;
+	s->vdev = vdev;
 
 	/* initialize ivtv_stream fields */
 	s->itv = itv;
@@ -172,10 +172,10 @@
 	int num_offset = ivtv_stream_info[type].num_offset;
 	int num = itv->instance + ivtv_first_minor + num_offset;
 
-	/* These four fields are always initialized. If v4l2dev == NULL, then
+	/* These four fields are always initialized. If vdev == NULL, then
 	   this stream is not in use. In that case no other fields but these
 	   four can be used. */
-	s->v4l2dev = NULL;
+	s->vdev = NULL;
 	s->itv = itv;
 	s->type = type;
 	s->name = ivtv_stream_info[type].name;
@@ -197,21 +197,21 @@
 	ivtv_stream_init(itv, type);
 
 	/* allocate and initialize the v4l2 video device structure */
-	s->v4l2dev = video_device_alloc();
-	if (s->v4l2dev == NULL) {
+	s->vdev = video_device_alloc();
+	if (s->vdev == NULL) {
 		IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name);
 		return -ENOMEM;
 	}
 
-	snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s",
-			itv->device.name, s->name);
+	snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s",
+			itv->v4l2_dev.name, s->name);
 
-	s->v4l2dev->num = num;
-	s->v4l2dev->v4l2_dev = &itv->device;
-	s->v4l2dev->fops = ivtv_stream_info[type].fops;
-	s->v4l2dev->release = video_device_release;
-	s->v4l2dev->tvnorms = V4L2_STD_ALL;
-	ivtv_set_funcs(s->v4l2dev);
+	s->vdev->num = num;
+	s->vdev->v4l2_dev = &itv->v4l2_dev;
+	s->vdev->fops = ivtv_stream_info[type].fops;
+	s->vdev->release = video_device_release;
+	s->vdev->tvnorms = V4L2_STD_ALL;
+	ivtv_set_funcs(s->vdev);
 	return 0;
 }
 
@@ -226,7 +226,7 @@
 		if (ivtv_prep_dev(itv, type))
 			break;
 
-		if (itv->streams[type].v4l2dev == NULL)
+		if (itv->streams[type].vdev == NULL)
 			continue;
 
 		/* Allocate Stream */
@@ -247,28 +247,28 @@
 	int vfl_type = ivtv_stream_info[type].vfl_type;
 	int num;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return 0;
 
-	num = s->v4l2dev->num;
+	num = s->vdev->num;
 	/* card number + user defined offset + device offset */
 	if (type != IVTV_ENC_STREAM_TYPE_MPG) {
 		struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
 
-		if (s_mpg->v4l2dev)
-			num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
+		if (s_mpg->vdev)
+			num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
 	}
-	video_set_drvdata(s->v4l2dev, s);
+	video_set_drvdata(s->vdev, s);
 
 	/* Register device. First try the desired minor, then any free one. */
-	if (video_register_device(s->v4l2dev, vfl_type, num)) {
+	if (video_register_device(s->vdev, vfl_type, num)) {
 		IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
 				s->name, num);
-		video_device_release(s->v4l2dev);
-		s->v4l2dev = NULL;
+		video_device_release(s->vdev);
+		s->vdev = NULL;
 		return -ENOMEM;
 	}
-	num = s->v4l2dev->num;
+	num = s->vdev->num;
 
 	switch (vfl_type) {
 	case VFL_TYPE_GRABBER:
@@ -316,9 +316,9 @@
 
 	/* Teardown all streams */
 	for (type = 0; type < IVTV_MAX_STREAMS; type++) {
-		struct video_device *vdev = itv->streams[type].v4l2dev;
+		struct video_device *vdev = itv->streams[type].vdev;
 
-		itv->streams[type].v4l2dev = NULL;
+		itv->streams[type].vdev = NULL;
 		if (vdev == NULL)
 			continue;
 
@@ -449,7 +449,7 @@
 	int captype = 0, subtype = 0;
 	int enable_passthrough = 0;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return -EINVAL;
 
 	IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
@@ -611,7 +611,7 @@
 	struct cx2341x_mpeg_params *p = &itv->params;
 	int datatype;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return -EINVAL;
 
 	IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
@@ -657,7 +657,7 @@
 {
 	struct ivtv *itv = s->itv;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return -EINVAL;
 
 	if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
@@ -705,7 +705,7 @@
 	for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
 		struct ivtv_stream *s = &itv->streams[i];
 
-		if (s->v4l2dev == NULL)
+		if (s->vdev == NULL)
 			continue;
 		if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
 			ivtv_stop_v4l2_encode_stream(s, 0);
@@ -720,7 +720,7 @@
 	int cap_type;
 	int stopmode;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return -EINVAL;
 
 	/* This function assumes that you are allowed to stop the capture
@@ -834,7 +834,7 @@
 {
 	struct ivtv *itv = s->itv;
 
-	if (s->v4l2dev == NULL)
+	if (s->vdev == NULL)
 		return -EINVAL;
 
 	if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
@@ -895,7 +895,7 @@
 	struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
 	struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
 
-	if (yuv_stream->v4l2dev == NULL || dec_stream->v4l2dev == NULL)
+	if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL)
 		return -EINVAL;
 
 	IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c
index 460db03..d07ad6c 100644
--- a/drivers/media/video/ivtv/ivtv-udma.c
+++ b/drivers/media/video/ivtv/ivtv-udma.c
@@ -93,7 +93,7 @@
 {
 	if (itv->udma.SG_handle == 0) {
 		/* Map DMA Page Array Buffer */
-		itv->udma.SG_handle = pci_map_single(itv->dev, itv->udma.SGarray,
+		itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray,
 			   sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
 		ivtv_udma_sync_for_cpu(itv);
 	}
@@ -147,7 +147,7 @@
 	}
 
 	/* Map SG List */
-	dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+	dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
 
 	/* Fill SG Array with new values */
 	ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
@@ -172,7 +172,7 @@
 
 	/* Unmap Scatterlist */
 	if (dma->SG_length) {
-		pci_unmap_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+		pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
 		dma->SG_length = 0;
 	}
 	/* sync DMA */
@@ -191,13 +191,13 @@
 
 	/* Unmap SG Array */
 	if (itv->udma.SG_handle) {
-		pci_unmap_single(itv->dev, itv->udma.SG_handle,
+		pci_unmap_single(itv->pdev, itv->udma.SG_handle,
 			 sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
 	}
 
 	/* Unmap Scatterlist */
 	if (itv->udma.SG_length) {
-		pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE);
+		pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE);
 	}
 
 	for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) {
diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h
index df727e2..ee3c9ef 100644
--- a/drivers/media/video/ivtv/ivtv-udma.h
+++ b/drivers/media/video/ivtv/ivtv-udma.h
@@ -35,13 +35,13 @@
 
 static inline void ivtv_udma_sync_for_device(struct ivtv *itv)
 {
-	pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, itv->udma.SG_handle,
+	pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle,
 		sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
 }
 
 static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv)
 {
-	pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle,
+	pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle,
 		sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index 5c5d1c4..f420d31 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -185,6 +185,8 @@
 		size = 4 + ((43 * line + 3) & ~3);
 	} else {
 		memcpy(dst + sd, "itv0", 4);
+		cpu_to_le32s(&linemask[0]);
+		cpu_to_le32s(&linemask[1]);
 		memcpy(dst + sd + 4, &linemask[0], 8);
 		size = 12 + ((43 * line + 3) & ~3);
 	}
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
index 8cd753d..b530dec 100644
--- a/drivers/media/video/ivtv/ivtv-version.h
+++ b/drivers/media/video/ivtv/ivtv-version.h
@@ -23,7 +23,7 @@
 #define IVTV_DRIVER_NAME "ivtv"
 #define IVTV_DRIVER_VERSION_MAJOR 1
 #define IVTV_DRIVER_VERSION_MINOR 4
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
+#define IVTV_DRIVER_VERSION_PATCHLEVEL 1
 
 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
 #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index ee91107..7912ed6 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -103,7 +103,7 @@
 		dma->page_count = 0;
 		return -ENOMEM;
 	}
-	dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+	dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
 
 	/* Fill SG Array with new values */
 	ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
@@ -910,7 +910,7 @@
 	/* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
 	yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
 	if (yi->blanking_ptr) {
-		yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
+		yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
 	} else {
 		yi->blanking_dmaptr = 0;
 		IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
@@ -1237,7 +1237,7 @@
 	if (yi->blanking_ptr) {
 		kfree(yi->blanking_ptr);
 		yi->blanking_ptr = NULL;
-		pci_unmap_single(itv->dev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
+		pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
 	}
 
 	/* Invalidate the old dimension information */
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 36abd2a..66e6eb5 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -1192,12 +1192,12 @@
 static int __init ivtvfb_callback_init(struct device *dev, void *p)
 {
 	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-	struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device);
+	struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
 
 	if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
 		if (ivtvfb_init_card(itv) == 0) {
 			IVTVFB_INFO("Framebuffer registered on %s\n",
-					itv->device.name);
+					itv->v4l2_dev.name);
 			(*(int *)p)++;
 		}
 	}
@@ -1207,7 +1207,7 @@
 static int ivtvfb_callback_cleanup(struct device *dev, void *p)
 {
 	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-	struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device);
+	struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
 
 	if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
 		if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index bae2d2b..841024b 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -39,19 +39,20 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/video_decoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 #include "ks0127.h"
 
 MODULE_DESCRIPTION("KS0127 video decoder driver");
 MODULE_AUTHOR("Ryan Drake");
 MODULE_LICENSE("GPL");
 
-#define KS_TYPE_UNKNOWN	0
-#define KS_TYPE_0122S	1
-#define KS_TYPE_0127	2
-#define KS_TYPE_0127B	3
+/* Addresses */
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
 
 /* ks0127 control registers */
 #define KS_STAT     0x00
@@ -197,15 +198,17 @@
 };
 
 struct ks0127 {
-	int		format_width;
-	int		format_height;
-	int		cap_width;
-	int		cap_height;
-	int		norm;
-	int		ks_type;
+	struct v4l2_subdev sd;
+	v4l2_std_id	norm;
+	int		ident;
 	u8 		regs[256];
 };
 
+static inline struct ks0127 *to_ks0127(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ks0127, sd);
+}
+
 
 static int debug; /* insmod parameter */
 
@@ -311,43 +314,45 @@
  */
 
 
-static u8 ks0127_read(struct i2c_client *c, u8 reg)
+static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	char val = 0;
 	struct i2c_msg msgs[] = {
-		{ c->addr, 0, sizeof(reg), &reg },
-		{ c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
+		{ client->addr, 0, sizeof(reg), &reg },
+		{ client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
 	};
 	int ret;
 
-	ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 	if (ret != ARRAY_SIZE(msgs))
-		v4l_dbg(1, debug, c, "read error\n");
+		v4l2_dbg(1, debug, sd, "read error\n");
 
 	return val;
 }
 
 
-static void ks0127_write(struct i2c_client *c, u8 reg, u8 val)
+static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-	struct ks0127 *ks = i2c_get_clientdata(c);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ks0127 *ks = to_ks0127(sd);
 	char msg[] = { reg, val };
 
-	if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg))
-		v4l_dbg(1, debug, c, "write error\n");
+	if (i2c_master_send(client, msg, sizeof(msg)) != sizeof(msg))
+		v4l2_dbg(1, debug, sd, "write error\n");
 
 	ks->regs[reg] = val;
 }
 
 
 /* generic bit-twiddling */
-static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v)
+static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v)
 {
-	struct ks0127 *ks = i2c_get_clientdata(client);
+	struct ks0127 *ks = to_ks0127(sd);
 
 	u8 val = ks->regs[reg];
 	val = (val & and_v) | or_v;
-	ks0127_write(client, reg, val);
+	ks0127_write(sd, reg, val);
 }
 
 
@@ -355,439 +360,363 @@
 /****************************************************************************
 * ks0127 private api
 ****************************************************************************/
-static void ks0127_reset(struct i2c_client *c)
+static void ks0127_init(struct v4l2_subdev *sd)
 {
-	struct ks0127 *ks = i2c_get_clientdata(c);
+	struct ks0127 *ks = to_ks0127(sd);
 	u8 *table = reg_defaults;
 	int i;
 
-	ks->ks_type = KS_TYPE_UNKNOWN;
+	ks->ident = V4L2_IDENT_KS0127;
 
-	v4l_dbg(1, debug, c, "reset\n");
+	v4l2_dbg(1, debug, sd, "reset\n");
 	msleep(1);
 
 	/* initialize all registers to known values */
 	/* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
 
 	for (i = 1; i < 33; i++)
-		ks0127_write(c, i, table[i]);
+		ks0127_write(sd, i, table[i]);
 
 	for (i = 35; i < 40; i++)
-		ks0127_write(c, i, table[i]);
+		ks0127_write(sd, i, table[i]);
 
 	for (i = 41; i < 56; i++)
-		ks0127_write(c, i, table[i]);
+		ks0127_write(sd, i, table[i]);
 
 	for (i = 58; i < 64; i++)
-		ks0127_write(c, i, table[i]);
+		ks0127_write(sd, i, table[i]);
 
 
-	if ((ks0127_read(c, KS_STAT) & 0x80) == 0) {
-		ks->ks_type = KS_TYPE_0122S;
-		v4l_dbg(1, debug, c, "ks0122s found\n");
+	if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) {
+		ks->ident = V4L2_IDENT_KS0122S;
+		v4l2_dbg(1, debug, sd, "ks0122s found\n");
 		return;
 	}
 
-	switch (ks0127_read(c, KS_CMDE) & 0x0f) {
+	switch (ks0127_read(sd, KS_CMDE) & 0x0f) {
 	case 0:
-		ks->ks_type = KS_TYPE_0127;
-		v4l_dbg(1, debug, c, "ks0127 found\n");
+		v4l2_dbg(1, debug, sd, "ks0127 found\n");
 		break;
 
 	case 9:
-		ks->ks_type = KS_TYPE_0127B;
-		v4l_dbg(1, debug, c, "ks0127B Revision A found\n");
+		ks->ident = V4L2_IDENT_KS0127B;
+		v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n");
 		break;
 
 	default:
-		v4l_dbg(1, debug, c, "unknown revision\n");
+		v4l2_dbg(1, debug, sd, "unknown revision\n");
 		break;
 	}
 }
 
-static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
+static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
 {
-	struct ks0127 *ks = i2c_get_clientdata(c);
-	int		*iarg = (int *)arg;
-	int		status;
+	struct ks0127 *ks = to_ks0127(sd);
 
-	if (!ks)
-		return -ENODEV;
+	switch (route->input) {
+	case KS_INPUT_COMPOSITE_1:
+	case KS_INPUT_COMPOSITE_2:
+	case KS_INPUT_COMPOSITE_3:
+	case KS_INPUT_COMPOSITE_4:
+	case KS_INPUT_COMPOSITE_5:
+	case KS_INPUT_COMPOSITE_6:
+		v4l2_dbg(1, debug, sd,
+			"s_routing %d: Composite\n", route->input);
+		/* autodetect 50/60 Hz */
+		ks0127_and_or(sd, KS_CMDA,   0xfc, 0x00);
+		/* VSE=0 */
+		ks0127_and_or(sd, KS_CMDA,   ~0x40, 0x00);
+		/* set input line */
+		ks0127_and_or(sd, KS_CMDB,   0xb0, route->input);
+		/* non-freerunning mode */
+		ks0127_and_or(sd, KS_CMDC,   0x70, 0x0a);
+		/* analog input */
+		ks0127_and_or(sd, KS_CMDD,   0x03, 0x00);
+		/* enable chroma demodulation */
+		ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00);
+		/* chroma trap, HYBWR=1 */
+		ks0127_and_or(sd, KS_LUMA,   0x00,
+			       (reg_defaults[KS_LUMA])|0x0c);
+		/* scaler fullbw, luma comb off */
+		ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81);
+		/* manual chroma comb .25 .5 .25 */
+		ks0127_and_or(sd, KS_VERTIC, 0x0f, 0x90);
 
-	switch (cmd) {
-	case DECODER_INIT:
-		v4l_dbg(1, debug, c, "DECODER_INIT\n");
-		ks0127_reset(c);
+		/* chroma path delay */
+		ks0127_and_or(sd, KS_CHROMB, 0x0f, 0x90);
+
+		ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]);
+		ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]);
+		ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+		ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
 		break;
 
-	case DECODER_SET_INPUT:
-		switch(*iarg) {
-		case KS_INPUT_COMPOSITE_1:
-		case KS_INPUT_COMPOSITE_2:
-		case KS_INPUT_COMPOSITE_3:
-		case KS_INPUT_COMPOSITE_4:
-		case KS_INPUT_COMPOSITE_5:
-		case KS_INPUT_COMPOSITE_6:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_INPUT %d: Composite\n", *iarg);
-			/* autodetect 50/60 Hz */
-			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
-			/* VSE=0 */
-			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);
-			/* set input line */
-			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);
-			/* non-freerunning mode */
-			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);
-			/* analog input */
-			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);
-			/* enable chroma demodulation */
-			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
-			/* chroma trap, HYBWR=1 */
-			ks0127_and_or(c, KS_LUMA,   0x00,
-				       (reg_defaults[KS_LUMA])|0x0c);
-			/* scaler fullbw, luma comb off */
-			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
-			/* manual chroma comb .25 .5 .25 */
-			ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90);
+	case KS_INPUT_SVIDEO_1:
+	case KS_INPUT_SVIDEO_2:
+	case KS_INPUT_SVIDEO_3:
+		v4l2_dbg(1, debug, sd,
+			"s_routing %d: S-Video\n", route->input);
+		/* autodetect 50/60 Hz */
+		ks0127_and_or(sd, KS_CMDA,   0xfc, 0x00);
+		/* VSE=0 */
+		ks0127_and_or(sd, KS_CMDA,   ~0x40, 0x00);
+		/* set input line */
+		ks0127_and_or(sd, KS_CMDB,   0xb0, route->input);
+		/* non-freerunning mode */
+		ks0127_and_or(sd, KS_CMDC,   0x70, 0x0a);
+		/* analog input */
+		ks0127_and_or(sd, KS_CMDD,   0x03, 0x00);
+		/* enable chroma demodulation */
+		ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00);
+		ks0127_and_or(sd, KS_LUMA, 0x00,
+			       reg_defaults[KS_LUMA]);
+		/* disable luma comb */
+		ks0127_and_or(sd, KS_VERTIA, 0x08,
+			       (reg_defaults[KS_VERTIA]&0xf0)|0x01);
+		ks0127_and_or(sd, KS_VERTIC, 0x0f,
+			       reg_defaults[KS_VERTIC]&0xf0);
 
-			/* chroma path delay */
-			ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90);
+		ks0127_and_or(sd, KS_CHROMB, 0x0f,
+			       reg_defaults[KS_CHROMB]&0xf0);
 
-			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
-			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
-			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
-			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
-			break;
-
-		case KS_INPUT_SVIDEO_1:
-		case KS_INPUT_SVIDEO_2:
-		case KS_INPUT_SVIDEO_3:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_INPUT %d: S-Video\n", *iarg);
-			/* autodetect 50/60 Hz */
-			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
-			/* VSE=0 */
-			ks0127_and_or(c, KS_CMDA,   ~0x40, 0x00);
-			/* set input line */
-			ks0127_and_or(c, KS_CMDB,   0xb0, *iarg);
-			/* non-freerunning mode */
-			ks0127_and_or(c, KS_CMDC,   0x70, 0x0a);
-			/* analog input */
-			ks0127_and_or(c, KS_CMDD,   0x03, 0x00);
-			/* enable chroma demodulation */
-			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
-			ks0127_and_or(c, KS_LUMA, 0x00,
-				       reg_defaults[KS_LUMA]);
-			/* disable luma comb */
-			ks0127_and_or(c, KS_VERTIA, 0x08,
-				       (reg_defaults[KS_VERTIA]&0xf0)|0x01);
-			ks0127_and_or(c, KS_VERTIC, 0x0f,
-				       reg_defaults[KS_VERTIC]&0xf0);
-
-			ks0127_and_or(c, KS_CHROMB, 0x0f,
-				       reg_defaults[KS_CHROMB]&0xf0);
-
-			ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
-			ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
-			ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
-			ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
-			break;
-
-		case KS_INPUT_YUV656:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_INPUT 15: YUV656\n");
-			if (ks->norm == VIDEO_MODE_NTSC ||
-			    ks->norm == KS_STD_PAL_M)
-				/* force 60 Hz */
-				ks0127_and_or(c, KS_CMDA,   0xfc, 0x03);
-			else
-				/* force 50 Hz */
-				ks0127_and_or(c, KS_CMDA,   0xfc, 0x02);
-
-			ks0127_and_or(c, KS_CMDA,   0xff, 0x40); /* VSE=1 */
-			/* set input line and VALIGN */
-			ks0127_and_or(c, KS_CMDB,   0xb0, (*iarg | 0x40));
-			/* freerunning mode, */
-			/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
-			ks0127_and_or(c, KS_CMDC,   0x70, 0x87);
-			/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
-			ks0127_and_or(c, KS_CMDD,   0x03, 0x08);
-			/* disable chroma demodulation */
-			ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30);
-			/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
-			ks0127_and_or(c, KS_LUMA,   0x00, 0x71);
-			ks0127_and_or(c, KS_VERTIC, 0x0f,
-				       reg_defaults[KS_VERTIC]&0xf0);
-
-			/* scaler fullbw, luma comb off */
-			ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
-
-			ks0127_and_or(c, KS_CHROMB, 0x0f,
-				       reg_defaults[KS_CHROMB]&0xf0);
-
-			ks0127_and_or(c, KS_CON, 0x00, 0x00);
-			ks0127_and_or(c, KS_BRT, 0x00, 32);	/* spec: 34 */
-				/* spec: 229 (e5) */
-			ks0127_and_or(c, KS_SAT, 0x00, 0xe8);
-			ks0127_and_or(c, KS_HUE, 0x00, 0);
-
-			ks0127_and_or(c, KS_UGAIN, 0x00, 238);
-			ks0127_and_or(c, KS_VGAIN, 0x00, 0x00);
-
-			/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
-			ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f);
-			ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00);
-			break;
-
-		default:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_INPUT: Unknown input %d\n", *iarg);
-			break;
-		}
-
-		/* hack: CDMLPF sometimes spontaneously switches on; */
-		/* force back off */
-		ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);
+		ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]);
+		ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]);
+		ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+		ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
 		break;
 
-	case DECODER_SET_OUTPUT:
-		switch(*iarg) {
-		case KS_OUTPUT_YUV656E:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n");
-			return -EINVAL;
+	case KS_INPUT_YUV656:
+		v4l2_dbg(1, debug, sd, "s_routing 15: YUV656\n");
+		if (ks->norm & V4L2_STD_525_60)
+			/* force 60 Hz */
+			ks0127_and_or(sd, KS_CMDA,   0xfc, 0x03);
+		else
+			/* force 50 Hz */
+			ks0127_and_or(sd, KS_CMDA,   0xfc, 0x02);
 
-		case KS_OUTPUT_EXV:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_OUTPUT: OUTPUT_EXV\n");
-			ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09);
-			break;
-		}
+		ks0127_and_or(sd, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+		/* set input line and VALIGN */
+		ks0127_and_or(sd, KS_CMDB,   0xb0, (route->input | 0x40));
+		/* freerunning mode, */
+		/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
+		ks0127_and_or(sd, KS_CMDC,   0x70, 0x87);
+		/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
+		ks0127_and_or(sd, KS_CMDD,   0x03, 0x08);
+		/* disable chroma demodulation */
+		ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x30);
+		/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
+		ks0127_and_or(sd, KS_LUMA,   0x00, 0x71);
+		ks0127_and_or(sd, KS_VERTIC, 0x0f,
+			       reg_defaults[KS_VERTIC]&0xf0);
+
+		/* scaler fullbw, luma comb off */
+		ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81);
+
+		ks0127_and_or(sd, KS_CHROMB, 0x0f,
+			       reg_defaults[KS_CHROMB]&0xf0);
+
+		ks0127_and_or(sd, KS_CON, 0x00, 0x00);
+		ks0127_and_or(sd, KS_BRT, 0x00, 32);	/* spec: 34 */
+			/* spec: 229 (e5) */
+		ks0127_and_or(sd, KS_SAT, 0x00, 0xe8);
+		ks0127_and_or(sd, KS_HUE, 0x00, 0);
+
+		ks0127_and_or(sd, KS_UGAIN, 0x00, 238);
+		ks0127_and_or(sd, KS_VGAIN, 0x00, 0x00);
+
+		/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
+		ks0127_and_or(sd, KS_UVOFFH, 0x00, 0x4f);
+		ks0127_and_or(sd, KS_UVOFFL, 0x00, 0x00);
 		break;
 
-	case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */
-		/* Set to automatic SECAM/Fsc mode */
-		ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
-
-		ks->norm = *iarg;
-		switch (*iarg) {
-		/* this is untested !! */
-		/* It just detects PAL_N/NTSC_M (no special frequencies) */
-		/* And you have to set the standard a second time afterwards */
-		case VIDEO_MODE_AUTO:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_NORM: AUTO\n");
-
-			/* The chip determines the format */
-			/* based on the current field rate */
-			ks0127_and_or(c, KS_CMDA,   0xfc, 0x00);
-			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
-			/* This is wrong for PAL ! As I said, */
-			/* you need to set the standard once again !! */
-			ks->format_height = 240;
-			ks->format_width = 704;
-			break;
-
-		case VIDEO_MODE_NTSC:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_NORM: NTSC_M\n");
-			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
-			ks->format_height = 240;
-			ks->format_width = 704;
-			break;
-
-		case KS_STD_NTSC_N:
-			v4l_dbg(1, debug, c,
-				"KS0127_SET_NORM: NTSC_N (fixme)\n");
-			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
-			ks->format_height = 240;
-			ks->format_width = 704;
-			break;
-
-		case VIDEO_MODE_PAL:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_NORM: PAL_N\n");
-			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
-			ks->format_height = 290;
-			ks->format_width = 704;
-			break;
-
-		case KS_STD_PAL_M:
-			v4l_dbg(1, debug, c,
-				"KS0127_SET_NORM: PAL_M (fixme)\n");
-			ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
-			ks->format_height = 290;
-			ks->format_width = 704;
-			break;
-
-		case VIDEO_MODE_SECAM:
-			v4l_dbg(1, debug, c,
-				"KS0127_SET_NORM: SECAM\n");
-			ks->format_height = 290;
-			ks->format_width = 704;
-
-			/* set to secam autodetection */
-			ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20);
-			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
-			schedule_timeout_interruptible(HZ/10+1);
-
-			/* did it autodetect? */
-			if (ks0127_read(c, KS_DEMOD) & 0x40)
-				break;
-
-			/* force to secam mode */
-			ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
-			break;
-
-		default:
-			v4l_dbg(1, debug, c,
-				"DECODER_SET_NORM: Unknown norm %d\n", *iarg);
-			break;
-		}
-		break;
-
-	case DECODER_SET_PICTURE:
-		v4l_dbg(1, debug, c,
-			"DECODER_SET_PICTURE: not yet supported\n");
-		return -EINVAL;
-
-	/* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */
-	/* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */
-	/* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */
-	/* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */
-	/* sam todo: KS0127_SET_AGC_MODE: */
-	/* sam todo: KS0127_SET_AGC: */
-	/* sam todo: KS0127_SET_CHROMA_MODE: */
-	/* sam todo: KS0127_SET_PIXCLK_MODE: */
-	/* sam todo: KS0127_SET_GAMMA_MODE: */
-	/* sam todo: KS0127_SET_UGAIN: */
-	/* sam todo: KS0127_SET_VGAIN: */
-	/* sam todo: KS0127_SET_INVALY: */
-	/* sam todo: KS0127_SET_INVALU: */
-	/* sam todo: KS0127_SET_INVALV: */
-	/* sam todo: KS0127_SET_UNUSEY: */
-	/* sam todo: KS0127_SET_UNUSEU: */
-	/* sam todo: KS0127_SET_UNUSEV: */
-	/* sam todo: KS0127_SET_VSALIGN_MODE: */
-
-	case DECODER_ENABLE_OUTPUT:
-	{
-		int enable;
-
-		iarg = arg;
-		enable = (*iarg != 0);
-		if (enable) {
-			v4l_dbg(1, debug, c,
-				"DECODER_ENABLE_OUTPUT on\n");
-			/* All output pins on */
-			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);
-			/* Obey the OEN pin */
-			ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);
-		} else {
-			v4l_dbg(1, debug, c,
-				"DECODER_ENABLE_OUTPUT off\n");
-			/* Video output pins off */
-			ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);
-			/* Ignore the OEN pin */
-			ks0127_and_or(c, KS_CDEM, 0x7f, 0x80);
-		}
+	default:
+		v4l2_dbg(1, debug, sd,
+			"s_routing: Unknown input %d\n", route->input);
 		break;
 	}
 
-	/* sam todo: KS0127_SET_OUTPUT_MODE: */
-	/* sam todo: KS0127_SET_WIDTH: */
-	/* sam todo: KS0127_SET_HEIGHT: */
-	/* sam todo: KS0127_SET_HSCALE: */
+	/* hack: CDMLPF sometimes spontaneously switches on; */
+	/* force back off */
+	ks0127_write(sd, KS_DEMOD, reg_defaults[KS_DEMOD]);
+	return 0;
+}
 
-	case DECODER_GET_STATUS:
-		v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n");
-		*iarg = 0;
-		status = ks0127_read(c, KS_STAT);
-		if (!(status & 0x20))		 /* NOVID not set */
-			*iarg = (*iarg | DECODER_STATUS_GOOD);
-		if ((status & 0x01))		      /* CLOCK set */
-			*iarg = (*iarg | DECODER_STATUS_COLOR);
-		if ((status & 0x08))		   /* PALDET set */
-			*iarg = (*iarg | DECODER_STATUS_PAL);
-		else
-			*iarg = (*iarg | DECODER_STATUS_NTSC);
-		break;
+static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct ks0127 *ks = to_ks0127(sd);
 
-	/* Catch any unknown command */
-	default:
-		v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd);
-		return -EINVAL;
+	/* Set to automatic SECAM/Fsc mode */
+	ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00);
+
+	ks->norm = std;
+	if (std & V4L2_STD_NTSC) {
+		v4l2_dbg(1, debug, sd,
+			"s_std: NTSC_M\n");
+		ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20);
+	} else if (std & V4L2_STD_PAL_N) {
+		v4l2_dbg(1, debug, sd,
+			"s_std: NTSC_N (fixme)\n");
+		ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40);
+	} else if (std & V4L2_STD_PAL) {
+		v4l2_dbg(1, debug, sd,
+			"s_std: PAL_N\n");
+		ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20);
+	} else if (std & V4L2_STD_PAL_M) {
+		v4l2_dbg(1, debug, sd,
+			"s_std: PAL_M (fixme)\n");
+		ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40);
+	} else if (std & V4L2_STD_SECAM) {
+		v4l2_dbg(1, debug, sd,
+			"s_std: SECAM\n");
+
+		/* set to secam autodetection */
+		ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20);
+		ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00);
+		schedule_timeout_interruptible(HZ/10+1);
+
+		/* did it autodetect? */
+		if (!(ks0127_read(sd, KS_DEMOD) & 0x40))
+			/* force to secam mode */
+			ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f);
+	} else {
+		v4l2_dbg(1, debug, sd, "s_std: Unknown norm %llx\n",
+			       (unsigned long long)std);
 	}
 	return 0;
 }
 
+static int ks0127_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	v4l2_dbg(1, debug, sd, "s_stream(%d)\n", enable);
+	if (enable) {
+		/* All output pins on */
+		ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x30);
+		/* Obey the OEN pin */
+		ks0127_and_or(sd, KS_CDEM, 0x7f, 0x00);
+	} else {
+		/* Video output pins off */
+		ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x00);
+		/* Ignore the OEN pin */
+		ks0127_and_or(sd, KS_CDEM, 0x7f, 0x80);
+	}
+	return 0;
+}
 
-/* Addresses to scan */
-#define I2C_KS0127_ADDON   0xD8
-#define I2C_KS0127_ONBOARD 0xDA
+static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
+{
+	int stat = V4L2_IN_ST_NO_SIGNAL;
+	u8 status;
+	v4l2_std_id std = V4L2_STD_ALL;
 
-static unsigned short normal_i2c[] = {
-	I2C_KS0127_ADDON >> 1,
-	I2C_KS0127_ONBOARD >> 1,
-	I2C_CLIENT_END
+	status = ks0127_read(sd, KS_STAT);
+	if (!(status & 0x20))		 /* NOVID not set */
+		stat = 0;
+	if (!(status & 0x01))		      /* CLOCK set */
+		stat |= V4L2_IN_ST_NO_COLOR;
+	if ((status & 0x08))		   /* PALDET set */
+		std = V4L2_STD_PAL;
+	else
+		std = V4L2_STD_NTSC;
+	if (pstd)
+		*pstd = std;
+	if (pstatus)
+		*pstatus = stat;
+	return 0;
+}
+
+static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	v4l2_dbg(1, debug, sd, "querystd\n");
+	return ks0127_status(sd, NULL, std);
+}
+
+static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	v4l2_dbg(1, debug, sd, "g_input_status\n");
+	return ks0127_status(sd, status, NULL);
+}
+
+static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ks0127 *ks = to_ks0127(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops ks0127_core_ops = {
+	.g_chip_ident = ks0127_g_chip_ident,
 };
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_tuner_ops ks0127_tuner_ops = {
+	.s_std = ks0127_s_std,
+};
 
-static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id)
+static const struct v4l2_subdev_video_ops ks0127_video_ops = {
+	.s_routing = ks0127_s_routing,
+	.s_stream = ks0127_s_stream,
+	.querystd = ks0127_querystd,
+	.g_input_status = ks0127_g_input_status,
+};
+
+static const struct v4l2_subdev_ops ks0127_ops = {
+	.core = &ks0127_core_ops,
+	.tuner = &ks0127_tuner_ops,
+	.video = &ks0127_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+
+static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct ks0127 *ks;
+	struct v4l2_subdev *sd;
 
-	v4l_info(c, "%s chip found @ 0x%x (%s)\n",
-		c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
-		c->addr << 1, c->adapter->name);
+	v4l_info(client, "%s chip found @ 0x%x (%s)\n",
+		client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
+		client->addr << 1, client->adapter->name);
 
 	ks = kzalloc(sizeof(*ks), GFP_KERNEL);
 	if (ks == NULL)
 		return -ENOMEM;
-
-	i2c_set_clientdata(c, ks);
-
-	ks->ks_type = KS_TYPE_UNKNOWN;
+	sd = &ks->sd;
+	v4l2_i2c_subdev_init(sd, client, &ks0127_ops);
 
 	/* power up */
 	init_reg_defaults();
-	ks0127_write(c, KS_CMDA, 0x2c);
+	ks0127_write(sd, KS_CMDA, 0x2c);
 	mdelay(10);
 
 	/* reset the device */
-	ks0127_reset(c);
+	ks0127_init(sd);
 	return 0;
 }
 
-static int ks0127_remove(struct i2c_client *c)
+static int ks0127_remove(struct i2c_client *client)
 {
-	struct ks0127 *ks = i2c_get_clientdata(c);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 
-	ks0127_write(c, KS_OFMTA, 0x20); /* tristate */
-	ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */
-
-	kfree(ks);
+	v4l2_device_unregister_subdev(sd);
+	ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */
+	ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */
+	kfree(to_ks0127(sd));
 	return 0;
 }
 
-static int ks0127_legacy_probe(struct i2c_adapter *adapter)
-{
-	return adapter->id == I2C_HW_B_ZR36067;
-}
-
 static const struct i2c_device_id ks0127_id[] = {
 	{ "ks0127", 0 },
+	{ "ks0127b", 0 },
+	{ "ks0122s", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ks0127_id);
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "ks0127",
-	.driverid = I2C_DRIVERID_KS0127,
-	.command = ks0127_command,
 	.probe = ks0127_probe,
 	.remove = ks0127_remove,
-	.legacy_probe = ks0127_legacy_probe,
 	.id_table = ks0127_id,
 };
diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h
index 1ec5788..cb8abd5 100644
--- a/drivers/media/video/ks0127.h
+++ b/drivers/media/video/ks0127.h
@@ -24,8 +24,6 @@
 #ifndef KS0127_H
 #define KS0127_H
 
-#include <linux/videodev.h>
-
 /* input channels */
 #define KS_INPUT_COMPOSITE_1    0
 #define KS_INPUT_COMPOSITE_2    1
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c
index de397ef..1f340fe 100644
--- a/drivers/media/video/m52790.c
+++ b/drivers/media/video/m52790.c
@@ -132,11 +132,6 @@
 	return 0;
 }
 
-static int m52790_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops m52790_core_ops = {
@@ -210,8 +205,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "m52790",
-	.driverid = I2C_DRIVERID_M52790,
-	.command = m52790_command,
 	.probe = m52790_probe,
 	.remove = m52790_remove,
 	.id_table = m52790_id,
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index b76e33d..2ad11f0 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1017,7 +1017,6 @@
 static int vidioc_querycap(struct file *file, void *fh,
 				struct v4l2_capability *cap)
 {
-	memset(cap, 0, sizeof(*cap));
 	strcpy(cap->driver, "meye");
 	strcpy(cap->card, "meye");
 	sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
@@ -1036,8 +1035,6 @@
 	if (i->index != 0)
 		return -EINVAL;
 
-	memset(i, 0, sizeof(*i));
-	i->index = 0;
 	strcpy(i->name, "Camera");
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 
@@ -1259,22 +1256,13 @@
 	if (f->index > 1)
 		return -EINVAL;
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (f->index == 0) {
 		/* standard YUV 422 capture */
-		memset(f, 0, sizeof(*f));
-		f->index = 0;
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		f->flags = 0;
 		strcpy(f->description, "YUV422");
 		f->pixelformat = V4L2_PIX_FMT_YUYV;
 	} else {
 		/* compressed MJPEG capture */
-		memset(f, 0, sizeof(*f));
-		f->index = 1;
-		f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		f->flags = V4L2_FMT_FLAG_COMPRESSED;
 		strcpy(f->description, "MJPEG");
 		f->pixelformat = V4L2_PIX_FMT_MJPEG;
@@ -1286,9 +1274,6 @@
 static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
 				struct v4l2_format *f)
 {
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
 	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
 		return -EINVAL;
@@ -1319,12 +1304,6 @@
 static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
 				    struct v4l2_format *f)
 {
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
 	switch (meye.mchip_mode) {
 	case MCHIP_HIC_MODE_CONT_OUT:
 	default:
@@ -1341,8 +1320,6 @@
 	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 	f->fmt.pix.sizeimage = f->fmt.pix.height *
 			       f->fmt.pix.bytesperline;
-	f->fmt.pix.colorspace = 0;
-	f->fmt.pix.priv = 0;
 
 	return 0;
 }
@@ -1350,9 +1327,6 @@
 static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
 				    struct v4l2_format *f)
 {
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
 	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
 		return -EINVAL;
@@ -1398,9 +1372,6 @@
 {
 	int i;
 
-	if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (req->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
@@ -1441,15 +1412,11 @@
 
 static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-	int index = buf->index;
+	unsigned int index = buf->index;
 
-	if (index < 0 || index >= gbuffers)
+	if (index >= gbuffers)
 		return -EINVAL;
 
-	memset(buf, 0, sizeof(*buf));
-
-	buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	buf->index = index;
 	buf->bytesused = meye.grab_buffer[index].size;
 	buf->flags = V4L2_BUF_FLAG_MAPPED;
 
@@ -1471,13 +1438,10 @@
 
 static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (buf->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
-	if (buf->index < 0 || buf->index >= gbuffers)
+	if (buf->index >= gbuffers)
 		return -EINVAL;
 
 	if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
@@ -1497,9 +1461,6 @@
 {
 	int reqnr;
 
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (buf->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 4d7a918..9e8e06c 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -366,29 +366,6 @@
 }
 
 /* ------------------------------------------------------------------------ */
-#ifdef CONFIG_VIDEO_ALLOW_V4L1
-static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
-{
-	if (rxsubchans == V4L2_TUNER_SUB_MONO)
-		return VIDEO_SOUND_MONO;
-	if (rxsubchans == V4L2_TUNER_SUB_STEREO)
-		return VIDEO_SOUND_STEREO;
-	if (audmode == V4L2_TUNER_MODE_LANG2)
-		return VIDEO_SOUND_LANG2;
-	return VIDEO_SOUND_LANG1;
-}
-
-static int msp_mode_v4l1_to_v4l2(int mode)
-{
-	if (mode & VIDEO_SOUND_STEREO)
-		return V4L2_TUNER_MODE_STEREO;
-	if (mode & VIDEO_SOUND_LANG2)
-		return V4L2_TUNER_MODE_LANG2;
-	if (mode & VIDEO_SOUND_LANG1)
-		return V4L2_TUNER_MODE_LANG1;
-	return V4L2_TUNER_MODE_MONO;
-}
-#endif
 
 static int msp_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
@@ -482,96 +459,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_ALLOW_V4L1
-static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
-	struct msp_state *state = to_state(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	switch (cmd) {
-	/* --- v4l ioctls --- */
-	/* take care: bttv does userspace copying, we'll get a
-	   kernel pointer here... */
-	case VIDIOCGAUDIO:
-	{
-		struct video_audio *va = arg;
-
-		va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
-		if (state->has_sound_processing)
-			va->flags |= VIDEO_AUDIO_BALANCE |
-				VIDEO_AUDIO_BASS |
-				VIDEO_AUDIO_TREBLE;
-		if (state->muted)
-			va->flags |= VIDEO_AUDIO_MUTE;
-		va->volume = state->volume;
-		va->balance = state->volume ? state->balance : 32768;
-		va->bass = state->bass;
-		va->treble = state->treble;
-
-		if (state->radio)
-			break;
-		if (state->opmode == OPMODE_AUTOSELECT)
-			msp_detect_stereo(client);
-		va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode);
-		break;
-	}
-
-	case VIDIOCSAUDIO:
-	{
-		struct video_audio *va = arg;
-
-		state->muted = (va->flags & VIDEO_AUDIO_MUTE);
-		state->volume = va->volume;
-		state->balance = va->balance;
-		state->bass = va->bass;
-		state->treble = va->treble;
-		msp_set_audio(client);
-
-		if (va->mode != 0 && state->radio == 0 &&
-		    state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) {
-			state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
-			msp_set_audmode(client);
-		}
-		break;
-	}
-
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *vc = arg;
-		int update = 0;
-		v4l2_std_id std;
-
-		if (state->radio)
-			update = 1;
-		state->radio = 0;
-		if (vc->norm == VIDEO_MODE_PAL)
-			std = V4L2_STD_PAL;
-		else if (vc->norm == VIDEO_MODE_SECAM)
-			std = V4L2_STD_SECAM;
-		else
-			std = V4L2_STD_NTSC;
-		if (std != state->v4l2_std) {
-			state->v4l2_std = std;
-			update = 1;
-		}
-		if (update)
-			msp_wake_thread(client);
-		break;
-	}
-
-	case VIDIOCSFREQ:
-	{
-		/* new channel -- kick audio carrier scan */
-		msp_wake_thread(client);
-		break;
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-#endif
-
 /* --- v4l2 ioctls --- */
 static int msp_s_radio(struct v4l2_subdev *sd)
 {
@@ -713,22 +600,24 @@
 	struct msp_state *state = to_state(sd);
 
 	switch (qc->id) {
-		case V4L2_CID_AUDIO_VOLUME:
-		case V4L2_CID_AUDIO_MUTE:
-			return v4l2_ctrl_query_fill_std(qc);
-		default:
-			break;
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+	default:
+		break;
 	}
 	if (!state->has_sound_processing)
 		return -EINVAL;
 	switch (qc->id) {
-		case V4L2_CID_AUDIO_LOUDNESS:
-		case V4L2_CID_AUDIO_BALANCE:
-		case V4L2_CID_AUDIO_BASS:
-		case V4L2_CID_AUDIO_TREBLE:
-			return v4l2_ctrl_query_fill_std(qc);
-		default:
-			return -EINVAL;
+	case V4L2_CID_AUDIO_LOUDNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
+	default:
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -820,9 +709,6 @@
 	.g_ctrl = msp_g_ctrl,
 	.s_ctrl = msp_s_ctrl,
 	.queryctrl = msp_queryctrl,
-#ifdef CONFIG_VIDEO_ALLOW_V4L1
-	.ioctl = msp_ioctl,
-#endif
 };
 
 static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index c1bf75e..fa7e509 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/log2.h>
-#include <linux/gpio.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
@@ -73,9 +72,7 @@
 	struct i2c_client *client;
 	struct soc_camera_device icd;
 	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
-	int switch_gpio;
 	unsigned char autoexposure;
-	unsigned char datawidth;
 };
 
 static int reg_read(struct soc_camera_device *icd, const u8 reg)
@@ -181,92 +178,28 @@
 	return 0;
 }
 
-static int bus_switch_request(struct mt9m001 *mt9m001,
-			      struct soc_camera_link *icl)
-{
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-	int ret;
-	unsigned int gpio = icl->gpio;
-
-	if (gpio_is_valid(gpio)) {
-		/* We have a data bus switch. */
-		ret = gpio_request(gpio, "mt9m001");
-		if (ret < 0) {
-			dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
-				gpio);
-			return ret;
-		}
-
-		ret = gpio_direction_output(gpio, 0);
-		if (ret < 0) {
-			dev_err(&mt9m001->client->dev,
-				"Cannot set GPIO %u to output\n", gpio);
-			gpio_free(gpio);
-			return ret;
-		}
-	}
-
-	mt9m001->switch_gpio = gpio;
-#else
-	mt9m001->switch_gpio = -EINVAL;
-#endif
-	return 0;
-}
-
-static void bus_switch_release(struct mt9m001 *mt9m001)
-{
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-	if (gpio_is_valid(mt9m001->switch_gpio))
-		gpio_free(mt9m001->switch_gpio);
-#endif
-}
-
-static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
-{
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-	if (!gpio_is_valid(mt9m001->switch_gpio))
-		return -ENODEV;
-
-	gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
-	return 0;
-#else
-	return -ENODEV;
-#endif
-}
-
-static int bus_switch_possible(struct mt9m001 *mt9m001)
-{
-#ifdef CONFIG_MT9M001_PCA9536_SWITCH
-	return gpio_is_valid(mt9m001->switch_gpio);
-#else
-	return 0;
-#endif
-}
-
 static int mt9m001_set_bus_param(struct soc_camera_device *icd,
 				 unsigned long flags)
 {
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
-	unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
-	int ret;
+	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+	unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
 
-	/* Flags validity verified in test_bus_param */
+	/* Only one width bit may be set */
+	if (!is_power_of_2(width_flag))
+		return -EINVAL;
 
-	if ((mt9m001->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
-	    (mt9m001->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
-	    (mt9m001->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
-		/* Well, we actually only can do 10 or 8 bits... */
-		if (width_flag == SOCAM_DATAWIDTH_9)
-			return -EINVAL;
-		ret = bus_switch_act(mt9m001,
-				     width_flag == SOCAM_DATAWIDTH_8);
-		if (ret < 0)
-			return ret;
+	if (icl->set_bus_param)
+		return icl->set_bus_param(icl, width_flag);
 
-		mt9m001->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
-	}
+	/*
+	 * Without board specific bus width settings we only support the
+	 * sensors native bus width
+	 */
+	if (width_flag == SOCAM_DATAWIDTH_10)
+		return 0;
 
-	return 0;
+	return -EINVAL;
 }
 
 static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
@@ -274,18 +207,20 @@
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
 	/* MT9M001 has all capture_format parameters fixed */
-	unsigned long flags = SOCAM_DATAWIDTH_10 | SOCAM_PCLK_SAMPLE_RISING |
+	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING |
 		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_MASTER;
+		SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER;
 
-	if (bus_switch_possible(mt9m001))
-		flags |= SOCAM_DATAWIDTH_8;
+	if (icl->query_bus_param)
+		flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK;
+	else
+		flags |= SOCAM_DATAWIDTH_10;
 
 	return soc_camera_apply_sensor_flags(icl, flags);
 }
 
-static int mt9m001_set_fmt(struct soc_camera_device *icd,
-			   __u32 pixfmt, struct v4l2_rect *rect)
+static int mt9m001_set_crop(struct soc_camera_device *icd,
+			    struct v4l2_rect *rect)
 {
 	struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
 	int ret;
@@ -324,6 +259,20 @@
 	return ret;
 }
 
+static int mt9m001_set_fmt(struct soc_camera_device *icd,
+			   struct v4l2_format *f)
+{
+	struct v4l2_rect rect = {
+		.left	= icd->x_current,
+		.top	= icd->y_current,
+		.width	= f->fmt.pix.width,
+		.height	= f->fmt.pix.height,
+	};
+
+	/* No support for scaling so far, just crop. TODO: use skipping */
+	return mt9m001_set_crop(icd, &rect);
+}
+
 static int mt9m001_try_fmt(struct soc_camera_device *icd,
 			   struct v4l2_format *f)
 {
@@ -449,6 +398,7 @@
 	.release		= mt9m001_release,
 	.start_capture		= mt9m001_start_capture,
 	.stop_capture		= mt9m001_stop_capture,
+	.set_crop		= mt9m001_set_crop,
 	.set_fmt		= mt9m001_set_fmt,
 	.try_fmt		= mt9m001_try_fmt,
 	.set_bus_param		= mt9m001_set_bus_param,
@@ -583,6 +533,7 @@
 	struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
 	s32 data;
 	int ret;
+	unsigned long flags;
 
 	/* We must have a parent by now. And it cannot be a wrong one.
 	 * So this entire test is completely redundant. */
@@ -603,18 +554,10 @@
 	case 0x8421:
 		mt9m001->model = V4L2_IDENT_MT9M001C12ST;
 		icd->formats = mt9m001_colour_formats;
-		if (gpio_is_valid(icl->gpio))
-			icd->num_formats = ARRAY_SIZE(mt9m001_colour_formats);
-		else
-			icd->num_formats = 1;
 		break;
 	case 0x8431:
 		mt9m001->model = V4L2_IDENT_MT9M001C12STM;
 		icd->formats = mt9m001_monochrome_formats;
-		if (gpio_is_valid(icl->gpio))
-			icd->num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
-		else
-			icd->num_formats = 1;
 		break;
 	default:
 		ret = -ENODEV;
@@ -623,6 +566,26 @@
 		goto ei2c;
 	}
 
+	icd->num_formats = 0;
+
+	/*
+	 * This is a 10bit sensor, so by default we only allow 10bit.
+	 * The platform may support different bus widths due to
+	 * different routing of the data lines.
+	 */
+	if (icl->query_bus_param)
+		flags = icl->query_bus_param(icl);
+	else
+		flags = SOCAM_DATAWIDTH_10;
+
+	if (flags & SOCAM_DATAWIDTH_10)
+		icd->num_formats++;
+	else
+		icd->formats++;
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		icd->num_formats++;
+
 	dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
 		 data == 0x8431 ? "C12STM" : "C12ST");
 
@@ -688,18 +651,10 @@
 	icd->height_max	= 1024;
 	icd->y_skip_top	= 1;
 	icd->iface	= icl->bus_id;
-	/* Default datawidth - this is the only width this camera (normally)
-	 * supports. It is only with extra logic that it can support
-	 * other widths. Therefore it seems to be a sensible default. */
-	mt9m001->datawidth = 10;
 	/* Simulated autoexposure. If enabled, we calculate shutter width
 	 * ourselves in the driver based on vertical blanking and frame width */
 	mt9m001->autoexposure = 1;
 
-	ret = bus_switch_request(mt9m001, icl);
-	if (ret)
-		goto eswinit;
-
 	ret = soc_camera_device_register(icd);
 	if (ret)
 		goto eisdr;
@@ -707,8 +662,6 @@
 	return 0;
 
 eisdr:
-	bus_switch_release(mt9m001);
-eswinit:
 	kfree(mt9m001);
 	return ret;
 }
@@ -718,7 +671,6 @@
 	struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
 
 	soc_camera_device_unregister(&mt9m001->icd);
-	bus_switch_release(mt9m001);
 	kfree(mt9m001);
 
 	return 0;
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 5b8e209..cdd1ddb 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -152,7 +152,7 @@
 	struct soc_camera_device icd;
 	int model;	/* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
 	enum mt9m111_context context;
-	unsigned int left, top, width, height;
+	struct v4l2_rect rect;
 	u32 pixfmt;
 	unsigned char autoexposure;
 	unsigned char datawidth;
@@ -249,12 +249,13 @@
 		return reg_write(CONTEXT_CONTROL, valA);
 }
 
-static int mt9m111_setup_rect(struct soc_camera_device *icd)
+static int mt9m111_setup_rect(struct soc_camera_device *icd,
+			      struct v4l2_rect *rect)
 {
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
 	int ret, is_raw_format;
-	int width = mt9m111->width;
-	int height = mt9m111->height;
+	int width = rect->width;
+	int height = rect->height;
 
 	if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8)
 	    || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16))
@@ -262,9 +263,9 @@
 	else
 		is_raw_format = 0;
 
-	ret = reg_write(COLUMN_START, mt9m111->left);
+	ret = reg_write(COLUMN_START, rect->left);
 	if (!ret)
-		ret = reg_write(ROW_START, mt9m111->top);
+		ret = reg_write(ROW_START, rect->top);
 
 	if (is_raw_format) {
 		if (!ret)
@@ -393,6 +394,8 @@
 
 static int mt9m111_reset(struct soc_camera_device *icd)
 {
+	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+	struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
 	int ret;
 
 	ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -401,6 +404,10 @@
 	if (!ret)
 		ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE
 				| MT9M111_RESET_RESET_SOC);
+
+	if (icl->reset)
+		icl->reset(&mt9m111->client->dev);
+
 	return ret;
 }
 
@@ -420,7 +427,7 @@
 	struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
 	unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
 		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
-		SOCAM_DATAWIDTH_8;
+		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
 
 	return soc_camera_apply_sensor_flags(icl, flags);
 }
@@ -430,6 +437,22 @@
 	return 0;
 }
 
+static int mt9m111_set_crop(struct soc_camera_device *icd,
+			    struct v4l2_rect *rect)
+{
+	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+	int ret;
+
+	dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
+		__func__, rect->left, rect->top, rect->width,
+		rect->height);
+
+	ret = mt9m111_setup_rect(icd, rect);
+	if (!ret)
+		mt9m111->rect = *rect;
+	return ret;
+}
+
 static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
 {
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
@@ -480,23 +503,27 @@
 }
 
 static int mt9m111_set_fmt(struct soc_camera_device *icd,
-			   __u32 pixfmt, struct v4l2_rect *rect)
+			   struct v4l2_format *f)
 {
 	struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_rect rect = {
+		.left	= mt9m111->rect.left,
+		.top	= mt9m111->rect.top,
+		.width	= pix->width,
+		.height	= pix->height,
+	};
 	int ret;
 
-	mt9m111->left = rect->left;
-	mt9m111->top = rect->top;
-	mt9m111->width = rect->width;
-	mt9m111->height = rect->height;
-
 	dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n",
-		__func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width,
-		mt9m111->height);
+		__func__, pix->pixelformat, rect.left, rect.top, rect.width,
+		rect.height);
 
-	ret = mt9m111_setup_rect(icd);
+	ret = mt9m111_setup_rect(icd, &rect);
 	if (!ret)
-		ret = mt9m111_set_pixfmt(icd, pixfmt);
+		ret = mt9m111_set_pixfmt(icd, pix->pixelformat);
+	if (!ret)
+		mt9m111->rect = rect;
 	return ret;
 }
 
@@ -627,6 +654,7 @@
 	.release		= mt9m111_release,
 	.start_capture		= mt9m111_start_capture,
 	.stop_capture		= mt9m111_stop_capture,
+	.set_crop		= mt9m111_set_crop,
 	.set_fmt		= mt9m111_set_fmt,
 	.try_fmt		= mt9m111_try_fmt,
 	.query_bus_param	= mt9m111_query_bus_param,
@@ -811,7 +839,7 @@
 
 	mt9m111_set_context(icd, mt9m111->context);
 	mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
-	mt9m111_setup_rect(icd);
+	mt9m111_setup_rect(icd, &mt9m111->rect);
 	mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
 	mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
 	mt9m111_set_global_gain(icd, icd->gain);
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 349d8e3..23f9ce9 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -144,13 +144,11 @@
 	int ret;
 
 	/* Disable chip output, synchronous option update */
-	dev_dbg(icd->vdev->parent, "%s\n", __func__);
-
 	ret = reg_write(icd, MT9T031_RESET, 1);
 	if (ret >= 0)
 		ret = reg_write(icd, MT9T031_RESET, 0);
 	if (ret >= 0)
-		ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3);
+		ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
 
 	return ret >= 0 ? 0 : -EIO;
 }
@@ -158,14 +156,14 @@
 static int mt9t031_release(struct soc_camera_device *icd)
 {
 	/* Disable the chip */
-	reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3);
+	reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
 	return 0;
 }
 
 static int mt9t031_start_capture(struct soc_camera_device *icd)
 {
 	/* Switch to master "normal" mode */
-	if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 3) < 0)
+	if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
 		return -EIO;
 	return 0;
 }
@@ -173,7 +171,7 @@
 static int mt9t031_stop_capture(struct soc_camera_device *icd)
 {
 	/* Stop sensor readout */
-	if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 3) < 0)
+	if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
 		return -EIO;
 	return 0;
 }
@@ -186,9 +184,9 @@
 		return -EINVAL;
 
 	if (flags & SOCAM_PCLK_SAMPLE_FALLING)
-		reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
-	else
 		reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+	else
+		reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
 
 	return 0;
 }
@@ -201,67 +199,73 @@
 	return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
 }
 
-static int mt9t031_set_fmt(struct soc_camera_device *icd,
-			   __u32 pixfmt, struct v4l2_rect *rect)
+/* Round up minima and round down maxima */
+static void recalculate_limits(struct soc_camera_device *icd,
+			       u16 xskip, u16 yskip)
+{
+	icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip;
+	icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip;
+	icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip;
+	icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip;
+	icd->width_max = MT9T031_MAX_WIDTH / xskip;
+	icd->height_max = MT9T031_MAX_HEIGHT / yskip;
+}
+
+static int mt9t031_set_params(struct soc_camera_device *icd,
+			      struct v4l2_rect *rect, u16 xskip, u16 yskip)
 {
 	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
 	int ret;
+	u16 xbin, ybin, width, height, left, top;
 	const u16 hblank = MT9T031_HORIZONTAL_BLANK,
 		vblank = MT9T031_VERTICAL_BLANK;
-	u16 xbin, xskip = mt9t031->xskip, ybin, yskip = mt9t031->yskip,
-		width = rect->width * xskip, height = rect->height * yskip;
 
-	if (pixfmt) {
-		/* S_FMT - use binning and skipping for scaling, recalculate */
-		/* Is this more optimal than just a division? */
-		for (xskip = 8; xskip > 1; xskip--)
-			if (rect->width * xskip <= icd->width_max)
-				break;
+	/* Make sure we don't exceed sensor limits */
+	if (rect->left + rect->width > icd->width_max)
+		rect->left = (icd->width_max - rect->width) / 2 + icd->x_min;
 
-		for (yskip = 8; yskip > 1; yskip--)
-			if (rect->height * yskip <= icd->height_max)
-				break;
+	if (rect->top + rect->height > icd->height_max)
+		rect->top = (icd->height_max - rect->height) / 2 + icd->y_min;
 
-		width = rect->width * xskip;
-		height = rect->height * yskip;
-
-		dev_dbg(&icd->dev, "xskip %u, width %u, yskip %u, height %u\n",
-			xskip, width, yskip, height);
-	}
+	width = rect->width * xskip;
+	height = rect->height * yskip;
+	left = rect->left * xskip;
+	top = rect->top * yskip;
 
 	xbin = min(xskip, (u16)3);
 	ybin = min(yskip, (u16)3);
 
-	/* Make sure we don't exceed frame limits */
-	if (rect->left + width > icd->width_max)
-		rect->left = (icd->width_max - width) / 2;
+	dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n",
+		xskip, width, rect->width, yskip, height, rect->height);
 
-	if (rect->top + height > icd->height_max)
-		rect->top = (icd->height_max - height) / 2;
-
-	/* Could just do roundup(rect->left, [xy]bin); but this is cheaper */
+	/* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */
 	switch (xbin) {
 	case 2:
-		rect->left = (rect->left + 1) & ~1;
+		left = (left + 3) & ~3;
 		break;
 	case 3:
-		rect->left = roundup(rect->left, 3);
+		left = roundup(left, 6);
 	}
 
 	switch (ybin) {
 	case 2:
-		rect->top = (rect->top + 1) & ~1;
+		top = (top + 3) & ~3;
 		break;
 	case 3:
-		rect->top = roundup(rect->top, 3);
+		top = roundup(top, 6);
 	}
 
+	/* Disable register update, reconfigure atomically */
+	ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1);
+	if (ret < 0)
+		return ret;
+
 	/* Blanking and start values - default... */
 	ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank);
 	if (ret >= 0)
 		ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank);
 
-	if (pixfmt) {
+	if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
 		/* Binning, skipping */
 		if (ret >= 0)
 			ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE,
@@ -270,14 +274,14 @@
 			ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE,
 					((ybin - 1) << 4) | (yskip - 1));
 	}
-	dev_dbg(&icd->dev, "new left %u, top %u\n", rect->left, rect->top);
+	dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top);
 
 	/* The caller provides a supported format, as guaranteed by
 	 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_COLUMN_START, rect->left);
+		ret = reg_write(icd, MT9T031_COLUMN_START, left);
 	if (ret >= 0)
-		ret = reg_write(icd, MT9T031_ROW_START, rect->top);
+		ret = reg_write(icd, MT9T031_ROW_START, top);
 	if (ret >= 0)
 		ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1);
 	if (ret >= 0)
@@ -297,12 +301,58 @@
 		}
 	}
 
-	if (!ret && pixfmt) {
+	/* Re-enable register update, commit all changes */
+	if (ret >= 0)
+		ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int mt9t031_set_crop(struct soc_camera_device *icd,
+			    struct v4l2_rect *rect)
+{
+	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+
+	/* CROP - no change in scaling, or in limits */
+	return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
+}
+
+static int mt9t031_set_fmt(struct soc_camera_device *icd,
+			   struct v4l2_format *f)
+{
+	struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+	int ret;
+	u16 xskip, yskip;
+	struct v4l2_rect rect = {
+		.left	= icd->x_current,
+		.top	= icd->y_current,
+		.width	= f->fmt.pix.width,
+		.height	= f->fmt.pix.height,
+	};
+
+	/*
+	 * try_fmt has put rectangle within limits.
+	 * S_FMT - use binning and skipping for scaling, recalculate
+	 * limits, used for cropping
+	 */
+	/* Is this more optimal than just a division? */
+	for (xskip = 8; xskip > 1; xskip--)
+		if (rect.width * xskip <= MT9T031_MAX_WIDTH)
+			break;
+
+	for (yskip = 8; yskip > 1; yskip--)
+		if (rect.height * yskip <= MT9T031_MAX_HEIGHT)
+			break;
+
+	recalculate_limits(icd, xskip, yskip);
+
+	ret = mt9t031_set_params(icd, &rect, xskip, yskip);
+	if (!ret) {
 		mt9t031->xskip = xskip;
 		mt9t031->yskip = yskip;
 	}
 
-	return ret < 0 ? ret : 0;
+	return ret;
 }
 
 static int mt9t031_try_fmt(struct soc_camera_device *icd,
@@ -310,14 +360,14 @@
 {
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (pix->height < icd->height_min)
-		pix->height = icd->height_min;
-	if (pix->height > icd->height_max)
-		pix->height = icd->height_max;
-	if (pix->width < icd->width_min)
-		pix->width = icd->width_min;
-	if (pix->width > icd->width_max)
-		pix->width = icd->width_max;
+	if (pix->height < MT9T031_MIN_HEIGHT)
+		pix->height = MT9T031_MIN_HEIGHT;
+	if (pix->height > MT9T031_MAX_HEIGHT)
+		pix->height = MT9T031_MAX_HEIGHT;
+	if (pix->width < MT9T031_MIN_WIDTH)
+		pix->width = MT9T031_MIN_WIDTH;
+	if (pix->width > MT9T031_MAX_WIDTH)
+		pix->width = MT9T031_MAX_WIDTH;
 
 	pix->width &= ~0x01; /* has to be even */
 	pix->height &= ~0x01; /* has to be even */
@@ -390,6 +440,14 @@
 		.step		= 1,
 		.default_value	= 0,
 	}, {
+		.id		= V4L2_CID_HFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Horizontally",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	}, {
 		.id		= V4L2_CID_GAIN,
 		.type		= V4L2_CTRL_TYPE_INTEGER,
 		.name		= "Gain",
@@ -431,6 +489,7 @@
 	.release		= mt9t031_release,
 	.start_capture		= mt9t031_start_capture,
 	.stop_capture		= mt9t031_stop_capture,
+	.set_crop		= mt9t031_set_crop,
 	.set_fmt		= mt9t031_set_fmt,
 	.try_fmt		= mt9t031_try_fmt,
 	.set_bus_param		= mt9t031_set_bus_param,
@@ -513,21 +572,23 @@
 			if (data < 0)
 				return -EIO;
 		} else {
-			/* Pack it into 1.125..15 variable step, register values 9..67 */
+			/* Pack it into 1.125..128 variable step, register values 9..0x7860 */
 			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
 			unsigned long range = qctrl->maximum - qctrl->default_value - 1;
+			/* calculated gain: map 65..127 to 9..1024 step 0.125 */
 			unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
-					       111 + range / 2) / range + 9;
+					       1015 + range / 2) / range + 9;
 
-			if (gain <= 32)
+			if (gain <= 32)		/* calculated gain 9..32 -> 9..32 */
 				data = gain;
-			else if (gain <= 64)
+			else if (gain <= 64)	/* calculated gain 33..64 -> 0x51..0x60 */
 				data = ((gain - 32) * 16 + 16) / 32 + 80;
 			else
-				data = ((gain - 64) * 7 + 28) / 56 + 96;
+				/* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */
+				data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
 
-			dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
-				 reg_read(icd, MT9T031_GLOBAL_GAIN), data);
+			dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n",
+				reg_read(icd, MT9T031_GLOBAL_GAIN), data);
 			data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
 			if (data < 0)
 				return -EIO;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index b04c8cb..4d3b481 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -13,7 +13,6 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/log2.h>
-#include <linux/gpio.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
@@ -89,9 +88,7 @@
 	struct i2c_client *client;
 	struct soc_camera_device icd;
 	int model;	/* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
-	int switch_gpio;
 	u16 chip_control;
-	unsigned char datawidth;
 };
 
 static int reg_read(struct soc_camera_device *icd, const u8 reg)
@@ -209,66 +206,6 @@
 	return 0;
 }
 
-static int bus_switch_request(struct mt9v022 *mt9v022, struct soc_camera_link *icl)
-{
-#ifdef CONFIG_MT9V022_PCA9536_SWITCH
-	int ret;
-	unsigned int gpio = icl->gpio;
-
-	if (gpio_is_valid(gpio)) {
-		/* We have a data bus switch. */
-		ret = gpio_request(gpio, "mt9v022");
-		if (ret < 0) {
-			dev_err(&mt9v022->client->dev, "Cannot get GPIO %u\n", gpio);
-			return ret;
-		}
-
-		ret = gpio_direction_output(gpio, 0);
-		if (ret < 0) {
-			dev_err(&mt9v022->client->dev,
-				"Cannot set GPIO %u to output\n", gpio);
-			gpio_free(gpio);
-			return ret;
-		}
-	}
-
-	mt9v022->switch_gpio = gpio;
-#else
-	mt9v022->switch_gpio = -EINVAL;
-#endif
-	return 0;
-}
-
-static void bus_switch_release(struct mt9v022 *mt9v022)
-{
-#ifdef CONFIG_MT9V022_PCA9536_SWITCH
-	if (gpio_is_valid(mt9v022->switch_gpio))
-		gpio_free(mt9v022->switch_gpio);
-#endif
-}
-
-static int bus_switch_act(struct mt9v022 *mt9v022, int go8bit)
-{
-#ifdef CONFIG_MT9V022_PCA9536_SWITCH
-	if (!gpio_is_valid(mt9v022->switch_gpio))
-		return -ENODEV;
-
-	gpio_set_value_cansleep(mt9v022->switch_gpio, go8bit);
-	return 0;
-#else
-	return -ENODEV;
-#endif
-}
-
-static int bus_switch_possible(struct mt9v022 *mt9v022)
-{
-#ifdef CONFIG_MT9V022_PCA9536_SWITCH
-	return gpio_is_valid(mt9v022->switch_gpio);
-#else
-	return 0;
-#endif
-}
-
 static int mt9v022_set_bus_param(struct soc_camera_device *icd,
 				 unsigned long flags)
 {
@@ -282,19 +219,17 @@
 	if (!is_power_of_2(width_flag))
 		return -EINVAL;
 
-	if ((mt9v022->datawidth != 10 && (width_flag == SOCAM_DATAWIDTH_10)) ||
-	    (mt9v022->datawidth != 9  && (width_flag == SOCAM_DATAWIDTH_9)) ||
-	    (mt9v022->datawidth != 8  && (width_flag == SOCAM_DATAWIDTH_8))) {
-		/* Well, we actually only can do 10 or 8 bits... */
-		if (width_flag == SOCAM_DATAWIDTH_9)
-			return -EINVAL;
-
-		ret = bus_switch_act(mt9v022,
-				     width_flag == SOCAM_DATAWIDTH_8);
-		if (ret < 0)
+	if (icl->set_bus_param) {
+		ret = icl->set_bus_param(icl, width_flag);
+		if (ret)
 			return ret;
-
-		mt9v022->datawidth = width_flag == SOCAM_DATAWIDTH_8 ? 8 : 10;
+	} else {
+		/*
+		 * Without board specific bus width settings we only support the
+		 * sensors native bus width
+		 */
+		if (width_flag != SOCAM_DATAWIDTH_10)
+			return -EINVAL;
 	}
 
 	flags = soc_camera_apply_sensor_flags(icl, flags);
@@ -328,44 +263,27 @@
 static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
 {
 	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
-	unsigned int width_flag = SOCAM_DATAWIDTH_10;
+	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+	unsigned int width_flag;
 
-	if (bus_switch_possible(mt9v022))
-		width_flag |= SOCAM_DATAWIDTH_8;
+	if (icl->query_bus_param)
+		width_flag = icl->query_bus_param(icl) &
+			SOCAM_DATAWIDTH_MASK;
+	else
+		width_flag = SOCAM_DATAWIDTH_10;
 
 	return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING |
 		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW |
 		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |
-		SOCAM_MASTER | SOCAM_SLAVE |
+		SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_SLAVE |
 		width_flag;
 }
 
-static int mt9v022_set_fmt(struct soc_camera_device *icd,
-			   __u32 pixfmt, struct v4l2_rect *rect)
+static int mt9v022_set_crop(struct soc_camera_device *icd,
+			    struct v4l2_rect *rect)
 {
-	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
 	int ret;
 
-	/* The caller provides a supported format, as verified per call to
-	 * icd->try_fmt(), datawidth is from our supported format list */
-	switch (pixfmt) {
-	case V4L2_PIX_FMT_GREY:
-	case V4L2_PIX_FMT_Y16:
-		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
-			return -EINVAL;
-		break;
-	case V4L2_PIX_FMT_SBGGR8:
-	case V4L2_PIX_FMT_SBGGR16:
-		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
-			return -EINVAL;
-		break;
-	case 0:
-		/* No format change, only geometry */
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	/* Like in example app. Contradicts the datasheet though */
 	ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
 	if (ret >= 0) {
@@ -403,6 +321,42 @@
 	return 0;
 }
 
+static int mt9v022_set_fmt(struct soc_camera_device *icd,
+			   struct v4l2_format *f)
+{
+	struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_rect rect = {
+		.left	= icd->x_current,
+		.top	= icd->y_current,
+		.width	= pix->width,
+		.height	= pix->height,
+	};
+
+	/* The caller provides a supported format, as verified per call to
+	 * icd->try_fmt(), datawidth is from our supported format list */
+	switch (pix->pixelformat) {
+	case V4L2_PIX_FMT_GREY:
+	case V4L2_PIX_FMT_Y16:
+		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
+			return -EINVAL;
+		break;
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SBGGR16:
+		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
+			return -EINVAL;
+		break;
+	case 0:
+		/* No format change, only geometry */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* No support for scaling on this camera, just crop. */
+	return mt9v022_set_crop(icd, &rect);
+}
+
 static int mt9v022_try_fmt(struct soc_camera_device *icd,
 			   struct v4l2_format *f)
 {
@@ -544,6 +498,7 @@
 	.release		= mt9v022_release,
 	.start_capture		= mt9v022_start_capture,
 	.stop_capture		= mt9v022_stop_capture,
+	.set_crop		= mt9v022_set_crop,
 	.set_fmt		= mt9v022_set_fmt,
 	.try_fmt		= mt9v022_try_fmt,
 	.set_bus_param		= mt9v022_set_bus_param,
@@ -699,6 +654,7 @@
 	struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
 	s32 data;
 	int ret;
+	unsigned long flags;
 
 	if (!icd->dev.parent ||
 	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
@@ -732,22 +688,36 @@
 		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
 		icd->formats = mt9v022_colour_formats;
-		if (gpio_is_valid(icl->gpio))
-			icd->num_formats = ARRAY_SIZE(mt9v022_colour_formats);
-		else
-			icd->num_formats = 1;
 	} else {
 		ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
 		icd->formats = mt9v022_monochrome_formats;
-		if (gpio_is_valid(icl->gpio))
-			icd->num_formats = ARRAY_SIZE(mt9v022_monochrome_formats);
-		else
-			icd->num_formats = 1;
 	}
 
-	if (!ret)
-		ret = soc_camera_video_start(icd);
+	if (ret < 0)
+		goto eisis;
+
+	icd->num_formats = 0;
+
+	/*
+	 * This is a 10bit sensor, so by default we only allow 10bit.
+	 * The platform may support different bus widths due to
+	 * different routing of the data lines.
+	 */
+	if (icl->query_bus_param)
+		flags = icl->query_bus_param(icl);
+	else
+		flags = SOCAM_DATAWIDTH_10;
+
+	if (flags & SOCAM_DATAWIDTH_10)
+		icd->num_formats++;
+	else
+		icd->formats++;
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		icd->num_formats++;
+
+	ret = soc_camera_video_start(icd);
 	if (ret < 0)
 		goto eisis;
 
@@ -812,14 +782,6 @@
 	icd->height_max	= 480;
 	icd->y_skip_top	= 1;
 	icd->iface	= icl->bus_id;
-	/* Default datawidth - this is the only width this camera (normally)
-	 * supports. It is only with extra logic that it can support
-	 * other widths. Therefore it seems to be a sensible default. */
-	mt9v022->datawidth = 10;
-
-	ret = bus_switch_request(mt9v022, icl);
-	if (ret)
-		goto eswinit;
 
 	ret = soc_camera_device_register(icd);
 	if (ret)
@@ -828,8 +790,6 @@
 	return 0;
 
 eisdr:
-	bus_switch_release(mt9v022);
-eswinit:
 	kfree(mt9v022);
 	return ret;
 }
@@ -839,7 +799,6 @@
 	struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
 
 	soc_camera_device_unregister(&mt9v022->icd);
-	bus_switch_release(mt9v022);
 	kfree(mt9v022);
 
 	return 0;
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
new file mode 100644
index 0000000..70629e1
--- /dev/null
+++ b/drivers/media/video/mx3_camera.c
@@ -0,0 +1,1220 @@
+/*
+ * V4L2 Driver for i.MX3x camera host
+ *
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@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/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf-dma-contig.h>
+#include <media/soc_camera.h>
+
+#include <mach/ipu.h>
+#include <mach/mx3_camera.h>
+
+#define MX3_CAM_DRV_NAME "mx3-camera"
+
+/* CMOS Sensor Interface Registers */
+#define CSI_REG_START		0x60
+
+#define CSI_SENS_CONF		(0x60 - CSI_REG_START)
+#define CSI_SENS_FRM_SIZE	(0x64 - CSI_REG_START)
+#define CSI_ACT_FRM_SIZE	(0x68 - CSI_REG_START)
+#define CSI_OUT_FRM_CTRL	(0x6C - CSI_REG_START)
+#define CSI_TST_CTRL		(0x70 - CSI_REG_START)
+#define CSI_CCIR_CODE_1		(0x74 - CSI_REG_START)
+#define CSI_CCIR_CODE_2		(0x78 - CSI_REG_START)
+#define CSI_CCIR_CODE_3		(0x7C - CSI_REG_START)
+#define CSI_FLASH_STROBE_1	(0x80 - CSI_REG_START)
+#define CSI_FLASH_STROBE_2	(0x84 - CSI_REG_START)
+
+#define CSI_SENS_CONF_VSYNC_POL_SHIFT		0
+#define CSI_SENS_CONF_HSYNC_POL_SHIFT		1
+#define CSI_SENS_CONF_DATA_POL_SHIFT		2
+#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT		3
+#define CSI_SENS_CONF_SENS_PRTCL_SHIFT		4
+#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT		7
+#define CSI_SENS_CONF_DATA_FMT_SHIFT		8
+#define CSI_SENS_CONF_DATA_WIDTH_SHIFT		10
+#define CSI_SENS_CONF_EXT_VSYNC_SHIFT		15
+#define CSI_SENS_CONF_DIVRATIO_SHIFT		16
+
+#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444	(0UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
+#define CSI_SENS_CONF_DATA_FMT_YUV422		(2UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
+#define CSI_SENS_CONF_DATA_FMT_BAYER		(3UL << CSI_SENS_CONF_DATA_FMT_SHIFT)
+
+#define MAX_VIDEO_MEM 16
+
+struct mx3_camera_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer			vb;
+	const struct soc_camera_data_format	*fmt;
+
+	/* One descriptot per scatterlist (per frame) */
+	struct dma_async_tx_descriptor		*txd;
+
+	/* We have to "build" a scatterlist ourselves - one element per frame */
+	struct scatterlist			sg;
+};
+
+/**
+ * struct mx3_camera_dev - i.MX3x camera (CSI) object
+ * @dev:		camera device, to which the coherent buffer is attached
+ * @icd:		currently attached camera sensor
+ * @clk:		pointer to clock
+ * @base:		remapped register base address
+ * @pdata:		platform data
+ * @platform_flags:	platform flags
+ * @mclk:		master clock frequency in Hz
+ * @capture:		list of capture videobuffers
+ * @lock:		protects video buffer lists
+ * @active:		active video buffer
+ * @idmac_channel:	array of pointers to IPU DMAC DMA channels
+ * @soc_host:		embedded soc_host object
+ */
+struct mx3_camera_dev {
+	struct device		*dev;
+	/*
+	 * i.MX3x is only supposed to handle one camera on its Camera Sensor
+	 * Interface. If anyone ever builds hardware to enable more than one
+	 * camera _simultaneously_, they will have to modify this driver too
+	 */
+	struct soc_camera_device *icd;
+	struct clk		*clk;
+
+	void __iomem		*base;
+
+	struct mx3_camera_pdata	*pdata;
+
+	unsigned long		platform_flags;
+	unsigned long		mclk;
+
+	struct list_head	capture;
+	spinlock_t		lock;		/* Protects video buffer lists */
+	struct mx3_camera_buffer *active;
+
+	/* IDMAC / dmaengine interface */
+	struct idmac_channel	*idmac_channel[1];	/* We need one channel */
+
+	struct soc_camera_host	soc_host;
+};
+
+struct dma_chan_request {
+	struct mx3_camera_dev	*mx3_cam;
+	enum ipu_channel	id;
+};
+
+static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt);
+
+static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg)
+{
+	return __raw_readl(mx3->base + reg);
+}
+
+static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg)
+{
+	__raw_writel(value, mx3->base + reg);
+}
+
+/* Called from the IPU IDMAC ISR */
+static void mx3_cam_dma_done(void *arg)
+{
+	struct idmac_tx_desc *desc = to_tx_desc(arg);
+	struct dma_chan *chan = desc->txd.chan;
+	struct idmac_channel *ichannel = to_idmac_chan(chan);
+	struct mx3_camera_dev *mx3_cam = ichannel->client;
+	struct videobuf_buffer *vb;
+
+	dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n",
+		desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0);
+
+	spin_lock(&mx3_cam->lock);
+	if (mx3_cam->active) {
+		vb = &mx3_cam->active->vb;
+
+		list_del_init(&vb->queue);
+		vb->state = VIDEOBUF_DONE;
+		do_gettimeofday(&vb->ts);
+		vb->field_count++;
+		wake_up(&vb->done);
+	}
+
+	if (list_empty(&mx3_cam->capture)) {
+		mx3_cam->active = NULL;
+		spin_unlock(&mx3_cam->lock);
+
+		/*
+		 * stop capture - without further buffers IPU_CHA_BUF0_RDY will
+		 * not get updated
+		 */
+		return;
+	}
+
+	mx3_cam->active = list_entry(mx3_cam->capture.next,
+				     struct mx3_camera_buffer, vb.queue);
+	mx3_cam->active->vb.state = VIDEOBUF_ACTIVE;
+	spin_unlock(&mx3_cam->lock);
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf)
+{
+	struct soc_camera_device *icd = vq->priv_data;
+	struct videobuf_buffer *vb = &buf->vb;
+	struct dma_async_tx_descriptor *txd = buf->txd;
+	struct idmac_channel *ichan;
+
+	BUG_ON(in_interrupt());
+
+	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+		vb, vb->baddr, vb->bsize);
+
+	/*
+	 * This waits until this buffer is out of danger, i.e., until it is no
+	 * longer in STATE_QUEUED or STATE_ACTIVE
+	 */
+	videobuf_waiton(vb, 0, 0);
+	if (txd) {
+		ichan = to_idmac_chan(txd->chan);
+		async_tx_ack(txd);
+	}
+	videobuf_dma_contig_free(vq, vb);
+	buf->txd = NULL;
+
+	vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+/*
+ * Videobuf operations
+ */
+
+/*
+ * Calculate the __buffer__ (not data) size and number of buffers.
+ * Called with .vb_lock held
+ */
+static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
+			      unsigned int *size)
+{
+	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	/*
+	 * bits-per-pixel (depth) as specified in camera's pixel format does
+	 * not necessarily match what the camera interface writes to RAM, but
+	 * it should be good enough for now.
+	 */
+	unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8);
+
+	if (!mx3_cam->idmac_channel[0])
+		return -EINVAL;
+
+	*size = icd->width * icd->height * bpp;
+
+	if (!*count)
+		*count = 32;
+
+	if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
+		*count = MAX_VIDEO_MEM * 1024 * 1024 / *size;
+
+	return 0;
+}
+
+/* Called with .vb_lock held */
+static int mx3_videobuf_prepare(struct videobuf_queue *vq,
+		struct videobuf_buffer *vb, enum v4l2_field field)
+{
+	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	struct mx3_camera_buffer *buf =
+		container_of(vb, struct mx3_camera_buffer, vb);
+	/* current_fmt _must_ always be set */
+	size_t new_size = icd->width * icd->height *
+		((icd->current_fmt->depth + 7) >> 3);
+	int ret;
+
+	/*
+	 * I think, in buf_prepare you only have to protect global data,
+	 * the actual buffer is yours
+	 */
+
+	if (buf->fmt	!= icd->current_fmt ||
+	    vb->width	!= icd->width ||
+	    vb->height	!= icd->height ||
+	    vb->field	!= field) {
+		buf->fmt	= icd->current_fmt;
+		vb->width	= icd->width;
+		vb->height	= icd->height;
+		vb->field	= field;
+		if (vb->state != VIDEOBUF_NEEDS_INIT)
+			free_buffer(vq, buf);
+	}
+
+	if (vb->baddr && vb->bsize < new_size) {
+		/* User provided buffer, but it is too small */
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (vb->state == VIDEOBUF_NEEDS_INIT) {
+		struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
+		struct scatterlist *sg = &buf->sg;
+
+		/*
+		 * The total size of video-buffers that will be allocated / mapped.
+		 * *size that we calculated in videobuf_setup gets assigned to
+		 * vb->bsize, and now we use the same calculation to get vb->size.
+		 */
+		vb->size = new_size;
+
+		/* This actually (allocates and) maps buffers */
+		ret = videobuf_iolock(vq, vb, NULL);
+		if (ret)
+			goto fail;
+
+		/*
+		 * We will have to configure the IDMAC channel. It has two slots
+		 * for DMA buffers, we shall enter the first two buffers there,
+		 * and then submit new buffers in DMA-ready interrupts
+		 */
+		sg_init_table(sg, 1);
+		sg_dma_address(sg)	= videobuf_to_dma_contig(vb);
+		sg_dma_len(sg)		= vb->size;
+
+		buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
+			&ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+			DMA_PREP_INTERRUPT);
+		if (!buf->txd) {
+			ret = -EIO;
+			goto fail;
+		}
+
+		buf->txd->callback_param	= buf->txd;
+		buf->txd->callback		= mx3_cam_dma_done;
+
+		vb->state = VIDEOBUF_PREPARED;
+	}
+
+	return 0;
+
+fail:
+	free_buffer(vq, buf);
+out:
+	return ret;
+}
+
+static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
+{
+	/* Add more formats as need arises and test possibilities appear... */
+	switch (fourcc) {
+	case V4L2_PIX_FMT_RGB565:
+		return IPU_PIX_FMT_RGB565;
+	case V4L2_PIX_FMT_RGB24:
+		return IPU_PIX_FMT_RGB24;
+	case V4L2_PIX_FMT_RGB332:
+		return IPU_PIX_FMT_RGB332;
+	case V4L2_PIX_FMT_YUV422P:
+		return IPU_PIX_FMT_YVU422P;
+	default:
+		return IPU_PIX_FMT_GENERIC;
+	}
+}
+
+/* Called with .vb_lock held */
+static void mx3_videobuf_queue(struct videobuf_queue *vq,
+			       struct videobuf_buffer *vb)
+{
+	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	struct mx3_camera_buffer *buf =
+		container_of(vb, struct mx3_camera_buffer, vb);
+	struct dma_async_tx_descriptor *txd = buf->txd;
+	struct idmac_channel *ichan = to_idmac_chan(txd->chan);
+	struct idmac_video_param *video = &ichan->params.video;
+	const struct soc_camera_data_format *data_fmt = icd->current_fmt;
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	/* This is the configuration of one sg-element */
+	video->out_pixel_fmt	= fourcc_to_ipu_pix(data_fmt->fourcc);
+	video->out_width	= icd->width;
+	video->out_height	= icd->height;
+	video->out_stride	= icd->width;
+
+#ifdef DEBUG
+	/* helps to see what DMA actually has written */
+	memset((void *)vb->baddr, 0xaa, vb->bsize);
+#endif
+
+	spin_lock_irqsave(&mx3_cam->lock, flags);
+
+	list_add_tail(&vb->queue, &mx3_cam->capture);
+
+	if (!mx3_cam->active) {
+		mx3_cam->active = buf;
+		vb->state = VIDEOBUF_ACTIVE;
+	} else {
+		vb->state = VIDEOBUF_QUEUED;
+	}
+
+	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+
+	cookie = txd->tx_submit(txd);
+	dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg));
+	if (cookie >= 0)
+		return;
+
+	/* Submit error */
+	vb->state = VIDEOBUF_PREPARED;
+
+	spin_lock_irqsave(&mx3_cam->lock, flags);
+
+	list_del_init(&vb->queue);
+
+	if (mx3_cam->active == buf)
+		mx3_cam->active = NULL;
+
+	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+}
+
+/* Called with .vb_lock held */
+static void mx3_videobuf_release(struct videobuf_queue *vq,
+				 struct videobuf_buffer *vb)
+{
+	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	struct mx3_camera_buffer *buf =
+		container_of(vb, struct mx3_camera_buffer, vb);
+	unsigned long flags;
+
+	dev_dbg(&icd->dev, "Release%s DMA 0x%08x (state %d), queue %sempty\n",
+		mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg),
+		 vb->state, list_empty(&vb->queue) ? "" : "not ");
+	spin_lock_irqsave(&mx3_cam->lock, flags);
+	if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
+	    !list_empty(&vb->queue)) {
+		vb->state = VIDEOBUF_ERROR;
+
+		list_del_init(&vb->queue);
+		if (mx3_cam->active == buf)
+			mx3_cam->active = NULL;
+	}
+	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+	free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops mx3_videobuf_ops = {
+	.buf_setup      = mx3_videobuf_setup,
+	.buf_prepare    = mx3_videobuf_prepare,
+	.buf_queue      = mx3_videobuf_queue,
+	.buf_release    = mx3_videobuf_release,
+};
+
+static void mx3_camera_init_videobuf(struct videobuf_queue *q,
+				     struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+
+	videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev,
+				       &mx3_cam->lock,
+				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				       V4L2_FIELD_NONE,
+				       sizeof(struct mx3_camera_buffer), icd);
+}
+
+/* First part of ipu_csi_init_interface() */
+static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam,
+				struct soc_camera_device *icd)
+{
+	u32 conf;
+	long rate;
+
+	/* Set default size: ipu_csi_set_window_size() */
+	csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE);
+	/* ...and position to 0:0: ipu_csi_set_window_pos() */
+	conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000;
+	csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL);
+
+	/* We use only gated clock synchronisation mode so far */
+	conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT;
+
+	/* Set generic data, platform-biggest bus-width */
+	conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
+
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
+		conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
+		conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
+		conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+	else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/
+		conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+
+	if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC)
+		conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT;
+	if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC)
+		conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT;
+	if (mx3_cam->platform_flags & MX3_CAMERA_DP)
+		conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
+	if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
+		conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
+	if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
+		conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
+	if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
+		conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
+
+	/* ipu_csi_init_interface() */
+	csi_reg_write(mx3_cam, conf, CSI_SENS_CONF);
+
+	clk_enable(mx3_cam->clk);
+	rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk);
+	dev_dbg(&icd->dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate);
+	if (rate)
+		clk_set_rate(mx3_cam->clk, rate);
+}
+
+/* Called with .video_lock held */
+static int mx3_camera_add_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	int ret;
+
+	if (mx3_cam->icd) {
+		ret = -EBUSY;
+		goto ebusy;
+	}
+
+	mx3_camera_activate(mx3_cam, icd);
+	ret = icd->ops->init(icd);
+	if (ret < 0) {
+		clk_disable(mx3_cam->clk);
+		goto einit;
+	}
+
+	mx3_cam->icd = icd;
+
+einit:
+ebusy:
+	if (!ret)
+		dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
+			 icd->devnum);
+
+	return ret;
+}
+
+/* Called with .video_lock held */
+static void mx3_camera_remove_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
+
+	BUG_ON(icd != mx3_cam->icd);
+
+	if (*ichan) {
+		dma_release_channel(&(*ichan)->dma_chan);
+		*ichan = NULL;
+	}
+
+	icd->ops->release(icd);
+
+	clk_disable(mx3_cam->clk);
+
+	mx3_cam->icd = NULL;
+
+	dev_info(&icd->dev, "MX3 Camera driver detached from camera %d\n",
+		 icd->devnum);
+}
+
+static bool channel_change_requested(struct soc_camera_device *icd,
+				     struct v4l2_rect *rect)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
+
+	/* Do buffers have to be re-allocated or channel re-configured? */
+	return ichan && rect->width * rect->height > icd->width * icd->height;
+}
+
+static int test_platform_param(struct mx3_camera_dev *mx3_cam,
+			       unsigned char buswidth, unsigned long *flags)
+{
+	/*
+	 * Platform specified synchronization and pixel clock polarities are
+	 * only a recommendation and are only used during probing. MX3x
+	 * camera interface only works in master mode, i.e., uses HSYNC and
+	 * VSYNC signals from the sensor
+	 */
+	*flags = SOCAM_MASTER |
+		SOCAM_HSYNC_ACTIVE_HIGH |
+		SOCAM_HSYNC_ACTIVE_LOW |
+		SOCAM_VSYNC_ACTIVE_HIGH |
+		SOCAM_VSYNC_ACTIVE_LOW |
+		SOCAM_PCLK_SAMPLE_RISING |
+		SOCAM_PCLK_SAMPLE_FALLING |
+		SOCAM_DATA_ACTIVE_HIGH |
+		SOCAM_DATA_ACTIVE_LOW;
+
+	/* If requested data width is supported by the platform, use it or any
+	 * possible lower value - i.MX31 is smart enough to schift bits */
+	switch (buswidth) {
+	case 15:
+		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15))
+			return -EINVAL;
+		*flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 |
+			SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
+		break;
+	case 10:
+		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10))
+			return -EINVAL;
+		*flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 |
+			SOCAM_DATAWIDTH_4;
+		break;
+	case 8:
+		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8))
+			return -EINVAL;
+		*flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
+		break;
+	case 4:
+		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4))
+			return -EINVAL;
+		*flags |= SOCAM_DATAWIDTH_4;
+		break;
+	default:
+		dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
+				    const unsigned int depth)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	unsigned long bus_flags, camera_flags;
+	int ret = test_platform_param(mx3_cam, depth, &bus_flags);
+
+	dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret);
+
+	if (ret < 0)
+		return ret;
+
+	camera_flags = icd->ops->query_bus_param(icd);
+
+	ret = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+	if (ret < 0)
+		dev_warn(&icd->dev, "Flags incompatible: camera %lx, host %lx\n",
+			 camera_flags, bus_flags);
+
+	return ret;
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+	struct dma_chan_request *rq = arg;
+	struct mx3_camera_pdata *pdata;
+
+	if (!rq)
+		return false;
+
+	pdata = rq->mx3_cam->dev->platform_data;
+
+	return rq->id == chan->chan_id &&
+		pdata->dma_dev == chan->device->dev;
+}
+
+static const struct soc_camera_data_format mx3_camera_formats[] = {
+	{
+		.name		= "Bayer (sRGB) 8 bit",
+		.depth		= 8,
+		.fourcc		= V4L2_PIX_FMT_SBGGR8,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+	}, {
+		.name		= "Monochrome 8 bit",
+		.depth		= 8,
+		.fourcc		= V4L2_PIX_FMT_GREY,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+	},
+};
+
+static bool buswidth_supported(struct soc_camera_host *ici, int depth)
+{
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+
+	switch (depth) {
+	case 4:
+		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4);
+	case 8:
+		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8);
+	case 10:
+		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10);
+	case 15:
+		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15);
+	}
+	return false;
+}
+
+static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
+				  struct soc_camera_format_xlate *xlate)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	int formats = 0, buswidth, ret;
+
+	buswidth = icd->formats[idx].depth;
+
+	if (!buswidth_supported(ici, buswidth))
+		return 0;
+
+	ret = mx3_camera_try_bus_param(icd, buswidth);
+	if (ret < 0)
+		return 0;
+
+	switch (icd->formats[idx].fourcc) {
+	case V4L2_PIX_FMT_SGRBG10:
+		formats++;
+		if (xlate) {
+			xlate->host_fmt = &mx3_camera_formats[0];
+			xlate->cam_fmt = icd->formats + idx;
+			xlate->buswidth = buswidth;
+			xlate++;
+			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+				mx3_camera_formats[0].name,
+				icd->formats[idx].name);
+		}
+		goto passthrough;
+	case V4L2_PIX_FMT_Y16:
+		formats++;
+		if (xlate) {
+			xlate->host_fmt = &mx3_camera_formats[1];
+			xlate->cam_fmt = icd->formats + idx;
+			xlate->buswidth = buswidth;
+			xlate++;
+			dev_dbg(&ici->dev, "Providing format %s using %s\n",
+				mx3_camera_formats[0].name,
+				icd->formats[idx].name);
+		}
+	default:
+passthrough:
+		/* Generic pass-through */
+		formats++;
+		if (xlate) {
+			xlate->host_fmt = icd->formats + idx;
+			xlate->cam_fmt = icd->formats + idx;
+			xlate->buswidth = buswidth;
+			xlate++;
+			dev_dbg(&ici->dev,
+				"Providing format %s in pass-through mode\n",
+				icd->formats[idx].name);
+		}
+	}
+
+	return formats;
+}
+
+static void configure_geometry(struct mx3_camera_dev *mx3_cam,
+			       struct v4l2_rect *rect)
+{
+	u32 ctrl, width_field, height_field;
+
+	/* Setup frame size - this cannot be changed on-the-fly... */
+	width_field = rect->width - 1;
+	height_field = rect->height - 1;
+	csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE);
+
+	csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1);
+	csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2);
+
+	csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE);
+
+	/* ...and position */
+	ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000;
+	/* Sensor does the cropping */
+	csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL);
+
+	/*
+	 * No need to free resources here if we fail, we'll see if we need to
+	 * do this next time we are called
+	 */
+}
+
+static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
+{
+	dma_cap_mask_t mask;
+	struct dma_chan *chan;
+	struct idmac_channel **ichan = &mx3_cam->idmac_channel[0];
+	/* We have to use IDMAC_IC_7 for Bayer / generic data */
+	struct dma_chan_request rq = {.mx3_cam = mx3_cam,
+				      .id = IDMAC_IC_7};
+
+	if (*ichan) {
+		struct videobuf_buffer *vb, *_vb;
+		dma_release_channel(&(*ichan)->dma_chan);
+		*ichan = NULL;
+		mx3_cam->active = NULL;
+		list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
+			list_del_init(&vb->queue);
+			vb->state = VIDEOBUF_ERROR;
+			wake_up(&vb->done);
+		}
+	}
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_cap_set(DMA_PRIVATE, mask);
+	chan = dma_request_channel(mask, chan_filter, &rq);
+	if (!chan)
+		return -EBUSY;
+
+	*ichan = to_idmac_chan(chan);
+	(*ichan)->client = mx3_cam;
+
+	return 0;
+}
+
+static int mx3_camera_set_crop(struct soc_camera_device *icd,
+			       struct v4l2_rect *rect)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+
+	/*
+	 * We now know pixel formats and can decide upon DMA-channel(s)
+	 * So far only direct camera-to-memory is supported
+	 */
+	if (channel_change_requested(icd, rect)) {
+		int ret = acquire_dma_channel(mx3_cam);
+		if (ret < 0)
+			return ret;
+	}
+
+	configure_geometry(mx3_cam, rect);
+
+	return icd->ops->set_crop(icd, rect);
+}
+
+static int mx3_camera_set_fmt(struct soc_camera_device *icd,
+			      struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_rect rect = {
+		.left	= icd->x_current,
+		.top	= icd->y_current,
+		.width	= pix->width,
+		.height	= pix->height,
+	};
+	int ret;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+	if (!xlate) {
+		dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+		return -EINVAL;
+	}
+
+	ret = acquire_dma_channel(mx3_cam);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Might have to perform a complete interface initialisation like in
+	 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
+	 * mxc_v4l2_s_fmt()
+	 */
+
+	configure_geometry(mx3_cam, &rect);
+
+	ret = icd->ops->set_fmt(icd, f);
+	if (!ret) {
+		icd->buswidth = xlate->buswidth;
+		icd->current_fmt = xlate->host_fmt;
+	}
+
+	return ret;
+}
+
+static int mx3_camera_try_fmt(struct soc_camera_device *icd,
+			      struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	__u32 pixfmt = pix->pixelformat;
+	enum v4l2_field field;
+	int ret;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (pixfmt && !xlate) {
+		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		return -EINVAL;
+	}
+
+	/* limit to MX3 hardware capabilities */
+	if (pix->height > 4096)
+		pix->height = 4096;
+	if (pix->width > 4096)
+		pix->width = 4096;
+
+	pix->bytesperline = pix->width *
+		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
+	pix->sizeimage = pix->height * pix->bytesperline;
+
+	/* camera has to see its format, but the user the original one */
+	pix->pixelformat = xlate->cam_fmt->fourcc;
+	/* limit to sensor capabilities */
+	ret = icd->ops->try_fmt(icd, f);
+	pix->pixelformat = xlate->host_fmt->fourcc;
+
+	field = pix->field;
+
+	if (field == V4L2_FIELD_ANY) {
+		pix->field = V4L2_FIELD_NONE;
+	} else if (field != V4L2_FIELD_NONE) {
+		dev_err(&icd->dev, "Field type %d unsupported.\n", field);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int mx3_camera_reqbufs(struct soc_camera_file *icf,
+			      struct v4l2_requestbuffers *p)
+{
+	return 0;
+}
+
+static unsigned int mx3_camera_poll(struct file *file, poll_table *pt)
+{
+	struct soc_camera_file *icf = file->private_data;
+
+	return videobuf_poll_stream(file, &icf->vb_vidq, pt);
+}
+
+static int mx3_camera_querycap(struct soc_camera_host *ici,
+			       struct v4l2_capability *cap)
+{
+	/* cap->name is set by the firendly caller:-> */
+	strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card));
+	cap->version = KERNEL_VERSION(0, 2, 2);
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct mx3_camera_dev *mx3_cam = ici->priv;
+	unsigned long bus_flags, camera_flags, common_flags;
+	u32 dw, sens_conf;
+	int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags);
+	const struct soc_camera_format_xlate *xlate;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (!xlate) {
+		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+		return -EINVAL;
+	}
+
+	dev_dbg(&ici->dev, "requested bus width %d bit: %d\n",
+		icd->buswidth, ret);
+
+	if (ret < 0)
+		return ret;
+
+	camera_flags = icd->ops->query_bus_param(icd);
+
+	common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+	if (!common_flags) {
+		dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n",
+			camera_flags, bus_flags);
+		return -EINVAL;
+	}
+
+	/* Make choices, based on platform preferences */
+	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+		if (mx3_cam->platform_flags & MX3_CAMERA_HSP)
+			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+		else
+			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+	}
+
+	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+		if (mx3_cam->platform_flags & MX3_CAMERA_VSP)
+			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+		else
+			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+	}
+
+	if ((common_flags & SOCAM_DATA_ACTIVE_HIGH) &&
+	    (common_flags & SOCAM_DATA_ACTIVE_LOW)) {
+		if (mx3_cam->platform_flags & MX3_CAMERA_DP)
+			common_flags &= ~SOCAM_DATA_ACTIVE_HIGH;
+		else
+			common_flags &= ~SOCAM_DATA_ACTIVE_LOW;
+	}
+
+	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
+	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
+		if (mx3_cam->platform_flags & MX3_CAMERA_PCP)
+			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
+		else
+			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
+	}
+
+	/* Make the camera work in widest common mode, we'll take care of
+	 * the rest */
+	if (common_flags & SOCAM_DATAWIDTH_15)
+		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
+			SOCAM_DATAWIDTH_15;
+	else if (common_flags & SOCAM_DATAWIDTH_10)
+		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
+			SOCAM_DATAWIDTH_10;
+	else if (common_flags & SOCAM_DATAWIDTH_8)
+		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
+			SOCAM_DATAWIDTH_8;
+	else
+		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
+			SOCAM_DATAWIDTH_4;
+
+	ret = icd->ops->set_bus_param(icd, common_flags);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * So far only gated clock mode is supported. Add a line
+	 *	(3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) |
+	 * below and select the required mode when supporting other
+	 * synchronisation protocols.
+	 */
+	sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) &
+		~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) |
+		  (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) |
+		  (1 << CSI_SENS_CONF_DATA_POL_SHIFT) |
+		  (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) |
+		  (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) |
+		  (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT));
+
+	/* TODO: Support RGB and YUV formats */
+
+	/* This has been set in mx3_camera_activate(), but we clear it above */
+	sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER;
+
+	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
+		sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT;
+	if (common_flags & SOCAM_HSYNC_ACTIVE_LOW)
+		sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT;
+	if (common_flags & SOCAM_VSYNC_ACTIVE_LOW)
+		sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT;
+	if (common_flags & SOCAM_DATA_ACTIVE_LOW)
+		sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
+
+	/* Just do what we're asked to do */
+	switch (xlate->host_fmt->depth) {
+	case 4:
+		dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+		break;
+	case 8:
+		dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+		break;
+	case 10:
+		dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+		break;
+	default:
+		/*
+		 * Actually it can only be 15 now, default is just to silence
+		 * compiler warnings
+		 */
+	case 15:
+		dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
+	}
+
+	csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
+
+	dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
+
+	return 0;
+}
+
+static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
+	.owner		= THIS_MODULE,
+	.add		= mx3_camera_add_device,
+	.remove		= mx3_camera_remove_device,
+#ifdef CONFIG_PM
+	.suspend	= mx3_camera_suspend,
+	.resume		= mx3_camera_resume,
+#endif
+	.set_crop	= mx3_camera_set_crop,
+	.set_fmt	= mx3_camera_set_fmt,
+	.try_fmt	= mx3_camera_try_fmt,
+	.get_formats	= mx3_camera_get_formats,
+	.init_videobuf	= mx3_camera_init_videobuf,
+	.reqbufs	= mx3_camera_reqbufs,
+	.poll		= mx3_camera_poll,
+	.querycap	= mx3_camera_querycap,
+	.set_bus_param	= mx3_camera_set_bus_param,
+};
+
+static int mx3_camera_probe(struct platform_device *pdev)
+{
+	struct mx3_camera_dev *mx3_cam;
+	struct resource *res;
+	void __iomem *base;
+	int err = 0;
+	struct soc_camera_host *soc_host;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -ENODEV;
+		goto egetres;
+	}
+
+	mx3_cam = vmalloc(sizeof(*mx3_cam));
+	if (!mx3_cam) {
+		dev_err(&pdev->dev, "Could not allocate mx3 camera object\n");
+		err = -ENOMEM;
+		goto ealloc;
+	}
+	memset(mx3_cam, 0, sizeof(*mx3_cam));
+
+	mx3_cam->clk = clk_get(&pdev->dev, "csi_clk");
+	if (IS_ERR(mx3_cam->clk)) {
+		err = PTR_ERR(mx3_cam->clk);
+		goto eclkget;
+	}
+
+	dev_set_drvdata(&pdev->dev, mx3_cam);
+
+	mx3_cam->pdata = pdev->dev.platform_data;
+	mx3_cam->platform_flags = mx3_cam->pdata->flags;
+	if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
+			MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 |
+			MX3_CAMERA_DATAWIDTH_15))) {
+		/* Platform hasn't set available data widths. This is bad.
+		 * Warn and use a default. */
+		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
+			 "data widths, using default 8 bit\n");
+		mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
+	}
+
+	mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000;
+	if (!mx3_cam->mclk) {
+		dev_warn(&pdev->dev,
+			 "mclk_10khz == 0! Please, fix your platform data. "
+			 "Using default 20MHz\n");
+		mx3_cam->mclk = 20000000;
+	}
+
+	/* list of video-buffers */
+	INIT_LIST_HEAD(&mx3_cam->capture);
+	spin_lock_init(&mx3_cam->lock);
+
+	base = ioremap(res->start, res->end - res->start + 1);
+	if (!base) {
+		err = -ENOMEM;
+		goto eioremap;
+	}
+
+	mx3_cam->base	= base;
+	mx3_cam->dev	= &pdev->dev;
+
+	soc_host		= &mx3_cam->soc_host;
+	soc_host->drv_name	= MX3_CAM_DRV_NAME;
+	soc_host->ops		= &mx3_soc_camera_host_ops;
+	soc_host->priv		= mx3_cam;
+	soc_host->dev.parent	= &pdev->dev;
+	soc_host->nr		= pdev->id;
+	err = soc_camera_host_register(soc_host);
+	if (err)
+		goto ecamhostreg;
+
+	/* IDMAC interface */
+	dmaengine_get();
+
+	return 0;
+
+ecamhostreg:
+	iounmap(base);
+eioremap:
+	clk_put(mx3_cam->clk);
+eclkget:
+	vfree(mx3_cam);
+ealloc:
+egetres:
+	return err;
+}
+
+static int __devexit mx3_camera_remove(struct platform_device *pdev)
+{
+	struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev);
+
+	clk_put(mx3_cam->clk);
+
+	soc_camera_host_unregister(&mx3_cam->soc_host);
+
+	iounmap(mx3_cam->base);
+
+	/*
+	 * The channel has either not been allocated,
+	 * or should have been released
+	 */
+	if (WARN_ON(mx3_cam->idmac_channel[0]))
+		dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan);
+
+	vfree(mx3_cam);
+
+	dmaengine_put();
+
+	dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n");
+
+	return 0;
+}
+
+static struct platform_driver mx3_camera_driver = {
+	.driver 	= {
+		.name	= MX3_CAM_DRV_NAME,
+	},
+	.probe		= mx3_camera_probe,
+	.remove		= __exit_p(mx3_camera_remove),
+};
+
+
+static int __devinit mx3_camera_init(void)
+{
+	return platform_driver_register(&mx3_camera_driver);
+}
+
+static void __exit mx3_camera_exit(void)
+{
+	platform_driver_unregister(&mx3_camera_driver);
+}
+
+module_init(mx3_camera_init);
+module_exit(mx3_camera_exit);
+
+MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index e3cbe14..84aec62 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -25,16 +25,20 @@
 
 #include <media/saa7146_vv.h>
 #include <media/tuner.h>
-#include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
 #include <media/saa7115.h>
 
 #include "mxb.h"
 #include "tea6415c.h"
 #include "tea6420.h"
-#include "tda9840.h"
 
-#define I2C_SAA7111 0x24
+#define	I2C_SAA5246A  0x11
+#define I2C_SAA7111A  0x24
+#define	I2C_TDA9840   0x42
+#define	I2C_TEA6415C  0x43
+#define	I2C_TEA6420_1 0x4c
+#define	I2C_TEA6420_2 0x4d
+#define	I2C_TUNER     0x60
 
 #define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
 
@@ -79,57 +83,35 @@
 static int video_audio_connect[MXB_INPUTS] =
 	{ 0, 1, 3, 3 };
 
-/* these are the necessary input-output-pins for bringing one audio source
-(see above) to the CD-output */
-static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
-		{
-		{{1,1,0},{1,1,0}},	/* Tuner */
-		{{5,1,0},{6,1,0}},	/* AUX 1 */
-		{{4,1,0},{6,1,0}},	/* AUX 2 */
-		{{3,1,0},{6,1,0}},	/* AUX 3 */
-		{{1,1,0},{3,1,0}},	/* Radio */
-		{{1,1,0},{2,1,0}},	/* CD-Rom */
-		{{6,1,0},{6,1,0}}	/* Mute */
-		};
+/* These are the necessary input-output-pins for bringing one audio source
+   (see above) to the CD-output. Note that gain is set to 0 in this table. */
+static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
+	{ { 1, 1 }, { 1, 1 } },	/* Tuner */
+	{ { 5, 1 }, { 6, 1 } },	/* AUX 1 */
+	{ { 4, 1 }, { 6, 1 } },	/* AUX 2 */
+	{ { 3, 1 }, { 6, 1 } },	/* AUX 3 */
+	{ { 1, 1 }, { 3, 1 } },	/* Radio */
+	{ { 1, 1 }, { 2, 1 } },	/* CD-Rom */
+	{ { 6, 1 }, { 6, 1 } }	/* Mute */
+};
 
-/* these are the necessary input-output-pins for bringing one audio source
-(see above) to the line-output */
-static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
-		{
-		{{2,3,0},{1,2,0}},
-		{{5,3,0},{6,2,0}},
-		{{4,3,0},{6,2,0}},
-		{{3,3,0},{6,2,0}},
-		{{2,3,0},{3,2,0}},
-		{{2,3,0},{2,2,0}},
-		{{6,3,0},{6,2,0}}	/* Mute */
-		};
+/* These are the necessary input-output-pins for bringing one audio source
+   (see above) to the line-output. Note that gain is set to 0 in this table. */
+static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
+	{ { 2, 3 }, { 1, 2 } },
+	{ { 5, 3 }, { 6, 2 } },
+	{ { 4, 3 }, { 6, 2 } },
+	{ { 3, 3 }, { 6, 2 } },
+	{ { 2, 3 }, { 3, 2 } },
+	{ { 2, 3 }, { 2, 2 } },
+	{ { 6, 3 }, { 6, 2 } }	/* Mute */
+};
 
 #define MAXCONTROLS	1
 static struct v4l2_queryctrl mxb_controls[] = {
 	{ V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
 };
 
-static struct saa7146_extension_ioctls ioctls[] = {
-	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_QUERYCTRL, 	SAA7146_BEFORE },
-	{ VIDIOC_G_CTRL,	SAA7146_BEFORE },
-	{ VIDIOC_S_CTRL,	SAA7146_BEFORE },
-	{ VIDIOC_G_TUNER, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_TUNER, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_FREQUENCY, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_G_AUDIO, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_S_AUDIO, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_DBG_G_REGISTER, 	SAA7146_EXCLUSIVE },
-	{ VIDIOC_DBG_S_REGISTER, 	SAA7146_EXCLUSIVE },
-	{ MXB_S_AUDIO_CD, 	SAA7146_EXCLUSIVE },	/* custom control */
-	{ MXB_S_AUDIO_LINE, 	SAA7146_EXCLUSIVE },	/* custom control */
-	{ 0,			0 }
-};
-
 struct mxb
 {
 	struct video_device	*video_dev;
@@ -137,12 +119,12 @@
 
 	struct i2c_adapter	i2c_adapter;
 
-	struct i2c_client	*saa7111a;
-	struct i2c_client	*tda9840;
-	struct i2c_client	*tea6415c;
-	struct i2c_client	*tuner;
-	struct i2c_client	*tea6420_1;
-	struct i2c_client	*tea6420_2;
+	struct v4l2_subdev	*saa7111a;
+	struct v4l2_subdev	*tda9840;
+	struct v4l2_subdev	*tea6415c;
+	struct v4l2_subdev	*tuner;
+	struct v4l2_subdev	*tea6420_1;
+	struct v4l2_subdev	*tea6420_2;
 
 	int	cur_mode;	/* current audio mode (mono, stereo, ...) */
 	int	cur_input;	/* current input */
@@ -150,84 +132,51 @@
 	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */
 };
 
+#define saa7111a_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
+#define tea6420_1_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->tea6420_1, o, f, ##args)
+#define tea6420_2_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->tea6420_2, o, f, ##args)
+#define tda9840_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->tda9840, o, f, ##args)
+#define tea6415c_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
+#define tuner_call(mxb, o, f, args...) \
+	v4l2_subdev_call(mxb->tuner, o, f, ##args)
+#define call_all(dev, o, f, args...) \
+	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
+
 static struct saa7146_extension extension;
 
-static int mxb_check_clients(struct device *dev, void *data)
+static int mxb_probe(struct saa7146_dev *dev)
 {
-	struct mxb *mxb = data;
-	struct i2c_client *client = i2c_verify_client(dev);
-
-	if (!client)
-		return 0;
-
-	if (I2C_ADDR_TEA6420_1 == client->addr)
-		mxb->tea6420_1 = client;
-	if (I2C_ADDR_TEA6420_2 == client->addr)
-		mxb->tea6420_2 = client;
-	if (I2C_TEA6415C_2 == client->addr)
-		mxb->tea6415c = client;
-	if (I2C_ADDR_TDA9840 == client->addr)
-		mxb->tda9840 = client;
-	if (I2C_SAA7111 == client->addr)
-		mxb->saa7111a = client;
-	if (0x60 == client->addr)
-		mxb->tuner = client;
-
-	return 0;
-}
-
-static int mxb_probe(struct saa7146_dev* dev)
-{
-	struct mxb* mxb = NULL;
-	int result;
-
-	result = request_module("saa7115");
-	if (result < 0) {
-		printk("mxb: saa7111 i2c module not available.\n");
-		return -ENODEV;
-	}
-	result = request_module("tea6420");
-	if (result < 0) {
-		printk("mxb: tea6420 i2c module not available.\n");
-		return -ENODEV;
-	}
-	result = request_module("tea6415c");
-	if (result < 0) {
-		printk("mxb: tea6415c i2c module not available.\n");
-		return -ENODEV;
-	}
-	result = request_module("tda9840");
-	if (result < 0) {
-		printk("mxb: tda9840 i2c module not available.\n");
-		return -ENODEV;
-	}
-	result = request_module("tuner");
-	if (result < 0) {
-		printk("mxb: tuner i2c module not available.\n");
-		return -ENODEV;
-	}
+	struct mxb *mxb = NULL;
 
 	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
-	if( NULL == mxb ) {
+	if (mxb == NULL) {
 		DEB_D(("not enough kernel memory.\n"));
 		return -ENOMEM;
 	}
 
-	mxb->i2c_adapter = (struct i2c_adapter) {
-		.class = I2C_CLASS_TV_ANALOG,
-	};
-
 	snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
 
 	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
-	if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
+	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
 		DEB_S(("cannot register i2c-device. skipping.\n"));
 		kfree(mxb);
 		return -EFAULT;
 	}
 
-	/* loop through all i2c-devices on the bus and look who is there */
-	device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients);
+	mxb->saa7111a = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa7115", "saa7111", I2C_SAA7111A);
+	mxb->tea6420_1 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_1);
+	mxb->tea6420_2 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_2);
+	mxb->tea6415c = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6415c", "tea6415c", I2C_TEA6415C);
+	mxb->tda9840 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tda9840", "tda9840", I2C_TDA9840);
+	mxb->tuner = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tuner", "tuner", I2C_TUNER);
+	if (v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa5246a", "saa5246a", I2C_SAA5246A)) {
+		printk(KERN_INFO "mxb: found teletext decoder\n");
+	}
 
 	/* check if all devices are present */
 	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
@@ -315,47 +264,45 @@
 	struct v4l2_routing route;
 
 	int i = 0, err = 0;
-	struct tea6415c_multiplex vm;
 
 	/* select video mode in saa7111a */
-	mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std);
+	saa7111a_call(mxb, tuner, s_std, std);
 
 	/* select tuner-output on saa7111a */
 	i = 0;
 	route.input = SAA7115_COMPOSITE0;
 	route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
-	mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+	saa7111a_call(mxb, video, s_routing, &route);
 
 	/* select a tuner type */
 	tun_setup.mode_mask = T_ANALOG_TV;
 	tun_setup.addr = ADDR_UNSET;
 	tun_setup.type = TUNER_PHILIPS_PAL;
-	mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup);
+	tuner_call(mxb, tuner, s_type_addr, &tun_setup);
 	/* tune in some frequency on tuner */
 	mxb->cur_freq.tuner = 0;
 	mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
 	mxb->cur_freq.frequency = freq;
-	mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY,
-					&mxb->cur_freq);
+	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
 
 	/* set a default video standard */
-	mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
+	tuner_call(mxb, tuner, s_std, std);
 
 	/* mute audio on tea6420s */
-	mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]);
-	mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]);
-	mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]);
-	mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]);
+	tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
+	tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
+	tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
+	tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
 
-	/* switch to tuner-channel on tea6415c*/
-	vm.out = 17;
-	vm.in  = 3;
-	mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
+	/* switch to tuner-channel on tea6415c */
+	route.input = 3;
+	route.output = 17;
+	tea6415c_call(mxb, video, s_routing, &route);
 
-	/* select tuner-output on multicable on tea6415c*/
-	vm.in  = 3;
-	vm.out = 13;
-	mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
+	/* select tuner-output on multicable on tea6415c */
+	route.input = 3;
+	route.output = 13;
+	tea6415c_call(mxb, video, s_routing, &route);
 
 	/* the rest for mxb */
 	mxb->cur_input = 0;
@@ -424,6 +371,343 @@
 }
 */
 
+static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	int i;
+
+	for (i = MAXCONTROLS - 1; i >= 0; i--) {
+		if (mxb_controls[i].id == qc->id) {
+			*qc = mxb_controls[i];
+			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+			return 0;
+		}
+	}
+	return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+	int i;
+
+	for (i = MAXCONTROLS - 1; i >= 0; i--) {
+		if (mxb_controls[i].id == vc->id)
+			break;
+	}
+
+	if (i < 0)
+		return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
+
+	if (vc->id == V4L2_CID_AUDIO_MUTE) {
+		vc->value = mxb->cur_mute;
+		DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+		return 0;
+	}
+
+	DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+	int i = 0;
+
+	for (i = MAXCONTROLS - 1; i >= 0; i--) {
+		if (mxb_controls[i].id == vc->id)
+			break;
+	}
+
+	if (i < 0)
+		return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
+
+	if (vc->id == V4L2_CID_AUDIO_MUTE) {
+		mxb->cur_mute = vc->value;
+		if (!vc->value) {
+			/* switch the audio-source */
+			tea6420_1_call(mxb, audio, s_routing,
+					&TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
+			tea6420_2_call(mxb, audio, s_routing,
+					&TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
+		} else {
+			tea6420_1_call(mxb, audio, s_routing,
+					&TEA6420_line[6][0]);
+			tea6420_2_call(mxb, audio, s_routing,
+					&TEA6420_line[6][1]);
+		}
+		DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
+	}
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+	if (i->index < 0 || i->index >= MXB_INPUTS)
+		return -EINVAL;
+	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+	*i = mxb->cur_input;
+
+	DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+	struct v4l2_routing route;
+	int i = 0;
+
+	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+
+	if (input < 0 || input >= MXB_INPUTS)
+		return -EINVAL;
+
+	mxb->cur_input = input;
+
+	saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
+			input_port_selection[input].hps_sync);
+
+	/* prepare switching of tea6415c and saa7111a;
+	   have a look at the 'background'-file for further informations  */
+	switch (input) {
+	case TUNER:
+		i = SAA7115_COMPOSITE0;
+		route.input = 3;
+		route.output = 17;
+
+		if (tea6415c_call(mxb, video, s_routing, &route)) {
+			printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
+			return -EFAULT;
+		}
+		/* connect tuner-output always to multicable */
+		route.input = 3;
+		route.output = 13;
+		break;
+	case AUX3_YC:
+		/* nothing to be done here. aux3_yc is
+		   directly connected to the saa711a */
+		i = SAA7115_SVIDEO1;
+		break;
+	case AUX3:
+		/* nothing to be done here. aux3 is
+		   directly connected to the saa711a */
+		i = SAA7115_COMPOSITE1;
+		break;
+	case AUX1:
+		i = SAA7115_COMPOSITE0;
+		route.input = 1;
+		route.output = 17;
+		break;
+	}
+
+	/* switch video in tea6415c only if necessary */
+	switch (input) {
+	case TUNER:
+	case AUX1:
+		if (tea6415c_call(mxb, video, s_routing, &route)) {
+			printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
+			return -EFAULT;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* switch video in saa7111a */
+	route.input = i;
+	route.output = 0;
+	if (saa7111a_call(mxb, video, s_routing, &route))
+		printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n");
+
+	/* switch the audio-source only if necessary */
+	if (0 == mxb->cur_mute) {
+		tea6420_1_call(mxb, audio, s_routing,
+				&TEA6420_line[video_audio_connect[input]][0]);
+		tea6420_2_call(mxb, audio, s_routing,
+				&TEA6420_line[video_audio_connect[input]][1]);
+	}
+
+	return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+
+	if (t->index) {
+		DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
+		return -EINVAL;
+	}
+
+	DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+
+	memset(t, 0, sizeof(*t));
+	strlcpy(t->name, "TV Tuner", sizeof(t->name));
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
+			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+	t->audmode = mxb->cur_mode;
+	return call_all(dev, tuner, g_tuner, t);
+}
+
+static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+
+	if (t->index) {
+		DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
+		return -EINVAL;
+	}
+
+	mxb->cur_mode = t->audmode;
+	return call_all(dev, tuner, s_tuner, t);
+}
+
+static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+
+	if (mxb->cur_input) {
+		DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
+					mxb->cur_input));
+		return -EINVAL;
+	}
+
+	*f = mxb->cur_freq;
+
+	DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	if (f->tuner)
+		return -EINVAL;
+
+	if (V4L2_TUNER_ANALOG_TV != f->type)
+		return -EINVAL;
+
+	if (mxb->cur_input) {
+		DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
+		return -EINVAL;
+	}
+
+	mxb->cur_freq = *f;
+	DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
+
+	/* tune in desired frequency */
+	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
+
+	/* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
+	spin_lock(&dev->slock);
+	vv->vbi_fieldcount = 0;
+	spin_unlock(&dev->slock);
+
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+
+	if (a->index < 0 || a->index > MXB_INPUTS) {
+		DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
+		return -EINVAL;
+	}
+
+	DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
+	memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+
+	return call_all(dev, core, g_register, reg);
+}
+
+static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+
+	return call_all(dev, core, s_register, reg);
+}
+#endif
+
+static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct mxb *mxb = (struct mxb *)dev->ext_priv;
+
+	switch (cmd) {
+	case MXB_S_AUDIO_CD:
+	{
+		int i = *(int *)arg;
+
+		if (i < 0 || i >= MXB_AUDIOS) {
+			DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
+			return -EINVAL;
+		}
+
+		DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
+
+		tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]);
+		tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]);
+
+		return 0;
+	}
+	case MXB_S_AUDIO_LINE:
+	{
+		int i = *(int *)arg;
+
+		if (i < 0 || i >= MXB_AUDIOS) {
+			DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
+			return -EINVAL;
+		}
+
+		DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
+		tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]);
+		tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]);
+
+		return 0;
+	}
+	default:
+/*
+		DEB2(printk("does not handle this ioctl.\n"));
+*/
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
 static struct saa7146_ext_vv vv_data;
 
 /* this function only gets called when the probing was successful */
@@ -437,6 +721,23 @@
 	   already did this in "mxb_vl42_probe" */
 
 	saa7146_vv_init(dev, &vv_data);
+	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
+	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
+	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
+	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
+	vv_data.ops.vidioc_g_input = vidioc_g_input;
+	vv_data.ops.vidioc_s_input = vidioc_s_input;
+	vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
+	vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
+	vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
+	vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
+	vv_data.ops.vidioc_g_audio = vidioc_g_audio;
+	vv_data.ops.vidioc_s_audio = vidioc_s_audio;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	vv_data.ops.vidioc_g_register = vidioc_g_register;
+	vv_data.ops.vidioc_s_register = vidioc_s_register;
+#endif
+	vv_data.ops.vidioc_default = vidioc_default;
 	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
 		ERR(("cannot register capture v4l2 device. skipping.\n"));
 		return -1;
@@ -449,13 +750,6 @@
 		}
 	}
 
-	i2c_use_client(mxb->tea6420_1);
-	i2c_use_client(mxb->tea6420_2);
-	i2c_use_client(mxb->tea6415c);
-	i2c_use_client(mxb->tda9840);
-	i2c_use_client(mxb->saa7111a);
-	i2c_use_client(mxb->tuner);
-
 	printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
 
 	mxb_num++;
@@ -469,13 +763,6 @@
 
 	DEB_EE(("dev:%p\n", dev));
 
-	i2c_release_client(mxb->tea6420_1);
-	i2c_release_client(mxb->tea6420_2);
-	i2c_release_client(mxb->tea6415c);
-	i2c_release_client(mxb->tda9840);
-	i2c_release_client(mxb->saa7111a);
-	i2c_release_client(mxb->tuner);
-
 	saa7146_unregister_device(&mxb->video_dev,dev);
 	if (MXB_BOARD_CAN_DO_VBI(dev))
 		saa7146_unregister_device(&mxb->vbi_dev, dev);
@@ -489,330 +776,9 @@
 	return 0;
 }
 
-static long mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct mxb *mxb = (struct mxb *)dev->ext_priv;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	switch(cmd) {
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *i = arg;
-
-		DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
-		if (i->index < 0 || i->index >= MXB_INPUTS)
-			return -EINVAL;
-		memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
-		return 0;
-	}
-	/* the saa7146 provides some controls (brightness, contrast, saturation)
-	   which gets registered *after* this function. because of this we have
-	   to return with a value != 0 even if the function succeded.. */
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *qc = arg;
-		int i;
-
-		for (i = MAXCONTROLS - 1; i >= 0; i--) {
-			if (mxb_controls[i].id == qc->id) {
-				*qc = mxb_controls[i];
-				DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
-				return 0;
-			}
-		}
-		return -EAGAIN;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *vc = arg;
-		int i;
-
-		for (i = MAXCONTROLS - 1; i >= 0; i--) {
-			if (mxb_controls[i].id == vc->id)
-				break;
-		}
-
-		if (i < 0)
-			return -EAGAIN;
-
-		if (vc->id == V4L2_CID_AUDIO_MUTE) {
-			vc->value = mxb->cur_mute;
-			DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
-			return 0;
-		}
-
-		DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
-		return 0;
-	}
-
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *vc = arg;
-		int i = 0;
-
-		for (i = MAXCONTROLS - 1; i >= 0; i--) {
-			if (mxb_controls[i].id == vc->id)
-				break;
-		}
-
-		if (i < 0)
-			return -EAGAIN;
-
-		if (vc->id == V4L2_CID_AUDIO_MUTE) {
-			mxb->cur_mute = vc->value;
-			if (!vc->value) {
-				/* switch the audio-source */
-				mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
-						&TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
-				mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
-						&TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
-			} else {
-				mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
-						&TEA6420_line[6][0]);
-				mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
-						&TEA6420_line[6][1]);
-			}
-			DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
-		}
-		return 0;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		int *input = (int *)arg;
-		*input = mxb->cur_input;
-
-		DEB_EE(("VIDIOC_G_INPUT %d.\n", *input));
-		return 0;
-	}
-	case VIDIOC_S_INPUT:
-	{
-		int input = *(int *)arg;
-		struct tea6415c_multiplex vm;
-		struct v4l2_routing route;
-		int i = 0;
-
-		DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
-
-		if (input < 0 || input >= MXB_INPUTS)
-			return -EINVAL;
-
-		mxb->cur_input = input;
-
-		saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
-				input_port_selection[input].hps_sync);
-
-		/* prepare switching of tea6415c and saa7111a;
-		   have a look at the 'background'-file for further informations  */
-		switch (input) {
-		case TUNER:
-			i = SAA7115_COMPOSITE0;
-			vm.in  = 3;
-			vm.out = 17;
-
-			if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
-				printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
-				return -EFAULT;
-			}
-			/* connect tuner-output always to multicable */
-			vm.in  = 3;
-			vm.out = 13;
-			break;
-		case AUX3_YC:
-			/* nothing to be done here. aux3_yc is
-			   directly connected to the saa711a */
-			i = SAA7115_SVIDEO1;
-			break;
-		case AUX3:
-			/* nothing to be done here. aux3 is
-			   directly connected to the saa711a */
-			i = SAA7115_COMPOSITE1;
-			break;
-		case AUX1:
-			i = SAA7115_COMPOSITE0;
-			vm.in  = 1;
-			vm.out = 17;
-			break;
-		}
-
-		/* switch video in tea6415c only if necessary */
-		switch (input) {
-		case TUNER:
-		case AUX1:
-			if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
-				printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
-				return -EFAULT;
-			}
-			break;
-		default:
-			break;
-		}
-
-		/* switch video in saa7111a */
-		route.input = i;
-		route.output = 0;
-		if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route))
-			printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
-
-		/* switch the audio-source only if necessary */
-		if( 0 == mxb->cur_mute ) {
-			mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
-					&TEA6420_line[video_audio_connect[input]][0]);
-			mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
-				       &TEA6420_line[video_audio_connect[input]][1]);
-		}
-
-		return 0;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (t->index) {
-			DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
-			return -EINVAL;
-		}
-
-		DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
-
-		memset(t, 0, sizeof(*t));
-		i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
-
-		strlcpy(t->name, "TV Tuner", sizeof(t->name));
-		t->type = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \
-			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-		t->audmode = mxb->cur_mode;
-		return 0;
-	}
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (t->index) {
-			DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
-			return -EINVAL;
-		}
-
-		mxb->cur_mode = t->audmode;
-		i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
-		return 0;
-	}
-	case VIDIOC_G_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		if (mxb->cur_input) {
-			DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
-						mxb->cur_input));
-			return -EINVAL;
-		}
-
-		*f = mxb->cur_freq;
-
-		DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
-		return 0;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		if (f->tuner)
-			return -EINVAL;
-
-		if (V4L2_TUNER_ANALOG_TV != f->type)
-			return -EINVAL;
-
-		if (mxb->cur_input) {
-			DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
-			return -EINVAL;
-		}
-
-		mxb->cur_freq = *f;
-		DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
-
-		/* tune in desired frequency */
-		mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq);
-
-		/* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
-		spin_lock(&dev->slock);
-		vv->vbi_fieldcount = 0;
-		spin_unlock(&dev->slock);
-
-		return 0;
-	}
-	case MXB_S_AUDIO_CD:
-	{
-		int i = *(int*)arg;
-
-		if (i < 0 || i >= MXB_AUDIOS) {
-			DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
-			return -EINVAL;
-		}
-
-		DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
-
-		mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
-		mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
-
-		return 0;
-	}
-	case MXB_S_AUDIO_LINE:
-	{
-		int i = *(int*)arg;
-
-		if (i < 0 || i >= MXB_AUDIOS) {
-			DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
-			return -EINVAL;
-		}
-
-		DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
-		mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
-		mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
-
-		return 0;
-	}
-	case VIDIOC_G_AUDIO:
-	{
-		struct v4l2_audio *a = arg;
-
-		if (a->index < 0 || a->index > MXB_INPUTS) {
-			DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
-			return -EINVAL;
-		}
-
-		DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
-		memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
-
-		return 0;
-	}
-	case VIDIOC_S_AUDIO:
-	{
-		struct v4l2_audio *a = arg;
-
-		DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
-		return 0;
-	}
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_DBG_S_REGISTER:
-	case VIDIOC_DBG_G_REGISTER:
-		i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
-		return 0;
-#endif
-	default:
-/*
-		DEB2(printk("does not handle this ioctl.\n"));
-*/
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
 {
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
-	int zero = 0;
-	int one = 1;
 
 	if (V4L2_STD_PAL_I == standard->id) {
 		v4l2_std_id std = V4L2_STD_PAL_I;
@@ -821,8 +787,8 @@
 		/* set the 7146 gpio register -- I don't know what this does exactly */
 		saa7146_write(dev, GPIO_CTRL, 0x00404050);
 		/* unset the 7111 gpio register -- I don't know what this does exactly */
-		mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero);
-		mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
+		saa7111a_call(mxb, core, s_gpio, 0);
+		tuner_call(mxb, tuner, s_std, std);
 	} else {
 		v4l2_std_id std = V4L2_STD_PAL_BG;
 
@@ -830,8 +796,8 @@
 		/* set the 7146 gpio register -- I don't know what this does exactly */
 		saa7146_write(dev, GPIO_CTRL, 0x00404050);
 		/* set the 7111 gpio register -- I don't know what this does exactly */
-		mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one);
-		mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
+		saa7111a_call(mxb, core, s_gpio, 1);
+		tuner_call(mxb, tuner, s_std, std);
 	}
 	return 0;
 }
@@ -885,8 +851,6 @@
 	.stds		= &standard[0],
 	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
 	.std_callback	= &std_callback,
-	.ioctls		= &ioctls[0],
-	.ioctl		= mxb_ioctl,
 };
 
 static struct saa7146_extension extension = {
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 73eb656..5fc4ac0 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -80,17 +80,17 @@
 {
 	int rval = 0;
 
-	cam->fck = clk_get(cam->dev, "cam_fck");
+	cam->fck = clk_get(cam->dev, "fck");
 	if (IS_ERR(cam->fck)) {
-		dev_err(cam->dev, "can't get cam_fck");
+		dev_err(cam->dev, "can't get camera fck");
 		rval = PTR_ERR(cam->fck);
 		omap24xxcam_clock_put(cam);
 		return rval;
 	}
 
-	cam->ick = clk_get(cam->dev, "cam_ick");
+	cam->ick = clk_get(cam->dev, "ick");
 	if (IS_ERR(cam->ick)) {
-		dev_err(cam->dev, "can't get cam_ick");
+		dev_err(cam->dev, "can't get camera ick");
 		rval = PTR_ERR(cam->ick);
 		omap24xxcam_clock_put(cam);
 	}
@@ -1285,9 +1285,6 @@
 	struct omap24xxcam_device *cam = ofh->cam;
 	int rval;
 
-	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	mutex_lock(&cam->mutex);
 	rval = vidioc_int_g_parm(cam->sdev, a);
 	mutex_unlock(&cam->mutex);
@@ -1303,9 +1300,6 @@
 	struct v4l2_streamparm old_streamparm;
 	int rval;
 
-	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	mutex_lock(&cam->mutex);
 	if (cam->streaming) {
 		rval = -EBUSY;
@@ -1665,7 +1659,6 @@
 	vfd->parent = cam->dev;
 
 	strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name));
-	vfd->vfl_type		 = VID_TYPE_CAPTURE | VID_TYPE_CHROMAKEY;
 	vfd->fops		 = &omap24xxcam_fops;
 	vfd->minor		 = -1;
 	vfd->ioctl_ops		 = &omap24xxcam_ioctl_fops;
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 05c14a2..0e2184e 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -12,18 +12,22 @@
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 
 MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
 MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
 MODULE_LICENSE("GPL");
 
+static int debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
 /*
  * Basic window sizes.  These probably belong somewhere more globally
  * useful.
@@ -189,11 +193,16 @@
  */
 struct ov7670_format_struct;  /* coming later */
 struct ov7670_info {
+	struct v4l2_subdev sd;
 	struct ov7670_format_struct *fmt;  /* Current format */
 	unsigned char sat;		/* Saturation value */
 	int hue;			/* Hue value */
 };
 
+static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ov7670_info, sd);
+}
 
 
 
@@ -400,24 +409,27 @@
  * Low-level register I/O.
  */
 
-static int ov7670_read(struct i2c_client *c, unsigned char reg,
+static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
 		unsigned char *value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret;
 
-	ret = i2c_smbus_read_byte_data(c, reg);
+	ret = i2c_smbus_read_byte_data(client, reg);
 	if (ret >= 0) {
-		*value = (unsigned char) ret;
+		*value = (unsigned char)ret;
 		ret = 0;
 	}
 	return ret;
 }
 
 
-static int ov7670_write(struct i2c_client *c, unsigned char reg,
+static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
 		unsigned char value)
 {
-	int ret = i2c_smbus_write_byte_data(c, reg, value);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret = i2c_smbus_write_byte_data(client, reg, value);
+
 	if (reg == REG_COM7 && (value & COM7_RESET))
 		msleep(2);  /* Wait for reset to run */
 	return ret;
@@ -427,10 +439,10 @@
 /*
  * Write a list of register settings; ff/ff stops the process.
  */
-static int ov7670_write_array(struct i2c_client *c, struct regval_list *vals)
+static int ov7670_write_array(struct v4l2_subdev *sd, struct regval_list *vals)
 {
 	while (vals->reg_num != 0xff || vals->value != 0xff) {
-		int ret = ov7670_write(c, vals->reg_num, vals->value);
+		int ret = ov7670_write(sd, vals->reg_num, vals->value);
 		if (ret < 0)
 			return ret;
 		vals++;
@@ -442,34 +454,35 @@
 /*
  * Stuff that knows about the sensor.
  */
-static void ov7670_reset(struct i2c_client *client)
+static int ov7670_reset(struct v4l2_subdev *sd, u32 val)
 {
-	ov7670_write(client, REG_COM7, COM7_RESET);
+	ov7670_write(sd, REG_COM7, COM7_RESET);
 	msleep(1);
+	return 0;
 }
 
 
-static int ov7670_init(struct i2c_client *client)
+static int ov7670_init(struct v4l2_subdev *sd, u32 val)
 {
-	return ov7670_write_array(client, ov7670_default_regs);
+	return ov7670_write_array(sd, ov7670_default_regs);
 }
 
 
 
-static int ov7670_detect(struct i2c_client *client)
+static int ov7670_detect(struct v4l2_subdev *sd)
 {
 	unsigned char v;
 	int ret;
 
-	ret = ov7670_init(client);
+	ret = ov7670_init(sd, 0);
 	if (ret < 0)
 		return ret;
-	ret = ov7670_read(client, REG_MIDH, &v);
+	ret = ov7670_read(sd, REG_MIDH, &v);
 	if (ret < 0)
 		return ret;
 	if (v != 0x7f) /* OV manuf. id. */
 		return -ENODEV;
-	ret = ov7670_read(client, REG_MIDL, &v);
+	ret = ov7670_read(sd, REG_MIDL, &v);
 	if (ret < 0)
 		return ret;
 	if (v != 0xa2)
@@ -477,12 +490,12 @@
 	/*
 	 * OK, we know we have an OmniVision chip...but which one?
 	 */
-	ret = ov7670_read(client, REG_PID, &v);
+	ret = ov7670_read(sd, REG_PID, &v);
 	if (ret < 0)
 		return ret;
 	if (v != 0x76)  /* PID + VER = 0x76 / 0x73 */
 		return -ENODEV;
-	ret = ov7670_read(client, REG_VER, &v);
+	ret = ov7670_read(sd, REG_VER, &v);
 	if (ret < 0)
 		return ret;
 	if (v != 0x73)  /* PID + VER = 0x76 / 0x73 */
@@ -627,7 +640,7 @@
 /*
  * Store a set of start/stop values into the camera.
  */
-static int ov7670_set_hw(struct i2c_client *client, int hstart, int hstop,
+static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
 		int vstart, int vstop)
 {
 	int ret;
@@ -637,26 +650,26 @@
  * hstart are in href[2:0], bottom 3 of hstop in href[5:3].  There is
  * a mystery "edge offset" value in the top two bits of href.
  */
-	ret =  ov7670_write(client, REG_HSTART, (hstart >> 3) & 0xff);
-	ret += ov7670_write(client, REG_HSTOP, (hstop >> 3) & 0xff);
-	ret += ov7670_read(client, REG_HREF, &v);
+	ret =  ov7670_write(sd, REG_HSTART, (hstart >> 3) & 0xff);
+	ret += ov7670_write(sd, REG_HSTOP, (hstop >> 3) & 0xff);
+	ret += ov7670_read(sd, REG_HREF, &v);
 	v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
 	msleep(10);
-	ret += ov7670_write(client, REG_HREF, v);
+	ret += ov7670_write(sd, REG_HREF, v);
 /*
  * Vertical: similar arrangement, but only 10 bits.
  */
-	ret += ov7670_write(client, REG_VSTART, (vstart >> 2) & 0xff);
-	ret += ov7670_write(client, REG_VSTOP, (vstop >> 2) & 0xff);
-	ret += ov7670_read(client, REG_VREF, &v);
+	ret += ov7670_write(sd, REG_VSTART, (vstart >> 2) & 0xff);
+	ret += ov7670_write(sd, REG_VSTOP, (vstop >> 2) & 0xff);
+	ret += ov7670_read(sd, REG_VREF, &v);
 	v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
 	msleep(10);
-	ret += ov7670_write(client, REG_VREF, v);
+	ret += ov7670_write(sd, REG_VREF, v);
 	return ret;
 }
 
 
-static int ov7670_enum_fmt(struct i2c_client *c, struct v4l2_fmtdesc *fmt)
+static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
 {
 	struct ov7670_format_struct *ofmt;
 
@@ -671,7 +684,8 @@
 }
 
 
-static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
+static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
+		struct v4l2_format *fmt,
 		struct ov7670_format_struct **ret_fmt,
 		struct ov7670_win_size **ret_wsize)
 {
@@ -715,18 +729,23 @@
 	return 0;
 }
 
+static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+	return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
+}
+
 /*
  * Set a format.
  */
-static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
+static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
 {
 	int ret;
 	struct ov7670_format_struct *ovfmt;
 	struct ov7670_win_size *wsize;
-	struct ov7670_info *info = i2c_get_clientdata(c);
-	unsigned char com7, clkrc;
+	struct ov7670_info *info = to_state(sd);
+	unsigned char com7, clkrc = 0;
 
-	ret = ov7670_try_fmt(c, fmt, &ovfmt, &wsize);
+	ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
 	if (ret)
 		return ret;
 	/*
@@ -735,7 +754,7 @@
 	 * the colors.
 	 */
 	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
-		ret = ov7670_read(c, REG_CLKRC, &clkrc);
+		ret = ov7670_read(sd, REG_CLKRC, &clkrc);
 		if (ret)
 			return ret;
 	}
@@ -747,20 +766,20 @@
 	 */
 	com7 = ovfmt->regs[0].value;
 	com7 |= wsize->com7_bit;
-	ov7670_write(c, REG_COM7, com7);
+	ov7670_write(sd, REG_COM7, com7);
 	/*
 	 * Now write the rest of the array.  Also store start/stops
 	 */
-	ov7670_write_array(c, ovfmt->regs + 1);
-	ov7670_set_hw(c, wsize->hstart, wsize->hstop, wsize->vstart,
+	ov7670_write_array(sd, ovfmt->regs + 1);
+	ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart,
 			wsize->vstop);
 	ret = 0;
 	if (wsize->regs)
-		ret = ov7670_write_array(c, wsize->regs);
+		ret = ov7670_write_array(sd, wsize->regs);
 	info->fmt = ovfmt;
 
 	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
-		ret = ov7670_write(c, REG_CLKRC, clkrc);
+		ret = ov7670_write(sd, REG_CLKRC, clkrc);
 	return ret;
 }
 
@@ -768,7 +787,7 @@
  * Implement G/S_PARM.  There is a "high quality" mode we could try
  * to do someday; for now, we just do the frame rate tweak.
  */
-static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 {
 	struct v4l2_captureparm *cp = &parms->parm.capture;
 	unsigned char clkrc;
@@ -776,7 +795,7 @@
 
 	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
-	ret = ov7670_read(c, REG_CLKRC, &clkrc);
+	ret = ov7670_read(sd, REG_CLKRC, &clkrc);
 	if (ret < 0)
 		return ret;
 	memset(cp, 0, sizeof(struct v4l2_captureparm));
@@ -788,7 +807,7 @@
 	return 0;
 }
 
-static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
+static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 {
 	struct v4l2_captureparm *cp = &parms->parm.capture;
 	struct v4l2_fract *tpf = &cp->timeperframe;
@@ -802,7 +821,7 @@
 	/*
 	 * CLKRC has a reserved bit, so let's preserve it.
 	 */
-	ret = ov7670_read(c, REG_CLKRC, &clkrc);
+	ret = ov7670_read(sd, REG_CLKRC, &clkrc);
 	if (ret < 0)
 		return ret;
 	if (tpf->numerator == 0 || tpf->denominator == 0)
@@ -816,7 +835,7 @@
 	clkrc = (clkrc & 0x80) | div;
 	tpf->numerator = 1;
 	tpf->denominator = OV7670_FRAME_RATE/div;
-	return ov7670_write(c, REG_CLKRC, clkrc);
+	return ov7670_write(sd, REG_CLKRC, clkrc);
 }
 
 
@@ -829,7 +848,7 @@
 
 
 
-static int ov7670_store_cmatrix(struct i2c_client *client,
+static int ov7670_store_cmatrix(struct v4l2_subdev *sd,
 		int matrix[CMATRIX_LEN])
 {
 	int i, ret;
@@ -839,7 +858,7 @@
 	 * Weird crap seems to exist in the upper part of
 	 * the sign bits register, so let's preserve it.
 	 */
-	ret = ov7670_read(client, REG_CMATRIX_SIGN, &signbits);
+	ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits);
 	signbits &= 0xc0;
 
 	for (i = 0; i < CMATRIX_LEN; i++) {
@@ -858,9 +877,9 @@
 			else
 				raw = matrix[i] & 0xff;
 		}
-		ret += ov7670_write(client, REG_CMATRIX_BASE + i, raw);
+		ret += ov7670_write(sd, REG_CMATRIX_BASE + i, raw);
 	}
-	ret += ov7670_write(client, REG_CMATRIX_SIGN, signbits);
+	ret += ov7670_write(sd, REG_CMATRIX_SIGN, signbits);
 	return ret;
 }
 
@@ -943,29 +962,29 @@
 
 
 
-static int ov7670_t_sat(struct i2c_client *client, int value)
+static int ov7670_s_sat(struct v4l2_subdev *sd, int value)
 {
-	struct ov7670_info *info = i2c_get_clientdata(client);
+	struct ov7670_info *info = to_state(sd);
 	int matrix[CMATRIX_LEN];
 	int ret;
 
 	info->sat = value;
 	ov7670_calc_cmatrix(info, matrix);
-	ret = ov7670_store_cmatrix(client, matrix);
+	ret = ov7670_store_cmatrix(sd, matrix);
 	return ret;
 }
 
-static int ov7670_q_sat(struct i2c_client *client, __s32 *value)
+static int ov7670_g_sat(struct v4l2_subdev *sd, __s32 *value)
 {
-	struct ov7670_info *info = i2c_get_clientdata(client);
+	struct ov7670_info *info = to_state(sd);
 
 	*value = info->sat;
 	return 0;
 }
 
-static int ov7670_t_hue(struct i2c_client *client, int value)
+static int ov7670_s_hue(struct v4l2_subdev *sd, int value)
 {
-	struct ov7670_info *info = i2c_get_clientdata(client);
+	struct ov7670_info *info = to_state(sd);
 	int matrix[CMATRIX_LEN];
 	int ret;
 
@@ -973,14 +992,14 @@
 		return -EINVAL;
 	info->hue = value;
 	ov7670_calc_cmatrix(info, matrix);
-	ret = ov7670_store_cmatrix(client, matrix);
+	ret = ov7670_store_cmatrix(sd, matrix);
 	return ret;
 }
 
 
-static int ov7670_q_hue(struct i2c_client *client, __s32 *value)
+static int ov7670_g_hue(struct v4l2_subdev *sd, __s32 *value)
 {
-	struct ov7670_info *info = i2c_get_clientdata(client);
+	struct ov7670_info *info = to_state(sd);
 
 	*value = info->hue;
 	return 0;
@@ -994,8 +1013,7 @@
 {
 	if ((v & 0x80) == 0)
 		return v + 128;
-	else
-		return 128 - (v & 0x7f);
+	return 128 - (v & 0x7f);
 }
 
 
@@ -1003,369 +1021,275 @@
 {
 	if (v > 127)
 		return v & 0x7f;
-	else
-		return (128 - v) | 0x80;
+	return (128 - v) | 0x80;
 }
 
-static int ov7670_t_brightness(struct i2c_client *client, int value)
+static int ov7670_s_brightness(struct v4l2_subdev *sd, int value)
 {
 	unsigned char com8 = 0, v;
 	int ret;
 
-	ov7670_read(client, REG_COM8, &com8);
+	ov7670_read(sd, REG_COM8, &com8);
 	com8 &= ~COM8_AEC;
-	ov7670_write(client, REG_COM8, com8);
+	ov7670_write(sd, REG_COM8, com8);
 	v = ov7670_abs_to_sm(value);
-	ret = ov7670_write(client, REG_BRIGHT, v);
+	ret = ov7670_write(sd, REG_BRIGHT, v);
 	return ret;
 }
 
-static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
+static int ov7670_g_brightness(struct v4l2_subdev *sd, __s32 *value)
 {
 	unsigned char v = 0;
-	int ret = ov7670_read(client, REG_BRIGHT, &v);
+	int ret = ov7670_read(sd, REG_BRIGHT, &v);
 
 	*value = ov7670_sm_to_abs(v);
 	return ret;
 }
 
-static int ov7670_t_contrast(struct i2c_client *client, int value)
+static int ov7670_s_contrast(struct v4l2_subdev *sd, int value)
 {
-	return ov7670_write(client, REG_CONTRAS, (unsigned char) value);
+	return ov7670_write(sd, REG_CONTRAS, (unsigned char) value);
 }
 
-static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
+static int ov7670_g_contrast(struct v4l2_subdev *sd, __s32 *value)
 {
 	unsigned char v = 0;
-	int ret = ov7670_read(client, REG_CONTRAS, &v);
+	int ret = ov7670_read(sd, REG_CONTRAS, &v);
 
 	*value = v;
 	return ret;
 }
 
-static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
+static int ov7670_g_hflip(struct v4l2_subdev *sd, __s32 *value)
 {
 	int ret;
 	unsigned char v = 0;
 
-	ret = ov7670_read(client, REG_MVFP, &v);
+	ret = ov7670_read(sd, REG_MVFP, &v);
 	*value = (v & MVFP_MIRROR) == MVFP_MIRROR;
 	return ret;
 }
 
 
-static int ov7670_t_hflip(struct i2c_client *client, int value)
+static int ov7670_s_hflip(struct v4l2_subdev *sd, int value)
 {
 	unsigned char v = 0;
 	int ret;
 
-	ret = ov7670_read(client, REG_MVFP, &v);
+	ret = ov7670_read(sd, REG_MVFP, &v);
 	if (value)
 		v |= MVFP_MIRROR;
 	else
 		v &= ~MVFP_MIRROR;
 	msleep(10);  /* FIXME */
-	ret += ov7670_write(client, REG_MVFP, v);
+	ret += ov7670_write(sd, REG_MVFP, v);
 	return ret;
 }
 
 
 
-static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
+static int ov7670_g_vflip(struct v4l2_subdev *sd, __s32 *value)
 {
 	int ret;
 	unsigned char v = 0;
 
-	ret = ov7670_read(client, REG_MVFP, &v);
+	ret = ov7670_read(sd, REG_MVFP, &v);
 	*value = (v & MVFP_FLIP) == MVFP_FLIP;
 	return ret;
 }
 
 
-static int ov7670_t_vflip(struct i2c_client *client, int value)
+static int ov7670_s_vflip(struct v4l2_subdev *sd, int value)
 {
 	unsigned char v = 0;
 	int ret;
 
-	ret = ov7670_read(client, REG_MVFP, &v);
+	ret = ov7670_read(sd, REG_MVFP, &v);
 	if (value)
 		v |= MVFP_FLIP;
 	else
 		v &= ~MVFP_FLIP;
 	msleep(10);  /* FIXME */
-	ret += ov7670_write(client, REG_MVFP, v);
+	ret += ov7670_write(sd, REG_MVFP, v);
 	return ret;
 }
 
-
-static struct ov7670_control {
-	struct v4l2_queryctrl qc;
-	int (*query)(struct i2c_client *c, __s32 *value);
-	int (*tweak)(struct i2c_client *c, int value);
-} ov7670_controls[] =
-{
-	{
-		.qc = {
-			.id = V4L2_CID_BRIGHTNESS,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "Brightness",
-			.minimum = 0,
-			.maximum = 255,
-			.step = 1,
-			.default_value = 0x80,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-		.tweak = ov7670_t_brightness,
-		.query = ov7670_q_brightness,
-	},
-	{
-		.qc = {
-			.id = V4L2_CID_CONTRAST,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "Contrast",
-			.minimum = 0,
-			.maximum = 127,
-			.step = 1,
-			.default_value = 0x40,   /* XXX ov7670 spec */
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-		.tweak = ov7670_t_contrast,
-		.query = ov7670_q_contrast,
-	},
-	{
-		.qc = {
-			.id = V4L2_CID_SATURATION,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "Saturation",
-			.minimum = 0,
-			.maximum = 256,
-			.step = 1,
-			.default_value = 0x80,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-		.tweak = ov7670_t_sat,
-		.query = ov7670_q_sat,
-	},
-	{
-		.qc = {
-			.id = V4L2_CID_HUE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "HUE",
-			.minimum = -180,
-			.maximum = 180,
-			.step = 5,
-			.default_value = 0,
-			.flags = V4L2_CTRL_FLAG_SLIDER
-		},
-		.tweak = ov7670_t_hue,
-		.query = ov7670_q_hue,
-	},
-	{
-		.qc = {
-			.id = V4L2_CID_VFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "Vertical flip",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-		},
-		.tweak = ov7670_t_vflip,
-		.query = ov7670_q_vflip,
-	},
-	{
-		.qc = {
-			.id = V4L2_CID_HFLIP,
-			.type = V4L2_CTRL_TYPE_BOOLEAN,
-			.name = "Horizontal mirror",
-			.minimum = 0,
-			.maximum = 1,
-			.step = 1,
-			.default_value = 0,
-		},
-		.tweak = ov7670_t_hflip,
-		.query = ov7670_q_hflip,
-	},
-};
-#define N_CONTROLS (ARRAY_SIZE(ov7670_controls))
-
-static struct ov7670_control *ov7670_find_control(__u32 id)
-{
-	int i;
-
-	for (i = 0; i < N_CONTROLS; i++)
-		if (ov7670_controls[i].qc.id == id)
-			return ov7670_controls + i;
-	return NULL;
-}
-
-
-static int ov7670_queryctrl(struct i2c_client *client,
+static int ov7670_queryctrl(struct v4l2_subdev *sd,
 		struct v4l2_queryctrl *qc)
 {
-	struct ov7670_control *ctrl = ov7670_find_control(qc->id);
-
-	if (ctrl == NULL)
-		return -EINVAL;
-	*qc = ctrl->qc;
-	return 0;
-}
-
-static int ov7670_g_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
-{
-	struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
-	int ret;
-
-	if (octrl == NULL)
-		return -EINVAL;
-	ret = octrl->query(client, &ctrl->value);
-	if (ret >= 0)
-		return 0;
-	return ret;
-}
-
-static int ov7670_s_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
-{
-	struct ov7670_control *octrl = ov7670_find_control(ctrl->id);
-	int ret;
-
-	if (octrl == NULL)
-		return -EINVAL;
-	ret =  octrl->tweak(client, ctrl->value);
-	if (ret >= 0)
-		return 0;
-	return ret;
-}
-
-
-
-
-
-
-/*
- * Basic i2c stuff.
- */
-static struct i2c_driver ov7670_driver;
-
-static int ov7670_attach(struct i2c_adapter *adapter)
-{
-	int ret;
-	struct i2c_client *client;
-	struct ov7670_info *info;
-
-	/*
-	 * For now: only deal with adapters we recognize.
-	 */
-	if (adapter->id != I2C_HW_SMBUS_CAFE)
-		return -ENODEV;
-
-	client = kzalloc(sizeof (struct i2c_client), GFP_KERNEL);
-	if (! client)
-		return -ENOMEM;
-	client->adapter = adapter;
-	client->addr = OV7670_I2C_ADDR;
-	client->driver = &ov7670_driver,
-	strcpy(client->name, "OV7670");
-	/*
-	 * Set up our info structure.
-	 */
-	info = kzalloc(sizeof (struct ov7670_info), GFP_KERNEL);
-	if (! info) {
-		ret = -ENOMEM;
-		goto out_free;
-	}
-	info->fmt = &ov7670_formats[0];
-	info->sat = 128;	/* Review this */
-	i2c_set_clientdata(client, info);
-
-	/*
-	 * Make sure it's an ov7670
-	 */
-	ret = ov7670_detect(client);
-	if (ret)
-		goto out_free_info;
-	ret = i2c_attach_client(client);
-	if (ret)
-		goto out_free_info;
-	return 0;
-
-  out_free_info:
-	kfree(info);
-  out_free:
-	kfree(client);
-	return ret;
-}
-
-
-static int ov7670_detach(struct i2c_client *client)
-{
-	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
-	kfree(client);
-	return 0;
-}
-
-
-static int ov7670_command(struct i2c_client *client, unsigned int cmd,
-		void *arg)
-{
-	switch (cmd) {
-	case VIDIOC_DBG_G_CHIP_IDENT:
-		return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0);
-
-	case VIDIOC_INT_RESET:
-		ov7670_reset(client);
-		return 0;
-
-	case VIDIOC_INT_INIT:
-		return ov7670_init(client);
-
-	case VIDIOC_ENUM_FMT:
-		return ov7670_enum_fmt(client, (struct v4l2_fmtdesc *) arg);
-	case VIDIOC_TRY_FMT:
-		return ov7670_try_fmt(client, (struct v4l2_format *) arg, NULL, NULL);
-	case VIDIOC_S_FMT:
-		return ov7670_s_fmt(client, (struct v4l2_format *) arg);
-	case VIDIOC_QUERYCTRL:
-		return ov7670_queryctrl(client, (struct v4l2_queryctrl *) arg);
-	case VIDIOC_S_CTRL:
-		return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
-	case VIDIOC_G_CTRL:
-		return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
-	case VIDIOC_S_PARM:
-		return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
-	case VIDIOC_G_PARM:
-		return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
+	/* Fill in min, max, step and default value for these controls. */
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_CONTRAST:
+		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
+	case V4L2_CID_VFLIP:
+	case V4L2_CID_HFLIP:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0);
 	}
 	return -EINVAL;
 }
 
+static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return ov7670_g_brightness(sd, &ctrl->value);
+	case V4L2_CID_CONTRAST:
+		return ov7670_g_contrast(sd, &ctrl->value);
+	case V4L2_CID_SATURATION:
+		return ov7670_g_sat(sd, &ctrl->value);
+	case V4L2_CID_HUE:
+		return ov7670_g_hue(sd, &ctrl->value);
+	case V4L2_CID_VFLIP:
+		return ov7670_g_vflip(sd, &ctrl->value);
+	case V4L2_CID_HFLIP:
+		return ov7670_g_hflip(sd, &ctrl->value);
+	}
+	return -EINVAL;
+}
 
+static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return ov7670_s_brightness(sd, ctrl->value);
+	case V4L2_CID_CONTRAST:
+		return ov7670_s_contrast(sd, ctrl->value);
+	case V4L2_CID_SATURATION:
+		return ov7670_s_sat(sd, ctrl->value);
+	case V4L2_CID_HUE:
+		return ov7670_s_hue(sd, ctrl->value);
+	case V4L2_CID_VFLIP:
+		return ov7670_s_vflip(sd, ctrl->value);
+	case V4L2_CID_HFLIP:
+		return ov7670_s_hflip(sd, ctrl->value);
+	}
+	return -EINVAL;
+}
 
-static struct i2c_driver ov7670_driver = {
-	.driver = {
-		.name = "ov7670",
-	},
-	.id 		= I2C_DRIVERID_OV7670,
-	.attach_adapter = ov7670_attach,
-	.detach_client	= ov7670_detach,
-	.command	= ov7670_command,
+static int ov7670_g_chip_ident(struct v4l2_subdev *sd,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	unsigned char val = 0;
+	int ret;
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	ret = ov7670_read(sd, reg->reg & 0xff, &val);
+	reg->val = val;
+	reg->size = 1;
+	return ret;
+}
+
+static int ov7670_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops ov7670_core_ops = {
+	.g_chip_ident = ov7670_g_chip_ident,
+	.g_ctrl = ov7670_g_ctrl,
+	.s_ctrl = ov7670_s_ctrl,
+	.queryctrl = ov7670_queryctrl,
+	.reset = ov7670_reset,
+	.init = ov7670_init,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ov7670_g_register,
+	.s_register = ov7670_s_register,
+#endif
 };
 
+static const struct v4l2_subdev_video_ops ov7670_video_ops = {
+	.enum_fmt = ov7670_enum_fmt,
+	.try_fmt = ov7670_try_fmt,
+	.s_fmt = ov7670_s_fmt,
+	.s_parm = ov7670_s_parm,
+	.g_parm = ov7670_g_parm,
+};
 
-/*
- * Module initialization
- */
-static int __init ov7670_mod_init(void)
+static const struct v4l2_subdev_ops ov7670_ops = {
+	.core = &ov7670_core_ops,
+	.video = &ov7670_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int ov7670_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-	printk(KERN_NOTICE "OmniVision ov7670 sensor driver, at your service\n");
-	return i2c_add_driver(&ov7670_driver);
+	struct v4l2_subdev *sd;
+	struct ov7670_info *info;
+	int ret;
+
+	info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL);
+	if (info == NULL)
+		return -ENOMEM;
+	sd = &info->sd;
+	v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
+
+	/* Make sure it's an ov7670 */
+	ret = ov7670_detect(sd);
+	if (ret) {
+		v4l_dbg(1, debug, client,
+			"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
+			client->addr << 1, client->adapter->name);
+		kfree(info);
+		return ret;
+	}
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	info->fmt = &ov7670_formats[0];
+	info->sat = 128;	/* Review this */
+
+	return 0;
 }
 
-static void __exit ov7670_mod_exit(void)
+
+static int ov7670_remove(struct i2c_client *client)
 {
-	i2c_del_driver(&ov7670_driver);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
 }
 
-module_init(ov7670_mod_init);
-module_exit(ov7670_mod_exit);
+static const struct i2c_device_id ov7670_id[] = {
+	{ "ov7670", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov7670_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "ov7670",
+	.probe = ov7670_probe,
+	.remove = ov7670_remove,
+	.id_table = ov7670_id,
+};
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 3c9e0ba..84b0fc1 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -217,10 +217,11 @@
 #define OCAP_4x         0x03	/* 4x */
 
 /* COM3 */
-#define SWAP_MASK       0x38
+#define SWAP_MASK       (SWAP_RGB | SWAP_YUV | SWAP_ML)
+#define IMG_MASK        (VFLIP_IMG | HFLIP_IMG)
 
-#define VFIMG_ON_OFF    0x80	/* Vertical flip image ON/OFF selection */
-#define HMIMG_ON_OFF    0x40	/* Horizontal mirror image ON/OFF selection */
+#define VFLIP_IMG       0x80	/* Vertical flip image ON/OFF selection */
+#define HFLIP_IMG       0x40	/* Horizontal mirror image ON/OFF selection */
 #define SWAP_RGB        0x20	/* Swap B/R  output sequence in RGB mode */
 #define SWAP_YUV        0x10	/* Swap Y/UV output sequence in YUV mode */
 #define SWAP_ML         0x08	/* Swap output MSB/LSB */
@@ -271,11 +272,13 @@
 #define SLCT_QVGA       0x40	/*   1 : QVGA */
 #define ITU656_ON_OFF   0x20	/* ITU656 protocol ON/OFF selection */
 				/* RGB output format control */
+#define FMT_MASK        0x0c	/*      Mask of color format */
 #define FMT_GBR422      0x00	/*      00 : GBR 4:2:2 */
 #define FMT_RGB565      0x04	/*      01 : RGB 565 */
 #define FMT_RGB555      0x08	/*      10 : RGB 555 */
 #define FMT_RGB444      0x0c	/* 11 : RGB 444 */
 				/* Output format control */
+#define OFMT_MASK       0x03    /*      Mask of output format */
 #define OFMT_YUV        0x00	/*      00 : YUV */
 #define OFMT_P_BRAW     0x01	/*      01 : Processed Bayer RAW */
 #define OFMT_RGB        0x02	/*      10 : RGB */
@@ -299,7 +302,7 @@
 #define GAIN_2x         0x00	/*    000 :   2x */
 #define GAIN_4x         0x10	/*    001 :   4x */
 #define GAIN_8x         0x20	/*    010 :   8x */
-#define GAIN_16x        0x30	/* 011 :  16x */
+#define GAIN_16x        0x30	/*    011 :  16x */
 #define GAIN_32x        0x40	/*    100 :  32x */
 #define GAIN_64x        0x50	/* 101 :  64x */
 #define GAIN_128x       0x60	/* 110 : 128x */
@@ -356,13 +359,6 @@
 #define VOSZ_QVGA       0x78
 
 /*
- * bit configure (32 bit)
- * this is used in struct ov772x_color_format :: option
- */
-#define OP_UV       0x00000001
-#define OP_SWAP_RGB 0x00000002
-
-/*
  * ID
  */
 #define OV7720  0x7720
@@ -380,8 +376,9 @@
 struct ov772x_color_format {
 	char                     *name;
 	__u32                     fourcc;
-	const struct regval_list *regs;
-	unsigned int              option;
+	u8                        dsp3;
+	u8                        com3;
+	u8                        com7;
 };
 
 struct ov772x_win_size {
@@ -399,39 +396,13 @@
 	const struct ov772x_color_format *fmt;
 	const struct ov772x_win_size     *win;
 	int                               model;
+	unsigned int                      flag_vflip:1;
+	unsigned int                      flag_hflip:1;
 };
 
 #define ENDMARKER { 0xff, 0xff }
 
 /*
- * register setting for color format
- */
-static const struct regval_list ov772x_RGB555_regs[] = {
-	{ COM3, 0x00 },
-	{ COM7, FMT_RGB555 | OFMT_RGB },
-	ENDMARKER,
-};
-
-static const struct regval_list ov772x_RGB565_regs[] = {
-	{ COM3, 0x00 },
-	{ COM7, FMT_RGB565 | OFMT_RGB },
-	ENDMARKER,
-};
-
-static const struct regval_list ov772x_YYUV_regs[] = {
-	{ COM3, SWAP_YUV },
-	{ COM7, OFMT_YUV },
-	ENDMARKER,
-};
-
-static const struct regval_list ov772x_UVYY_regs[] = {
-	{ COM3, 0x00 },
-	{ COM7, OFMT_YUV },
-	ENDMARKER,
-};
-
-
-/*
  * register setting for window size
  */
 static const struct regval_list ov772x_qvga_regs[] = {
@@ -500,38 +471,48 @@
 /*
  * color format list
  */
-#define T_YUYV 0
 static const struct ov772x_color_format ov772x_cfmts[] = {
-	[T_YUYV] = {
+	{
 		SETFOURCC(YUYV),
-		.regs   = ov772x_YYUV_regs,
+		.dsp3   = 0x0,
+		.com3   = SWAP_YUV,
+		.com7   = OFMT_YUV,
 	},
 	{
 		SETFOURCC(YVYU),
-		.regs   = ov772x_YYUV_regs,
-		.option = OP_UV,
+		.dsp3   = UV_ON,
+		.com3   = SWAP_YUV,
+		.com7   = OFMT_YUV,
 	},
 	{
 		SETFOURCC(UYVY),
-		.regs   = ov772x_UVYY_regs,
+		.dsp3   = 0x0,
+		.com3   = 0x0,
+		.com7   = OFMT_YUV,
 	},
 	{
 		SETFOURCC(RGB555),
-		.regs   = ov772x_RGB555_regs,
-		.option = OP_SWAP_RGB,
+		.dsp3   = 0x0,
+		.com3   = SWAP_RGB,
+		.com7   = FMT_RGB555 | OFMT_RGB,
 	},
 	{
 		SETFOURCC(RGB555X),
-		.regs   = ov772x_RGB555_regs,
+		.dsp3   = 0x0,
+		.com3   = 0x0,
+		.com7   = FMT_RGB555 | OFMT_RGB,
 	},
 	{
 		SETFOURCC(RGB565),
-		.regs   = ov772x_RGB565_regs,
-		.option = OP_SWAP_RGB,
+		.dsp3   = 0x0,
+		.com3   = SWAP_RGB,
+		.com7   = FMT_RGB565 | OFMT_RGB,
 	},
 	{
 		SETFOURCC(RGB565X),
-		.regs   = ov772x_RGB565_regs,
+		.dsp3   = 0x0,
+		.com3   = 0x0,
+		.com7   = FMT_RGB565 | OFMT_RGB,
 	},
 };
 
@@ -562,6 +543,27 @@
 	.regs     = ov772x_qvga_regs,
 };
 
+static const struct v4l2_queryctrl ov772x_controls[] = {
+	{
+		.id		= V4L2_CID_VFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Vertically",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+	{
+		.id		= V4L2_CID_HFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Horizontally",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+};
+
 
 /*
  * general function
@@ -587,8 +589,11 @@
 					  u8  set)
 {
 	s32 val = i2c_smbus_read_byte_data(client, command);
+	if (val < 0)
+		return val;
+
 	val &= ~mask;
-	val |=  set;
+	val |= set & mask;
 
 	return i2c_smbus_write_byte_data(client, command, val);
 }
@@ -635,74 +640,24 @@
 static int ov772x_start_capture(struct soc_camera_device *icd)
 {
 	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
-	int                 ret;
 
-	if (!priv->win)
-		priv->win = &ov772x_win_vga;
-	if (!priv->fmt)
-		priv->fmt = &ov772x_cfmts[T_YUYV];
-
-	/*
-	 * reset hardware
-	 */
-	ov772x_reset(priv->client);
-
-	/*
-	 * set color format
-	 */
-	ret = ov772x_write_array(priv->client, priv->fmt->regs);
-	if (ret < 0)
-		goto start_end;
-
-	/*
-	 * set size format
-	 */
-	ret = ov772x_write_array(priv->client, priv->win->regs);
-	if (ret < 0)
-		goto start_end;
-
-	/*
-	 * set COM7 bit ( QVGA or VGA )
-	 */
-	ret = ov772x_mask_set(priv->client,
-			      COM7, SLCT_MASK, priv->win->com7_bit);
-	if (ret < 0)
-		goto start_end;
-
-	/*
-	 * set UV setting
-	 */
-	if (priv->fmt->option & OP_UV) {
-		ret = ov772x_mask_set(priv->client,
-				      DSP_CTRL3, UV_MASK, UV_ON);
-		if (ret < 0)
-			goto start_end;
+	if (!priv->win || !priv->fmt) {
+		dev_err(&icd->dev, "norm or win select error\n");
+		return -EPERM;
 	}
 
-	/*
-	 * set SWAP setting
-	 */
-	if (priv->fmt->option & OP_SWAP_RGB) {
-		ret = ov772x_mask_set(priv->client,
-				      COM3, SWAP_MASK, SWAP_RGB);
-		if (ret < 0)
-			goto start_end;
-	}
+	ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
 
 	dev_dbg(&icd->dev,
 		 "format %s, win %s\n", priv->fmt->name, priv->win->name);
 
-start_end:
-	priv->fmt = NULL;
-	priv->win = NULL;
-
-	return ret;
+	return 0;
 }
 
 static int ov772x_stop_capture(struct soc_camera_device *icd)
 {
 	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
-	ov772x_reset(priv->client);
+	ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
 	return 0;
 }
 
@@ -718,11 +673,54 @@
 	struct soc_camera_link *icl = priv->client->dev.platform_data;
 	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
 		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
-		priv->info->buswidth;
+		SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
 
 	return soc_camera_apply_sensor_flags(icl, flags);
 }
 
+static int ov772x_get_control(struct soc_camera_device *icd,
+			      struct v4l2_control *ctrl)
+{
+	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		ctrl->value = priv->flag_vflip;
+		break;
+	case V4L2_CID_HFLIP:
+		ctrl->value = priv->flag_hflip;
+		break;
+	}
+	return 0;
+}
+
+static int ov772x_set_control(struct soc_camera_device *icd,
+			      struct v4l2_control *ctrl)
+{
+	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+	int ret = 0;
+	u8 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		val = ctrl->value ? VFLIP_IMG : 0x00;
+		priv->flag_vflip = ctrl->value;
+		if (priv->info->flags & OV772X_FLAG_VFLIP)
+			val ^= VFLIP_IMG;
+		ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
+		break;
+	case V4L2_CID_HFLIP:
+		val = ctrl->value ? HFLIP_IMG : 0x00;
+		priv->flag_hflip = ctrl->value;
+		if (priv->info->flags & OV772X_FLAG_HFLIP)
+			val ^= HFLIP_IMG;
+		ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
+		break;
+	}
+
+	return ret;
+}
+
 static int ov772x_get_chip_id(struct soc_camera_device *icd,
 			      struct v4l2_dbg_chip_ident   *id)
 {
@@ -787,13 +785,11 @@
 	return win;
 }
 
-
-static int ov772x_set_fmt(struct soc_camera_device *icd,
-			  __u32                     pixfmt,
-			  struct v4l2_rect         *rect)
+static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
+			     u32 pixfmt)
 {
-	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
 	int ret = -EINVAL;
+	u8  val;
 	int i;
 
 	/*
@@ -803,17 +799,99 @@
 	for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
 		if (pixfmt == ov772x_cfmts[i].fourcc) {
 			priv->fmt = ov772x_cfmts + i;
-			ret = 0;
 			break;
 		}
 	}
+	if (!priv->fmt)
+		goto ov772x_set_fmt_error;
 
 	/*
 	 * select win
 	 */
-	priv->win = ov772x_select_win(rect->width, rect->height);
+	priv->win = ov772x_select_win(width, height);
+
+	/*
+	 * reset hardware
+	 */
+	ov772x_reset(priv->client);
+
+	/*
+	 * set size format
+	 */
+	ret = ov772x_write_array(priv->client, priv->win->regs);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+
+	/*
+	 * set DSP_CTRL3
+	 */
+	val = priv->fmt->dsp3;
+	if (val) {
+		ret = ov772x_mask_set(priv->client,
+				      DSP_CTRL3, UV_MASK, val);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+	}
+
+	/*
+	 * set COM3
+	 */
+	val = priv->fmt->com3;
+	if (priv->info->flags & OV772X_FLAG_VFLIP)
+		val |= VFLIP_IMG;
+	if (priv->info->flags & OV772X_FLAG_HFLIP)
+		val |= HFLIP_IMG;
+	if (priv->flag_vflip)
+		val ^= VFLIP_IMG;
+	if (priv->flag_hflip)
+		val ^= HFLIP_IMG;
+
+	ret = ov772x_mask_set(priv->client,
+			      COM3, SWAP_MASK | IMG_MASK, val);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+
+	/*
+	 * set COM7
+	 */
+	val = priv->win->com7_bit | priv->fmt->com7;
+	ret = ov772x_mask_set(priv->client,
+			      COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
+			      val);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
 
 	return ret;
+
+ov772x_set_fmt_error:
+
+	ov772x_reset(priv->client);
+	priv->win = NULL;
+	priv->fmt = NULL;
+
+	return ret;
+}
+
+static int ov772x_set_crop(struct soc_camera_device *icd,
+			   struct v4l2_rect *rect)
+{
+	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+
+	if (!priv->fmt)
+		return -EINVAL;
+
+	return ov772x_set_params(priv, rect->width, rect->height,
+				 priv->fmt->fourcc);
+}
+
+static int ov772x_set_fmt(struct soc_camera_device *icd,
+			  struct v4l2_format *f)
+{
+	struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	return ov772x_set_params(priv, pix->width, pix->height,
+				 pix->pixelformat);
 }
 
 static int ov772x_try_fmt(struct soc_camera_device *icd,
@@ -889,7 +967,6 @@
 		 i2c_smbus_read_byte_data(priv->client, MIDH),
 		 i2c_smbus_read_byte_data(priv->client, MIDL));
 
-
 	return soc_camera_video_start(icd);
 }
 
@@ -906,10 +983,15 @@
 	.release		= ov772x_release,
 	.start_capture		= ov772x_start_capture,
 	.stop_capture		= ov772x_stop_capture,
+	.set_crop		= ov772x_set_crop,
 	.set_fmt		= ov772x_set_fmt,
 	.try_fmt		= ov772x_try_fmt,
 	.set_bus_param		= ov772x_set_bus_param,
 	.query_bus_param	= ov772x_query_bus_param,
+	.controls		= ov772x_controls,
+	.num_controls		= ARRAY_SIZE(ov772x_controls),
+	.get_control		= ov772x_get_control,
+	.set_control		= ov772x_set_control,
 	.get_chip_id		= ov772x_get_chip_id,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.get_register		= ov772x_get_register,
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index c841f4e..d573d84 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -15,6 +15,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-i2c-drv.h>
 #include "ovcamchip_priv.h"
 
 #define DRIVER_VERSION "v2.27 for Linux 2.6"
@@ -44,6 +47,7 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
+
 /* Registers common to all chips, that are needed for detection */
 #define GENERIC_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
 #define GENERIC_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
@@ -61,10 +65,6 @@
 	[CC_OV6630AF]	= "OV6630AF",
 };
 
-/* Forward declarations */
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 /* ----------------------------------------------------------------------- */
 
 int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals)
@@ -253,112 +253,36 @@
 
 	/* Test for 7xx0 */
 	PDEBUG(3, "Testing for 0V7xx0");
-	c->addr = OV7xx0_SID;
-	if (init_camchip(c) < 0) {
-		/* Test for 6xx0 */
-		PDEBUG(3, "Testing for 0V6xx0");
-		c->addr = OV6xx0_SID;
-		if (init_camchip(c) < 0) {
-			return -ENODEV;
-		} else {
-			if (ov6xx0_detect(c) < 0) {
-				PERROR("Failed to init OV6xx0");
-				return -EIO;
-			}
-		}
-	} else {
+	if (init_camchip(c) < 0)
+		return -ENODEV;
+	/* 7-bit addresses with bit 0 set are for the OV7xx0 */
+	if (c->addr & 1) {
 		if (ov7xx0_detect(c) < 0) {
 			PERROR("Failed to init OV7xx0");
 			return -EIO;
 		}
+		return 0;
 	}
-
+	/* Test for 6xx0 */
+	PDEBUG(3, "Testing for 0V6xx0");
+	if (ov6xx0_detect(c) < 0) {
+		PERROR("Failed to init OV6xx0");
+		return -EIO;
+	}
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static int ovcamchip_attach(struct i2c_adapter *adap)
+static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
-	int rc = 0;
-	struct ovcamchip *ov;
-	struct i2c_client *c;
-
-	/* I2C is not a PnP bus, so we can never be certain that we're talking
-	 * to the right chip. To prevent damage to EEPROMS and such, only
-	 * attach to adapters that are known to contain OV camera chips. */
-
-	switch (adap->id) {
-	case I2C_HW_SMBUS_OV511:
-	case I2C_HW_SMBUS_OV518:
-	case I2C_HW_SMBUS_W9968CF:
-		PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
-		break;
-	default:
-		PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id);
-		return -ENODEV;
-	}
-
-	c = kmalloc(sizeof *c, GFP_KERNEL);
-	if (!c) {
-		rc = -ENOMEM;
-		goto no_client;
-	}
-	memcpy(c, &client_template, sizeof *c);
-	c->adapter = adap;
-	strcpy(c->name, "OV????");
-
-	ov = kzalloc(sizeof *ov, GFP_KERNEL);
-	if (!ov) {
-		rc = -ENOMEM;
-		goto no_ov;
-	}
-	i2c_set_clientdata(c, ov);
-
-	rc = ovcamchip_detect(c);
-	if (rc < 0)
-		goto error;
-
-	strcpy(c->name, chip_names[ov->subtype]);
-
-	PDEBUG(1, "Camera chip detection complete");
-
-	i2c_attach_client(c);
-
-	return rc;
-error:
-	kfree(ov);
-no_ov:
-	kfree(c);
-no_client:
-	PDEBUG(1, "returning %d", rc);
-	return rc;
-}
-
-static int ovcamchip_detach(struct i2c_client *c)
-{
-	struct ovcamchip *ov = i2c_get_clientdata(c);
-	int rc;
-
-	rc = ov->sops->free(c);
-	if (rc < 0)
-		return rc;
-
-	i2c_detach_client(c);
-
-	kfree(ov);
-	kfree(c);
-	return 0;
-}
-
-static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
-{
-	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ovcamchip *ov = to_ovcamchip(sd);
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
 
 	if (!ov->initialized &&
 	    cmd != OVCAMCHIP_CMD_Q_SUBTYPE &&
 	    cmd != OVCAMCHIP_CMD_INITIALIZE) {
-		dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n");
+		v4l2_err(sd, "Camera chip not initialized yet!\n");
 		return -EPERM;
 	}
 
@@ -379,10 +303,10 @@
 
 		if (ov->mono) {
 			if (ov->subtype != CC_OV7620)
-				dev_warn(&c->dev, "Warning: Monochrome not "
+				v4l2_warn(sd, "Monochrome not "
 					"implemented for this chip\n");
 			else
-				dev_info(&c->dev, "Initializing chip as "
+				v4l2_info(sd, "Initializing chip as "
 					"monochrome\n");
 		}
 
@@ -400,35 +324,72 @@
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver driver = {
-	.driver = {
-		.name =		"ovcamchip",
-	},
-	.id =			I2C_DRIVERID_OVCAMCHIP,
-	.attach_adapter =	ovcamchip_attach,
-	.detach_client =	ovcamchip_detach,
-	.command =		ovcamchip_command,
+static const struct v4l2_subdev_core_ops ovcamchip_core_ops = {
+	.ioctl = ovcamchip_ioctl,
 };
 
-static struct i2c_client client_template = {
-	.name =		"(unset)",
-	.driver =	&driver,
+static const struct v4l2_subdev_ops ovcamchip_ops = {
+	.core = &ovcamchip_core_ops,
 };
 
-static int __init ovcamchip_init(void)
+static int ovcamchip_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-#ifdef DEBUG
-	ovcamchip_debug = debug;
-#endif
+	struct ovcamchip *ov;
+	struct v4l2_subdev *sd;
+	int rc = 0;
 
-	PINFO(DRIVER_VERSION " : " DRIVER_DESC);
-	return i2c_add_driver(&driver);
+	ov = kzalloc(sizeof *ov, GFP_KERNEL);
+	if (!ov) {
+		rc = -ENOMEM;
+		goto no_ov;
+	}
+	sd = &ov->sd;
+	v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops);
+
+	rc = ovcamchip_detect(client);
+	if (rc < 0)
+		goto error;
+
+	v4l_info(client, "%s found @ 0x%02x (%s)\n",
+			chip_names[ov->subtype], client->addr << 1, client->adapter->name);
+
+	PDEBUG(1, "Camera chip detection complete");
+
+	return rc;
+error:
+	kfree(ov);
+no_ov:
+	PDEBUG(1, "returning %d", rc);
+	return rc;
 }
 
-static void __exit ovcamchip_exit(void)
+static int ovcamchip_remove(struct i2c_client *client)
 {
-	i2c_del_driver(&driver);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ovcamchip *ov = to_ovcamchip(sd);
+	int rc;
+
+	v4l2_device_unregister_subdev(sd);
+	rc = ov->sops->free(client);
+	if (rc < 0)
+		return rc;
+
+	kfree(ov);
+	return 0;
 }
 
-module_init(ovcamchip_init);
-module_exit(ovcamchip_exit);
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id ovcamchip_id[] = {
+	{ "ovcamchip", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ovcamchip_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "ovcamchip",
+	.probe = ovcamchip_probe,
+	.remove = ovcamchip_remove,
+	.id_table = ovcamchip_id,
+};
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index a05650f..4f07b78 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -16,6 +16,7 @@
 #define __LINUX_OVCAMCHIP_PRIV_H
 
 #include <linux/i2c.h>
+#include <media/v4l2-subdev.h>
 #include <media/ovcamchip.h>
 
 #ifdef DEBUG
@@ -46,6 +47,7 @@
 };
 
 struct ovcamchip {
+	struct v4l2_subdev sd;
 	struct ovcamchip_ops *sops;
 	void *spriv;               /* Private data for OV7x10.c etc... */
 	int subtype;               /* = SEN_OV7610 etc... */
@@ -53,6 +55,11 @@
 	int initialized;           /* OVCAMCHIP_CMD_INITIALIZE was successful */
 };
 
+static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ovcamchip, sd);
+}
+
 extern struct ovcamchip_ops ov6x20_ops;
 extern struct ovcamchip_ops ov6x30_ops;
 extern struct ovcamchip_ops ov7x10_ops;
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
index 854c2a8..f9b6001 100644
--- a/drivers/media/video/pvrusb2/Kconfig
+++ b/drivers/media/video/pvrusb2/Kconfig
@@ -40,10 +40,10 @@
 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
 	select DVB_S5H1409 if !DVB_FE_CUSTOMISE
 	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+	select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 
 	  This option enables a DVB interface for the pvrusb2 driver.
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
index 4fda2de..de2fc14 100644
--- a/drivers/media/video/pvrusb2/Makefile
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -2,14 +2,15 @@
 obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
 obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
 
-pvrusb2-objs	:= pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
-		   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+pvrusb2-objs	:= pvrusb2-i2c-core.o \
+		   pvrusb2-audio.o \
 		   pvrusb2-encoder.o pvrusb2-video-v4l.o \
-		   pvrusb2-eeprom.o pvrusb2-tuner.o \
+		   pvrusb2-eeprom.o \
 		   pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
 		   pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
 		   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
 		   pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
+		   pvrusb2-cs53l32a.o \
 		   $(obj-pvrusb2-dvb-y) \
 		   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
index cdedaa5..ccf2a3c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -26,14 +26,6 @@
 #include <media/msp3400.h>
 #include <media/v4l2-common.h>
 
-struct pvr2_msp3400_handler {
-	struct pvr2_hdw *hdw;
-	struct pvr2_i2c_client *client;
-	struct pvr2_i2c_handler i2c_handler;
-	unsigned long stale_mask;
-};
-
-
 
 struct routing_scheme {
 	const int *def;
@@ -63,123 +55,33 @@
 	},
 };
 
-/* This function selects the correct audio input source */
-static void set_stereo(struct pvr2_msp3400_handler *ctxt)
+void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 {
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	struct v4l2_routing route;
-	const struct routing_scheme *sp;
-	unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+	if (hdw->input_dirty || hdw->force_dirty) {
+		struct v4l2_routing route;
+		const struct routing_scheme *sp;
+		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
 
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
 
-	if ((sid < ARRAY_SIZE(routing_schemes)) &&
-	    ((sp = routing_schemes + sid) != NULL) &&
-	    (hdw->input_val >= 0) &&
-	    (hdw->input_val < sp->cnt)) {
-		route.input = sp->def[hdw->input_val];
-	} else {
-		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "*** WARNING *** i2c msp3400 v4l2 set_stereo:"
-			   " Invalid routing scheme (%u) and/or input (%d)",
-			   sid,hdw->input_val);
-		return;
-	}
-	route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-
-static int check_stereo(struct pvr2_msp3400_handler *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->input_dirty;
-}
-
-
-struct pvr2_msp3400_ops {
-	void (*update)(struct pvr2_msp3400_handler *);
-	int (*check)(struct pvr2_msp3400_handler *);
-};
-
-
-static const struct pvr2_msp3400_ops msp3400_ops[] = {
-	{ .update = set_stereo, .check = check_stereo},
-};
-
-
-static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
-		msk = 1 << idx;
-		if (ctxt->stale_mask & msk) continue;
-		if (msp3400_ops[idx].check(ctxt)) {
-			ctxt->stale_mask |= msk;
+		if ((sid < ARRAY_SIZE(routing_schemes)) &&
+		    ((sp = routing_schemes + sid) != NULL) &&
+		    (hdw->input_val >= 0) &&
+		    (hdw->input_val < sp->cnt)) {
+			route.input = sp->def[hdw->input_val];
+		} else {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "*** WARNING *** subdev msp3400 set_input:"
+				   " Invalid routing scheme (%u)"
+				   " and/or input (%d)",
+				   sid, hdw->input_val);
+			return;
 		}
-	}
-	return ctxt->stale_mask != 0;
-}
-
-
-static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) {
-		msk = 1 << idx;
-		if (!(ctxt->stale_mask & msk)) continue;
-		ctxt->stale_mask &= ~msk;
-		msp3400_ops[idx].update(ctxt);
+		route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+		sd->ops->audio->s_routing(sd, &route);
 	}
 }
 
-
-static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
-{
-	ctxt->client->handler = NULL;
-	kfree(ctxt);
-}
-
-
-static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
-					  char *buf,unsigned int cnt)
-{
-	return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
-}
-
-
-static const struct pvr2_i2c_handler_functions msp3400_funcs = {
-	.detach = (void (*)(void *))pvr2_msp3400_detach,
-	.check = (int (*)(void *))msp3400_check,
-	.update = (void (*)(void *))msp3400_update,
-	.describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
-};
-
-
-int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
-	struct pvr2_msp3400_handler *ctxt;
-	if (cp->handler) return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
-	if (!ctxt) return 0;
-
-	ctxt->i2c_handler.func_data = ctxt;
-	ctxt->i2c_handler.func_table = &msp3400_funcs;
-	ctxt->client = cp;
-	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1;
-	cp->handler = &ctxt->i2c_handler;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
-		   cp->client->addr);
-	return !0;
-}
-
-
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
   *** Local Variables: ***
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h
index ac54eed..e3e63d7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-audio.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h
@@ -22,10 +22,8 @@
 #ifndef __PVRUSB2_AUDIO_H
 #define __PVRUSB2_AUDIO_H
 
-#include "pvrusb2-i2c-core.h"
-
-int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
-
+#include "pvrusb2-hdw-internal.h"
+void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
 #endif /* __PVRUSB2_AUDIO_H */
 
 /*
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
new file mode 100644
index 0000000..b5c3428
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
@@ -0,0 +1,95 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   v4l-dvb cs53l32a module.
+
+*/
+
+#include "pvrusb2-cs53l32a.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct routing_scheme {
+	const int *def;
+	unsigned int cnt;
+};
+
+
+static const int routing_scheme1[] = {
+	[PVR2_CVAL_INPUT_TV] = 2,  /* 1 or 2 seems to work here */
+	[PVR2_CVAL_INPUT_RADIO] = 2,
+	[PVR2_CVAL_INPUT_COMPOSITE] = 0,
+	[PVR2_CVAL_INPUT_SVIDEO] =  0,
+};
+
+static const struct routing_scheme routing_schemes[] = {
+	[PVR2_ROUTING_SCHEME_ONAIR] = {
+		.def = routing_scheme1,
+		.cnt = ARRAY_SIZE(routing_scheme1),
+	},
+};
+
+
+void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+	if (hdw->input_dirty || hdw->force_dirty) {
+		struct v4l2_routing route;
+		const struct routing_scheme *sp;
+		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+			   hdw->input_val);
+		if ((sid < ARRAY_SIZE(routing_schemes)) &&
+		    ((sp = routing_schemes + sid) != NULL) &&
+		    (hdw->input_val >= 0) &&
+		    (hdw->input_val < sp->cnt)) {
+			route.input = sp->def[hdw->input_val];
+		} else {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "*** WARNING *** subdev v4l2 set_input:"
+				   " Invalid routing scheme (%u)"
+				   " and/or input (%d)",
+				   sid, hdw->input_val);
+			return;
+		}
+		route.output = 0;
+		sd->ops->audio->s_routing(sd, &route);
+	}
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
similarity index 64%
rename from drivers/media/video/pvrusb2/pvrusb2-tuner.h
rename to drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
index ef4afaf..53ba548 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-tuner.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
@@ -2,6 +2,7 @@
  *
  *
  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@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
@@ -17,14 +18,24 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
-#ifndef __PVRUSB2_TUNER_H
-#define __PVRUSB2_TUNER_H
 
-#include "pvrusb2-i2c-core.h"
+#ifndef __PVRUSB2_CS53L32A_H
+#define __PVRUSB2_CS53L32A_H
 
-int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+/*
 
-#endif /* __PVRUSB2_TUNER_H */
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles device video processing.  This interface is
+   used internally by the driver; higher level code should only
+   interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+#include "pvrusb2-hdw-internal.h"
+void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
+
+#endif /* __PVRUSB2_AUDIO_CS53L32A_H */
 
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 895859e..4e017ff 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -28,7 +28,6 @@
 
 #include "pvrusb2-cx2584x-v4l.h"
 #include "pvrusb2-video-v4l.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
 
 
 #include "pvrusb2-hdw-internal.h"
@@ -39,14 +38,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-struct pvr2_v4l_cx2584x {
-	struct pvr2_i2c_handler handler;
-	struct pvr2_decoder_ctrl ctrl;
-	struct pvr2_i2c_client *client;
-	struct pvr2_hdw *hdw;
-	unsigned long stale_mask;
-};
-
 
 struct routing_scheme_item {
 	int vid;
@@ -110,218 +101,44 @@
 	},
 };
 
-static void set_input(struct pvr2_v4l_cx2584x *ctxt)
+void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 {
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	struct v4l2_routing route;
-	enum cx25840_video_input vid_input;
-	enum cx25840_audio_input aud_input;
-	const struct routing_scheme *sp;
-	unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
+	if (hdw->input_dirty || hdw->force_dirty) {
+		struct v4l2_routing route;
+		enum cx25840_video_input vid_input;
+		enum cx25840_audio_input aud_input;
+		const struct routing_scheme *sp;
+		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
 
-	memset(&route,0,sizeof(route));
+		memset(&route, 0, sizeof(route));
 
-	if ((sid < ARRAY_SIZE(routing_schemes)) &&
-	    ((sp = routing_schemes + sid) != NULL) &&
-	    (hdw->input_val >= 0) &&
-	    (hdw->input_val < sp->cnt)) {
-		vid_input = sp->def[hdw->input_val].vid;
-		aud_input = sp->def[hdw->input_val].aud;
-	} else {
-		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "*** WARNING *** i2c cx2584x set_input:"
-			   " Invalid routing scheme (%u) and/or input (%d)",
-			   sid,hdw->input_val);
-		return;
-	}
-
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
-		   vid_input,aud_input);
-	route.input = (u32)vid_input;
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
-	route.input = (u32)aud_input;
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-
-static int check_input(struct pvr2_v4l_cx2584x *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->input_dirty != 0;
-}
-
-
-static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
-{
-	u32 val;
-	struct pvr2_hdw *hdw = ctxt->hdw;
-
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
-		   hdw->srate_val);
-	switch (hdw->srate_val) {
-	default:
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
-		val = 48000;
-		break;
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
-		val = 44100;
-		break;
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
-		val = 32000;
-		break;
-	}
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
-}
-
-
-static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->srate_dirty != 0;
-}
-
-
-struct pvr2_v4l_cx2584x_ops {
-	void (*update)(struct pvr2_v4l_cx2584x *);
-	int (*check)(struct pvr2_v4l_cx2584x *);
-};
-
-
-static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
-	{ .update = set_input, .check = check_input},
-	{ .update = set_audio, .check = check_audio},
-};
-
-
-static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
-{
-	ctxt->client->handler = NULL;
-	pvr2_hdw_set_decoder(ctxt->hdw,NULL);
-	kfree(ctxt);
-}
-
-
-static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
-		msk = 1 << idx;
-		if (ctxt->stale_mask & msk) continue;
-		if (decoder_ops[idx].check(ctxt)) {
-			ctxt->stale_mask |= msk;
+		if ((sid < ARRAY_SIZE(routing_schemes)) &&
+		    ((sp = routing_schemes + sid) != NULL) &&
+		    (hdw->input_val >= 0) &&
+		    (hdw->input_val < sp->cnt)) {
+			vid_input = sp->def[hdw->input_val].vid;
+			aud_input = sp->def[hdw->input_val].aud;
+		} else {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "*** WARNING *** subdev cx2584x set_input:"
+				   " Invalid routing scheme (%u)"
+				   " and/or input (%d)",
+				   sid, hdw->input_val);
+			return;
 		}
-	}
-	return ctxt->stale_mask != 0;
-}
 
-
-static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
-		msk = 1 << idx;
-		if (!(ctxt->stale_mask & msk)) continue;
-		ctxt->stale_mask &= ~msk;
-		decoder_ops[idx].update(ctxt);
+		pvr2_trace(PVR2_TRACE_CHIPS,
+			   "subdev cx2584x set_input vid=0x%x aud=0x%x",
+			   vid_input, aud_input);
+		route.input = (u32)vid_input;
+		sd->ops->video->s_routing(sd, &route);
+		route.input = (u32)aud_input;
+		sd->ops->audio->s_routing(sd, &route);
 	}
 }
 
 
-static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
-{
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
-	pvr2_v4l2_cmd_stream(ctxt->client,fl);
-}
-
-
-static int decoder_detect(struct pvr2_i2c_client *cp)
-{
-	int ret;
-	/* Attempt to query the decoder - let's see if it will answer */
-	struct v4l2_queryctrl qc;
-
-	memset(&qc,0,sizeof(qc));
-
-	qc.id = V4L2_CID_BRIGHTNESS;
-
-	ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
-	return ret == 0; /* Return true if it answered */
-}
-
-
-static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
-				     char *buf,unsigned int cnt)
-{
-	return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
-}
-
-
-static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
-{
-	int ret;
-	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL);
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
-}
-
-
-static const struct pvr2_i2c_handler_functions hfuncs = {
-	.detach = (void (*)(void *))decoder_detach,
-	.check = (int (*)(void *))decoder_check,
-	.update = (void (*)(void *))decoder_update,
-	.describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
-};
-
-
-int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
-			       struct pvr2_i2c_client *cp)
-{
-	struct pvr2_v4l_cx2584x *ctxt;
-
-	if (hdw->decoder_ctrl) return 0;
-	if (cp->handler) return 0;
-	if (!decoder_detect(cp)) return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
-	if (!ctxt) return 0;
-
-	ctxt->handler.func_data = ctxt;
-	ctxt->handler.func_table = &hfuncs;
-	ctxt->ctrl.ctxt = ctxt;
-	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
-	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-	ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
-	ctxt->client = cp;
-	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
-	pvr2_hdw_set_decoder(hdw,&ctxt->ctrl);
-	cp->handler = &ctxt->handler;
-	{
-		/*
-		  Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
-		  of nuttiness for cx25840 causes that module to
-		  correctly set up its video scaling.  This is really
-		  a problem in the cx25840 module itself, but we work
-		  around it here.  The problem has not been seen in
-		  ivtv because there VBI is supported and set up.  We
-		  don't do VBI here (at least not yet) and thus we
-		  never attempted to even set it up.
-		 */
-		struct v4l2_format fmt;
-		memset(&fmt,0,sizeof(fmt));
-		fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
-		pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
-	}
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
-		   cp->client->addr);
-	return !0;
-}
-
-
-
 
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
index 66abf77..e35c232 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -34,9 +34,9 @@
 
 
 
-#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
 
-int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
 
 
 #endif /* __PVRUSB2_CX2584X_V4L_H */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index ca892fb..fbe3856 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -23,7 +23,6 @@
 #include "pvrusb2-debugifc.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-debug.h"
-#include "pvrusb2-i2c-core.h"
 
 struct debugifc_mask_item {
 	const char *name;
@@ -147,10 +146,6 @@
 	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 	ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
 	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-	ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n");
-	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-	ccnt = pvr2_i2c_report(hdw,buf,acnt);
-	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 
 	return bcnt;
 }
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
index e24ff59..2f8d467 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
@@ -22,16 +22,16 @@
 
 struct pvr2_hdw;
 
-/* Non-intrusively print some useful debugging info from inside the
-   driver.  This should work even if the driver appears to be
-   wedged. */
-int pvr2_debugifc_print_info(struct pvr2_hdw *,
-			     char *buf_ptr,unsigned int buf_size);
-
 /* Print general status of driver.  This will also trigger a probe of
    the USB link.  Unlike print_info(), this one synchronizes with the
    driver so the information should be self-consistent (but it will
    hang if the driver is wedged). */
+int pvr2_debugifc_print_info(struct pvr2_hdw *,
+			     char *buf_ptr, unsigned int buf_size);
+
+/* Non-intrusively print some useful debugging info from inside the
+   driver.  This should work even if the driver appears to be
+   wedged. */
 int pvr2_debugifc_print_status(struct pvr2_hdw *,
 			       char *buf_ptr,unsigned int buf_size);
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index cbe2a34..1cb6a26 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -46,10 +46,11 @@
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 29xxx */
 
-static const char *pvr2_client_29xxx[] = {
-	"msp3400",
-	"saa7115",
-	"tuner",
+static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = {
+	{ .module_id = PVR2_CLIENT_ID_SAA7115 },
+	{ .module_id = PVR2_CLIENT_ID_MSP3400 },
+	{ .module_id = PVR2_CLIENT_ID_TUNER },
+	{ .module_id = PVR2_CLIENT_ID_DEMOD },
 };
 
 static const char *pvr2_fw1_names_29xxx[] = {
@@ -59,8 +60,8 @@
 static const struct pvr2_device_desc pvr2_device_29xxx = {
 		.description = "WinTV PVR USB2 Model Category 29xxx",
 		.shortname = "29xxx",
-		.client_modules.lst = pvr2_client_29xxx,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx),
+		.client_table.lst = pvr2_cli_29xxx,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx),
 		.fx2_firmware.lst = pvr2_fw1_names_29xxx,
 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
 		.flag_has_hauppauge_rom = !0,
@@ -77,10 +78,11 @@
 /*------------------------------------------------------------------------*/
 /* Hauppauge PVR-USB2 Model 24xxx */
 
-static const char *pvr2_client_24xxx[] = {
-	"cx25840",
-	"tuner",
-	"wm8775",
+static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = {
+	{ .module_id = PVR2_CLIENT_ID_CX25840 },
+	{ .module_id = PVR2_CLIENT_ID_TUNER },
+	{ .module_id = PVR2_CLIENT_ID_WM8775 },
+	{ .module_id = PVR2_CLIENT_ID_DEMOD },
 };
 
 static const char *pvr2_fw1_names_24xxx[] = {
@@ -90,8 +92,8 @@
 static const struct pvr2_device_desc pvr2_device_24xxx = {
 		.description = "WinTV PVR USB2 Model Category 24xxx",
 		.shortname = "24xxx",
-		.client_modules.lst = pvr2_client_24xxx,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx),
+		.client_table.lst = pvr2_cli_24xxx,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx),
 		.fx2_firmware.lst = pvr2_fw1_names_24xxx,
 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx),
 		.flag_has_cx25840 = !0,
@@ -111,16 +113,16 @@
 /*------------------------------------------------------------------------*/
 /* GOTVIEW USB2.0 DVD2 */
 
-static const char *pvr2_client_gotview_2[] = {
-	"cx25840",
-	"tuner",
+static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
+	{ .module_id = PVR2_CLIENT_ID_CX25840 },
+	{ .module_id = PVR2_CLIENT_ID_TUNER },
 };
 
 static const struct pvr2_device_desc pvr2_device_gotview_2 = {
 		.description = "Gotview USB 2.0 DVD 2",
 		.shortname = "gv2",
-		.client_modules.lst = pvr2_client_gotview_2,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+		.client_table.lst = pvr2_cli_gotview_2,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
 		.flag_has_cx25840 = !0,
 		.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
 		.flag_has_analogtuner = !0,
@@ -140,8 +142,8 @@
 static const struct pvr2_device_desc pvr2_device_gotview_2d = {
 		.description = "Gotview USB 2.0 DVD Deluxe",
 		.shortname = "gv2d",
-		.client_modules.lst = pvr2_client_gotview_2,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2),
+		.client_table.lst = pvr2_cli_gotview_2,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
 		.flag_has_cx25840 = !0,
 		.default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
 		.flag_has_analogtuner = !0,
@@ -181,29 +183,29 @@
 	return 0;
 }
 
-static struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
 	.frontend_attach = pvr2_lgdt3303_attach,
 	.tuner_attach    = pvr2_lgh06xf_attach,
 };
 #endif
 
-static const char *pvr2_client_onair_creator[] = {
-	"saa7115",
-	"tuner",
-	"cs53l32a",
+static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = {
+	{ .module_id = PVR2_CLIENT_ID_SAA7115 },
+	{ .module_id = PVR2_CLIENT_ID_CS53L32A },
+	{ .module_id = PVR2_CLIENT_ID_TUNER },
 };
 
 static const struct pvr2_device_desc pvr2_device_onair_creator = {
 		.description = "OnAir Creator Hybrid USB tuner",
 		.shortname = "oac",
-		.client_modules.lst = pvr2_client_onair_creator,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator),
+		.client_table.lst = pvr2_cli_onair_creator,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator),
 		.default_tuner_type = TUNER_LG_TDVS_H06XF,
 		.flag_has_analogtuner = !0,
 		.flag_has_composite = !0,
 		.flag_has_svideo = !0,
 		.flag_digital_requires_cx23416 = !0,
-		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+		.signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
 		.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
 		.default_std_mask = V4L2_STD_NTSC_M,
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
@@ -241,29 +243,29 @@
 	return 0;
 }
 
-static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
 	.frontend_attach = pvr2_lgdt3302_attach,
 	.tuner_attach    = pvr2_fcv1236d_attach,
 };
 #endif
 
-static const char *pvr2_client_onair_usb2[] = {
-	"saa7115",
-	"tuner",
-	"cs53l32a",
+static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = {
+	{ .module_id = PVR2_CLIENT_ID_SAA7115 },
+	{ .module_id = PVR2_CLIENT_ID_CS53L32A },
+	{ .module_id = PVR2_CLIENT_ID_TUNER },
 };
 
 static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
 		.description = "OnAir USB2 Hybrid USB tuner",
 		.shortname = "oa2",
-		.client_modules.lst = pvr2_client_onair_usb2,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2),
+		.client_table.lst = pvr2_cli_onair_usb2,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2),
 		.default_tuner_type = TUNER_PHILIPS_FCV1236D,
 		.flag_has_analogtuner = !0,
 		.flag_has_composite = !0,
 		.flag_has_svideo = !0,
 		.flag_digital_requires_cx23416 = !0,
-		.signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+		.signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
 		.digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
 		.default_std_mask = V4L2_STD_NTSC_M,
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
@@ -314,15 +316,16 @@
 	return 0;
 }
 
-static struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
 	.frontend_attach = pvr2_tda10048_attach,
 	.tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
 };
 #endif
 
-static const char *pvr2_client_73xxx[] = {
-	"cx25840",
-	"tuner",
+static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = {
+	{ .module_id = PVR2_CLIENT_ID_CX25840 },
+	{ .module_id = PVR2_CLIENT_ID_TUNER,
+	  .i2c_address_list = "\x42"},
 };
 
 static const char *pvr2_fw1_names_73xxx[] = {
@@ -332,8 +335,8 @@
 static const struct pvr2_device_desc pvr2_device_73xxx = {
 		.description = "WinTV HVR-1900 Model Category 73xxx",
 		.shortname = "73xxx",
-		.client_modules.lst = pvr2_client_73xxx,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx),
+		.client_table.lst = pvr2_cli_73xxx,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
 		.fx2_firmware.lst = pvr2_fw1_names_73xxx,
 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
 		.flag_has_cx25840 = !0,
@@ -418,22 +421,17 @@
 	return 0;
 }
 
-static struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_750xx_dvb_props = {
 	.frontend_attach = pvr2_s5h1409_attach,
 	.tuner_attach    = pvr2_tda18271_8295_attach,
 };
 
-static struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+static const struct pvr2_dvb_props pvr2_751xx_dvb_props = {
 	.frontend_attach = pvr2_s5h1411_attach,
 	.tuner_attach    = pvr2_tda18271_8295_attach,
 };
 #endif
 
-static const char *pvr2_client_75xxx[] = {
-	"cx25840",
-	"tuner",
-};
-
 static const char *pvr2_fw1_names_75xxx[] = {
 		"v4l-pvrusb2-73xxx-01.fw",
 };
@@ -441,8 +439,8 @@
 static const struct pvr2_device_desc pvr2_device_750xx = {
 		.description = "WinTV HVR-1950 Model Category 750xx",
 		.shortname = "750xx",
-		.client_modules.lst = pvr2_client_75xxx,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+		.client_table.lst = pvr2_cli_73xxx,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
 		.fx2_firmware.lst = pvr2_fw1_names_75xxx,
 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
 		.flag_has_cx25840 = !0,
@@ -463,8 +461,8 @@
 static const struct pvr2_device_desc pvr2_device_751xx = {
 		.description = "WinTV HVR-1950 Model Category 751xx",
 		.shortname = "751xx",
-		.client_modules.lst = pvr2_client_75xxx,
-		.client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx),
+		.client_table.lst = pvr2_cli_73xxx,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
 		.fx2_firmware.lst = pvr2_fw1_names_75xxx,
 		.fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
 		.flag_has_cx25840 = !0,
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index cb3a33e..3e55338 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -33,6 +33,34 @@
 */
 
 
+#define PVR2_CLIENT_ID_NULL 0
+#define PVR2_CLIENT_ID_MSP3400 1
+#define PVR2_CLIENT_ID_CX25840 2
+#define PVR2_CLIENT_ID_SAA7115 3
+#define PVR2_CLIENT_ID_TUNER 4
+#define PVR2_CLIENT_ID_CS53L32A 5
+#define PVR2_CLIENT_ID_WM8775 6
+#define PVR2_CLIENT_ID_DEMOD 7
+
+struct pvr2_device_client_desc {
+	/* One ovr PVR2_CLIENT_ID_xxxx */
+	unsigned char module_id;
+
+	/* Null-terminated array of I2C addresses to try in order
+	   initialize the module.  It's safe to make this null terminated
+	   since we're never going to encounter an i2c device with an
+	   address of zero.  If this is a null pointer or zero-length,
+	   then no I2C addresses have been specified, in which case we'll
+	   try some compiled in defaults for now. */
+	unsigned char *i2c_address_list;
+};
+
+struct pvr2_device_client_table {
+	const struct pvr2_device_client_desc *lst;
+	unsigned char cnt;
+};
+
+
 struct pvr2_string_table {
 	const char **lst;
 	unsigned int cnt;
@@ -40,6 +68,7 @@
 
 #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
 #define PVR2_ROUTING_SCHEME_GOTVIEW 1
+#define PVR2_ROUTING_SCHEME_ONAIR 2
 
 #define PVR2_DIGITAL_SCHEME_NONE 0
 #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
@@ -66,6 +95,9 @@
 	/* List of additional client modules we need to load */
 	struct pvr2_string_table client_modules;
 
+	/* List of defined client modules we need to load */
+	struct pvr2_device_client_table client_table;
+
 	/* List of FX2 firmware file names we should search; if empty then
 	   FX2 firmware check / load is skipped and we assume the device
 	   was initialized from internal ROM. */
@@ -73,7 +105,7 @@
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
 	/* callback functions to handle attachment of digital tuner & demod */
-	struct pvr2_dvb_props *dvb_props;
+	const struct pvr2_dvb_props *dvb_props;
 
 #endif
 	/* Initial standard bits to use for this device, if not zero.
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
index 77b3c33..b7f5c49 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -321,7 +321,7 @@
 static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
 {
 	struct pvr2_hdw *hdw = adap->channel.hdw;
-	struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+	const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
 	int ret = 0;
 
 	if (dvb_props == NULL) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index 273d2a1..54ac534 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -347,7 +347,7 @@
 	int encMisc3Arg = 0;
 
 #if 0
-	/* This inexplicable bit happens in the Hauppage windows
+	/* This inexplicable bit happens in the Hauppauge windows
 	   driver (for both 24xxx and 29xxx devices).  However I
 	   currently see no difference in behavior with or without
 	   this stuff.  Leave this here as a note of its existence,
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index de7ee72..5d75eb5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -38,6 +38,7 @@
 #include <linux/mutex.h>
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-io.h"
+#include <media/v4l2-device.h>
 #include <media/cx2341x.h>
 #include "pvrusb2-devattr.h"
 
@@ -57,8 +58,6 @@
 #define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
 #define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
 
-struct pvr2_decoder;
-
 typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
 typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
 typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
@@ -139,22 +138,6 @@
 };
 
 
-struct pvr2_decoder_ctrl {
-	void *ctxt;
-	void (*detach)(void *);
-	void (*enable)(void *,int);
-	void (*force_reset)(void *);
-};
-
-#define PVR2_I2C_PEND_DETECT  0x01  /* Need to detect a client type */
-#define PVR2_I2C_PEND_CLIENT  0x02  /* Client needs a specific update */
-#define PVR2_I2C_PEND_REFRESH 0x04  /* Client has specific pending bits */
-#define PVR2_I2C_PEND_STALE   0x08  /* Broadcast pending bits */
-
-#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\
-			   PVR2_I2C_PEND_CLIENT |\
-			   PVR2_I2C_PEND_REFRESH |\
-			   PVR2_I2C_PEND_STALE)
 
 /* Disposition of firmware1 loading situation */
 #define FW1_STATE_UNKNOWN 0
@@ -179,6 +162,8 @@
 	struct usb_device *usb_dev;
 	struct usb_interface *usb_intf;
 
+	/* Our handle into the v4l2 sub-device architecture */
+	struct v4l2_device v4l2_dev;
 	/* Device description, anything that must adjust behavior based on
 	   device specific info will use information held here. */
 	const struct pvr2_device_desc *hdw_desc;
@@ -186,7 +171,6 @@
 	/* Kernel worker thread handling */
 	struct workqueue_struct *workqueue;
 	struct work_struct workpoll;     /* Update driver state */
-	struct work_struct worki2csync;  /* Update i2c clients */
 
 	/* Video spigot */
 	struct pvr2_stream *vid_stream;
@@ -195,20 +179,26 @@
 	struct mutex big_lock_mutex;
 	int big_lock_held;  /* For debugging */
 
+	/* This is a simple string which identifies the instance of this
+	   driver.  It is unique within the set of existing devices, but
+	   there is no attempt to keep the name consistent with the same
+	   physical device each time. */
 	char name[32];
 
+	/* This is a simple string which identifies the physical device
+	   instance itself - if possible.  (If not possible, then it is
+	   based on the specific driver instance, similar to name above.)
+	   The idea here is that userspace might hopefully be able to use
+	   this recognize specific tuners.  It will encode a serial number,
+	   if available. */
+	char identifier[32];
+
 	/* I2C stuff */
 	struct i2c_adapter i2c_adap;
 	struct i2c_algorithm i2c_algo;
 	pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
 	int i2c_cx25840_hack_state;
 	int i2c_linked;
-	unsigned int i2c_pend_types;    /* Which types of update are needed */
-	unsigned long i2c_pend_mask;    /* Change bits we need to scan */
-	unsigned long i2c_stale_mask;   /* Pending broadcast change bits */
-	unsigned long i2c_active_mask;  /* All change bits currently in use */
-	struct list_head i2c_clients;
-	struct mutex i2c_list_lock;
 
 	/* Frequency table */
 	unsigned int freqTable[FREQTABLE_SIZE];
@@ -275,6 +265,7 @@
 	wait_queue_head_t state_wait_data;
 
 
+	int force_dirty;        /* consider all controls dirty if true */
 	int flag_ok;            /* device in known good state */
 	int flag_disconnected;  /* flag_ok == 0 due to disconnect */
 	int flag_init_ok;       /* true if structure is fully initialized */
@@ -283,17 +274,13 @@
 	int flag_decoder_missed;/* We've noticed missing decoder */
 	int flag_tripped;       /* Indicates overall failure to start */
 
-	struct pvr2_decoder_ctrl *decoder_ctrl;
+	unsigned int decoder_client_id;
 
 	// CPU firmware info (used to help find / save firmware data)
 	char *fw_buffer;
 	unsigned int fw_size;
 	int fw_cpu_flag; /* True if we are dealing with the CPU */
 
-	// True if there is a request to trigger logging of state in each
-	// module.
-	int log_requested;
-
 	/* Tuner / frequency control stuff */
 	unsigned int tuner_type;
 	int tuner_updated;
@@ -391,7 +378,8 @@
 
 /* This function gets the current frequency */
 unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *);
-void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *);
+
+void pvr2_hdw_status_poll(struct pvr2_hdw *);
 
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index fa304e5..7a65b42 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -24,17 +24,22 @@
 #include <linux/firmware.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/tuner.h>
 #include "pvrusb2.h"
 #include "pvrusb2-std.h"
 #include "pvrusb2-util.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-i2c-core.h"
-#include "pvrusb2-tuner.h"
 #include "pvrusb2-eeprom.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-encoder.h"
 #include "pvrusb2-debug.h"
 #include "pvrusb2-fx2-cmd.h"
+#include "pvrusb2-wm8775.h"
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-cs53l32a.h"
+#include "pvrusb2-audio.h"
 
 #define TV_MIN_FREQ     55250000L
 #define TV_MAX_FREQ    850000000L
@@ -104,6 +109,39 @@
 /* size of a firmware chunk */
 #define FIRMWARE_CHUNK_SIZE 0x2000
 
+typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *,
+					struct v4l2_subdev *);
+
+static const pvr2_subdev_update_func pvr2_module_update_functions[] = {
+	[PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update,
+	[PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update,
+	[PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update,
+	[PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update,
+	[PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update,
+};
+
+static const char *module_names[] = {
+	[PVR2_CLIENT_ID_MSP3400] = "msp3400",
+	[PVR2_CLIENT_ID_CX25840] = "cx25840",
+	[PVR2_CLIENT_ID_SAA7115] = "saa7115",
+	[PVR2_CLIENT_ID_TUNER] = "tuner",
+	[PVR2_CLIENT_ID_DEMOD] = "tuner",
+	[PVR2_CLIENT_ID_CS53L32A] = "cs53l32a",
+	[PVR2_CLIENT_ID_WM8775] = "wm8775",
+};
+
+
+static const unsigned char *module_i2c_addresses[] = {
+	[PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63",
+	[PVR2_CLIENT_ID_DEMOD] = "\x43",
+	[PVR2_CLIENT_ID_MSP3400] = "\x40",
+	[PVR2_CLIENT_ID_SAA7115] = "\x21",
+	[PVR2_CLIENT_ID_WM8775] = "\x1b",
+	[PVR2_CLIENT_ID_CX25840] = "\x44",
+	[PVR2_CLIENT_ID_CS53L32A] = "\x11",
+};
+
+
 /* Define the list of additional controls we'll dynamically construct based
    on query of the cx2341x module. */
 struct pvr2_mpeg_ids {
@@ -277,7 +315,6 @@
 static void pvr2_hdw_state_sched(struct pvr2_hdw *);
 static int pvr2_hdw_state_eval(struct pvr2_hdw *);
 static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
-static void pvr2_hdw_worker_i2c(struct work_struct *work);
 static void pvr2_hdw_worker_poll(struct work_struct *work);
 static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
 static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
@@ -642,7 +679,7 @@
 	unsigned long fv;
 	struct pvr2_hdw *hdw = cptr->hdw;
 	if (hdw->tuner_signal_stale) {
-		pvr2_i2c_core_status_poll(hdw);
+		pvr2_hdw_status_poll(hdw);
 	}
 	fv = hdw->tuner_signal_info.rangehigh;
 	if (!fv) {
@@ -664,7 +701,7 @@
 	unsigned long fv;
 	struct pvr2_hdw *hdw = cptr->hdw;
 	if (hdw->tuner_signal_stale) {
-		pvr2_i2c_core_status_poll(hdw);
+		pvr2_hdw_status_poll(hdw);
 	}
 	fv = hdw->tuner_signal_info.rangelow;
 	if (!fv) {
@@ -858,7 +895,7 @@
 static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
 {
 	struct pvr2_hdw *hdw = cptr->hdw;
-	pvr2_i2c_core_status_poll(hdw);
+	pvr2_hdw_status_poll(hdw);
 	*vp = hdw->tuner_signal_info.signal;
 	return 0;
 }
@@ -868,7 +905,7 @@
 	int val = 0;
 	unsigned int subchan;
 	struct pvr2_hdw *hdw = cptr->hdw;
-	pvr2_i2c_core_status_poll(hdw);
+	pvr2_hdw_status_poll(hdw);
 	subchan = hdw->tuner_signal_info.rxsubchans;
 	if (subchan & V4L2_TUNER_SUB_MONO) {
 		val |= (1 << V4L2_TUNER_MODE_MONO);
@@ -1283,6 +1320,12 @@
 }
 
 
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw)
+{
+	return hdw->identifier;
+}
+
+
 unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
 {
 	return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
@@ -1634,33 +1677,27 @@
 
 static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
 {
-	if (!hdw->decoder_ctrl) {
-		if (!hdw->flag_decoder_missed) {
-			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "WARNING: No decoder present");
-			hdw->flag_decoder_missed = !0;
-			trace_stbit("flag_decoder_missed",
-				    hdw->flag_decoder_missed);
-		}
-		return -EIO;
+	/* Even though we really only care about the video decoder chip at
+	   this point, we'll broadcast stream on/off to all sub-devices
+	   anyway, just in case somebody else wants to hear the
+	   command... */
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s",
+		   (enablefl ? "on" : "off"));
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl);
+	if (hdw->decoder_client_id) {
+		/* We get here if the encoder has been noticed.  Otherwise
+		   we'll issue a warning to the user (which should
+		   normally never happen). */
+		return 0;
 	}
-	hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl);
-	return 0;
-}
-
-
-void pvr2_hdw_set_decoder(struct pvr2_hdw *hdw,struct pvr2_decoder_ctrl *ptr)
-{
-	if (hdw->decoder_ctrl == ptr) return;
-	hdw->decoder_ctrl = ptr;
-	if (hdw->decoder_ctrl && hdw->flag_decoder_missed) {
-		hdw->flag_decoder_missed = 0;
+	if (!hdw->flag_decoder_missed) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "WARNING: No decoder present");
+		hdw->flag_decoder_missed = !0;
 		trace_stbit("flag_decoder_missed",
 			    hdw->flag_decoder_missed);
-		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Decoder has appeared");
-		pvr2_hdw_state_sched(hdw);
 	}
+	return -EIO;
 }
 
 
@@ -1927,6 +1964,166 @@
 }
 
 
+static unsigned int pvr2_copy_i2c_addr_list(
+	unsigned short *dst, const unsigned char *src,
+	unsigned int dst_max)
+{
+	unsigned int cnt = 0;
+	if (!src) return 0;
+	while (src[cnt] && (cnt + 1) < dst_max) {
+		dst[cnt] = src[cnt];
+		cnt++;
+	}
+	dst[cnt] = I2C_CLIENT_END;
+	return cnt;
+}
+
+
+static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
+				const struct pvr2_device_client_desc *cd)
+{
+	const char *fname;
+	unsigned char mid;
+	struct v4l2_subdev *sd;
+	unsigned int i2ccnt;
+	const unsigned char *p;
+	/* Arbitrary count - max # i2c addresses we will probe */
+	unsigned short i2caddr[25];
+
+	mid = cd->module_id;
+	fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
+	if (!fname) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Module ID %u for device %s has no name",
+			   mid,
+			   hdw->hdw_desc->description);
+		return -EINVAL;
+	}
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "Module ID %u (%s) for device %s being loaded...",
+		   mid, fname,
+		   hdw->hdw_desc->description);
+
+	i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
+					 ARRAY_SIZE(i2caddr));
+	if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
+			 module_i2c_addresses[mid] : NULL) != NULL)) {
+		/* Second chance: Try default i2c address list */
+		i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
+						 ARRAY_SIZE(i2caddr));
+		if (i2ccnt) {
+			pvr2_trace(PVR2_TRACE_INIT,
+				   "Module ID %u:"
+				   " Using default i2c address list",
+				   mid);
+		}
+	}
+
+	if (!i2ccnt) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Module ID %u (%s) for device %s:"
+			   " No i2c addresses",
+			   mid, fname, hdw->hdw_desc->description);
+		return -EINVAL;
+	}
+
+	/* Note how the 2nd and 3rd arguments are the same for both
+	 * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev().  Why?
+	 * Well the 2nd argument is the module name to load, while the 3rd
+	 * argument is documented in the framework as being the "chipid" -
+	 * and every other place where I can find examples of this, the
+	 * "chipid" appears to just be the module name again.  So here we
+	 * just do the same thing. */
+	if (i2ccnt == 1) {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Module ID %u:"
+			   " Setting up with specified i2c address 0x%x",
+			   mid, i2caddr[0]);
+		sd = v4l2_i2c_new_subdev(&hdw->i2c_adap,
+					 fname, fname,
+					 i2caddr[0]);
+	} else {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Module ID %u:"
+			   " Setting up with address probe list",
+			   mid);
+		sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap,
+						fname, fname,
+						i2caddr);
+	}
+
+	if (!sd) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Module ID %u (%s) for device %s failed to load",
+			   mid, fname, hdw->hdw_desc->description);
+		return -EIO;
+	}
+
+	/* Tag this sub-device instance with the module ID we know about.
+	   In other places we'll use that tag to determine if the instance
+	   requires special handling. */
+	sd->grp_id = mid;
+
+	pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname);
+
+
+	/* client-specific setup... */
+	switch (mid) {
+	case PVR2_CLIENT_ID_CX25840:
+		hdw->decoder_client_id = mid;
+		{
+			/*
+			  Mike Isely <isely@pobox.com> 19-Nov-2006 - This
+			  bit of nuttiness for cx25840 causes that module
+			  to correctly set up its video scaling.  This is
+			  really a problem in the cx25840 module itself,
+			  but we work around it here.  The problem has not
+			  been seen in ivtv because there VBI is supported
+			  and set up.  We don't do VBI here (at least not
+			  yet) and thus we never attempted to even set it
+			  up.
+			*/
+			struct v4l2_format fmt;
+			pvr2_trace(PVR2_TRACE_INIT,
+				   "Module ID %u:"
+				   " Executing cx25840 VBI hack",
+				   mid);
+			memset(&fmt, 0, sizeof(fmt));
+			fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+			v4l2_device_call_all(&hdw->v4l2_dev, mid,
+					     video, s_fmt, &fmt);
+		}
+		break;
+	case PVR2_CLIENT_ID_SAA7115:
+		hdw->decoder_client_id = mid;
+		break;
+	default: break;
+	}
+
+	return 0;
+}
+
+
+static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw)
+{
+	unsigned int idx;
+	const struct pvr2_string_table *cm;
+	const struct pvr2_device_client_table *ct;
+	int okFl = !0;
+
+	cm = &hdw->hdw_desc->client_modules;
+	for (idx = 0; idx < cm->cnt; idx++) {
+		request_module(cm->lst[idx]);
+	}
+
+	ct = &hdw->hdw_desc->client_table;
+	for (idx = 0; idx < ct->cnt; idx++) {
+		if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0;
+	}
+	if (!okFl) pvr2_hdw_render_useless(hdw);
+}
+
+
 static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
 {
 	int ret;
@@ -1966,9 +2163,7 @@
 
 	if (!pvr2_hdw_dev_ok(hdw)) return;
 
-	for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
-		request_module(hdw->hdw_desc->client_modules.lst[idx]);
-	}
+	hdw->force_dirty = !0;
 
 	if (!hdw->hdw_desc->flag_no_powerup) {
 		pvr2_hdw_cmd_powerup(hdw);
@@ -1987,6 +2182,11 @@
 	pvr2_i2c_core_init(hdw);
 	if (!pvr2_hdw_dev_ok(hdw)) return;
 
+	pvr2_hdw_load_modules(hdw);
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0);
+
 	for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
 		cptr = hdw->controls + idx;
 		if (cptr->info->skip_init) continue;
@@ -2024,6 +2224,19 @@
 		hdw->std_mask_eeprom = V4L2_STD_ALL;
 	}
 
+	if (hdw->serial_number) {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"sn-%lu", hdw->serial_number);
+	} else if (hdw->unit_number >= 0) {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"unit-%c",
+				hdw->unit_number + 'a');
+	} else {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"unit-??");
+	}
+	hdw->identifier[idx] = 0;
+
 	pvr2_hdw_setup_std(hdw);
 
 	if (!get_default_tuner_type(hdw)) {
@@ -2032,8 +2245,6 @@
 			   hdw->tuner_type);
 	}
 
-	pvr2_i2c_core_check_stale(hdw);
-	hdw->tuner_updated = 0;
 
 	if (!pvr2_hdw_dev_ok(hdw)) return;
 
@@ -2171,11 +2382,14 @@
 	struct pvr2_hdw *hdw = NULL;
 	int valid_std_mask;
 	struct pvr2_ctrl *cptr;
+	struct usb_device *usb_dev;
 	const struct pvr2_device_desc *hdw_desc;
 	__u8 ifnum;
 	struct v4l2_queryctrl qctrl;
 	struct pvr2_ctl_info *ciptr;
 
+	usb_dev = interface_to_usbdev(intf);
+
 	hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
 
 	if (hdw_desc == NULL) {
@@ -2360,6 +2574,11 @@
 	hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
 	if (!hdw->ctl_read_urb) goto fail;
 
+	if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Error registering with v4l core, giving up");
+		goto fail;
+	}
 	mutex_lock(&pvr2_unit_mtx); do {
 		for (idx = 0; idx < PVR_NUM; idx++) {
 			if (unit_pointers[idx]) continue;
@@ -2382,7 +2601,6 @@
 
 	hdw->workqueue = create_singlethread_workqueue(hdw->name);
 	INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
-	INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
 
 	pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
 		   hdw->unit_number,hdw->name);
@@ -2391,12 +2609,9 @@
 	hdw->flag_ok = !0;
 
 	hdw->usb_intf = intf;
-	hdw->usb_dev = interface_to_usbdev(intf);
+	hdw->usb_dev = usb_dev;
 
-	scnprintf(hdw->bus_info,sizeof(hdw->bus_info),
-		  "usb %s address %d",
-		  dev_name(&hdw->usb_dev->dev),
-		  hdw->usb_dev->devnum);
+	usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info));
 
 	ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
 	usb_set_interface(hdw->usb_dev,ifnum,0);
@@ -2454,6 +2669,10 @@
 		hdw->ctl_write_buffer = NULL;
 	}
 	hdw->flag_disconnected = !0;
+	/* If we don't do this, then there will be a dangling struct device
+	   reference to our disappearing device persisting inside the V4L
+	   core... */
+	v4l2_device_disconnect(&hdw->v4l2_dev);
 	hdw->usb_dev = NULL;
 	hdw->usb_intf = NULL;
 	pvr2_hdw_render_useless(hdw);
@@ -2481,10 +2700,8 @@
 		pvr2_stream_destroy(hdw->vid_stream);
 		hdw->vid_stream = NULL;
 	}
-	if (hdw->decoder_ctrl) {
-		hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
-	}
 	pvr2_i2c_core_done(hdw);
+	v4l2_device_unregister(&hdw->v4l2_dev);
 	pvr2_hdw_remove_usb_stuff(hdw);
 	mutex_lock(&pvr2_unit_mtx); do {
 		if ((hdw->unit_number >= 0) &&
@@ -2678,6 +2895,150 @@
 }
 
 
+static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
+				    const char *name, int val)
+{
+	struct v4l2_control ctrl;
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val);
+	memset(&ctrl, 0, sizeof(ctrl));
+	ctrl.id = id;
+	ctrl.value = val;
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl);
+}
+
+#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \
+	if ((hdw)->lab##_dirty || (hdw)->force_dirty) {		\
+		pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
+	}
+
+/* Execute whatever commands are required to update the state of all the
+   sub-devices so that they match our current control values. */
+static void pvr2_subdev_update(struct pvr2_hdw *hdw)
+{
+	struct v4l2_subdev *sd;
+	unsigned int id;
+	pvr2_subdev_update_func fp;
+
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev update...");
+
+	if (hdw->tuner_updated || hdw->force_dirty) {
+		struct tuner_setup setup;
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)",
+			   hdw->tuner_type);
+		if (((int)(hdw->tuner_type)) >= 0) {
+			setup.addr = ADDR_UNSET;
+			setup.type = hdw->tuner_type;
+			setup.mode_mask = T_RADIO | T_ANALOG_TV;
+			v4l2_device_call_all(&hdw->v4l2_dev, 0,
+					     tuner, s_type_addr, &setup);
+		}
+	}
+
+	if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) {
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard");
+		if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+			v4l2_device_call_all(&hdw->v4l2_dev, 0,
+					     tuner, s_radio);
+		} else {
+			v4l2_std_id vs;
+			vs = hdw->std_mask_cur;
+			v4l2_device_call_all(&hdw->v4l2_dev, 0,
+					     tuner, s_std, vs);
+		}
+		hdw->tuner_signal_stale = !0;
+		hdw->cropcap_stale = !0;
+	}
+
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass);
+	PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble);
+
+	if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) {
+		struct v4l2_tuner vt;
+		memset(&vt, 0, sizeof(vt));
+		vt.audmode = hdw->audiomode_val;
+		v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt);
+	}
+
+	if (hdw->freqDirty || hdw->force_dirty) {
+		unsigned long fv;
+		struct v4l2_frequency freq;
+		fv = pvr2_hdw_get_cur_freq(hdw);
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv);
+		if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw);
+		memset(&freq, 0, sizeof(freq));
+		if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+			/* ((fv * 1000) / 62500) */
+			freq.frequency = (fv * 2) / 125;
+		} else {
+			freq.frequency = fv / 62500;
+		}
+		/* tuner-core currently doesn't seem to care about this, but
+		   let's set it anyway for completeness. */
+		if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+			freq.type = V4L2_TUNER_RADIO;
+		} else {
+			freq.type = V4L2_TUNER_ANALOG_TV;
+		}
+		freq.tuner = 0;
+		v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner,
+				     s_frequency, &freq);
+	}
+
+	if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
+		struct v4l2_format fmt;
+		memset(&fmt, 0, sizeof(fmt));
+		fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		fmt.fmt.pix.width = hdw->res_hor_val;
+		fmt.fmt.pix.height = hdw->res_ver_val;
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
+			   fmt.fmt.pix.width, fmt.fmt.pix.height);
+		v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt);
+	}
+
+	if (hdw->srate_dirty || hdw->force_dirty) {
+		u32 val;
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d",
+			   hdw->srate_val);
+		switch (hdw->srate_val) {
+		default:
+		case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+			val = 48000;
+			break;
+		case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+			val = 44100;
+			break;
+		case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+			val = 32000;
+			break;
+		}
+		v4l2_device_call_all(&hdw->v4l2_dev, 0,
+				     audio, s_clock_freq, val);
+	}
+
+	/* Unable to set crop parameters; there is apparently no equivalent
+	   for VIDIOC_S_CROP */
+
+	v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+		id = sd->grp_id;
+		if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue;
+		fp = pvr2_module_update_functions[id];
+		if (!fp) continue;
+		(*fp)(hdw, sd);
+	}
+
+	if (hdw->tuner_signal_stale || hdw->cropcap_stale) {
+		pvr2_hdw_status_poll(hdw);
+	}
+}
+
+
 /* Figure out if we need to commit control changes.  If so, mark internal
    state flags to indicate this fact and return true.  Otherwise do nothing
    else and return false. */
@@ -2686,7 +3047,7 @@
 	unsigned int idx;
 	struct pvr2_ctrl *cptr;
 	int value;
-	int commit_flag = 0;
+	int commit_flag = hdw->force_dirty;
 	char buf[100];
 	unsigned int bcnt,ccnt;
 
@@ -2842,18 +3203,6 @@
 		cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
 	}
 
-	/* Scan i2c core at this point - before we clear all the dirty
-	   bits.  Various parts of the i2c core will notice dirty bits as
-	   appropriate and arrange to broadcast or directly send updates to
-	   the client drivers in order to keep everything in sync */
-	pvr2_i2c_core_check_stale(hdw);
-
-	for (idx = 0; idx < hdw->control_cnt; idx++) {
-		cptr = hdw->controls + idx;
-		if (!cptr->info->clear_dirty) continue;
-		cptr->info->clear_dirty(cptr);
-	}
-
 	if (hdw->active_stream_type != hdw->desired_stream_type) {
 		/* Handle any side effects of stream config here */
 		hdw->active_stream_type = hdw->desired_stream_type;
@@ -2873,8 +3222,16 @@
 		}
 	}
 
-	/* Now execute i2c core update */
-	pvr2_i2c_core_sync(hdw);
+	/* Check and update state for all sub-devices. */
+	pvr2_subdev_update(hdw);
+
+	hdw->tuner_updated = 0;
+	hdw->force_dirty = 0;
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		if (!cptr->info->clear_dirty) continue;
+		cptr->info->clear_dirty(cptr);
+	}
 
 	if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
 	    hdw->state_encoder_run) {
@@ -2904,15 +3261,6 @@
 }
 
 
-static void pvr2_hdw_worker_i2c(struct work_struct *work)
-{
-	struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,worki2csync);
-	LOCK_TAKE(hdw->big_lock); do {
-		pvr2_i2c_core_sync(hdw);
-	} while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
 static void pvr2_hdw_worker_poll(struct work_struct *work)
 {
 	int fl = 0;
@@ -2973,7 +3321,7 @@
 void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
 {
 	LOCK_TAKE(hdw->big_lock); do {
-		pvr2_i2c_core_status_poll(hdw);
+		pvr2_hdw_status_poll(hdw);
 	} while (0); LOCK_GIVE(hdw->big_lock);
 }
 
@@ -2983,7 +3331,7 @@
 	if (!hdw->cropcap_stale) {
 		return 0;
 	}
-	pvr2_i2c_core_status_poll(hdw);
+	pvr2_hdw_status_poll(hdw);
 	if (hdw->cropcap_stale) {
 		return -EIO;
 	}
@@ -3010,7 +3358,7 @@
 {
 	LOCK_TAKE(hdw->big_lock); do {
 		if (hdw->tuner_signal_stale) {
-			pvr2_i2c_core_status_poll(hdw);
+			pvr2_hdw_status_poll(hdw);
 		}
 		memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
 	} while (0); LOCK_GIVE(hdw->big_lock);
@@ -3029,11 +3377,8 @@
 {
 	int nr = pvr2_hdw_get_unit_number(hdw);
 	LOCK_TAKE(hdw->big_lock); do {
-		hdw->log_requested = !0;
 		printk(KERN_INFO "pvrusb2: =================  START STATUS CARD #%d  =================\n", nr);
-		pvr2_i2c_core_check_stale(hdw);
-		hdw->log_requested = 0;
-		pvr2_i2c_core_sync(hdw);
+		v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
 		pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
 		cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
 		pvr2_hdw_state_log_state(hdw);
@@ -3716,22 +4061,16 @@
 
 int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
 {
-	if (!hdw->decoder_ctrl) {
-		pvr2_trace(PVR2_TRACE_INIT,
-			   "Unable to reset decoder: nothing attached");
-		return -ENOTTY;
-	}
-
-	if (!hdw->decoder_ctrl->force_reset) {
-		pvr2_trace(PVR2_TRACE_INIT,
-			   "Unable to reset decoder: not implemented");
-		return -ENOTTY;
-	}
-
 	pvr2_trace(PVR2_TRACE_INIT,
 		   "Requesting decoder reset");
-	hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt);
-	return 0;
+	if (hdw->decoder_client_id) {
+		v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+				     core, reset, 0);
+		return 0;
+	}
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "Unable to reset decoder: nothing attached");
+	return -ENOTTY;
 }
 
 
@@ -4476,6 +4815,79 @@
 }
 
 
+/* Generate report containing info about attached sub-devices and attached
+   i2c clients, including an indication of which attached i2c clients are
+   actually sub-devices. */
+static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
+					    char *buf, unsigned int acnt)
+{
+	struct v4l2_subdev *sd;
+	unsigned int tcnt = 0;
+	unsigned int ccnt;
+	struct i2c_client *client;
+	struct list_head *item;
+	void *cd;
+	const char *p;
+	unsigned int id;
+
+	ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:");
+	tcnt += ccnt;
+	v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+		id = sd->grp_id;
+		p = NULL;
+		if (id < ARRAY_SIZE(module_names)) p = module_names[id];
+		if (p) {
+			ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p);
+			tcnt += ccnt;
+		} else {
+			ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+					 " (unknown id=%u)", id);
+			tcnt += ccnt;
+		}
+	}
+	ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
+	tcnt += ccnt;
+
+	ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n");
+	tcnt += ccnt;
+
+	mutex_lock(&hdw->i2c_adap.clist_lock);
+	list_for_each(item, &hdw->i2c_adap.clients) {
+		client = list_entry(item, struct i2c_client, list);
+		ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+				 "  %s: i2c=%02x", client->name, client->addr);
+		tcnt += ccnt;
+		cd = i2c_get_clientdata(client);
+		v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+			if (cd == sd) {
+				id = sd->grp_id;
+				p = NULL;
+				if (id < ARRAY_SIZE(module_names)) {
+					p = module_names[id];
+				}
+				if (p) {
+					ccnt = scnprintf(buf + tcnt,
+							 acnt - tcnt,
+							 " subdev=%s", p);
+					tcnt += ccnt;
+				} else {
+					ccnt = scnprintf(buf + tcnt,
+							 acnt - tcnt,
+							 " subdev= id %u)",
+							 id);
+					tcnt += ccnt;
+				}
+				break;
+			}
+		}
+		ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n");
+		tcnt += ccnt;
+	}
+	mutex_unlock(&hdw->i2c_adap.clist_lock);
+	return tcnt;
+}
+
+
 unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
 				   char *buf,unsigned int acnt)
 {
@@ -4490,6 +4902,8 @@
 		buf[0] = '\n'; ccnt = 1;
 		bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 	}
+	ccnt = pvr2_hdw_report_clients(hdw, buf, acnt);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 	LOCK_GIVE(hdw->big_lock);
 	return bcnt;
 }
@@ -4497,14 +4911,25 @@
 
 static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
 {
-	char buf[128];
-	unsigned int idx,ccnt;
+	char buf[256];
+	unsigned int idx, ccnt;
+	unsigned int lcnt, ucnt;
 
 	for (idx = 0; ; idx++) {
 		ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf));
 		if (!ccnt) break;
 		printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf);
 	}
+	ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf));
+	ucnt = 0;
+	while (ucnt < ccnt) {
+		lcnt = 0;
+		while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) {
+			lcnt++;
+		}
+		printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt);
+		ucnt += lcnt + 1;
+	}
 }
 
 
@@ -4641,6 +5066,30 @@
 }
 
 
+void pvr2_hdw_status_poll(struct pvr2_hdw *hdw)
+{
+	struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+	memset(vtp, 0, sizeof(*vtp));
+	hdw->tuner_signal_stale = 0;
+	/* Note: There apparently is no replacement for VIDIOC_CROPCAP
+	   using v4l2-subdev - therefore we can't support that AT ALL right
+	   now.  (Of course, no sub-drivers seem to implement it either.
+	   But now it's a a chicken and egg problem...) */
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner,
+			     &hdw->tuner_signal_info);
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
+		   " type=%u strength=%u audio=0x%x cap=0x%x"
+		   " low=%u hi=%u",
+		   vtp->type,
+		   vtp->signal, vtp->rxsubchans, vtp->capability,
+		   vtp->rangelow, vtp->rangehigh);
+
+	/* We have to do this to avoid getting into constant polling if
+	   there's nobody to answer a poll of cropcap info. */
+	hdw->cropcap_stale = 0;
+}
+
+
 unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
 {
 	return hdw->input_avail_mask;
@@ -4736,7 +5185,6 @@
 			     int setFl, u64 *val_ptr)
 {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-	struct pvr2_i2c_client *cp;
 	struct v4l2_dbg_register req;
 	int stat = 0;
 	int okFl = 0;
@@ -4746,21 +5194,9 @@
 	req.match = *match;
 	req.reg = reg_id;
 	if (setFl) req.val = *val_ptr;
-	mutex_lock(&hdw->i2c_list_lock); do {
-		list_for_each_entry(cp, &hdw->i2c_clients, list) {
-			if (!v4l2_chip_match_i2c_client(
-				    cp->client,
-				    &req.match)) {
-				continue;
-			}
-			stat = pvr2_i2c_client_cmd(
-				cp,(setFl ? VIDIOC_DBG_S_REGISTER :
-				    VIDIOC_DBG_G_REGISTER),&req);
-			if (!setFl) *val_ptr = req.val;
-			okFl = !0;
-			break;
-		}
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	/* It would be nice to know if a sub-device answered the request */
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req);
+	if (!setFl) *val_ptr = req.val;
 	if (okFl) {
 		return stat;
 	}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 1b4fec3..7b69405 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -132,6 +132,9 @@
 /* Retrieve bus location info of device */
 const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *);
 
+/* Retrieve per-instance string identifier for this specific device */
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *);
+
 /* Called when hardware has been unplugged */
 void pvr2_hdw_disconnect(struct pvr2_hdw *);
 
@@ -236,8 +239,7 @@
 				     enum pvr2_v4l_type index,int);
 
 /* Direct read/write access to chip's registers:
-   match_type - how to interpret match_chip (e.g. driver ID, i2c address)
-   match_chip - chip match value (e.g. I2C_DRIVERD_xxxx)
+   match - specify criteria to identify target chip (this is a v4l dbg struct)
    reg_id  - register number to access
    setFl   - true to set the register, false to read it
    val_ptr - storage location for source / result. */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
deleted file mode 100644
index 94a4771..0000000
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public 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/kernel.h>
-#include "pvrusb2-i2c-core.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
-#include "pvrusb2-audio.h"
-#include "pvrusb2-tuner.h"
-#include "pvrusb2-video-v4l.h"
-#include "pvrusb2-cx2584x-v4l.h"
-#include "pvrusb2-wm8775.h"
-
-#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
-
-#define OP_STANDARD 0
-#define OP_AUDIOMODE 1
-#define OP_BCSH 2
-#define OP_VOLUME 3
-#define OP_FREQ 4
-#define OP_AUDIORATE 5
-#define OP_CROP 6
-#define OP_SIZE 7
-#define OP_LOG 8
-
-static const struct pvr2_i2c_op * const ops[] = {
-	[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
-	[OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode,
-	[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
-	[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
-	[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
-	[OP_CROP] = &pvr2_i2c_op_v4l2_crop,
-	[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
-	[OP_LOG] = &pvr2_i2c_op_v4l2_log,
-};
-
-void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
-	int id;
-	id = cp->client->driver->id;
-	cp->ctl_mask = ((1 << OP_STANDARD) |
-			(1 << OP_AUDIOMODE) |
-			(1 << OP_BCSH) |
-			(1 << OP_VOLUME) |
-			(1 << OP_FREQ) |
-			(1 << OP_CROP) |
-			(1 << OP_SIZE) |
-			(1 << OP_LOG));
-	cp->status_poll = pvr2_v4l2_cmd_status_poll;
-
-	if (id == I2C_DRIVERID_MSP3400) {
-		if (pvr2_i2c_msp3400_setup(hdw,cp)) {
-			return;
-		}
-	}
-	if (id == I2C_DRIVERID_TUNER) {
-		if (pvr2_i2c_tuner_setup(hdw,cp)) {
-			return;
-		}
-	}
-	if (id == I2C_DRIVERID_CX25840) {
-		if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
-			return;
-		}
-	}
-	if (id == I2C_DRIVERID_WM8775) {
-		if (pvr2_i2c_wm8775_setup(hdw,cp)) {
-			return;
-		}
-	}
-	if (id == I2C_DRIVERID_SAA711X) {
-		if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
-			return;
-		}
-	}
-}
-
-
-const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
-{
-	if (idx >= ARRAY_SIZE(ops))
-		return NULL;
-	return ops[idx];
-}
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 75 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
deleted file mode 100644
index 16bb119..0000000
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public 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 "pvrusb2-i2c-cmd-v4l2.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-
-static void set_standard(struct pvr2_hdw *hdw)
-{
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard");
-
-	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-		pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL);
-	} else {
-		v4l2_std_id vs;
-		vs = hdw->std_mask_cur;
-		pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
-	}
-	hdw->tuner_signal_stale = !0;
-	hdw->cropcap_stale = !0;
-}
-
-
-static int check_standard(struct pvr2_hdw *hdw)
-{
-	return (hdw->input_dirty != 0) || (hdw->std_dirty != 0);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = {
-	.check = check_standard,
-	.update = set_standard,
-	.name = "v4l2_standard",
-};
-
-
-static void set_bcsh(struct pvr2_hdw *hdw)
-{
-	struct v4l2_control ctrl;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
-		   " b=%d c=%d s=%d h=%d",
-		   hdw->brightness_val,hdw->contrast_val,
-		   hdw->saturation_val,hdw->hue_val);
-	memset(&ctrl,0,sizeof(ctrl));
-	ctrl.id = V4L2_CID_BRIGHTNESS;
-	ctrl.value = hdw->brightness_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_CONTRAST;
-	ctrl.value = hdw->contrast_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_SATURATION;
-	ctrl.value = hdw->saturation_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_HUE;
-	ctrl.value = hdw->hue_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-}
-
-
-static int check_bcsh(struct pvr2_hdw *hdw)
-{
-	return (hdw->brightness_dirty ||
-		hdw->contrast_dirty ||
-		hdw->saturation_dirty ||
-		hdw->hue_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = {
-	.check = check_bcsh,
-	.update = set_bcsh,
-	.name = "v4l2_bcsh",
-};
-
-
-static void set_volume(struct pvr2_hdw *hdw)
-{
-	struct v4l2_control ctrl;
-	pvr2_trace(PVR2_TRACE_CHIPS,
-		   "i2c v4l2 set_volume"
-		   "(vol=%d bal=%d bas=%d treb=%d mute=%d)",
-		   hdw->volume_val,
-		   hdw->balance_val,
-		   hdw->bass_val,
-		   hdw->treble_val,
-		   hdw->mute_val);
-	memset(&ctrl,0,sizeof(ctrl));
-	ctrl.id = V4L2_CID_AUDIO_MUTE;
-	ctrl.value = hdw->mute_val ? 1 : 0;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_AUDIO_VOLUME;
-	ctrl.value = hdw->volume_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_AUDIO_BALANCE;
-	ctrl.value = hdw->balance_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_AUDIO_BASS;
-	ctrl.value = hdw->bass_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-	ctrl.id = V4L2_CID_AUDIO_TREBLE;
-	ctrl.value = hdw->treble_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
-}
-
-
-static int check_volume(struct pvr2_hdw *hdw)
-{
-	return (hdw->volume_dirty ||
-		hdw->balance_dirty ||
-		hdw->bass_dirty ||
-		hdw->treble_dirty ||
-		hdw->mute_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
-	.check = check_volume,
-	.update = set_volume,
-	.name = "v4l2_volume",
-};
-
-
-static void set_audiomode(struct pvr2_hdw *hdw)
-{
-	struct v4l2_tuner vt;
-	memset(&vt,0,sizeof(vt));
-	vt.audmode = hdw->audiomode_val;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt);
-}
-
-
-static int check_audiomode(struct pvr2_hdw *hdw)
-{
-	return (hdw->input_dirty ||
-		hdw->audiomode_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = {
-	.check = check_audiomode,
-	.update = set_audiomode,
-	.name = "v4l2_audiomode",
-};
-
-
-static void set_frequency(struct pvr2_hdw *hdw)
-{
-	unsigned long fv;
-	struct v4l2_frequency freq;
-	fv = pvr2_hdw_get_cur_freq(hdw);
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
-	if (hdw->tuner_signal_stale) {
-		pvr2_i2c_core_status_poll(hdw);
-	}
-	memset(&freq,0,sizeof(freq));
-	if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
-		// ((fv * 1000) / 62500)
-		freq.frequency = (fv * 2) / 125;
-	} else {
-		freq.frequency = fv / 62500;
-	}
-	/* tuner-core currently doesn't seem to care about this, but
-	   let's set it anyway for completeness. */
-	if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-		freq.type = V4L2_TUNER_RADIO;
-	} else {
-		freq.type = V4L2_TUNER_ANALOG_TV;
-	}
-	freq.tuner = 0;
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
-}
-
-
-static int check_frequency(struct pvr2_hdw *hdw)
-{
-	return hdw->freqDirty != 0;
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = {
-	.check = check_frequency,
-	.update = set_frequency,
-	.name = "v4l2_freq",
-};
-
-
-static void set_size(struct pvr2_hdw *hdw)
-{
-	struct v4l2_format fmt;
-
-	memset(&fmt,0,sizeof(fmt));
-
-	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	fmt.fmt.pix.width = hdw->res_hor_val;
-	fmt.fmt.pix.height = hdw->res_ver_val;
-
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
-			   fmt.fmt.pix.width,fmt.fmt.pix.height);
-
-	pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt);
-}
-
-
-static int check_size(struct pvr2_hdw *hdw)
-{
-	return (hdw->res_hor_dirty || hdw->res_ver_dirty);
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
-	.check = check_size,
-	.update = set_size,
-	.name = "v4l2_size",
-};
-
-
-static void set_crop(struct pvr2_hdw *hdw)
-{
-	struct v4l2_crop crop;
-
-	memset(&crop, 0, sizeof crop);
-	crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	crop.c.left = hdw->cropl_val;
-	crop.c.top = hdw->cropt_val;
-	crop.c.height = hdw->croph_val;
-	crop.c.width = hdw->cropw_val;
-
-	pvr2_trace(PVR2_TRACE_CHIPS,
-		   "i2c v4l2 set_crop crop=%d:%d:%d:%d",
-		   crop.c.width, crop.c.height, crop.c.left, crop.c.top);
-
-	pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
-}
-
-static int check_crop(struct pvr2_hdw *hdw)
-{
-	return (hdw->cropl_dirty || hdw->cropt_dirty ||
-		hdw->cropw_dirty || hdw->croph_dirty);
-}
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
-	.check = check_crop,
-	.update = set_crop,
-	.name = "v4l2_crop",
-};
-
-
-static void do_log(struct pvr2_hdw *hdw)
-{
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
-	pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL);
-
-}
-
-
-static int check_log(struct pvr2_hdw *hdw)
-{
-	return hdw->log_requested != 0;
-}
-
-
-const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
-	.check = check_log,
-	.update = do_log,
-	.name = "v4l2_log",
-};
-
-
-void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
-{
-	pvr2_i2c_client_cmd(cp,
-			    (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL);
-}
-
-
-void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
-{
-	int stat;
-	struct pvr2_hdw *hdw = cp->hdw;
-	if (hdw->cropcap_stale) {
-		hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP,
-					   &hdw->cropcap_info);
-		if (stat == 0) {
-			/* Check was successful, so the data is no
-			   longer considered stale. */
-			hdw->cropcap_stale = 0;
-		}
-	}
-	pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info);
-}
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
deleted file mode 100644
index eb744a2..0000000
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public 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 __PVRUSB2_CMD_V4L2_H
-#define __PVRUSB2_CMD_V4L2_H
-
-#include "pvrusb2-i2c-core.h"
-
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
-extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
-
-void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
-void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *);
-
-#endif /* __PVRUSB2_CMD_V4L2_H */
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index d6a3540..9464862 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -18,6 +18,7 @@
  *
  */
 
+#include <linux/i2c.h>
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
@@ -29,8 +30,7 @@
 /*
 
   This module attempts to implement a compliant I2C adapter for the pvrusb2
-  device.  By doing this we can then make use of existing functionality in
-  V4L (e.g. tuner.c) rather than rolling our own.
+  device.
 
 */
 
@@ -42,10 +42,6 @@
 module_param_array(ir_mode, int, NULL, 0444);
 MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
 
-static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
-					     unsigned int detail,
-					     char *buf,unsigned int maxlen);
-
 static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
 			  u8 i2c_addr,      /* I2C address we're talking to */
 			  u8 *data,         /* Data to write */
@@ -524,414 +520,13 @@
 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
 }
 
-static int pvr2_i2c_core_singleton(struct i2c_client *cp,
-				   unsigned int cmd,void *arg)
-{
-	int stat;
-	if (!cp) return -EINVAL;
-	if (!(cp->driver)) return -EINVAL;
-	if (!(cp->driver->command)) return -EINVAL;
-	if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN;
-	stat = cp->driver->command(cp,cmd,arg);
-	module_put(cp->driver->driver.owner);
-	return stat;
-}
-
-int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
-{
-	int stat;
-	if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
-		char buf[100];
-		unsigned int cnt;
-		cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
-					       buf,sizeof(buf));
-		pvr2_trace(PVR2_TRACE_I2C_CMD,
-			   "i2c COMMAND (code=%u 0x%x) to %.*s",
-			   cmd,cmd,cnt,buf);
-	}
-	stat = pvr2_i2c_core_singleton(cp->client,cmd,arg);
-	if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
-		char buf[100];
-		unsigned int cnt;
-		cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
-					       buf,sizeof(buf));
-		pvr2_trace(PVR2_TRACE_I2C_CMD,
-			   "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat);
-	}
-	return stat;
-}
-
-int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
-{
-	struct pvr2_i2c_client *cp, *ncp;
-	int stat = -EINVAL;
-
-	if (!hdw) return stat;
-
-	mutex_lock(&hdw->i2c_list_lock);
-	list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
-		if (!cp->recv_enable) continue;
-		mutex_unlock(&hdw->i2c_list_lock);
-		stat = pvr2_i2c_client_cmd(cp,cmd,arg);
-		mutex_lock(&hdw->i2c_list_lock);
-	}
-	mutex_unlock(&hdw->i2c_list_lock);
-	return stat;
-}
-
-
-static int handler_check(struct pvr2_i2c_client *cp)
-{
-	struct pvr2_i2c_handler *hp = cp->handler;
-	if (!hp) return 0;
-	if (!hp->func_table->check) return 0;
-	return hp->func_table->check(hp->func_data) != 0;
-}
-
-#define BUFSIZE 500
-
-
-void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw)
-{
-	struct pvr2_i2c_client *cp;
-	mutex_lock(&hdw->i2c_list_lock); do {
-		struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
-		memset(vtp,0,sizeof(*vtp));
-		list_for_each_entry(cp, &hdw->i2c_clients, list) {
-			if (!cp->detected_flag) continue;
-			if (!cp->status_poll) continue;
-			cp->status_poll(cp);
-		}
-		hdw->tuner_signal_stale = 0;
-		pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll"
-			   " type=%u strength=%u audio=0x%x cap=0x%x"
-			   " low=%u hi=%u",
-			   vtp->type,
-			   vtp->signal,vtp->rxsubchans,vtp->capability,
-			   vtp->rangelow,vtp->rangehigh);
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
-}
-
-
-/* Issue various I2C operations to bring chip-level drivers into sync with
-   state stored in this driver. */
-void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
-{
-	unsigned long msk;
-	unsigned int idx;
-	struct pvr2_i2c_client *cp, *ncp;
-
-	if (!hdw->i2c_linked) return;
-	if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
-		return;
-	}
-	mutex_lock(&hdw->i2c_list_lock); do {
-		pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN");
-		if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) {
-			/* One or more I2C clients have attached since we
-			   last synced.  So scan the list and identify the
-			   new clients. */
-			char *buf;
-			unsigned int cnt;
-			unsigned long amask = 0;
-			buf = kmalloc(BUFSIZE,GFP_KERNEL);
-			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
-			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
-			list_for_each_entry(cp, &hdw->i2c_clients, list) {
-				if (!cp->detected_flag) {
-					cp->ctl_mask = 0;
-					pvr2_i2c_probe(hdw,cp);
-					cp->detected_flag = !0;
-					msk = cp->ctl_mask;
-					cnt = 0;
-					if (buf) {
-						cnt = pvr2_i2c_client_describe(
-							cp,
-							PVR2_I2C_DETAIL_ALL,
-							buf,BUFSIZE);
-					}
-					trace_i2c("Probed: %.*s",cnt,buf);
-					if (handler_check(cp)) {
-						hdw->i2c_pend_types |=
-							PVR2_I2C_PEND_CLIENT;
-					}
-					cp->pend_mask = msk;
-					hdw->i2c_pend_mask |= msk;
-					hdw->i2c_pend_types |=
-						PVR2_I2C_PEND_REFRESH;
-				}
-				amask |= cp->ctl_mask;
-			}
-			hdw->i2c_active_mask = amask;
-			if (buf) kfree(buf);
-		}
-		if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) {
-			/* Need to do one or more global updates.  Arrange
-			   for this to happen. */
-			unsigned long m2;
-			pvr2_trace(PVR2_TRACE_I2C_CORE,
-				   "i2c: PEND_STALE (0x%lx)",
-				   hdw->i2c_stale_mask);
-			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
-			list_for_each_entry(cp, &hdw->i2c_clients, list) {
-				m2 = hdw->i2c_stale_mask;
-				m2 &= cp->ctl_mask;
-				m2 &= ~cp->pend_mask;
-				if (m2) {
-					pvr2_trace(PVR2_TRACE_I2C_CORE,
-						   "i2c: cp=%p setting 0x%lx",
-						   cp,m2);
-					cp->pend_mask |= m2;
-				}
-			}
-			hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
-			hdw->i2c_stale_mask = 0;
-			hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH;
-		}
-		if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) {
-			/* One or more client handlers are asking for an
-			   update.  Run through the list of known clients
-			   and update each one. */
-			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
-			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
-			list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients,
-						 list) {
-				if (!cp->handler) continue;
-				if (!cp->handler->func_table->update) continue;
-				pvr2_trace(PVR2_TRACE_I2C_CORE,
-					   "i2c: cp=%p update",cp);
-				mutex_unlock(&hdw->i2c_list_lock);
-				cp->handler->func_table->update(
-					cp->handler->func_data);
-				mutex_lock(&hdw->i2c_list_lock);
-				/* If client's update function set some
-				   additional pending bits, account for that
-				   here. */
-				if (cp->pend_mask & ~hdw->i2c_pend_mask) {
-					hdw->i2c_pend_mask |= cp->pend_mask;
-					hdw->i2c_pend_types |=
-						PVR2_I2C_PEND_REFRESH;
-				}
-			}
-		}
-		if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) {
-			const struct pvr2_i2c_op *opf;
-			unsigned long pm;
-			/* Some actual updates are pending.  Walk through
-			   each update type and perform it. */
-			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH"
-				   " (0x%lx)",hdw->i2c_pend_mask);
-			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH;
-			pm = hdw->i2c_pend_mask;
-			hdw->i2c_pend_mask = 0;
-			for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
-				if (!(pm & msk)) continue;
-				pm &= ~msk;
-				list_for_each_entry(cp, &hdw->i2c_clients,
-						    list) {
-					if (cp->pend_mask & msk) {
-						cp->pend_mask &= ~msk;
-						cp->recv_enable = !0;
-					} else {
-						cp->recv_enable = 0;
-					}
-				}
-				opf = pvr2_i2c_get_op(idx);
-				if (!opf) continue;
-				mutex_unlock(&hdw->i2c_list_lock);
-				opf->update(hdw);
-				mutex_lock(&hdw->i2c_list_lock);
-			}
-		}
-		pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END");
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
-}
-
-int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
-{
-	unsigned long msk,sm,pm;
-	unsigned int idx;
-	const struct pvr2_i2c_op *opf;
-	struct pvr2_i2c_client *cp;
-	unsigned int pt = 0;
-
-	pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN");
-
-	pm = hdw->i2c_active_mask;
-	sm = 0;
-	for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
-		if (!(msk & pm)) continue;
-		pm &= ~msk;
-		opf = pvr2_i2c_get_op(idx);
-		if (!opf) continue;
-		if (opf->check(hdw)) {
-			sm |= msk;
-		}
-	}
-	if (sm) pt |= PVR2_I2C_PEND_STALE;
-
-	list_for_each_entry(cp, &hdw->i2c_clients, list)
-		if (handler_check(cp))
-			pt |= PVR2_I2C_PEND_CLIENT;
-
-	if (pt) {
-		mutex_lock(&hdw->i2c_list_lock); do {
-			hdw->i2c_pend_types |= pt;
-			hdw->i2c_stale_mask |= sm;
-			hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
-		} while (0); mutex_unlock(&hdw->i2c_list_lock);
-	}
-
-	pvr2_trace(PVR2_TRACE_I2C_CORE,
-		   "i2c: types=0x%x stale=0x%lx pend=0x%lx",
-		   hdw->i2c_pend_types,
-		   hdw->i2c_stale_mask,
-		   hdw->i2c_pend_mask);
-	pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END");
-
-	return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
-}
-
-static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
-					     unsigned int detail,
-					     char *buf,unsigned int maxlen)
-{
-	unsigned int ccnt,bcnt;
-	int spcfl = 0;
-	const struct pvr2_i2c_op *opf;
-
-	ccnt = 0;
-	if (detail & PVR2_I2C_DETAIL_DEBUG) {
-		bcnt = scnprintf(buf,maxlen,
-				 "ctxt=%p ctl_mask=0x%lx",
-				 cp,cp->ctl_mask);
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		spcfl = !0;
-	}
-	bcnt = scnprintf(buf,maxlen,
-			 "%s%s @ 0x%x",
-			 (spcfl ? " " : ""),
-			 cp->client->name,
-			 cp->client->addr);
-	ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-	if ((detail & PVR2_I2C_DETAIL_HANDLER) &&
-	    cp->handler && cp->handler->func_table->describe) {
-		bcnt = scnprintf(buf,maxlen," (");
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		bcnt = cp->handler->func_table->describe(
-			cp->handler->func_data,buf,maxlen);
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		bcnt = scnprintf(buf,maxlen,")");
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-	}
-	if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
-		unsigned int idx;
-		unsigned long msk,sm;
-
-		bcnt = scnprintf(buf,maxlen," [");
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		sm = 0;
-		spcfl = 0;
-		for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
-			if (!(cp->ctl_mask & msk)) continue;
-			opf = pvr2_i2c_get_op(idx);
-			if (opf) {
-				bcnt = scnprintf(buf,maxlen,"%s%s",
-						 spcfl ? " " : "",
-						 opf->name);
-				ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-				spcfl = !0;
-			} else {
-				sm |= msk;
-			}
-		}
-		if (sm) {
-			bcnt = scnprintf(buf,maxlen,"%s%lx",
-					 idx != 0 ? " " : "",sm);
-			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		}
-		bcnt = scnprintf(buf,maxlen,"]");
-		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-	}
-	return ccnt;
-}
-
-unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
-			     char *buf,unsigned int maxlen)
-{
-	unsigned int ccnt,bcnt;
-	struct pvr2_i2c_client *cp;
-	ccnt = 0;
-	mutex_lock(&hdw->i2c_list_lock); do {
-		list_for_each_entry(cp, &hdw->i2c_clients, list) {
-			bcnt = pvr2_i2c_client_describe(
-				cp,
-				(PVR2_I2C_DETAIL_HANDLER|
-				 PVR2_I2C_DETAIL_CTLMASK),
-				buf,maxlen);
-			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-			bcnt = scnprintf(buf,maxlen,"\n");
-			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
-		}
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
-	return ccnt;
-}
-
 static int pvr2_i2c_attach_inform(struct i2c_client *client)
 {
-	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
-	struct pvr2_i2c_client *cp;
-	int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
-	cp = kzalloc(sizeof(*cp),GFP_KERNEL);
-	trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
-		  client->name,
-		  client->addr,cp);
-	if (!cp) return -ENOMEM;
-	cp->hdw = hdw;
-	INIT_LIST_HEAD(&cp->list);
-	cp->client = client;
-	mutex_lock(&hdw->i2c_list_lock); do {
-		hdw->cropcap_stale = !0;
-		list_add_tail(&cp->list,&hdw->i2c_clients);
-		hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
-	if (fl) queue_work(hdw->workqueue,&hdw->worki2csync);
 	return 0;
 }
 
 static int pvr2_i2c_detach_inform(struct i2c_client *client)
 {
-	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
-	struct pvr2_i2c_client *cp, *ncp;
-	unsigned long amask = 0;
-	int foundfl = 0;
-	mutex_lock(&hdw->i2c_list_lock); do {
-		hdw->cropcap_stale = !0;
-		list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
-			if (cp->client == client) {
-				trace_i2c("pvr2_i2c_detach"
-					  " [client=%s @ 0x%x ctxt=%p]",
-					  client->name,
-					  client->addr,cp);
-				if (cp->handler &&
-				    cp->handler->func_table->detach) {
-					cp->handler->func_table->detach(
-						cp->handler->func_data);
-				}
-				list_del(&cp->list);
-				kfree(cp);
-				foundfl = !0;
-				continue;
-			}
-			amask |= cp->ctl_mask;
-		}
-		hdw->i2c_active_mask = amask;
-	} while (0); mutex_unlock(&hdw->i2c_list_lock);
-	if (!foundfl) {
-		trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
-			  client->name,
-			  client->addr);
-	}
 	return 0;
 }
 
@@ -942,7 +537,7 @@
 
 static struct i2c_adapter pvr2_i2c_adap_template = {
 	.owner         = THIS_MODULE,
-	.class	   = I2C_CLASS_TV_ANALOG,
+	.class	       = 0,
 	.id            = I2C_HW_B_BT848,
 	.client_register = pvr2_i2c_attach_inform,
 	.client_unregister = pvr2_i2c_detach_inform,
@@ -1009,12 +604,8 @@
 	hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
 	hdw->i2c_adap.algo = &hdw->i2c_algo;
 	hdw->i2c_adap.algo_data = hdw;
-	hdw->i2c_pend_mask = 0;
-	hdw->i2c_stale_mask = 0;
-	hdw->i2c_active_mask = 0;
-	INIT_LIST_HEAD(&hdw->i2c_clients);
-	mutex_init(&hdw->i2c_list_lock);
 	hdw->i2c_linked = !0;
+	i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
 	i2c_add_adapter(&hdw->i2c_adap);
 	if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
 		/* Probe for a different type of IR receiver on this
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index 6ef7a1c..6a75769 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -20,68 +20,13 @@
 #ifndef __PVRUSB2_I2C_CORE_H
 #define __PVRUSB2_I2C_CORE_H
 
-#include <linux/list.h>
-#include <linux/i2c.h>
-
 struct pvr2_hdw;
-struct pvr2_i2c_client;
-struct pvr2_i2c_handler;
-struct pvr2_i2c_handler_functions;
-struct pvr2_i2c_op;
-struct pvr2_i2c_op_functions;
-
-struct pvr2_i2c_client {
-	struct i2c_client *client;
-	struct pvr2_i2c_handler *handler;
-	struct list_head list;
-	struct pvr2_hdw *hdw;
-	int detected_flag;
-	int recv_enable;
-	unsigned long pend_mask;
-	unsigned long ctl_mask;
-	void (*status_poll)(struct pvr2_i2c_client *);
-};
-
-struct pvr2_i2c_handler {
-	void *func_data;
-	const struct pvr2_i2c_handler_functions *func_table;
-};
-
-struct pvr2_i2c_handler_functions {
-	void (*detach)(void *);
-	int (*check)(void *);
-	void (*update)(void *);
-	unsigned int (*describe)(void *,char *,unsigned int);
-};
-
-struct pvr2_i2c_op {
-	int (*check)(struct pvr2_hdw *);
-	void (*update)(struct pvr2_hdw *);
-	const char *name;
-};
 
 void pvr2_i2c_core_init(struct pvr2_hdw *);
 void pvr2_i2c_core_done(struct pvr2_hdw *);
 
-int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg);
-int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
 
-int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
-void pvr2_i2c_core_sync(struct pvr2_hdw *);
-void pvr2_i2c_core_status_poll(struct pvr2_hdw *);
-unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
-#define PVR2_I2C_DETAIL_DEBUG   0x0001
-#define PVR2_I2C_DETAIL_HANDLER 0x0002
-#define PVR2_I2C_DETAIL_CTLMASK 0x0004
-#define PVR2_I2C_DETAIL_ALL (\
-	PVR2_I2C_DETAIL_DEBUG |\
-	PVR2_I2C_DETAIL_HANDLER |\
-	PVR2_I2C_DETAIL_CTLMASK)
-
-void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
-const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
-
-#endif /* __PVRUSB2_I2C_CORE_H */
+#endif /* __PVRUSB2_I2C_ADAPTER_H */
 
 
 /*
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index 9b3c874..8689ddb 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -137,10 +137,10 @@
 	ret = usb_register(&pvr_driver);
 
 	if (ret == 0)
-		printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+		printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":"
 		       DRIVER_DESC "\n");
 	if (pvrusb2_debug)
-		printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n",
+		printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n",
 		       pvrusb2_debug,pvrusb2_debug);
 
 	pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index e641cd9..e20ba1e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -627,16 +627,8 @@
 	pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
 
 	class_dev->class = &class_ptr->class;
-	if (pvr2_hdw_get_sn(sfp->channel.hdw)) {
-		dev_set_name(class_dev, "sn-%lu",
-			 pvr2_hdw_get_sn(sfp->channel.hdw));
-	} else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) {
-		dev_set_name(class_dev, "unit-%c",
-			 pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a');
-	} else {
-		kfree(class_dev);
-		return;
-	}
+	dev_set_name(class_dev, "%s",
+		     pvr2_hdw_get_device_identifier(sfp->channel.hdw));
 
 	class_dev->parent = &usb_dev->dev;
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
deleted file mode 100644
index 07775d1..0000000
--- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public 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 "pvrusb2.h"
-#include "pvrusb2-util.h"
-#include "pvrusb2-tuner.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-
-struct pvr2_tuner_handler {
-	struct pvr2_hdw *hdw;
-	struct pvr2_i2c_client *client;
-	struct pvr2_i2c_handler i2c_handler;
-	int type_update_fl;
-};
-
-
-static void set_type(struct pvr2_tuner_handler *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	struct tuner_setup setup;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type);
-	if (((int)(hdw->tuner_type)) < 0) return;
-
-	setup.addr = ADDR_UNSET;
-	setup.type = hdw->tuner_type;
-	setup.mode_mask = T_RADIO | T_ANALOG_TV;
-	/* We may really want mode_mask to be T_ANALOG_TV for now */
-	pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup);
-	ctxt->type_update_fl = 0;
-}
-
-
-static int tuner_check(struct pvr2_tuner_handler *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	if (hdw->tuner_updated) ctxt->type_update_fl = !0;
-	return ctxt->type_update_fl != 0;
-}
-
-
-static void tuner_update(struct pvr2_tuner_handler *ctxt)
-{
-	if (ctxt->type_update_fl) set_type(ctxt);
-}
-
-
-static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt)
-{
-	ctxt->client->handler = NULL;
-	kfree(ctxt);
-}
-
-
-static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt)
-{
-	return scnprintf(buf,cnt,"handler: pvrusb2-tuner");
-}
-
-
-static const struct pvr2_i2c_handler_functions tuner_funcs = {
-	.detach = (void (*)(void *))pvr2_tuner_detach,
-	.check = (int (*)(void *))tuner_check,
-	.update = (void (*)(void *))tuner_update,
-	.describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe,
-};
-
-
-int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
-	struct pvr2_tuner_handler *ctxt;
-	if (cp->handler) return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
-	if (!ctxt) return 0;
-
-	ctxt->i2c_handler.func_data = ctxt;
-	ctxt->i2c_handler.func_table = &tuner_funcs;
-	ctxt->type_update_fl = !0;
-	ctxt->client = cp;
-	ctxt->hdw = hdw;
-	cp->handler = &ctxt->i2c_handler;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up",
-		   cp->client->addr);
-	return !0;
-}
-
-
-
-
-/*
-  Stuff for Emacs to see, in order to encourage consistent editing style:
-  *** Local Variables: ***
-  *** mode: c ***
-  *** fill-column: 70 ***
-  *** tab-width: 8 ***
-  *** c-basic-offset: 8 ***
-  *** End: ***
-  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 878fd52..9e0f2b0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -91,7 +91,7 @@
 	.card           = "Hauppauge WinTV pvr-usb2",
 	.bus_info       = "usb",
 	.version        = KERNEL_VERSION(0,8,0),
-	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
 			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
 			   V4L2_CAP_READWRITE),
 	.reserved       = {0,0,0,0}
@@ -952,10 +952,6 @@
 			   unsigned int cmd, unsigned long arg)
 {
 
-/* Temporary hack : use ivtv api until a v4l2 one is available. */
-#define IVTV_IOC_G_CODEC        0xFFEE7703
-#define IVTV_IOC_S_CODEC        0xFFEE7704
-	if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
 	return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
 }
 
@@ -1268,8 +1264,9 @@
 		dip->minor_type = pvr2_v4l_type_video;
 		nr_ptr = video_nr;
 		if (!dip->stream) {
-			err("Failed to set up pvrusb2 v4l video dev"
-			    " due to missing stream instance");
+			pr_err(KBUILD_MODNAME
+				": Failed to set up pvrusb2 v4l video dev"
+				" due to missing stream instance\n");
 			return;
 		}
 		break;
@@ -1286,8 +1283,8 @@
 		break;
 	default:
 		/* Bail out (this should be impossible) */
-		err("Failed to set up pvrusb2 v4l dev"
-		    " due to unrecognized config");
+		pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
+		    " due to unrecognized config\n");
 		return;
 	}
 
@@ -1303,7 +1300,8 @@
 				   dip->v4l_type, mindevnum) < 0) &&
 	    (video_register_device(&dip->devbase,
 				   dip->v4l_type, -1) < 0)) {
-		err("Failed to register pvrusb2 v4l device");
+		pr_err(KBUILD_MODNAME
+			": Failed to register pvrusb2 v4l device\n");
 	}
 
 	printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index 4059648..b3862f5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -28,7 +28,7 @@
 */
 
 #include "pvrusb2-video-v4l.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
+
 
 
 #include "pvrusb2-hdw-internal.h"
@@ -39,15 +39,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-struct pvr2_v4l_decoder {
-	struct pvr2_i2c_handler handler;
-	struct pvr2_decoder_ctrl ctrl;
-	struct pvr2_i2c_client *client;
-	struct pvr2_hdw *hdw;
-	unsigned long stale_mask;
-};
-
-
 struct routing_scheme {
 	const int *def;
 	unsigned int cnt;
@@ -63,190 +54,51 @@
 	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2,
 };
 
+static const int routing_scheme1[] = {
+	[PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
+	[PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
+	[PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3,
+	[PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
+};
+
 static const struct routing_scheme routing_schemes[] = {
 	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = {
 		.def = routing_scheme0,
 		.cnt = ARRAY_SIZE(routing_scheme0),
 	},
+	[PVR2_ROUTING_SCHEME_ONAIR] = {
+		.def = routing_scheme1,
+		.cnt = ARRAY_SIZE(routing_scheme1),
+	},
 };
 
-static void set_input(struct pvr2_v4l_decoder *ctxt)
+void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 {
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	struct v4l2_routing route;
-	const struct routing_scheme *sp;
-	unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
-
-	if ((sid < ARRAY_SIZE(routing_schemes)) &&
-	    ((sp = routing_schemes + sid) != NULL) &&
-	    (hdw->input_val >= 0) &&
-	    (hdw->input_val < sp->cnt)) {
-		route.input = sp->def[hdw->input_val];
-	} else {
-		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "*** WARNING *** i2c v4l2 set_input:"
-			   " Invalid routing scheme (%u) and/or input (%d)",
-			   sid,hdw->input_val);
-		return;
-	}
-
-	route.output = 0;
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
-}
-
-
-static int check_input(struct pvr2_v4l_decoder *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->input_dirty != 0;
-}
-
-
-static void set_audio(struct pvr2_v4l_decoder *ctxt)
-{
-	u32 val;
-	struct pvr2_hdw *hdw = ctxt->hdw;
-
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d",
-		   hdw->srate_val);
-	switch (hdw->srate_val) {
-	default:
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
-		val = 48000;
-		break;
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
-		val = 44100;
-		break;
-	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
-		val = 32000;
-		break;
-	}
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
-}
-
-
-static int check_audio(struct pvr2_v4l_decoder *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->srate_dirty != 0;
-}
-
-
-struct pvr2_v4l_decoder_ops {
-	void (*update)(struct pvr2_v4l_decoder *);
-	int (*check)(struct pvr2_v4l_decoder *);
-};
-
-
-static const struct pvr2_v4l_decoder_ops decoder_ops[] = {
-	{ .update = set_input, .check = check_input},
-	{ .update = set_audio, .check = check_audio},
-};
-
-
-static void decoder_detach(struct pvr2_v4l_decoder *ctxt)
-{
-	ctxt->client->handler = NULL;
-	pvr2_hdw_set_decoder(ctxt->hdw,NULL);
-	kfree(ctxt);
-}
-
-
-static int decoder_check(struct pvr2_v4l_decoder *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
-		msk = 1 << idx;
-		if (ctxt->stale_mask & msk) continue;
-		if (decoder_ops[idx].check(ctxt)) {
-			ctxt->stale_mask |= msk;
+	if (hdw->input_dirty || hdw->force_dirty) {
+		struct v4l2_routing route;
+		const struct routing_scheme *sp;
+		unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+			   hdw->input_val);
+		if ((sid < ARRAY_SIZE(routing_schemes)) &&
+		    ((sp = routing_schemes + sid) != NULL) &&
+		    (hdw->input_val >= 0) &&
+		    (hdw->input_val < sp->cnt)) {
+			route.input = sp->def[hdw->input_val];
+		} else {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "*** WARNING *** subdev v4l2 set_input:"
+				   " Invalid routing scheme (%u)"
+				   " and/or input (%d)",
+				   sid, hdw->input_val);
+			return;
 		}
-	}
-	return ctxt->stale_mask != 0;
-}
-
-
-static void decoder_update(struct pvr2_v4l_decoder *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) {
-		msk = 1 << idx;
-		if (!(ctxt->stale_mask & msk)) continue;
-		ctxt->stale_mask &= ~msk;
-		decoder_ops[idx].update(ctxt);
+		route.output = 0;
+		sd->ops->video->s_routing(sd, &route);
 	}
 }
 
 
-static int decoder_detect(struct pvr2_i2c_client *cp)
-{
-	/* Attempt to query the decoder - let's see if it will answer */
-	struct v4l2_tuner vt;
-	int ret;
-
-	memset(&vt,0,sizeof(vt));
-	ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt);
-	return ret == 0; /* Return true if it answered */
-}
-
-
-static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl)
-{
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl);
-	pvr2_v4l2_cmd_stream(ctxt->client,fl);
-}
-
-
-static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
-{
-	return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
-}
-
-
-static const struct pvr2_i2c_handler_functions hfuncs = {
-	.detach = (void (*)(void *))decoder_detach,
-	.check = (int (*)(void *))decoder_check,
-	.update = (void (*)(void *))decoder_update,
-	.describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
-};
-
-
-int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
-			       struct pvr2_i2c_client *cp)
-{
-	struct pvr2_v4l_decoder *ctxt;
-
-	if (hdw->decoder_ctrl) return 0;
-	if (cp->handler) return 0;
-	if (!decoder_detect(cp)) return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
-	if (!ctxt) return 0;
-
-	ctxt->handler.func_data = ctxt;
-	ctxt->handler.func_table = &hfuncs;
-	ctxt->ctrl.ctxt = ctxt;
-	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
-	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
-	ctxt->client = cp;
-	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1;
-	pvr2_hdw_set_decoder(hdw,&ctxt->ctrl);
-	cp->handler = &ctxt->handler;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
-		   cp->client->addr);
-	return !0;
-}
-
-
-
-
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
   *** Local Variables: ***
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
index 4ff5b89..3b0bd5d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
@@ -32,11 +32,8 @@
 */
 
 
-
-#include "pvrusb2-i2c-core.h"
-
-int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
-
+#include "pvrusb2-hdw-internal.h"
+void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *);
 
 #endif /* __PVRUSB2_VIDEO_V4L_H */
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index f6fcf0a..1670aa4 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -27,7 +27,6 @@
 */
 
 #include "pvrusb2-wm8775.h"
-#include "pvrusb2-i2c-cmd-v4l2.h"
 
 
 #include "pvrusb2-hdw-internal.h"
@@ -37,128 +36,31 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-struct pvr2_v4l_wm8775 {
-	struct pvr2_i2c_handler handler;
-	struct pvr2_i2c_client *client;
-	struct pvr2_hdw *hdw;
-	unsigned long stale_mask;
-};
-
-
-static void set_input(struct pvr2_v4l_wm8775 *ctxt)
+void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
 {
-	struct v4l2_routing route;
-	struct pvr2_hdw *hdw = ctxt->hdw;
+	if (hdw->input_dirty || hdw->force_dirty) {
+		struct v4l2_routing route;
 
-	memset(&route,0,sizeof(route));
+		memset(&route, 0, sizeof(route));
 
-	switch(hdw->input_val) {
-	case PVR2_CVAL_INPUT_RADIO:
-		route.input = 1;
-		break;
-	default:
-		/* All other cases just use the second input */
-		route.input = 2;
-		break;
-	}
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)",
-		   hdw->input_val,route.input);
-
-	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
-}
-
-static int check_input(struct pvr2_v4l_wm8775 *ctxt)
-{
-	struct pvr2_hdw *hdw = ctxt->hdw;
-	return hdw->input_dirty != 0;
-}
-
-
-struct pvr2_v4l_wm8775_ops {
-	void (*update)(struct pvr2_v4l_wm8775 *);
-	int (*check)(struct pvr2_v4l_wm8775 *);
-};
-
-
-static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = {
-	{ .update = set_input, .check = check_input},
-};
-
-
-static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt,
-				     char *buf,unsigned int cnt)
-{
-	return scnprintf(buf,cnt,"handler: pvrusb2-wm8775");
-}
-
-
-static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt)
-{
-	ctxt->client->handler = NULL;
-	kfree(ctxt);
-}
-
-
-static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
-		msk = 1 << idx;
-		if (ctxt->stale_mask & msk) continue;
-		if (wm8775_ops[idx].check(ctxt)) {
-			ctxt->stale_mask |= msk;
+		switch (hdw->input_val) {
+		case PVR2_CVAL_INPUT_RADIO:
+			route.input = 1;
+			break;
+		default:
+			/* All other cases just use the second input */
+			route.input = 2;
+			break;
 		}
-	}
-	return ctxt->stale_mask != 0;
-}
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775"
+			   " set_input(val=%d route=0x%x)",
+			   hdw->input_val, route.input);
 
-
-static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
-{
-	unsigned long msk;
-	unsigned int idx;
-
-	for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) {
-		msk = 1 << idx;
-		if (!(ctxt->stale_mask & msk)) continue;
-		ctxt->stale_mask &= ~msk;
-		wm8775_ops[idx].update(ctxt);
+		sd->ops->audio->s_routing(sd, &route);
 	}
 }
 
 
-static const struct pvr2_i2c_handler_functions hfuncs = {
-	.detach = (void (*)(void *))wm8775_detach,
-	.check = (int (*)(void *))wm8775_check,
-	.update = (void (*)(void *))wm8775_update,
-	.describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe,
-};
-
-
-int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
-{
-	struct pvr2_v4l_wm8775 *ctxt;
-
-	if (cp->handler) return 0;
-
-	ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL);
-	if (!ctxt) return 0;
-
-	ctxt->handler.func_data = ctxt;
-	ctxt->handler.func_table = &hfuncs;
-	ctxt->client = cp;
-	ctxt->hdw = hdw;
-	ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1;
-	cp->handler = &ctxt->handler;
-	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
-		   cp->client->addr);
-	return !0;
-}
-
-
-
 
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
index 8070909..0577bc7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
@@ -34,9 +34,9 @@
 
 
 
-#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
 
-int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd);
 
 
 #endif /* __PVRUSB2_WM8775_H */
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
index 7298cf2..8b9f0aa 100644
--- a/drivers/media/video/pwc/Kconfig
+++ b/drivers/media/video/pwc/Kconfig
@@ -35,3 +35,13 @@
 	  Say Y here in order to have the pwc driver generate verbose debugging
 	  messages.
 	  A special module options 'trace' is used to control the verbosity.
+
+config USB_PWC_INPUT_EVDEV
+	bool "USB Philips Cameras input events device support"
+	default y
+	depends on USB_PWC && INPUT
+	---help---
+	  This option makes USB Philips cameras register the snapshot button as
+	  an input device to report button events.
+
+	  If you are in doubt, say Y.
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 0d81018..7c542ca 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -53,6 +53,7 @@
    - Xavier Roche: QuickCam Pro 4000 ID
    - Jens Knudsen: QuickCam Zoom ID
    - J. Debert: QuickCam for Notebooks ID
+   - Pham Thanh Nam: webcam snapshot button as an event input device
 */
 
 #include <linux/errno.h>
@@ -61,6 +62,9 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/usb/input.h>
+#endif
 #include <linux/vmalloc.h>
 #include <asm/io.h>
 
@@ -586,6 +590,23 @@
 				pdev->vframe_count);
 }
 
+static void pwc_snapshot_button(struct pwc_device *pdev, int down)
+{
+	if (down) {
+		PWC_TRACE("Snapshot button pressed.\n");
+		pdev->snapshot_button_status = 1;
+	} else {
+		PWC_TRACE("Snapshot button released.\n");
+	}
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+	if (pdev->button_dev) {
+		input_report_key(pdev->button_dev, BTN_0, down);
+		input_sync(pdev->button_dev);
+	}
+#endif
+}
+
 static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
 {
 	int awake = 0;
@@ -603,13 +624,7 @@
 			pdev->vframes_error++;
 		}
 		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-			if (ptr[0] & 0x01) {
-				pdev->snapshot_button_status = 1;
-				PWC_TRACE("Snapshot button pressed.\n");
-			}
-			else {
-				PWC_TRACE("Snapshot button released.\n");
-			}
+			pwc_snapshot_button(pdev, ptr[0] & 0x01);
 		}
 		if ((ptr[0] ^ pdev->vmirror) & 0x02) {
 			if (ptr[0] & 0x02)
@@ -633,12 +648,7 @@
 	else if (pdev->type == 740 || pdev->type == 720) {
 		unsigned char *ptr = (unsigned char *)fbuf->data;
 		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-			if (ptr[0] & 0x01) {
-				pdev->snapshot_button_status = 1;
-				PWC_TRACE("Snapshot button pressed.\n");
-			}
-			else
-				PWC_TRACE("Snapshot button released.\n");
+			pwc_snapshot_button(pdev, ptr[0] & 0x01);
 		}
 		pdev->vmirror = ptr[0] & 0x03;
 	}
@@ -1115,6 +1125,7 @@
 	}
 
 	mutex_lock(&pdev->modlock);
+	pwc_construct(pdev); /* set min/max sizes correct */
 	if (!pdev->usb_init) {
 		PWC_DEBUG_OPEN("Doing first time initialization.\n");
 		pdev->usb_init = 1;
@@ -1139,7 +1150,6 @@
 	if (pwc_set_leds(pdev, led_on, led_off) < 0)
 		PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
 
-	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* So far, so good. Allocate memory. */
 	i = pwc_allocate_buffers(pdev);
@@ -1216,6 +1226,15 @@
 {
 	pwc_remove_sysfs_files(pdev->vdev);
 	video_unregister_device(pdev->vdev);
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+	if (pdev->button_dev) {
+		input_unregister_device(pdev->button_dev);
+		input_free_device(pdev->button_dev);
+		kfree(pdev->button_dev->phys);
+		pdev->button_dev = NULL;
+	}
+#endif
 }
 
 /* Note that all cleanup is done in the reverse order as in _open */
@@ -1483,6 +1502,9 @@
 	int features = 0;
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+	char *phys = NULL;
+#endif
 
 	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
 	product_id = le16_to_cpu(udev->descriptor.idProduct);
@@ -1807,6 +1829,35 @@
 	pwc_set_leds(pdev, 0, 0);
 	pwc_camera_power(pdev, 0);
 
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+	/* register webcam snapshot button input device */
+	pdev->button_dev = input_allocate_device();
+	if (!pdev->button_dev) {
+		PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
+		return -ENOMEM;
+	}
+
+	pdev->button_dev->name = "PWC snapshot button";
+	phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath);
+	if (!phys) {
+		input_free_device(pdev->button_dev);
+		return -ENOMEM;
+	}
+	pdev->button_dev->phys = phys;
+	usb_to_input_id(pdev->udev, &pdev->button_dev->id);
+	pdev->button_dev->dev.parent = &pdev->udev->dev;
+	pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
+	pdev->button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+
+	rc = input_register_device(pdev->button_dev);
+	if (rc) {
+		input_free_device(pdev->button_dev);
+		kfree(pdev->button_dev->phys);
+		pdev->button_dev = NULL;
+		return rc;
+	}
+#endif
+
 	return 0;
 
 err_unreg:
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 01411fb..0be6f81 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -37,6 +37,9 @@
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/input.h>
+#endif
 
 #include "pwc-uncompress.h"
 #include <media/pwc-ioctl.h>
@@ -255,6 +258,9 @@
    int pan_angle;			/* in degrees * 100 */
    int tilt_angle;			/* absolute angle; 0,0 is home position */
    int snapshot_button_status;		/* set to 1 when the user push the button, reset to 0 when this value is read */
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+   struct input_dev *button_dev;	/* webcam snapshot button input */
+#endif
 
    /*** Misc. data ***/
    wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 07c334f..c522616 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -35,7 +35,6 @@
 #include <linux/videodev2.h>
 
 #include <mach/dma.h>
-#include <mach/pxa-regs.h>
 #include <mach/camera.h>
 
 #define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
@@ -879,6 +878,7 @@
 		SOCAM_HSYNC_ACTIVE_LOW |
 		SOCAM_VSYNC_ACTIVE_HIGH |
 		SOCAM_VSYNC_ACTIVE_LOW |
+		SOCAM_DATA_ACTIVE_HIGH |
 		SOCAM_PCLK_SAMPLE_RISING |
 		SOCAM_PCLK_SAMPLE_FALLING;
 
@@ -1150,46 +1150,28 @@
 	return formats;
 }
 
-static int pxa_camera_set_fmt(struct soc_camera_device *icd,
-			      __u32 pixfmt, struct v4l2_rect *rect)
+static int pxa_camera_set_crop(struct soc_camera_device *icd,
+			       struct v4l2_rect *rect)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
-	const struct soc_camera_data_format *cam_fmt = NULL;
-	const struct soc_camera_format_xlate *xlate = NULL;
 	struct soc_camera_sense sense = {
 		.master_clock = pcdev->mclk,
 		.pixel_clock_max = pcdev->ciclk / 4,
 	};
 	int ret;
 
-	if (pixfmt) {
-		xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
-		if (!xlate) {
-			dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
-			return -EINVAL;
-		}
-
-		cam_fmt = xlate->cam_fmt;
-	}
-
 	/* If PCLK is used to latch data from the sensor, check sense */
 	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
 		icd->sense = &sense;
 
-	switch (pixfmt) {
-	case 0:				/* Only geometry change */
-		ret = icd->ops->set_fmt(icd, pixfmt, rect);
-		break;
-	default:
-		ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect);
-	}
+	ret = icd->ops->set_crop(icd, rect);
 
 	icd->sense = NULL;
 
 	if (ret < 0) {
-		dev_warn(&ici->dev, "Failed to configure for format %x\n",
-			 pixfmt);
+		dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n",
+			 rect->width, rect->height, rect->left, rect->top);
 	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
 		if (sense.pixel_clock > sense.pixel_clock_max) {
 			dev_err(&ici->dev,
@@ -1200,7 +1182,55 @@
 		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
 	}
 
-	if (pixfmt && !ret) {
+	return ret;
+}
+
+static int pxa_camera_set_fmt(struct soc_camera_device *icd,
+			      struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct pxa_camera_dev *pcdev = ici->priv;
+	const struct soc_camera_data_format *cam_fmt = NULL;
+	const struct soc_camera_format_xlate *xlate = NULL;
+	struct soc_camera_sense sense = {
+		.master_clock = pcdev->mclk,
+		.pixel_clock_max = pcdev->ciclk / 4,
+	};
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_format cam_f = *f;
+	int ret;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+	if (!xlate) {
+		dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+		return -EINVAL;
+	}
+
+	cam_fmt = xlate->cam_fmt;
+
+	/* If PCLK is used to latch data from the sensor, check sense */
+	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+		icd->sense = &sense;
+
+	cam_f.fmt.pix.pixelformat = cam_fmt->fourcc;
+	ret = icd->ops->set_fmt(icd, &cam_f);
+
+	icd->sense = NULL;
+
+	if (ret < 0) {
+		dev_warn(&ici->dev, "Failed to configure for format %x\n",
+			 pix->pixelformat);
+	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
+		if (sense.pixel_clock > sense.pixel_clock_max) {
+			dev_err(&ici->dev,
+				"pixel clock %lu set by the camera too high!",
+				sense.pixel_clock);
+			return -EIO;
+		}
+		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
+	}
+
+	if (!ret) {
 		icd->buswidth = xlate->buswidth;
 		icd->current_fmt = xlate->host_fmt;
 	}
@@ -1364,6 +1394,7 @@
 	.remove		= pxa_camera_remove_device,
 	.suspend	= pxa_camera_suspend,
 	.resume		= pxa_camera_resume,
+	.set_crop	= pxa_camera_set_crop,
 	.get_formats	= pxa_camera_get_formats,
 	.set_fmt	= pxa_camera_set_fmt,
 	.try_fmt	= pxa_camera_try_fmt,
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 13f85ad..b5be633 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -336,14 +336,19 @@
 			     u16 index, u16 value, void *buf,
 			     s32 buf_len, int bOut);
 
+/* dev_err macro with driver name */
+#define S2255_DRIVER_NAME "s2255"
+#define s2255_dev_err(dev, fmt, arg...)					\
+		dev_err(dev, S2255_DRIVER_NAME " - " fmt, ##arg)
+
 #define dprintk(level, fmt, arg...)					\
 	do {								\
 		if (*s2255_debug >= (level)) {				\
-			printk(KERN_DEBUG "s2255: " fmt, ##arg);	\
+			printk(KERN_DEBUG S2255_DRIVER_NAME		\
+				": " fmt, ##arg);			\
 		}							\
 	} while (0)
 
-
 static struct usb_driver s2255_driver;
 
 
@@ -528,14 +533,14 @@
 	int len;
 	dprintk(100, "udev %p urb %p", udev, urb);
 	if (urb->status) {
-		dev_err(&udev->dev, "URB failed with status %d", urb->status);
+		dev_err(&udev->dev, "URB failed with status %d\n", urb->status);
 		atomic_set(&data->fw_state, S2255_FW_FAILED);
 		/* wake up anything waiting for the firmware */
 		wake_up(&data->wait_fw);
 		return;
 	}
 	if (data->fw_urb == NULL) {
-		dev_err(&udev->dev, "s2255 disconnected\n");
+		s2255_dev_err(&udev->dev, "disconnected\n");
 		atomic_set(&data->fw_state, S2255_FW_FAILED);
 		/* wake up anything waiting for the firmware */
 		wake_up(&data->wait_fw);
@@ -841,8 +846,7 @@
 	struct s2255_dev *dev = fh->dev;
 	strlcpy(cap->driver, "s2255", sizeof(cap->driver));
 	strlcpy(cap->card, "s2255", sizeof(cap->card));
-	strlcpy(cap->bus_info, dev_name(&dev->udev->dev),
-		sizeof(cap->bus_info));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 	cap->version = S2255_VERSION;
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
 	return 0;
@@ -1278,7 +1282,7 @@
 	}
 
 	if (!res_get(dev, fh)) {
-		dev_err(&dev->udev->dev, "s2255: stream busy\n");
+		s2255_dev_err(&dev->udev->dev, "stream busy\n");
 		return -EBUSY;
 	}
 
@@ -1545,7 +1549,8 @@
 
 	switch (atomic_read(&dev->fw_data->fw_state)) {
 	case S2255_FW_FAILED:
-		err("2255 firmware load failed. retrying.\n");
+		s2255_dev_err(&dev->udev->dev,
+			"firmware load failed. retrying.\n");
 		s2255_fwload_start(dev, 1);
 		wait_event_timeout(dev->fw_data->wait_fw,
 				   ((atomic_read(&dev->fw_data->fw_state)
@@ -2173,7 +2178,8 @@
 
 	printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
 	if (fw_ver < CUR_USB_FWVER)
-		err("usb firmware not up to date %d\n", fw_ver);
+		dev_err(&dev->udev->dev,
+			"usb firmware not up to date %d\n", fw_ver);
 
 	for (j = 0; j < MAX_CHANNELS; j++) {
 		dev->b_acquire[j] = 0;
@@ -2228,13 +2234,13 @@
 	dprintk(100, "read pipe completion %p, status %d\n", purb,
 		purb->status);
 	if (pipe_info == NULL) {
-		err("no context !");
+		dev_err(&purb->dev->dev, "no context!\n");
 		return;
 	}
 
 	dev = pipe_info->dev;
 	if (dev == NULL) {
-		err("no context !");
+		dev_err(&purb->dev->dev, "no context!\n");
 		return;
 	}
 	status = purb->status;
@@ -2286,7 +2292,7 @@
 		pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!pipe_info->stream_urb) {
 			dev_err(&dev->udev->dev,
-				"ReadStream: Unable to alloc URB");
+				"ReadStream: Unable to alloc URB\n");
 			return -ENOMEM;
 		}
 		/* transfer buffer allocated in board_init */
@@ -2391,7 +2397,7 @@
 	int j;
 
 	if (dev == NULL) {
-		err("s2255: invalid device");
+		s2255_dev_err(&dev->udev->dev, "invalid device\n");
 		return;
 	}
 	dprintk(4, "stop read pipe\n");
@@ -2453,7 +2459,7 @@
 	/* allocate memory for our device state and initialize it to zero */
 	dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
 	if (dev == NULL) {
-		err("s2255: out of memory");
+		s2255_dev_err(&interface->dev, "out of memory\n");
 		goto error;
 	}
 
@@ -2487,7 +2493,7 @@
 	}
 
 	if (!dev->read_endpoint) {
-		dev_err(&interface->dev, "Could not find bulk-in endpoint");
+		dev_err(&interface->dev, "Could not find bulk-in endpoint\n");
 		goto error;
 	}
 
@@ -2583,7 +2589,7 @@
 }
 
 static struct usb_driver s2255_driver = {
-	.name = "s2255",
+	.name = S2255_DRIVER_NAME,
 	.probe = s2255_probe,
 	.disconnect = s2255_disconnect,
 	.id_table = s2255_table,
@@ -2597,7 +2603,8 @@
 	result = usb_register(&s2255_driver);
 
 	if (result)
-		err("usb_register failed. Error number %d", result);
+		pr_err(KBUILD_MODNAME
+			": usb_register failed. Error number %d\n", result);
 
 	dprintk(2, "s2255_init: done\n");
 	return result;
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index e637e44..da47b2f 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -46,10 +46,11 @@
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/videotext.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ioctl.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
 MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver");
@@ -388,13 +389,19 @@
 
 struct saa5246a_device
 {
+	struct v4l2_subdev sd;
+	struct video_device *vdev;
 	u8     pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
 	int    is_searching[NUM_DAUS];
-	struct i2c_client *client;
 	unsigned long in_use;
 	struct mutex lock;
 };
 
+static inline struct saa5246a_device *to_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa5246a_device, sd);
+}
+
 static struct video_device saa_template;	/* Declared near bottom */
 
 /*
@@ -403,12 +410,13 @@
 
 static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
 	char buf[64];
 
 	buf[0] = reg;
 	memcpy(buf+1, data, count);
 
-	if(i2c_master_send(t->client, buf, count+1)==count+1)
+	if (i2c_master_send(client, buf, count + 1) == count + 1)
 		return 0;
 	return -1;
 }
@@ -436,7 +444,9 @@
  */
 static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf)
 {
-	if(i2c_master_recv(t->client, buf, count)!=count)
+	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
+
+	if (i2c_master_recv(client, buf, count) != count)
 		return -1;
 	return 0;
 }
@@ -961,9 +971,6 @@
 {
 	struct saa5246a_device *t = video_drvdata(file);
 
-	if (t->client == NULL)
-		return -ENODEV;
-
 	if (test_and_set_bit(0, &t->in_use))
 		return -EBUSY;
 
@@ -1033,18 +1040,29 @@
 	.minor    = -1,
 };
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-I2C_CLIENT_INSMOD;
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5246A, 0);
+}
+
+static const struct v4l2_subdev_core_ops saa5246a_core_ops = {
+	.g_chip_ident = saa5246a_g_chip_ident,
+};
+
+static const struct v4l2_subdev_ops saa5246a_ops = {
+	.core = &saa5246a_core_ops,
+};
+
 
 static int saa5246a_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	int pgbuf;
 	int err;
-	struct video_device *vd;
 	struct saa5246a_device *t;
+	struct v4l2_subdev *sd;
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
@@ -1053,40 +1071,43 @@
 	t = kzalloc(sizeof(*t), GFP_KERNEL);
 	if (t == NULL)
 		return -ENOMEM;
+	sd = &t->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa5246a_ops);
 	mutex_init(&t->lock);
 
 	/* Now create a video4linux device */
-	vd = video_device_alloc();
-	if (vd == NULL) {
+	t->vdev = video_device_alloc();
+	if (t->vdev == NULL) {
 		kfree(t);
 		return -ENOMEM;
 	}
-	i2c_set_clientdata(client, vd);
-	memcpy(vd, &saa_template, sizeof(*vd));
+	memcpy(t->vdev, &saa_template, sizeof(*t->vdev));
 
 	for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
 		memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
 		t->is_searching[pgbuf] = false;
 	}
-	video_set_drvdata(vd, t);
+	video_set_drvdata(t->vdev, t);
 
 	/* Register it */
-	err = video_register_device(vd, VFL_TYPE_VTX, -1);
+	err = video_register_device(t->vdev, VFL_TYPE_VTX, -1);
 	if (err < 0) {
 		kfree(t);
-		video_device_release(vd);
+		video_device_release(t->vdev);
+		t->vdev = NULL;
 		return err;
 	}
-	t->client = client;
 	return 0;
 }
 
 static int saa5246a_remove(struct i2c_client *client)
 {
-	struct video_device *vd = i2c_get_clientdata(client);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa5246a_device *t = to_dev(sd);
 
-	video_unregister_device(vd);
-	kfree(video_get_drvdata(vd));
+	video_unregister_device(t->vdev);
+	v4l2_device_unregister_subdev(sd);
+	kfree(t);
 	return 0;
 }
 
@@ -1098,7 +1119,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa5246a",
-	.driverid = I2C_DRIVERID_SAA5249,
 	.probe = saa5246a_probe,
 	.remove = saa5246a_remove,
 	.id_table = saa5246a_id,
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index e297651..48b27fe 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -50,15 +50,17 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/videotext.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ioctl.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
 MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver");
 MODULE_LICENSE("GPL");
 
+
 #define VTX_VER_MAJ 1
 #define VTX_VER_MIN 8
 
@@ -95,17 +97,23 @@
 
 struct saa5249_device
 {
+	struct v4l2_subdev sd;
+	struct video_device *vdev;
 	vdau_t vdau[NUM_DAUS];			/* Data for virtual DAUs (the 5249 only has one */
 						/* real DAU, so we have to simulate some more) */
 	int vtx_use_count;
 	int is_searching[NUM_DAUS];
 	int disp_mode;
 	int virtual_mode;
-	struct i2c_client *client;
 	unsigned long in_use;
 	struct mutex lock;
 };
 
+static inline struct saa5249_device *to_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa5249_device, sd);
+}
+
 
 #define CCTWR 34		/* I²C write/read-address of vtx-chip */
 #define CCTRD 35
@@ -147,12 +155,13 @@
 
 static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
 	char buf[64];
 
 	buf[0] = reg;
 	memcpy(buf+1, data, count);
 
-	if (i2c_master_send(t->client, buf, count + 1) == count + 1)
+	if (i2c_master_send(client, buf, count + 1) == count + 1)
 		return 0;
 	return -1;
 }
@@ -180,7 +189,9 @@
 
 static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
 {
-	if(i2c_master_recv(t->client, buf, count)!=count)
+	struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
+
+	if (i2c_master_recv(client, buf, count) != count)
 		return -1;
 	return 0;
 }
@@ -497,9 +508,6 @@
 	struct saa5249_device *t = video_drvdata(file);
 	int pgbuf;
 
-	if (t->client == NULL)
-		return -ENODEV;
-
 	if (test_and_set_bit(0, &t->in_use))
 		return -EBUSY;
 
@@ -553,18 +561,28 @@
 	.release 	= video_device_release,
 };
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+static int saa5249_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-I2C_CLIENT_INSMOD;
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5249, 0);
+}
+
+static const struct v4l2_subdev_core_ops saa5249_core_ops = {
+	.g_chip_ident = saa5249_g_chip_ident,
+};
+
+static const struct v4l2_subdev_ops saa5249_ops = {
+	.core = &saa5249_core_ops,
+};
 
 static int saa5249_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	int pgbuf;
 	int err;
-	struct video_device *vd;
 	struct saa5249_device *t;
+	struct v4l2_subdev *sd;
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
@@ -573,16 +591,17 @@
 	t = kzalloc(sizeof(*t), GFP_KERNEL);
 	if (t == NULL)
 		return -ENOMEM;
+	sd = &t->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa5249_ops);
 	mutex_init(&t->lock);
 
 	/* Now create a video4linux device */
-	vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
-	if (vd == NULL) {
+	t->vdev = video_device_alloc();
+	if (t->vdev == NULL) {
 		kfree(client);
 		return -ENOMEM;
 	}
-	i2c_set_clientdata(client, vd);
-	memcpy(vd, &saa_template, sizeof(*vd));
+	memcpy(t->vdev, &saa_template, sizeof(*t->vdev));
 
 	for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
 		memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
@@ -593,26 +612,27 @@
 		t->vdau[pgbuf].stopped = true;
 		t->is_searching[pgbuf] = false;
 	}
-	video_set_drvdata(vd, t);
+	video_set_drvdata(t->vdev, t);
 
 	/* Register it */
-	err = video_register_device(vd, VFL_TYPE_VTX, -1);
+	err = video_register_device(t->vdev, VFL_TYPE_VTX, -1);
 	if (err < 0) {
 		kfree(t);
-		kfree(vd);
+		video_device_release(t->vdev);
+		t->vdev = NULL;
 		return err;
 	}
-	t->client = client;
 	return 0;
 }
 
 static int saa5249_remove(struct i2c_client *client)
 {
-	struct video_device *vd = i2c_get_clientdata(client);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa5249_device *t = to_dev(sd);
 
-	video_unregister_device(vd);
-	kfree(video_get_drvdata(vd));
-	kfree(vd);
+	video_unregister_device(t->vdev);
+	v4l2_device_unregister_subdev(sd);
+	kfree(t);
 	return 0;
 }
 
@@ -624,7 +644,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa5249",
-	.driverid = I2C_DRIVERID_SAA5249,
 	.probe = saa5249_probe,
 	.remove = saa5249_remove,
 	.id_table = saa5249_id,
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index f050242..c25e81a 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -23,7 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/types.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -32,15 +32,10 @@
 #include <asm/uaccess.h>
 
 #include <media/rds.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {
-	0x20 >> 1,
-	0x22 >> 1,
-	I2C_CLIENT_END,
-};
-
-I2C_CLIENT_INSMOD;
 
 /* insmod options */
 static unsigned int debug;
@@ -72,9 +67,8 @@
 #define dprintk     if (debug) printk
 
 struct saa6588 {
-	struct i2c_client client;
-	struct work_struct work;
-	struct timer_list timer;
+	struct v4l2_subdev sd;
+	struct delayed_work work;
 	spinlock_t lock;
 	unsigned char *buffer;
 	unsigned int buf_size;
@@ -86,8 +80,10 @@
 	int data_available_for_read;
 };
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
+static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa6588, sd);
+}
 
 /* ---------------------------------------------------------------------- */
 
@@ -258,6 +254,7 @@
 
 static void saa6588_i2c_poll(struct saa6588 *s)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&s->sd);
 	unsigned long flags;
 	unsigned char tmpbuf[6];
 	unsigned char blocknum;
@@ -265,7 +262,7 @@
 
 	/* Although we only need 3 bytes, we have to read at least 6.
 	   SAA6588 returns garbage otherwise */
-	if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) {
+	if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) {
 		if (debug > 1)
 			dprintk(PREFIX "read error!\n");
 		return;
@@ -316,23 +313,17 @@
 	wake_up_interruptible(&s->read_queue);
 }
 
-static void saa6588_timer(unsigned long data)
-{
-	struct saa6588 *s = (struct saa6588 *)data;
-
-	schedule_work(&s->work);
-}
-
 static void saa6588_work(struct work_struct *work)
 {
-	struct saa6588 *s = container_of(work, struct saa6588, work);
+	struct saa6588 *s = container_of(work, struct saa6588, work.work);
 
 	saa6588_i2c_poll(s);
-	mod_timer(&s->timer, jiffies + msecs_to_jiffies(20));
+	schedule_delayed_work(&s->work, msecs_to_jiffies(20));
 }
 
 static int saa6588_configure(struct saa6588 *s)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(&s->sd);
 	unsigned char buf[3];
 	int rc;
 
@@ -380,7 +371,8 @@
 	dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",
 		buf[0], buf[1], buf[2]);
 
-	if (3 != (rc = i2c_master_send(&s->client, buf, 3)))
+	rc = i2c_master_send(client, buf, 3);
+	if (rc != 3)
 		printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
 
 	return 0;
@@ -388,70 +380,10 @@
 
 /* ---------------------------------------------------------------------- */
 
-static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
+static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
-	struct saa6588 *s;
-	client_template.adapter = adap;
-	client_template.addr = addr;
-
-	printk(PREFIX "chip found @ 0x%x\n", addr << 1);
-
-	if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL)))
-		return -ENOMEM;
-
-	s->buf_size = bufblocks * 3;
-
-	if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) {
-		kfree(s);
-		return -ENOMEM;
-	}
-	spin_lock_init(&s->lock);
-	s->client = client_template;
-	s->block_count = 0;
-	s->wr_index = 0;
-	s->rd_index = 0;
-	s->last_blocknum = 0xff;
-	init_waitqueue_head(&s->read_queue);
-	s->data_available_for_read = 0;
-	i2c_set_clientdata(&s->client, s);
-	i2c_attach_client(&s->client);
-
-	saa6588_configure(s);
-
-	/* start polling via eventd */
-	INIT_WORK(&s->work, saa6588_work);
-	init_timer(&s->timer);
-	s->timer.function = saa6588_timer;
-	s->timer.data = (unsigned long)s;
-	schedule_work(&s->work);
-	return 0;
-}
-
-static int saa6588_probe(struct i2c_adapter *adap)
-{
-	if (adap->class & I2C_CLASS_TV_ANALOG)
-		return i2c_probe(adap, &addr_data, saa6588_attach);
-	return 0;
-}
-
-static int saa6588_detach(struct i2c_client *client)
-{
-	struct saa6588 *s = i2c_get_clientdata(client);
-
-	del_timer_sync(&s->timer);
-	flush_scheduled_work();
-
-	i2c_detach_client(client);
-	kfree(s->buffer);
-	kfree(s);
-	return 0;
-}
-
-static int saa6588_command(struct i2c_client *client, unsigned int cmd,
-							void *arg)
-{
-	struct saa6588 *s = i2c_get_clientdata(client);
-	struct rds_command *a = (struct rds_command *)arg;
+	struct saa6588 *s = to_saa6588(sd);
+	struct rds_command *a = arg;
 
 	switch (cmd) {
 		/* --- open() for /dev/radio --- */
@@ -479,45 +411,94 @@
 
 	default:
 		/* nothing */
-		break;
+		return -ENOIOCTLCMD;
 	}
 	return 0;
 }
 
+static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa6588_core_ops = {
+	.g_chip_ident = saa6588_g_chip_ident,
+	.ioctl = saa6588_ioctl,
+};
+
+static const struct v4l2_subdev_ops saa6588_ops = {
+	.core = &saa6588_core_ops,
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6588_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct saa6588 *s;
+	struct v4l2_subdev *sd;
+
+	v4l_info(client, "saa6588 found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	s = kzalloc(sizeof(*s), GFP_KERNEL);
+	if (s == NULL)
+		return -ENOMEM;
+
+	s->buf_size = bufblocks * 3;
+
+	s->buffer = kmalloc(s->buf_size, GFP_KERNEL);
+	if (s->buffer == NULL) {
+		kfree(s);
+		return -ENOMEM;
+	}
+	sd = &s->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa6588_ops);
+	spin_lock_init(&s->lock);
+	s->block_count = 0;
+	s->wr_index = 0;
+	s->rd_index = 0;
+	s->last_blocknum = 0xff;
+	init_waitqueue_head(&s->read_queue);
+	s->data_available_for_read = 0;
+
+	saa6588_configure(s);
+
+	/* start polling via eventd */
+	INIT_DELAYED_WORK(&s->work, saa6588_work);
+	schedule_delayed_work(&s->work, 0);
+	return 0;
+}
+
+static int saa6588_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa6588 *s = to_saa6588(sd);
+
+	v4l2_device_unregister_subdev(sd);
+
+	cancel_delayed_work_sync(&s->work);
+
+	kfree(s->buffer);
+	kfree(s);
+	return 0;
+}
+
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver driver = {
-	.driver = {
-		.name = "saa6588",
-	},
-	.id = -1,		/* FIXME */
-	.attach_adapter = saa6588_probe,
-	.detach_client = saa6588_detach,
-	.command = saa6588_command,
+static const struct i2c_device_id saa6588_id[] = {
+	{ "saa6588", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa6588_id);
 
-static struct i2c_client client_template = {
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa6588",
-	.driver = &driver,
+	.probe = saa6588_probe,
+	.remove = saa6588_remove,
+	.id_table = saa6588_id,
 };
-
-static int __init saa6588_init_module(void)
-{
-	return i2c_add_driver(&driver);
-}
-
-static void __exit saa6588_cleanup_module(void)
-{
-	i2c_del_driver(&driver);
-}
-
-module_init(saa6588_init_module);
-module_exit(saa6588_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 3786069..df4e08d 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -33,15 +33,16 @@
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
 MODULE_AUTHOR("Pauline Middelink");
 MODULE_LICENSE("GPL");
 
+
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
@@ -52,9 +53,10 @@
 #define SAA7110_NR_REG		0x35
 
 struct saa7110 {
+	struct v4l2_subdev sd;
 	u8 reg[SAA7110_NR_REG];
 
-	int norm;
+	v4l2_std_id norm;
 	int input;
 	int enable;
 	int bright;
@@ -65,20 +67,28 @@
 	wait_queue_head_t wq;
 };
 
+static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7110, sd);
+}
+
 /* ----------------------------------------------------------------------- */
 /* I2C support functions						   */
 /* ----------------------------------------------------------------------- */
 
-static int saa7110_write(struct i2c_client *client, u8 reg, u8 value)
+static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
-	struct saa7110 *decoder = i2c_get_clientdata(client);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7110 *decoder = to_saa7110(sd);
 
 	decoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
+static int saa7110_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7110 *decoder = to_saa7110(sd);
 	int ret = -1;
 	u8 reg = *data;		/* first register to write to */
 
@@ -89,15 +99,13 @@
 	/* the saa7110 has an autoincrement function, use it if
 	 * the adapter understands raw I2C */
 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		struct saa7110 *decoder = i2c_get_clientdata(client);
-
 		ret = i2c_master_send(client, data, len);
 
 		/* Cache the written data */
 		memcpy(decoder->reg + reg, data + 1, len - 1);
 	} else {
 		for (++data, --len; len; len--) {
-			ret = saa7110_write(client, reg++, *data++);
+			ret = saa7110_write(sd, reg++, *data++);
 			if (ret < 0)
 				break;
 		}
@@ -106,8 +114,10 @@
 	return ret;
 }
 
-static inline int saa7110_read(struct i2c_client *client)
+static inline int saa7110_read(struct v4l2_subdev *sd)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_read_byte(client);
 }
 
@@ -115,11 +125,11 @@
 /* SAA7110 functions							   */
 /* ----------------------------------------------------------------------- */
 
-#define FRESP_06H_COMPST 0x03	//0x13
-#define FRESP_06H_SVIDEO 0x83	//0xC0
+#define FRESP_06H_COMPST 0x03	/*0x13*/
+#define FRESP_06H_SVIDEO 0x83	/*0xC0*/
 
 
-static int saa7110_selmux(struct i2c_client *client, int chan)
+static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
 {
 	static const unsigned char modes[9][8] = {
 		/* mode 0 */
@@ -150,17 +160,17 @@
 		{FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
 			      0x44, 0x75, 0x21}
 	};
-	struct saa7110 *decoder = i2c_get_clientdata(client);
+	struct saa7110 *decoder = to_saa7110(sd);
 	const unsigned char *ptr = modes[chan];
 
-	saa7110_write(client, 0x06, ptr[0]);	/* Luminance control    */
-	saa7110_write(client, 0x20, ptr[1]);	/* Analog Control #1    */
-	saa7110_write(client, 0x21, ptr[2]);	/* Analog Control #2    */
-	saa7110_write(client, 0x22, ptr[3]);	/* Mixer Control #1     */
-	saa7110_write(client, 0x2C, ptr[4]);	/* Mixer Control #2     */
-	saa7110_write(client, 0x30, ptr[5]);	/* ADCs gain control    */
-	saa7110_write(client, 0x31, ptr[6]);	/* Mixer Control #3     */
-	saa7110_write(client, 0x21, ptr[7]);	/* Analog Control #2    */
+	saa7110_write(sd, 0x06, ptr[0]);	/* Luminance control    */
+	saa7110_write(sd, 0x20, ptr[1]);	/* Analog Control #1    */
+	saa7110_write(sd, 0x21, ptr[2]);	/* Analog Control #2    */
+	saa7110_write(sd, 0x22, ptr[3]);	/* Mixer Control #1     */
+	saa7110_write(sd, 0x2C, ptr[4]);	/* Mixer Control #2     */
+	saa7110_write(sd, 0x30, ptr[5]);	/* ADCs gain control    */
+	saa7110_write(sd, 0x31, ptr[6]);	/* Mixer Control #3     */
+	saa7110_write(sd, 0x21, ptr[7]);	/* Analog Control #2    */
 	decoder->input = chan;
 
 	return 0;
@@ -176,246 +186,260 @@
 	/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
 };
 
-static int determine_norm(struct i2c_client *client)
+static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
 {
 	DEFINE_WAIT(wait);
-	struct saa7110 *decoder = i2c_get_clientdata(client);
+	struct saa7110 *decoder = to_saa7110(sd);
 	int status;
 
 	/* mode changed, start automatic detection */
-	saa7110_write_block(client, initseq, sizeof(initseq));
-	saa7110_selmux(client, decoder->input);
+	saa7110_write_block(sd, initseq, sizeof(initseq));
+	saa7110_selmux(sd, decoder->input);
 	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 	schedule_timeout(msecs_to_jiffies(250));
 	finish_wait(&decoder->wq, &wait);
-	status = saa7110_read(client);
+	status = saa7110_read(sd);
 	if (status & 0x40) {
-		v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status);
-		return decoder->norm;	// no change
+		v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
+		return decoder->norm;	/* no change*/
 	}
 	if ((status & 3) == 0) {
-		saa7110_write(client, 0x06, 0x83);
+		saa7110_write(sd, 0x06, 0x83);
 		if (status & 0x20) {
-			v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status);
-			//saa7110_write(client,0x2E,0x81);
-			return VIDEO_MODE_NTSC;
+			v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
+			/*saa7110_write(sd,0x2E,0x81);*/
+			return V4L2_STD_NTSC;
 		}
-		v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status);
-		//saa7110_write(client,0x2E,0x9A);
-		return VIDEO_MODE_PAL;
+		v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
+		/*saa7110_write(sd,0x2E,0x9A);*/
+		return V4L2_STD_PAL;
 	}
-	//saa7110_write(client,0x06,0x03);
+	/*saa7110_write(sd,0x06,0x03);*/
 	if (status & 0x20) {	/* 60Hz */
-		v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status);
-		saa7110_write(client, 0x0D, 0x86);
-		saa7110_write(client, 0x0F, 0x50);
-		saa7110_write(client, 0x11, 0x2C);
-		//saa7110_write(client,0x2E,0x81);
-		return VIDEO_MODE_NTSC;
+		v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC)\n", status);
+		saa7110_write(sd, 0x0D, 0x86);
+		saa7110_write(sd, 0x0F, 0x50);
+		saa7110_write(sd, 0x11, 0x2C);
+		/*saa7110_write(sd,0x2E,0x81);*/
+		return V4L2_STD_NTSC;
 	}
 
 	/* 50Hz -> PAL/SECAM */
-	saa7110_write(client, 0x0D, 0x86);
-	saa7110_write(client, 0x0F, 0x10);
-	saa7110_write(client, 0x11, 0x59);
-	//saa7110_write(client,0x2E,0x9A);
+	saa7110_write(sd, 0x0D, 0x86);
+	saa7110_write(sd, 0x0F, 0x10);
+	saa7110_write(sd, 0x11, 0x59);
+	/*saa7110_write(sd,0x2E,0x9A);*/
 
 	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
 	schedule_timeout(msecs_to_jiffies(250));
 	finish_wait(&decoder->wq, &wait);
 
-	status = saa7110_read(client);
+	status = saa7110_read(sd);
 	if ((status & 0x03) == 0x01) {
-		v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status);
-		saa7110_write(client, 0x0D, 0x87);
-		return VIDEO_MODE_SECAM;
+		v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
+		saa7110_write(sd, 0x0D, 0x87);
+		return V4L2_STD_SECAM;
 	}
-	v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status);
-	return VIDEO_MODE_PAL;
+	v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
+	return V4L2_STD_PAL;
 }
 
-static int
-saa7110_command (struct i2c_client *client,
-		 unsigned int       cmd,
-		 void              *arg)
+static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
 {
-	struct saa7110 *decoder = i2c_get_clientdata(client);
-	int v;
+	struct saa7110 *decoder = to_saa7110(sd);
+	int res = V4L2_IN_ST_NO_SIGNAL;
+	int status = saa7110_read(sd);
 
-	switch (cmd) {
-	case 0:
-		//saa7110_write_block(client, initseq, sizeof(initseq));
-		break;
+	v4l2_dbg(1, debug, sd, "status=0x%02x norm=%llx\n",
+		       status, (unsigned long long)decoder->norm);
+	if (!(status & 0x40))
+		res = 0;
+	if (!(status & 0x03))
+		res |= V4L2_IN_ST_NO_COLOR;
 
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *dc = arg;
+	*pstatus = res;
+	return 0;
+}
 
-		dc->flags =
-		    VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
-		    VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
-		dc->inputs = SAA7110_MAX_INPUT;
-		dc->outputs = SAA7110_MAX_OUTPUT;
-		break;
-	}
+static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	*(v4l2_std_id *)std = determine_norm(sd);
+	return 0;
+}
 
-	case DECODER_GET_STATUS:
-	{
-		int status;
-		int res = 0;
+static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
 
-		status = saa7110_read(client);
-		v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n",
-			       status, decoder->norm);
-		if (!(status & 0x40))
-			res |= DECODER_STATUS_GOOD;
-		if (status & 0x03)
-			res |= DECODER_STATUS_COLOR;
-
-		switch (decoder->norm) {
-		case VIDEO_MODE_NTSC:
-			res |= DECODER_STATUS_NTSC;
-			break;
-		case VIDEO_MODE_PAL:
-			res |= DECODER_STATUS_PAL;
-			break;
-		case VIDEO_MODE_SECAM:
-			res |= DECODER_STATUS_SECAM;
-			break;
-		}
-		*(int *) arg = res;
-		break;
-	}
-
-	case DECODER_SET_NORM:
-		v = *(int *) arg;
-		if (decoder->norm != v) {
-			decoder->norm = v;
-			//saa7110_write(client, 0x06, 0x03);
-			switch (v) {
-			case VIDEO_MODE_NTSC:
-				saa7110_write(client, 0x0D, 0x86);
-				saa7110_write(client, 0x0F, 0x50);
-				saa7110_write(client, 0x11, 0x2C);
-				//saa7110_write(client, 0x2E, 0x81);
-				v4l_dbg(1, debug, client, "switched to NTSC\n");
-				break;
-			case VIDEO_MODE_PAL:
-				saa7110_write(client, 0x0D, 0x86);
-				saa7110_write(client, 0x0F, 0x10);
-				saa7110_write(client, 0x11, 0x59);
-				//saa7110_write(client, 0x2E, 0x9A);
-				v4l_dbg(1, debug, client, "switched to PAL\n");
-				break;
-			case VIDEO_MODE_SECAM:
-				saa7110_write(client, 0x0D, 0x87);
-				saa7110_write(client, 0x0F, 0x10);
-				saa7110_write(client, 0x11, 0x59);
-				//saa7110_write(client, 0x2E, 0x9A);
-				v4l_dbg(1, debug, client, "switched to SECAM\n");
-				break;
-			case VIDEO_MODE_AUTO:
-				v4l_dbg(1, debug, client, "switched to AUTO\n");
-				decoder->norm = determine_norm(client);
-				*(int *) arg = decoder->norm;
-				break;
-			default:
-				return -EPERM;
-			}
-		}
-		break;
-
-	case DECODER_SET_INPUT:
-		v = *(int *) arg;
-		if (v < 0 || v >= SAA7110_MAX_INPUT) {
-			v4l_dbg(1, debug, client, "input=%d not available\n", v);
+	if (decoder->norm != std) {
+		decoder->norm = std;
+		/*saa7110_write(sd, 0x06, 0x03);*/
+		if (std & V4L2_STD_NTSC) {
+			saa7110_write(sd, 0x0D, 0x86);
+			saa7110_write(sd, 0x0F, 0x50);
+			saa7110_write(sd, 0x11, 0x2C);
+			/*saa7110_write(sd, 0x2E, 0x81);*/
+			v4l2_dbg(1, debug, sd, "switched to NTSC\n");
+		} else if (std & V4L2_STD_PAL) {
+			saa7110_write(sd, 0x0D, 0x86);
+			saa7110_write(sd, 0x0F, 0x10);
+			saa7110_write(sd, 0x11, 0x59);
+			/*saa7110_write(sd, 0x2E, 0x9A);*/
+			v4l2_dbg(1, debug, sd, "switched to PAL\n");
+		} else if (std & V4L2_STD_SECAM) {
+			saa7110_write(sd, 0x0D, 0x87);
+			saa7110_write(sd, 0x0F, 0x10);
+			saa7110_write(sd, 0x11, 0x59);
+			/*saa7110_write(sd, 0x2E, 0x9A);*/
+			v4l2_dbg(1, debug, sd, "switched to SECAM\n");
+		} else {
 			return -EINVAL;
 		}
-		if (decoder->input != v) {
-			saa7110_selmux(client, v);
-			v4l_dbg(1, debug, client, "switched to input=%d\n", v);
-		}
-		break;
-
-	case DECODER_SET_OUTPUT:
-		v = *(int *) arg;
-		/* not much choice of outputs */
-		if (v != 0)
-			return -EINVAL;
-		break;
-
-	case DECODER_ENABLE_OUTPUT:
-		v = *(int *) arg;
-		if (decoder->enable != v) {
-			decoder->enable = v;
-			saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
-			v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off");
-		}
-		break;
-
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *pic = arg;
-
-		if (decoder->bright != pic->brightness) {
-			/* We want 0 to 255 we get 0-65535 */
-			decoder->bright = pic->brightness;
-			saa7110_write(client, 0x19, decoder->bright >> 8);
-		}
-		if (decoder->contrast != pic->contrast) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->contrast = pic->contrast;
-			saa7110_write(client, 0x13,
-				      decoder->contrast >> 9);
-		}
-		if (decoder->sat != pic->colour) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->sat = pic->colour;
-			saa7110_write(client, 0x12, decoder->sat >> 9);
-		}
-		if (decoder->hue != pic->hue) {
-			/* We want -128 to 127 we get 0-65535 */
-			decoder->hue = pic->hue;
-			saa7110_write(client, 0x07,
-				      (decoder->hue >> 8) - 128);
-		}
-		break;
 	}
+	return 0;
+}
 
-	case DECODER_DUMP:
-		if (!debug)
-			break;
-		for (v = 0; v < SAA7110_NR_REG; v += 16) {
-			int j;
-			v4l_dbg(1, debug, client, "%02x:", v);
-			for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++)
-				printk(KERN_CONT " %02x", decoder->reg[v + j]);
-			printk(KERN_CONT "\n");
-		}
-		break;
+static int saa7110_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
 
+	if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) {
+		v4l2_dbg(1, debug, sd, "input=%d not available\n", route->input);
+		return -EINVAL;
+	}
+	if (decoder->input != route->input) {
+		saa7110_selmux(sd, route->input);
+		v4l2_dbg(1, debug, sd, "switched to input=%d\n", route->input);
+	}
+	return 0;
+}
+
+static int saa7110_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	if (decoder->enable != enable) {
+		decoder->enable = enable;
+		saa7110_write(sd, 0x0E, enable ? 0x18 : 0x80);
+		v4l2_dbg(1, debug, sd, "YUV %s\n", enable ? "on" : "off");
+	}
+	return 0;
+}
+
+static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 	default:
-		v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
 		return -EINVAL;
 	}
 	return 0;
 }
 
+static int saa7110_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = decoder->bright;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctrl->value = decoder->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctrl->value = decoder->sat;
+		break;
+	case V4L2_CID_HUE:
+		ctrl->value = decoder->hue;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int saa7110_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (decoder->bright != ctrl->value) {
+			decoder->bright = ctrl->value;
+			saa7110_write(sd, 0x19, decoder->bright);
+		}
+		break;
+	case V4L2_CID_CONTRAST:
+		if (decoder->contrast != ctrl->value) {
+			decoder->contrast = ctrl->value;
+			saa7110_write(sd, 0x13, decoder->contrast);
+		}
+		break;
+	case V4L2_CID_SATURATION:
+		if (decoder->sat != ctrl->value) {
+			decoder->sat = ctrl->value;
+			saa7110_write(sd, 0x12, decoder->sat);
+		}
+		break;
+	case V4L2_CID_HUE:
+		if (decoder->hue != ctrl->value) {
+			decoder->hue = ctrl->value;
+			saa7110_write(sd, 0x07, decoder->hue);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-/*
- * Generic i2c probe
- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
- */
+static const struct v4l2_subdev_core_ops saa7110_core_ops = {
+	.g_chip_ident = saa7110_g_chip_ident,
+	.g_ctrl = saa7110_g_ctrl,
+	.s_ctrl = saa7110_s_ctrl,
+	.queryctrl = saa7110_queryctrl,
+};
 
-static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END };
+static const struct v4l2_subdev_tuner_ops saa7110_tuner_ops = {
+	.s_std = saa7110_s_std,
+};
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_video_ops saa7110_video_ops = {
+	.s_routing = saa7110_s_routing,
+	.s_stream = saa7110_s_stream,
+	.querystd = saa7110_querystd,
+	.g_input_status = saa7110_g_input_status,
+};
+
+static const struct v4l2_subdev_ops saa7110_ops = {
+	.core = &saa7110_core_ops,
+	.tuner = &saa7110_tuner_ops,
+	.video = &saa7110_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
 
 static int saa7110_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct saa7110 *decoder;
+	struct v4l2_subdev *sd;
 	int rv;
 
 	/* Check if the adapter supports the needed features */
@@ -429,7 +453,9 @@
 	decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
 	if (!decoder)
 		return -ENOMEM;
-	decoder->norm = VIDEO_MODE_PAL;
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
+	decoder->norm = V4L2_STD_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
 	decoder->bright = 32768;
@@ -437,30 +463,29 @@
 	decoder->hue = 32768;
 	decoder->sat = 32768;
 	init_waitqueue_head(&decoder->wq);
-	i2c_set_clientdata(client, decoder);
 
-	rv = saa7110_write_block(client, initseq, sizeof(initseq));
+	rv = saa7110_write_block(sd, initseq, sizeof(initseq));
 	if (rv < 0) {
-		v4l_dbg(1, debug, client, "init status %d\n", rv);
+		v4l2_dbg(1, debug, sd, "init status %d\n", rv);
 	} else {
 		int ver, status;
-		saa7110_write(client, 0x21, 0x10);
-		saa7110_write(client, 0x0e, 0x18);
-		saa7110_write(client, 0x0D, 0x04);
-		ver = saa7110_read(client);
-		saa7110_write(client, 0x0D, 0x06);
-		//mdelay(150);
-		status = saa7110_read(client);
-		v4l_dbg(1, debug, client, "version %x, status=0x%02x\n",
+		saa7110_write(sd, 0x21, 0x10);
+		saa7110_write(sd, 0x0e, 0x18);
+		saa7110_write(sd, 0x0D, 0x04);
+		ver = saa7110_read(sd);
+		saa7110_write(sd, 0x0D, 0x06);
+		/*mdelay(150);*/
+		status = saa7110_read(sd);
+		v4l2_dbg(1, debug, sd, "version %x, status=0x%02x\n",
 			       ver, status);
-		saa7110_write(client, 0x0D, 0x86);
-		saa7110_write(client, 0x0F, 0x10);
-		saa7110_write(client, 0x11, 0x59);
-		//saa7110_write(client, 0x2E, 0x9A);
+		saa7110_write(sd, 0x0D, 0x86);
+		saa7110_write(sd, 0x0F, 0x10);
+		saa7110_write(sd, 0x11, 0x59);
+		/*saa7110_write(sd, 0x2E, 0x9A);*/
 	}
 
-	//saa7110_selmux(client,0);
-	//determine_norm(client);
+	/*saa7110_selmux(sd,0);*/
+	/*determine_norm(sd);*/
 	/* setup and implicit mode 0 select has been performed */
 
 	return 0;
@@ -468,7 +493,10 @@
 
 static int saa7110_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_saa7110(sd));
 	return 0;
 }
 
@@ -482,8 +510,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa7110",
-	.driverid = I2C_DRIVERID_SAA7110,
-	.command = saa7110_command,
 	.probe = saa7110_probe,
 	.remove = saa7110_remove,
 	.id_table = saa7110_id,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
deleted file mode 100644
index a4738a2..0000000
--- a/drivers/media/video/saa7111.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * saa7111 - Philips SAA7111A video decoder driver version 0.0.3
- *
- * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * Slight changes for video timing and attachment output by
- * Wolfgang Scherr <scherr@net4you.net>
- *
- * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
- *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
- *
- * Changes by Michael Hunold <michael@mihu.de>
- *    - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/types.h>
-#include <linux/ioctl.h>
-#include <asm/uaccess.h>
-#include <linux/i2c.h>
-#include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
-
-MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
-MODULE_AUTHOR("Dave Perks");
-MODULE_LICENSE("GPL");
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
-
-/* ----------------------------------------------------------------------- */
-
-#define SAA7111_NR_REG		0x18
-
-struct saa7111 {
-	unsigned char reg[SAA7111_NR_REG];
-
-	int norm;
-	int input;
-	int enable;
-};
-
-/* ----------------------------------------------------------------------- */
-
-static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value)
-{
-	struct saa7111 *decoder = i2c_get_clientdata(client);
-
-	decoder->reg[reg] = value;
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
-{
-	struct saa7111 *decoder = i2c_get_clientdata(client);
-
-	if (decoder->reg[reg] != value) {
-		decoder->reg[reg] = value;
-		i2c_smbus_write_byte_data(client, reg, value);
-	}
-}
-
-static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
-{
-	int ret = -1;
-	u8 reg;
-
-	/* the saa7111 has an autoincrement function, use it if
-	 * the adapter understands raw I2C */
-	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		/* do raw I2C, not smbus compatible */
-		struct saa7111 *decoder = i2c_get_clientdata(client);
-		u8 block_data[32];
-		int block_len;
-
-		while (len >= 2) {
-			block_len = 0;
-			block_data[block_len++] = reg = data[0];
-			do {
-				block_data[block_len++] =
-				    decoder->reg[reg++] = data[1];
-				len -= 2;
-				data += 2;
-			} while (len >= 2 && data[0] == reg && block_len < 32);
-			ret = i2c_master_send(client, block_data, block_len);
-			if (ret < 0)
-				break;
-		}
-	} else {
-		/* do some slow I2C emulation kind of thing */
-		while (len >= 2) {
-			reg = *data++;
-			ret = saa7111_write(client, reg, *data++);
-			if (ret < 0)
-				break;
-			len -= 2;
-		}
-	}
-
-	return ret;
-}
-
-static int saa7111_init_decoder(struct i2c_client *client,
-		struct video_decoder_init *init)
-{
-	return saa7111_write_block(client, init->data, init->len);
-}
-
-static inline int saa7111_read(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const unsigned char saa7111_i2c_init[] = {
-	0x00, 0x00,		/* 00 - ID byte */
-	0x01, 0x00,		/* 01 - reserved */
-
-	/*front end */
-	0x02, 0xd0,		/* 02 - FUSE=3, GUDL=2, MODE=0 */
-	0x03, 0x23,		/* 03 - HLNRS=0, VBSL=1, WPOFF=0,
-				 * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
-	0x04, 0x00,		/* 04 - GAI1=256 */
-	0x05, 0x00,		/* 05 - GAI2=256 */
-
-	/* decoder */
-	0x06, 0xf3,		/* 06 - HSB at  13(50Hz) /  17(60Hz)
-				 * pixels after end of last line */
-	/*0x07, 0x13,     * 07 - HSS at 113(50Hz) / 117(60Hz) pixels
-				 * after end of last line */
-	0x07, 0xe8,		/* 07 - HSS seems to be needed to
-				 * work with NTSC, too */
-	0x08, 0xc8,		/* 08 - AUFD=1, FSEL=1, EXFIL=0,
-				 * VTRC=1, HPLL=0, VNOI=0 */
-	0x09, 0x01,		/* 09 - BYPS=0, PREF=0, BPSS=0,
-				 * VBLB=0, UPTCV=0, APER=1 */
-	0x0a, 0x80,		/* 0a - BRIG=128 */
-	0x0b, 0x47,		/* 0b - CONT=1.109 */
-	0x0c, 0x40,		/* 0c - SATN=1.0 */
-	0x0d, 0x00,		/* 0d - HUE=0 */
-	0x0e, 0x01,		/* 0e - CDTO=0, CSTD=0, DCCF=0,
-				 * FCTC=0, CHBW=1 */
-	0x0f, 0x00,		/* 0f - reserved */
-	0x10, 0x48,		/* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
-	0x11, 0x1c,		/* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
-				 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
-	0x12, 0x00,		/* 12 - output control 2 */
-	0x13, 0x00,		/* 13 - output control 3 */
-	0x14, 0x00,		/* 14 - reserved */
-	0x15, 0x00,		/* 15 - VBI */
-	0x16, 0x00,		/* 16 - VBI */
-	0x17, 0x00,		/* 17 - VBI */
-};
-
-static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	struct saa7111 *decoder = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case 0:
-		break;
-	case DECODER_INIT:
-	{
-		struct video_decoder_init *init = arg;
-		struct video_decoder_init vdi;
-
-		if (NULL != init)
-			return saa7111_init_decoder(client, init);
-		vdi.data = saa7111_i2c_init;
-		vdi.len = sizeof(saa7111_i2c_init);
-		return saa7111_init_decoder(client, &vdi);
-	}
-
-	case DECODER_DUMP:
-	{
-		int i;
-
-		for (i = 0; i < SAA7111_NR_REG; i += 16) {
-			int j;
-
-			v4l_info(client, "%03x", i);
-			for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
-				printk(KERN_CONT " %02x",
-				       saa7111_read(client, i + j));
-			}
-			printk(KERN_CONT "\n");
-		}
-		break;
-	}
-
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *cap = arg;
-
-		cap->flags = VIDEO_DECODER_PAL |
-			     VIDEO_DECODER_NTSC |
-			     VIDEO_DECODER_SECAM |
-			     VIDEO_DECODER_AUTO |
-			     VIDEO_DECODER_CCIR;
-		cap->inputs = 8;
-		cap->outputs = 1;
-		break;
-	}
-
-	case DECODER_GET_STATUS:
-	{
-		int *iarg = arg;
-		int status;
-		int res;
-
-		status = saa7111_read(client, 0x1f);
-		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
-		res = 0;
-		if ((status & (1 << 6)) == 0) {
-			res |= DECODER_STATUS_GOOD;
-		}
-		switch (decoder->norm) {
-		case VIDEO_MODE_NTSC:
-			res |= DECODER_STATUS_NTSC;
-			break;
-		case VIDEO_MODE_PAL:
-			res |= DECODER_STATUS_PAL;
-			break;
-		case VIDEO_MODE_SECAM:
-			res |= DECODER_STATUS_SECAM;
-			break;
-		default:
-		case VIDEO_MODE_AUTO:
-			if ((status & (1 << 5)) != 0) {
-				res |= DECODER_STATUS_NTSC;
-			} else {
-				res |= DECODER_STATUS_PAL;
-			}
-			break;
-		}
-		if ((status & (1 << 0)) != 0) {
-			res |= DECODER_STATUS_COLOR;
-		}
-		*iarg = res;
-		break;
-	}
-
-	case DECODER_SET_GPIO:
-	{
-		int *iarg = arg;
-		if (0 != *iarg) {
-			saa7111_write(client, 0x11,
-				(decoder->reg[0x11] | 0x80));
-		} else {
-			saa7111_write(client, 0x11,
-				(decoder->reg[0x11] & 0x7f));
-		}
-		break;
-	}
-
-	case DECODER_SET_VBI_BYPASS:
-	{
-		int *iarg = arg;
-		if (0 != *iarg) {
-			saa7111_write(client, 0x13,
-				(decoder->reg[0x13] & 0xf0) | 0x0a);
-		} else {
-			saa7111_write(client, 0x13,
-				(decoder->reg[0x13] & 0xf0));
-		}
-		break;
-	}
-
-	case DECODER_SET_NORM:
-	{
-		int *iarg = arg;
-
-		switch (*iarg) {
-
-		case VIDEO_MODE_NTSC:
-			saa7111_write(client, 0x08,
-				      (decoder->reg[0x08] & 0x3f) | 0x40);
-			saa7111_write(client, 0x0e,
-				      (decoder->reg[0x0e] & 0x8f));
-			break;
-
-		case VIDEO_MODE_PAL:
-			saa7111_write(client, 0x08,
-				      (decoder->reg[0x08] & 0x3f) | 0x00);
-			saa7111_write(client, 0x0e,
-				      (decoder->reg[0x0e] & 0x8f));
-			break;
-
-		case VIDEO_MODE_SECAM:
-			saa7111_write(client, 0x08,
-				      (decoder->reg[0x08] & 0x3f) | 0x00);
-			saa7111_write(client, 0x0e,
-				      (decoder->reg[0x0e] & 0x8f) | 0x50);
-			break;
-
-		case VIDEO_MODE_AUTO:
-			saa7111_write(client, 0x08,
-				      (decoder->reg[0x08] & 0x3f) | 0x80);
-			saa7111_write(client, 0x0e,
-				      (decoder->reg[0x0e] & 0x8f));
-			break;
-
-		default:
-			return -EINVAL;
-
-		}
-		decoder->norm = *iarg;
-		break;
-	}
-
-	case DECODER_SET_INPUT:
-	{
-		int *iarg = arg;
-
-		if (*iarg < 0 || *iarg > 7) {
-			return -EINVAL;
-		}
-
-		if (decoder->input != *iarg) {
-			decoder->input = *iarg;
-			/* select mode */
-			saa7111_write(client, 0x02,
-				      (decoder->
-				       reg[0x02] & 0xf8) | decoder->input);
-			/* bypass chrominance trap for modes 4..7 */
-			saa7111_write(client, 0x09,
-				      (decoder->
-				       reg[0x09] & 0x7f) | ((decoder->
-							     input >
-							     3) ? 0x80 :
-							    0));
-		}
-		break;
-	}
-
-	case DECODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0) {
-			return -EINVAL;
-		}
-		break;
-	}
-
-	case DECODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-		int enable = (*iarg != 0);
-
-		if (decoder->enable != enable) {
-			decoder->enable = enable;
-
-			/* RJ: If output should be disabled (for
-			 * playing videos), we also need a open PLL.
-			 * The input is set to 0 (where no input
-			 * source is connected), although this
-			 * is not necessary.
-			 *
-			 * If output should be enabled, we have to
-			 * reverse the above.
-			 */
-
-			if (decoder->enable) {
-				saa7111_write(client, 0x02,
-					      (decoder->
-					       reg[0x02] & 0xf8) |
-					      decoder->input);
-				saa7111_write(client, 0x08,
-					      (decoder->reg[0x08] & 0xfb));
-				saa7111_write(client, 0x11,
-					      (decoder->
-					       reg[0x11] & 0xf3) | 0x0c);
-			} else {
-				saa7111_write(client, 0x02,
-					      (decoder->reg[0x02] & 0xf8));
-				saa7111_write(client, 0x08,
-					      (decoder->
-					       reg[0x08] & 0xfb) | 0x04);
-				saa7111_write(client, 0x11,
-					      (decoder->reg[0x11] & 0xf3));
-			}
-		}
-		break;
-	}
-
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *pic = arg;
-
-		/* We want 0 to 255 we get 0-65535 */
-		saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
-		/* We want 0 to 127 we get 0-65535 */
-		saa7111_write(client, 0x0b, pic->contrast >> 9);
-		/* We want 0 to 127 we get 0-65535 */
-		saa7111_write(client, 0x0c, pic->colour >> 9);
-		/* We want -128 to 127 we get 0-65535 */
-		saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
-		break;
-	}
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
-static int saa7111_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	int i;
-	struct saa7111 *decoder;
-	struct video_decoder_init vdi;
-
-	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	v4l_info(client, "chip found @ 0x%x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
-	if (decoder == NULL) {
-		kfree(client);
-		return -ENOMEM;
-	}
-	decoder->norm = VIDEO_MODE_NTSC;
-	decoder->input = 0;
-	decoder->enable = 1;
-	i2c_set_clientdata(client, decoder);
-
-	vdi.data = saa7111_i2c_init;
-	vdi.len = sizeof(saa7111_i2c_init);
-	i = saa7111_init_decoder(client, &vdi);
-	if (i < 0) {
-		v4l_dbg(1, debug, client, "init status %d\n", i);
-	} else {
-		v4l_dbg(1, debug, client, "revision %x\n",
-			saa7111_read(client, 0x00) >> 4);
-	}
-	return 0;
-}
-
-static int saa7111_remove(struct i2c_client *client)
-{
-	kfree(i2c_get_clientdata(client));
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct i2c_device_id saa7111_id[] = {
-	{ "saa7111_old", 0 },	/* "saa7111" maps to the saa7115 driver */
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, saa7111_id);
-
-static struct v4l2_i2c_driver_data v4l2_i2c_data = {
-	.name = "saa7111",
-	.driverid = I2C_DRIVERID_SAA7111A,
-	.command = saa7111_command,
-	.probe = saa7111_probe,
-	.remove = saa7111_remove,
-	.id_table = saa7111_id,
-};
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
deleted file mode 100644
index 7ca709f..0000000
--- a/drivers/media/video/saa7114.c
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- * saa7114 - Philips SAA7114H video decoder driver version 0.0.1
- *
- * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
- *
- * Based on saa7111 driver by Dave Perks
- *
- * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * Slight changes for video timing and attachment output by
- * Wolfgang Scherr <scherr@net4you.net>
- *
- * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
- *    - moved over to linux>=2.4.x i2c protocol (1/1/2003)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/types.h>
-#include <linux/ioctl.h>
-#include <asm/uaccess.h>
-#include <linux/i2c.h>
-#include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
-
-MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
-MODULE_AUTHOR("Maxim Yevtyushkin");
-MODULE_LICENSE("GPL");
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
-
-/* ----------------------------------------------------------------------- */
-
-struct saa7114 {
-	unsigned char reg[0xf0 * 2];
-
-	int norm;
-	int input;
-	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
-	int playback;
-};
-
-#define   I2C_DELAY   10
-
-
-//#define SAA_7114_NTSC_HSYNC_START       (-3)
-//#define SAA_7114_NTSC_HSYNC_STOP        (-18)
-
-#define SAA_7114_NTSC_HSYNC_START  (-17)
-#define SAA_7114_NTSC_HSYNC_STOP   (-32)
-
-//#define SAA_7114_NTSC_HOFFSET           (5)
-#define SAA_7114_NTSC_HOFFSET		(6)
-#define SAA_7114_NTSC_VOFFSET           (10)
-#define SAA_7114_NTSC_WIDTH             (720)
-#define SAA_7114_NTSC_HEIGHT            (250)
-
-#define SAA_7114_SECAM_HSYNC_START      (-17)
-#define SAA_7114_SECAM_HSYNC_STOP       (-32)
-
-#define SAA_7114_SECAM_HOFFSET          (2)
-#define SAA_7114_SECAM_VOFFSET          (10)
-#define SAA_7114_SECAM_WIDTH            (720)
-#define SAA_7114_SECAM_HEIGHT           (300)
-
-#define SAA_7114_PAL_HSYNC_START        (-17)
-#define SAA_7114_PAL_HSYNC_STOP         (-32)
-
-#define SAA_7114_PAL_HOFFSET            (2)
-#define SAA_7114_PAL_VOFFSET            (10)
-#define SAA_7114_PAL_WIDTH              (720)
-#define SAA_7114_PAL_HEIGHT             (300)
-
-
-
-#define SAA_7114_VERTICAL_CHROMA_OFFSET         0	//0x50504040
-#define SAA_7114_VERTICAL_LUMA_OFFSET           0
-
-#define REG_ADDR(x) (((x) << 1) + 1)
-#define LOBYTE(x) ((unsigned char)((x) & 0xff))
-#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
-#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
-#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
-
-
-/* ----------------------------------------------------------------------- */
-
-static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value);
-}
-
-static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
-{
-	int ret = -1;
-	u8 reg;
-
-	/* the saa7114 has an autoincrement function, use it if
-	 * the adapter understands raw I2C */
-	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		/* do raw I2C, not smbus compatible */
-		u8 block_data[32];
-		int block_len;
-
-		while (len >= 2) {
-			block_len = 0;
-			block_data[block_len++] = reg = data[0];
-			do {
-				block_data[block_len++] = data[1];
-				reg++;
-				len -= 2;
-				data += 2;
-			} while (len >= 2 && data[0] == reg && block_len < 32);
-			ret = i2c_master_send(client, block_data, block_len);
-			if (ret < 0)
-				break;
-		}
-	} else {
-		/* do some slow I2C emulation kind of thing */
-		while (len >= 2) {
-			reg = *data++;
-			ret = saa7114_write(client, reg, *data++);
-			if (ret < 0)
-				break;
-			len -= 2;
-		}
-	}
-
-	return ret;
-}
-
-static inline int saa7114_read(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-/* ----------------------------------------------------------------------- */
-
-// initially set NTSC, composite
-
-
-static const unsigned char init[] = {
-	0x00, 0x00,		/* 00 - ID byte , chip version,
-				 * read only */
-	0x01, 0x08,		/* 01 - X,X,X,X, IDEL3 to IDEL0 -
-				 * horizontal increment delay,
-				 * recommended position */
-	0x02, 0x00,		/* 02 - FUSE=3, GUDL=2, MODE=0 ;
-				 * input control */
-	0x03, 0x10,		/* 03 - HLNRS=0, VBSL=1, WPOFF=0,
-				 * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
-	0x04, 0x90,		/* 04 - GAI1=256 */
-	0x05, 0x90,		/* 05 - GAI2=256 */
-	0x06, SAA_7114_NTSC_HSYNC_START,	/* 06 - HSB: hsync start,
-				 * depends on the video standard */
-	0x07, SAA_7114_NTSC_HSYNC_STOP,	/* 07 - HSS: hsync stop, depends
-				 *on the video standard */
-	0x08, 0xb8,		/* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
-				 * HPLL: free running in playback, locked
-				 * in capture, VNOI=0 */
-	0x09, 0x80,		/* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0,
-				 * UPTCV=0, APER=1; depends from input */
-	0x0a, 0x80,		/* 0a - BRIG=128 */
-	0x0b, 0x44,		/* 0b - CONT=1.109 */
-	0x0c, 0x40,		/* 0c - SATN=1.0 */
-	0x0d, 0x00,		/* 0d - HUE=0 */
-	0x0e, 0x84,		/* 0e - CDTO, CSTD2 to 0, DCVF, FCTC,
-				 * CCOMB; depends from video standard */
-	0x0f, 0x24,		/* 0f - ACGC,CGAIN6 to CGAIN0; depends
-				 * from video standard */
-	0x10, 0x03,		/* 10 - OFFU1 to 0, OFFV1 to 0, CHBW,
-				 * LCBW2 to 0 */
-	0x11, 0x59,		/* 11 - COLO, RTP1, HEDL1 to 0, RTP0,
-				 * YDEL2 to 0 */
-	0x12, 0xc9,		/* 12 - RT signal control RTSE13 to 10
-				 * and 03 to 00 */
-	0x13, 0x80,		/* 13 - RT/X port output control  */
-	0x14, 0x00,		/* 14 - analog, ADC, compatibility control */
-	0x15, 0x00,		/* 15 - VGATE start FID change  */
-	0x16, 0xfe,		/* 16 - VGATE stop */
-	0x17, 0x00,		/* 17 - Misc., VGATE MSBs */
-	0x18, 0x40,		/* RAWG */
-	0x19, 0x80,		/* RAWO */
-	0x1a, 0x00,
-	0x1b, 0x00,
-	0x1c, 0x00,
-	0x1d, 0x00,
-	0x1e, 0x00,
-	0x1f, 0x00,		/* status byte, read only */
-	0x20, 0x00,		/* video decoder reserved part */
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x00,
-	0x25, 0x00,
-	0x26, 0x00,
-	0x27, 0x00,
-	0x28, 0x00,
-	0x29, 0x00,
-	0x2a, 0x00,
-	0x2b, 0x00,
-	0x2c, 0x00,
-	0x2d, 0x00,
-	0x2e, 0x00,
-	0x2f, 0x00,
-	0x30, 0xbc,		/* audio clock generator */
-	0x31, 0xdf,
-	0x32, 0x02,
-	0x33, 0x00,
-	0x34, 0xcd,
-	0x35, 0xcc,
-	0x36, 0x3a,
-	0x37, 0x00,
-	0x38, 0x03,
-	0x39, 0x10,
-	0x3a, 0x00,
-	0x3b, 0x00,
-	0x3c, 0x00,
-	0x3d, 0x00,
-	0x3e, 0x00,
-	0x3f, 0x00,
-	0x40, 0x00,		/* VBI data slicer */
-	0x41, 0xff,
-	0x42, 0xff,
-	0x43, 0xff,
-	0x44, 0xff,
-	0x45, 0xff,
-	0x46, 0xff,
-	0x47, 0xff,
-	0x48, 0xff,
-	0x49, 0xff,
-	0x4a, 0xff,
-	0x4b, 0xff,
-	0x4c, 0xff,
-	0x4d, 0xff,
-	0x4e, 0xff,
-	0x4f, 0xff,
-	0x50, 0xff,
-	0x51, 0xff,
-	0x52, 0xff,
-	0x53, 0xff,
-	0x54, 0xff,
-	0x55, 0xff,
-	0x56, 0xff,
-	0x57, 0xff,
-	0x58, 0x40,		// framing code
-	0x59, 0x47,		// horizontal offset
-	0x5a, 0x06,		// vertical offset
-	0x5b, 0x83,		// field offset
-	0x5c, 0x00,		// reserved
-	0x5d, 0x3e,		// header and data
-	0x5e, 0x00,		// sliced data
-	0x5f, 0x00,		// reserved
-	0x60, 0x00,		/* video decoder reserved part */
-	0x61, 0x00,
-	0x62, 0x00,
-	0x63, 0x00,
-	0x64, 0x00,
-	0x65, 0x00,
-	0x66, 0x00,
-	0x67, 0x00,
-	0x68, 0x00,
-	0x69, 0x00,
-	0x6a, 0x00,
-	0x6b, 0x00,
-	0x6c, 0x00,
-	0x6d, 0x00,
-	0x6e, 0x00,
-	0x6f, 0x00,
-	0x70, 0x00,		/* video decoder reserved part */
-	0x71, 0x00,
-	0x72, 0x00,
-	0x73, 0x00,
-	0x74, 0x00,
-	0x75, 0x00,
-	0x76, 0x00,
-	0x77, 0x00,
-	0x78, 0x00,
-	0x79, 0x00,
-	0x7a, 0x00,
-	0x7b, 0x00,
-	0x7c, 0x00,
-	0x7d, 0x00,
-	0x7e, 0x00,
-	0x7f, 0x00,
-	0x80, 0x00,		/* X-port, I-port and scaler */
-	0x81, 0x00,
-	0x82, 0x00,
-	0x83, 0x00,
-	0x84, 0xc5,
-	0x85, 0x0d,		// hsync and vsync ?
-	0x86, 0x40,
-	0x87, 0x01,
-	0x88, 0x00,
-	0x89, 0x00,
-	0x8a, 0x00,
-	0x8b, 0x00,
-	0x8c, 0x00,
-	0x8d, 0x00,
-	0x8e, 0x00,
-	0x8f, 0x00,
-	0x90, 0x03,		/* Task A definition           */
-	0x91, 0x08,
-	0x92, 0x00,
-	0x93, 0x40,
-	0x94, 0x00,		// window settings
-	0x95, 0x00,
-	0x96, 0x00,
-	0x97, 0x00,
-	0x98, 0x00,
-	0x99, 0x00,
-	0x9a, 0x00,
-	0x9b, 0x00,
-	0x9c, 0x00,
-	0x9d, 0x00,
-	0x9e, 0x00,
-	0x9f, 0x00,
-	0xa0, 0x01,		/* horizontal integer prescaling ratio */
-	0xa1, 0x00,		/* horizontal prescaler accumulation
-				 * sequence length */
-	0xa2, 0x00,		/* UV FIR filter, Y FIR filter, prescaler
-				 * DC gain */
-	0xa3, 0x00,
-	0xa4, 0x80,		// luminance brightness
-	0xa5, 0x40,		// luminance gain
-	0xa6, 0x40,		// chrominance saturation
-	0xa7, 0x00,
-	0xa8, 0x00,		// horizontal luminance scaling increment
-	0xa9, 0x04,
-	0xaa, 0x00,		// horizontal luminance phase offset
-	0xab, 0x00,
-	0xac, 0x00,		// horizontal chrominance scaling increment
-	0xad, 0x02,
-	0xae, 0x00,		// horizontal chrominance phase offset
-	0xaf, 0x00,
-	0xb0, 0x00,		// vertical luminance scaling increment
-	0xb1, 0x04,
-	0xb2, 0x00,		// vertical chrominance scaling increment
-	0xb3, 0x04,
-	0xb4, 0x00,
-	0xb5, 0x00,
-	0xb6, 0x00,
-	0xb7, 0x00,
-	0xb8, 0x00,
-	0xb9, 0x00,
-	0xba, 0x00,
-	0xbb, 0x00,
-	0xbc, 0x00,
-	0xbd, 0x00,
-	0xbe, 0x00,
-	0xbf, 0x00,
-	0xc0, 0x02,		// Task B definition
-	0xc1, 0x08,
-	0xc2, 0x00,
-	0xc3, 0x40,
-	0xc4, 0x00,		// window settings
-	0xc5, 0x00,
-	0xc6, 0x00,
-	0xc7, 0x00,
-	0xc8, 0x00,
-	0xc9, 0x00,
-	0xca, 0x00,
-	0xcb, 0x00,
-	0xcc, 0x00,
-	0xcd, 0x00,
-	0xce, 0x00,
-	0xcf, 0x00,
-	0xd0, 0x01,		// horizontal integer prescaling ratio
-	0xd1, 0x00,		// horizontal prescaler accumulation sequence length
-	0xd2, 0x00,		// UV FIR filter, Y FIR filter, prescaler DC gain
-	0xd3, 0x00,
-	0xd4, 0x80,		// luminance brightness
-	0xd5, 0x40,		// luminance gain
-	0xd6, 0x40,		// chrominance saturation
-	0xd7, 0x00,
-	0xd8, 0x00,		// horizontal luminance scaling increment
-	0xd9, 0x04,
-	0xda, 0x00,		// horizontal luminance phase offset
-	0xdb, 0x00,
-	0xdc, 0x00,		// horizontal chrominance scaling increment
-	0xdd, 0x02,
-	0xde, 0x00,		// horizontal chrominance phase offset
-	0xdf, 0x00,
-	0xe0, 0x00,		// vertical luminance scaling increment
-	0xe1, 0x04,
-	0xe2, 0x00,		// vertical chrominance scaling increment
-	0xe3, 0x04,
-	0xe4, 0x00,
-	0xe5, 0x00,
-	0xe6, 0x00,
-	0xe7, 0x00,
-	0xe8, 0x00,
-	0xe9, 0x00,
-	0xea, 0x00,
-	0xeb, 0x00,
-	0xec, 0x00,
-	0xed, 0x00,
-	0xee, 0x00,
-	0xef, 0x00
-};
-
-static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	struct saa7114 *decoder = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case 0:
-		//dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
-		//saa7114_write_block(client, init, sizeof(init));
-		break;
-
-	case DECODER_DUMP:
-	{
-		int i;
-
-		if (!debug)
-			break;
-		v4l_info(client, "decoder dump\n");
-
-		for (i = 0; i < 32; i += 16) {
-			int j;
-
-			v4l_info(client, "%03x", i);
-			for (j = 0; j < 16; ++j) {
-				printk(KERN_CONT " %02x",
-				       saa7114_read(client, i + j));
-			}
-			printk(KERN_CONT "\n");
-		}
-		break;
-	}
-
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *cap = arg;
-
-		v4l_dbg(1, debug, client, "get capabilities\n");
-
-		cap->flags = VIDEO_DECODER_PAL |
-			     VIDEO_DECODER_NTSC |
-			     VIDEO_DECODER_AUTO |
-			     VIDEO_DECODER_CCIR;
-		cap->inputs = 8;
-		cap->outputs = 1;
-		break;
-	}
-
-	case DECODER_GET_STATUS:
-	{
-		int *iarg = arg;
-		int status;
-		int res;
-
-		status = saa7114_read(client, 0x1f);
-
-		v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
-		res = 0;
-		if ((status & (1 << 6)) == 0) {
-			res |= DECODER_STATUS_GOOD;
-		}
-		switch (decoder->norm) {
-		case VIDEO_MODE_NTSC:
-			res |= DECODER_STATUS_NTSC;
-			break;
-		case VIDEO_MODE_PAL:
-			res |= DECODER_STATUS_PAL;
-			break;
-		case VIDEO_MODE_SECAM:
-			res |= DECODER_STATUS_SECAM;
-			break;
-		default:
-		case VIDEO_MODE_AUTO:
-			if ((status & (1 << 5)) != 0) {
-				res |= DECODER_STATUS_NTSC;
-			} else {
-				res |= DECODER_STATUS_PAL;
-			}
-			break;
-		}
-		if ((status & (1 << 0)) != 0) {
-			res |= DECODER_STATUS_COLOR;
-		}
-		*iarg = res;
-		break;
-	}
-
-	case DECODER_SET_NORM:
-	{
-		int *iarg = arg;
-
-		short int hoff = 0, voff = 0, w = 0, h = 0;
-
-		v4l_dbg(1, debug, client, "set norm\n");
-
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			v4l_dbg(1, debug, client, "NTSC\n");
-			decoder->reg[REG_ADDR(0x06)] =
-			    SAA_7114_NTSC_HSYNC_START;
-			decoder->reg[REG_ADDR(0x07)] =
-			    SAA_7114_NTSC_HSYNC_STOP;
-
-			decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8;	// PLL free when playback, PLL close when capture
-
-			decoder->reg[REG_ADDR(0x0e)] = 0x85;
-			decoder->reg[REG_ADDR(0x0f)] = 0x24;
-
-			hoff = SAA_7114_NTSC_HOFFSET;
-			voff = SAA_7114_NTSC_VOFFSET;
-			w = SAA_7114_NTSC_WIDTH;
-			h = SAA_7114_NTSC_HEIGHT;
-
-			break;
-
-		case VIDEO_MODE_PAL:
-			v4l_dbg(1, debug, client, "PAL\n");
-			decoder->reg[REG_ADDR(0x06)] =
-			    SAA_7114_PAL_HSYNC_START;
-			decoder->reg[REG_ADDR(0x07)] =
-			    SAA_7114_PAL_HSYNC_STOP;
-
-			decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8;	// PLL free when playback, PLL close when capture
-
-			decoder->reg[REG_ADDR(0x0e)] = 0x81;
-			decoder->reg[REG_ADDR(0x0f)] = 0x24;
-
-			hoff = SAA_7114_PAL_HOFFSET;
-			voff = SAA_7114_PAL_VOFFSET;
-			w = SAA_7114_PAL_WIDTH;
-			h = SAA_7114_PAL_HEIGHT;
-
-			break;
-
-		default:
-			v4l_dbg(1, debug, client, "Unknown video mode\n");
-			return -EINVAL;
-		}
-
-
-		decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff);	// hoffset low
-		decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f;	// hoffset high
-		decoder->reg[REG_ADDR(0x96)] = LOBYTE(w);	// width low
-		decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f;	// width high
-		decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff);	// voffset low
-		decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f;	// voffset high
-		decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2);	// height low
-		decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f;	// height high
-		decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w);	// out width low
-		decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f;	// out width high
-		decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h);	// out height low
-		decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f;	// out height high
-
-		decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff);	// hoffset low
-		decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f;	// hoffset high
-		decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w);	// width low
-		decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f;	// width high
-		decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff);	// voffset low
-		decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f;	// voffset high
-		decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2);	// height low
-		decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f;	// height high
-		decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w);	// out width low
-		decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f;	// out width high
-		decoder->reg[REG_ADDR(0xce)] = LOBYTE(h);	// out height low
-		decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f;	// out height high
-
-
-		saa7114_write(client, 0x80, 0x06);	// i-port and scaler back end clock selection, task A&B off
-		saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
-		saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
-
-		saa7114_write_block(client, decoder->reg + (0x06 << 1),
-				    3 << 1);
-		saa7114_write_block(client, decoder->reg + (0x0e << 1),
-				    2 << 1);
-		saa7114_write_block(client, decoder->reg + (0x5a << 1),
-				    2 << 1);
-
-		saa7114_write_block(client, decoder->reg + (0x94 << 1),
-				    (0x9f + 1 - 0x94) << 1);
-		saa7114_write_block(client, decoder->reg + (0xc4 << 1),
-				    (0xcf + 1 - 0xc4) << 1);
-
-		saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
-		saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
-		saa7114_write(client, 0x80, 0x36);	// i-port and scaler back end clock selection
-
-		decoder->norm = *iarg;
-		break;
-	}
-
-	case DECODER_SET_INPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
-		if (*iarg < 0 || *iarg > 7) {
-			return -EINVAL;
-		}
-
-		if (decoder->input != *iarg) {
-			v4l_dbg(1, debug, client, "now setting %s input\n",
-				*iarg >= 6 ? "S-Video" : "Composite");
-			decoder->input = *iarg;
-
-			/* select mode */
-			decoder->reg[REG_ADDR(0x02)] =
-			    (decoder->
-			     reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
-							    input <
-							    6 ? 0x0 : 0x9);
-			saa7114_write(client, 0x02,
-				      decoder->reg[REG_ADDR(0x02)]);
-
-			/* bypass chrominance trap for modes 6..9 */
-			decoder->reg[REG_ADDR(0x09)] =
-			    (decoder->
-			     reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
-							    input <
-							    6 ? 0x0 :
-							    0x80);
-			saa7114_write(client, 0x09,
-				      decoder->reg[REG_ADDR(0x09)]);
-
-			decoder->reg[REG_ADDR(0x0e)] =
-			    decoder->input <
-			    6 ? decoder->
-			    reg[REG_ADDR(0x0e)] | 1 : decoder->
-			    reg[REG_ADDR(0x0e)] & ~1;
-			saa7114_write(client, 0x0e,
-				      decoder->reg[REG_ADDR(0x0e)]);
-		}
-		break;
-	}
-
-	case DECODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "set output\n");
-
-		/* not much choice of outputs */
-		if (*iarg != 0) {
-			return -EINVAL;
-		}
-		break;
-	}
-
-	case DECODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-		int enable = (*iarg != 0);
-
-		v4l_dbg(1, debug, client, "%s output\n",
-			enable ? "enable" : "disable");
-
-		decoder->playback = !enable;
-
-		if (decoder->enable != enable) {
-			decoder->enable = enable;
-
-			/* RJ: If output should be disabled (for
-			 * playing videos), we also need a open PLL.
-			 * The input is set to 0 (where no input
-			 * source is connected), although this
-			 * is not necessary.
-			 *
-			 * If output should be enabled, we have to
-			 * reverse the above.
-			 */
-
-			if (decoder->enable) {
-				decoder->reg[REG_ADDR(0x08)] = 0xb8;
-				decoder->reg[REG_ADDR(0x12)] = 0xc9;
-				decoder->reg[REG_ADDR(0x13)] = 0x80;
-				decoder->reg[REG_ADDR(0x87)] = 0x01;
-			} else {
-				decoder->reg[REG_ADDR(0x08)] = 0x7c;
-				decoder->reg[REG_ADDR(0x12)] = 0x00;
-				decoder->reg[REG_ADDR(0x13)] = 0x00;
-				decoder->reg[REG_ADDR(0x87)] = 0x00;
-			}
-
-			saa7114_write_block(client,
-					    decoder->reg + (0x12 << 1),
-					    2 << 1);
-			saa7114_write(client, 0x08,
-				      decoder->reg[REG_ADDR(0x08)]);
-			saa7114_write(client, 0x87,
-				      decoder->reg[REG_ADDR(0x87)]);
-			saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
-			saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
-			saa7114_write(client, 0x80, 0x36);
-
-		}
-		break;
-	}
-
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *pic = arg;
-
-		v4l_dbg(1, debug, client,
-			"decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
-			pic->brightness, pic->contrast, pic->colour, pic->hue);
-
-		if (decoder->bright != pic->brightness) {
-			/* We want 0 to 255 we get 0-65535 */
-			decoder->bright = pic->brightness;
-			saa7114_write(client, 0x0a, decoder->bright >> 8);
-		}
-		if (decoder->contrast != pic->contrast) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->contrast = pic->contrast;
-			saa7114_write(client, 0x0b,
-				      decoder->contrast >> 9);
-		}
-		if (decoder->sat != pic->colour) {
-			/* We want 0 to 127 we get 0-65535 */
-			decoder->sat = pic->colour;
-			saa7114_write(client, 0x0c, decoder->sat >> 9);
-		}
-		if (decoder->hue != pic->hue) {
-			/* We want -128 to 127 we get 0-65535 */
-			decoder->hue = pic->hue;
-			saa7114_write(client, 0x0d,
-				      (decoder->hue - 32768) >> 8);
-		}
-		break;
-	}
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
-static int saa7114_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
-{
-	int i, err[30];
-	short int hoff = SAA_7114_NTSC_HOFFSET;
-	short int voff = SAA_7114_NTSC_VOFFSET;
-	short int w = SAA_7114_NTSC_WIDTH;
-	short int h = SAA_7114_NTSC_HEIGHT;
-	struct saa7114 *decoder;
-
-	/* Check if the adapter supports the needed features */
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	v4l_info(client, "chip found @ 0x%x (%s)\n",
-			client->addr << 1, client->adapter->name);
-
-	decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
-	if (decoder == NULL)
-		return -ENOMEM;
-	decoder->norm = VIDEO_MODE_NTSC;
-	decoder->input = -1;
-	decoder->enable = 1;
-	decoder->bright = 32768;
-	decoder->contrast = 32768;
-	decoder->hue = 32768;
-	decoder->sat = 32768;
-	decoder->playback = 0;	// initially capture mode useda
-	i2c_set_clientdata(client, decoder);
-
-	memcpy(decoder->reg, init, sizeof(init));
-
-	decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff);	// hoffset low
-	decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f;	// hoffset high
-	decoder->reg[REG_ADDR(0x96)] = LOBYTE(w);	// width low
-	decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f;	// width high
-	decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff);	// voffset low
-	decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f;	// voffset high
-	decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2);	// height low
-	decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f;	// height high
-	decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w);	// out width low
-	decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f;	// out width high
-	decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h);	// out height low
-	decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f;	// out height high
-
-	decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff);	// hoffset low
-	decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f;	// hoffset high
-	decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w);	// width low
-	decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f;	// width high
-	decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff);	// voffset low
-	decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f;	// voffset high
-	decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2);	// height low
-	decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f;	// height high
-	decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w);	// out width low
-	decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f;	// out width high
-	decoder->reg[REG_ADDR(0xce)] = LOBYTE(h);	// out height low
-	decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f;	// out height high
-
-	decoder->reg[REG_ADDR(0xb8)] =
-	    LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xb9)] =
-	    HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xba)] =
-	    LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xbb)] =
-	    HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-
-	decoder->reg[REG_ADDR(0xbc)] =
-	    LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xbd)] =
-	    HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xbe)] =
-	    LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xbf)] =
-	    HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-
-	decoder->reg[REG_ADDR(0xe8)] =
-	    LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xe9)] =
-	    HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xea)] =
-	    LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-	decoder->reg[REG_ADDR(0xeb)] =
-	    HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
-
-	decoder->reg[REG_ADDR(0xec)] =
-	    LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xed)] =
-	    HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xee)] =
-	    LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-	decoder->reg[REG_ADDR(0xef)] =
-	    HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
-
-
-	decoder->reg[REG_ADDR(0x13)] = 0x80;	// RTC0 on
-	decoder->reg[REG_ADDR(0x87)] = 0x01;	// I-Port
-	decoder->reg[REG_ADDR(0x12)] = 0xc9;	// RTS0
-
-	decoder->reg[REG_ADDR(0x02)] = 0xc0;	// set composite1 input, aveasy
-	decoder->reg[REG_ADDR(0x09)] = 0x00;	// chrominance trap
-	decoder->reg[REG_ADDR(0x0e)] |= 1;	// combfilter on
-
-
-	v4l_dbg(1, debug, client, "starting init\n");
-
-	err[0] =
-	    saa7114_write_block(client, decoder->reg + (0x20 << 1),
-				0x10 << 1);
-	err[1] =
-	    saa7114_write_block(client, decoder->reg + (0x30 << 1),
-				0x10 << 1);
-	err[2] =
-	    saa7114_write_block(client, decoder->reg + (0x63 << 1),
-				(0x7f + 1 - 0x63) << 1);
-	err[3] =
-	    saa7114_write_block(client, decoder->reg + (0x89 << 1),
-				6 << 1);
-	err[4] =
-	    saa7114_write_block(client, decoder->reg + (0xb8 << 1),
-				8 << 1);
-	err[5] =
-	    saa7114_write_block(client, decoder->reg + (0xe8 << 1),
-				8 << 1);
-
-
-	for (i = 0; i <= 5; i++) {
-		if (err[i] < 0) {
-			v4l_dbg(1, debug, client,
-				"init error %d at stage %d, leaving attach.\n",
-				i, err[i]);
-			kfree(decoder);
-			return -EIO;
-		}
-	}
-
-	for (i = 6; i < 8; i++) {
-		v4l_dbg(1, debug, client,
-			"reg[0x%02x] = 0x%02x (0x%02x)\n",
-			i, saa7114_read(client, i),
-			decoder->reg[REG_ADDR(i)]);
-	}
-
-	v4l_dbg(1, debug, client,
-		"performing decoder reset sequence\n");
-
-	err[6] = saa7114_write(client, 0x80, 0x06);	// i-port and scaler backend clock selection, task A&B off
-	err[7] = saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
-	err[8] = saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
-
-	for (i = 6; i <= 8; i++) {
-		if (err[i] < 0) {
-			v4l_dbg(1, debug, client,
-				"init error %d at stage %d, leaving attach.\n",
-				i, err[i]);
-			kfree(decoder);
-			return -EIO;
-		}
-	}
-
-	v4l_dbg(1, debug, client, "performing the rest of init\n");
-
-	err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
-	err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1);	// big seq
-	err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1);	// slicer
-	err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1);	// ?
-	err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1);	// ?
-	err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1);	// Task A
-	err[15] =
-	    saa7114_write_block(client, decoder->reg + (0x94 << 1),
-				12 << 1);
-	err[16] =
-	    saa7114_write_block(client, decoder->reg + (0xa0 << 1),
-				8 << 1);
-	err[17] =
-	    saa7114_write_block(client, decoder->reg + (0xa8 << 1),
-				8 << 1);
-	err[18] =
-	    saa7114_write_block(client, decoder->reg + (0xb0 << 1),
-				8 << 1);
-	err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1);	// Task B
-	err[15] =
-	    saa7114_write_block(client, decoder->reg + (0xc4 << 1),
-				12 << 1);
-	err[16] =
-	    saa7114_write_block(client, decoder->reg + (0xd0 << 1),
-				8 << 1);
-	err[17] =
-	    saa7114_write_block(client, decoder->reg + (0xd8 << 1),
-				8 << 1);
-	err[18] =
-	    saa7114_write_block(client, decoder->reg + (0xe0 << 1),
-				8 << 1);
-
-	for (i = 9; i <= 18; i++) {
-		if (err[i] < 0) {
-			v4l_dbg(1, debug, client,
-				"init error %d at stage %d, leaving attach.\n",
-				i, err[i]);
-			kfree(decoder);
-			return -EIO;
-		}
-	}
-
-
-	for (i = 6; i < 8; i++) {
-		v4l_dbg(1, debug, client,
-			"reg[0x%02x] = 0x%02x (0x%02x)\n",
-			i, saa7114_read(client, i),
-			decoder->reg[REG_ADDR(i)]);
-	}
-
-
-	for (i = 0x11; i <= 0x13; i++) {
-		v4l_dbg(1, debug, client,
-			"reg[0x%02x] = 0x%02x (0x%02x)\n",
-			i, saa7114_read(client, i),
-			decoder->reg[REG_ADDR(i)]);
-	}
-
-
-	v4l_dbg(1, debug, client, "setting video input\n");
-
-	err[19] =
-	    saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
-	err[20] =
-	    saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]);
-	err[21] =
-	    saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]);
-
-	for (i = 19; i <= 21; i++) {
-		if (err[i] < 0) {
-			v4l_dbg(1, debug, client,
-				"init error %d at stage %d, leaving attach.\n",
-				i, err[i]);
-			kfree(decoder);
-			return -EIO;
-		}
-	}
-
-	v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
-
-	err[22] = saa7114_write(client, 0x88, 0xd8);	// sw reset scaler
-	err[23] = saa7114_write(client, 0x88, 0xf8);	// sw reset scaler release
-	err[24] = saa7114_write(client, 0x80, 0x36);	// i-port and scaler backend clock selection, task A&B off
-
-
-	for (i = 22; i <= 24; i++) {
-		if (err[i] < 0) {
-			v4l_dbg(1, debug, client,
-				"init error %d at stage %d, leaving attach.\n",
-				i, err[i]);
-			kfree(decoder);
-			return -EIO;
-		}
-	}
-
-	err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]);
-	err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
-	err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
-
-	v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
-		saa7114_read(client, 0x00) >> 4,
-		saa7114_read(client, 0x1f));
-	v4l_dbg(1, debug, client,
-		"power save control: 0x%02x, scaler status: 0x%02x\n",
-		saa7114_read(client, 0x88),
-		saa7114_read(client, 0x8f));
-
-
-	for (i = 0x94; i < 0x96; i++) {
-		v4l_dbg(1, debug, client,
-			"reg[0x%02x] = 0x%02x (0x%02x)\n",
-			i, saa7114_read(client, i),
-			decoder->reg[REG_ADDR(i)]);
-	}
-
-	//i = saa7114_write_block(client, init, sizeof(init));
-	return 0;
-}
-
-static int saa7114_remove(struct i2c_client *client)
-{
-	kfree(i2c_get_clientdata(client));
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct i2c_device_id saa7114_id[] = {
-	{ "saa7114_old", 0 },	/* "saa7114" maps to the saa7115 driver */
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, saa7114_id);
-
-static struct v4l2_i2c_driver_data v4l2_i2c_data = {
-	.name = "saa7114",
-	.driverid = I2C_DRIVERID_SAA7114,
-	.command = saa7114_command,
-	.probe = saa7114_probe,
-	.remove = saa7114_remove,
-	.id_table = saa7114_id,
-};
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 46c796c..cebf159 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -778,7 +778,7 @@
 		break;
 
 	case V4L2_CID_HUE:
-		if (ctrl->value < -127 || ctrl->value > 127) {
+		if (ctrl->value < -128 || ctrl->value > 127) {
 			v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
 			return -ERANGE;
 		}
@@ -931,8 +931,8 @@
 	/* Prevent unnecessary standard changes. During a standard
 	   change the I-Port is temporarily disabled. Any devices
 	   reading from that port can get confused.
-	   Note that VIDIOC_S_STD is also used to switch from
-	   radio to TV mode, so if a VIDIOC_S_STD is broadcast to
+	   Note that s_std is also used to switch from
+	   radio to TV mode, so if a s_std is broadcast to
 	   all I2C devices then you do not want to have an unwanted
 	   side-effect here. */
 	if (std == state->std)
@@ -1206,10 +1206,12 @@
 {
 	switch (qc->id) {
 	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
 	case V4L2_CID_CONTRAST:
 	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
 	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill_std(qc);
+		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 	default:
 		return -EINVAL;
 	}
@@ -1308,11 +1310,12 @@
 	v4l2_dbg(1, debug, sd, "%s output\n",
 			enable ? "enable" : "disable");
 
-	if (state->enable != enable) {
-		state->enable = enable;
-		saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,
-				state->enable);
-	}
+	if (state->enable == enable)
+		return 0;
+	state->enable = enable;
+	if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
+		return 0;
+	saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
 	return 0;
 }
 
@@ -1370,6 +1373,47 @@
 	}
 }
 
+static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct saa711x_state *state = to_state(sd);
+	int reg1e;
+
+	*std = V4L2_STD_ALL;
+	if (state->ident != V4L2_IDENT_SAA7115)
+		return 0;
+	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
+
+	switch (reg1e & 0x03) {
+	case 1:
+		*std = V4L2_STD_NTSC;
+		break;
+	case 2:
+		*std = V4L2_STD_PAL;
+		break;
+	case 3:
+		*std = V4L2_STD_SECAM;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct saa711x_state *state = to_state(sd);
+	int reg1e = 0x80;
+	int reg1f;
+
+	*status = V4L2_IN_ST_NO_SIGNAL;
+	if (state->ident == V4L2_IDENT_SAA7115)
+		reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
+	reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+	if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
+		*status = 0;
+	return 0;
+}
+
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
 {
@@ -1493,6 +1537,8 @@
 	.g_vbi_data = saa711x_g_vbi_data,
 	.decode_vbi_line = saa711x_decode_vbi_line,
 	.s_stream = saa711x_s_stream,
+	.querystd = saa711x_querystd,
+	.g_input_status = saa711x_g_input_status,
 };
 
 static const struct v4l2_subdev_ops saa711x_ops = {
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 05221d4..128bb8b 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -810,7 +810,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa7127",
-	.driverid = I2C_DRIVERID_SAA7127,
 	.probe = saa7127_probe,
 	.remove = saa7127_remove,
 	.id_table = saa7127_id,
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index fc2164e..0ba6898 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -6,6 +6,7 @@
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM
 	select CRC32
+	select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
 	---help---
 	  This is a video4linux driver for Philips SAA713x based
 	  TV cards.
@@ -35,8 +36,16 @@
 	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
 	select DVB_TDA826X if !DVB_FE_CUSTOMISE
 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+	select DVB_ISL6405 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+	select DVB_ZL10036 if !DVB_FE_CUSTOMISE
+	select DVB_MT312 if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  This adds support for DVB cards based on the
 	  Philips saa7134 chip.
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 1fee6e8..dc2213e 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -33,9 +33,10 @@
 #include <linux/i2c.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 #include <linux/init.h>
 #include <linux/crc32.h>
 
@@ -44,10 +45,6 @@
 #define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
 #define MPEG_PID_MAX ((1 << 14) - 1)
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
-
-I2C_CLIENT_INSMOD;
 
 MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
 MODULE_AUTHOR("Andrew de Quincey");
@@ -95,6 +92,7 @@
 };
 
 struct saa6752hs_state {
+	struct v4l2_subdev            sd;
 	int 			      chip;
 	u32 			      revision;
 	int 			      has_ac3;
@@ -115,6 +113,11 @@
 	SAA6752HS_COMMAND_MAX
 };
 
+static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa6752hs_state, sd);
+}
+
 /* ---------------------------------------------------------------------- */
 
 static u8 PAT[] = {
@@ -360,185 +363,191 @@
 	return 0;
 }
 
-static void saa6752hs_set_subsampling(struct i2c_client *client,
-				      struct v4l2_format *f)
+
+static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
+		struct v4l2_ext_control *ctrl)
 {
-	struct saa6752hs_state *h = i2c_get_clientdata(client);
-	int dist_352, dist_480, dist_720;
-
-	/*
-	  FIXME: translate and round width/height into EMPRESS
-	  subsample type:
-
-	  type   |   PAL   |  NTSC
-	  ---------------------------
-	  SIF    | 352x288 | 352x240
-	  1/2 D1 | 352x576 | 352x480
-	  2/3 D1 | 480x576 | 480x480
-	  D1     | 720x576 | 720x480
-	*/
-
-	dist_352 = abs(f->fmt.pix.width - 352);
-	dist_480 = abs(f->fmt.pix.width - 480);
-	dist_720 = abs(f->fmt.pix.width - 720);
-	if (dist_720 < dist_480) {
-		f->fmt.pix.width = 720;
-		f->fmt.pix.height = 576;
-		h->video_format = SAA6752HS_VF_D1;
-	}
-	else if (dist_480 < dist_352) {
-		f->fmt.pix.width = 480;
-		f->fmt.pix.height = 576;
-		h->video_format = SAA6752HS_VF_2_3_D1;
-	}
-	else {
-		f->fmt.pix.width = 352;
-		if (abs(f->fmt.pix.height - 576) <
-		    abs(f->fmt.pix.height - 288)) {
-			f->fmt.pix.height = 576;
-			h->video_format = SAA6752HS_VF_1_2_D1;
-		}
-		else {
-			f->fmt.pix.height = 288;
-			h->video_format = SAA6752HS_VF_SIF;
-		}
-	}
-}
-
-
-static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
-		struct v4l2_ext_control *ctrl, unsigned int cmd)
-{
-	int old = 0, new;
-	int set = (cmd == VIDIOC_S_EXT_CTRLS);
-
-	new = ctrl->value;
 	switch (ctrl->id) {
-		case V4L2_CID_MPEG_STREAM_TYPE:
-			old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
-			if (set && new != old)
-				return -ERANGE;
-			new = old;
-			break;
-		case V4L2_CID_MPEG_STREAM_PID_PMT:
-			old = params->ts_pid_pmt;
-			if (set && new > MPEG_PID_MAX)
-				return -ERANGE;
-			if (new > MPEG_PID_MAX)
-				new = MPEG_PID_MAX;
-			params->ts_pid_pmt = new;
-			break;
-		case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-			old = params->ts_pid_audio;
-			if (set && new > MPEG_PID_MAX)
-				return -ERANGE;
-			if (new > MPEG_PID_MAX)
-				new = MPEG_PID_MAX;
-			params->ts_pid_audio = new;
-			break;
-		case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-			old = params->ts_pid_video;
-			if (set && new > MPEG_PID_MAX)
-				return -ERANGE;
-			if (new > MPEG_PID_MAX)
-				new = MPEG_PID_MAX;
-			params->ts_pid_video = new;
-			break;
-		case V4L2_CID_MPEG_STREAM_PID_PCR:
-			old = params->ts_pid_pcr;
-			if (set && new > MPEG_PID_MAX)
-				return -ERANGE;
-			if (new > MPEG_PID_MAX)
-				new = MPEG_PID_MAX;
-			params->ts_pid_pcr = new;
-			break;
-		case V4L2_CID_MPEG_AUDIO_ENCODING:
-			old = params->au_encoding;
-			if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
-			    (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
-				return -ERANGE;
-			new = old;
-			break;
-		case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-			old = params->au_l2_bitrate;
-			if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
-				   new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
-				return -ERANGE;
-			if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
-				new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
-			else
-				new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
-			params->au_l2_bitrate = new;
-			break;
-		case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-			if (!has_ac3)
-				return -EINVAL;
-			old = params->au_ac3_bitrate;
-			if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
-				   new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
-				return -ERANGE;
-			if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
-				new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
-			else
-				new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
-			params->au_ac3_bitrate = new;
-			break;
-		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-			old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
-			if (set && new != old)
-				return -ERANGE;
-			new = old;
-			break;
-		case V4L2_CID_MPEG_VIDEO_ENCODING:
-			old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
-			if (set && new != old)
-				return -ERANGE;
-			new = old;
-			break;
-		case V4L2_CID_MPEG_VIDEO_ASPECT:
-			old = params->vi_aspect;
-			if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
-				   new != V4L2_MPEG_VIDEO_ASPECT_4x3)
-				return -ERANGE;
-			if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
-				new = V4L2_MPEG_VIDEO_ASPECT_4x3;
-			params->vi_aspect = new;
-			break;
-		case V4L2_CID_MPEG_VIDEO_BITRATE:
-			old = params->vi_bitrate * 1000;
-			new = 1000 * (new / 1000);
-			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-				return -ERANGE;
-			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
-			params->vi_bitrate = new / 1000;
-			break;
-		case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-			old = params->vi_bitrate_peak * 1000;
-			new = 1000 * (new / 1000);
-			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-				return -ERANGE;
-			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
-			params->vi_bitrate_peak = new / 1000;
-			break;
-		case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-			old = params->vi_bitrate_mode;
-			params->vi_bitrate_mode = new;
-			break;
-		default:
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PMT:
+		ctrl->value = params->ts_pid_pmt;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+		ctrl->value = params->ts_pid_audio;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+		ctrl->value = params->ts_pid_video;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PCR:
+		ctrl->value = params->ts_pid_pcr;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		ctrl->value = params->au_encoding;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		ctrl->value = params->au_l2_bitrate;
+		break;
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		if (!has_ac3)
 			return -EINVAL;
+		ctrl->value = params->au_ac3_bitrate;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		ctrl->value = params->vi_aspect;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctrl->value = params->vi_bitrate * 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		ctrl->value = params->vi_bitrate_peak * 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		ctrl->value = params->vi_bitrate_mode;
+		break;
+	default:
+		return -EINVAL;
 	}
-	if (cmd == VIDIOC_G_EXT_CTRLS)
-		ctrl->value = old;
-	else
-		ctrl->value = new;
 	return 0;
 }
 
-static int saa6752hs_qctrl(struct saa6752hs_state *h,
-		struct v4l2_queryctrl *qctrl)
+static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
+		struct v4l2_ext_control *ctrl, int set)
 {
+	int old = 0, new;
+
+	new = ctrl->value;
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+		if (set && new != old)
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PMT:
+		old = params->ts_pid_pmt;
+		if (set && new > MPEG_PID_MAX)
+			return -ERANGE;
+		if (new > MPEG_PID_MAX)
+			new = MPEG_PID_MAX;
+		params->ts_pid_pmt = new;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+		old = params->ts_pid_audio;
+		if (set && new > MPEG_PID_MAX)
+			return -ERANGE;
+		if (new > MPEG_PID_MAX)
+			new = MPEG_PID_MAX;
+		params->ts_pid_audio = new;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+		old = params->ts_pid_video;
+		if (set && new > MPEG_PID_MAX)
+			return -ERANGE;
+		if (new > MPEG_PID_MAX)
+			new = MPEG_PID_MAX;
+		params->ts_pid_video = new;
+		break;
+	case V4L2_CID_MPEG_STREAM_PID_PCR:
+		old = params->ts_pid_pcr;
+		if (set && new > MPEG_PID_MAX)
+			return -ERANGE;
+		if (new > MPEG_PID_MAX)
+			new = MPEG_PID_MAX;
+		params->ts_pid_pcr = new;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		old = params->au_encoding;
+		if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+		    (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		old = params->au_l2_bitrate;
+		if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
+			   new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
+			return -ERANGE;
+		if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
+			new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+		else
+			new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+		params->au_l2_bitrate = new;
+		break;
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		if (!has_ac3)
+			return -EINVAL;
+		old = params->au_ac3_bitrate;
+		if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
+			   new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
+			return -ERANGE;
+		if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
+			new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
+		else
+			new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
+		params->au_ac3_bitrate = new;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+		if (set && new != old)
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		if (set && new != old)
+			return -ERANGE;
+		new = old;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		old = params->vi_aspect;
+		if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
+			   new != V4L2_MPEG_VIDEO_ASPECT_4x3)
+			return -ERANGE;
+		if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
+			new = V4L2_MPEG_VIDEO_ASPECT_4x3;
+		params->vi_aspect = new;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		old = params->vi_bitrate * 1000;
+		new = 1000 * (new / 1000);
+		if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			return -ERANGE;
+		if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+		params->vi_bitrate = new / 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		old = params->vi_bitrate_peak * 1000;
+		new = 1000 * (new / 1000);
+		if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			return -ERANGE;
+		if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+			new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+		params->vi_bitrate_peak = new / 1000;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		old = params->vi_bitrate_mode;
+		params->vi_bitrate_mode = new;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ctrl->value = new;
+	return 0;
+}
+
+
+static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+	struct saa6752hs_state *h = to_state(sd);
 	struct saa6752hs_mpeg_params *params = &h->params;
 	int err;
 
@@ -583,7 +592,7 @@
 				V4L2_MPEG_VIDEO_ASPECT_4x3);
 
 	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-		err = v4l2_ctrl_query_fill_std(qctrl);
+		err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
 		if (err == 0 &&
 		    params->vi_bitrate_mode ==
 				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
@@ -597,12 +606,20 @@
 				V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
 
 	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
 	case V4L2_CID_MPEG_STREAM_PID_PMT:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
 	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
 	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
 	case V4L2_CID_MPEG_STREAM_PID_PCR:
-		return v4l2_ctrl_query_fill_std(qctrl);
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
 
 	default:
 		break;
@@ -610,8 +627,7 @@
 	return -EINVAL;
 }
 
-static int saa6752hs_qmenu(struct saa6752hs_state *h,
-		struct v4l2_querymenu *qmenu)
+static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
 {
 	static const u32 mpeg_audio_encoding[] = {
 		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
@@ -632,11 +648,12 @@
 		V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
 		V4L2_CTRL_MENU_IDS_END
 	};
+	struct saa6752hs_state *h = to_state(sd);
 	struct v4l2_queryctrl qctrl;
 	int err;
 
 	qctrl.id = qmenu->id;
-	err = saa6752hs_qctrl(h, &qctrl);
+	err = saa6752hs_queryctrl(sd, &qctrl);
 	if (err)
 		return err;
 	switch (qmenu->id) {
@@ -656,17 +673,16 @@
 	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
 }
 
-static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes)
+static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
 {
 	unsigned char buf[9], buf2[4];
-	struct saa6752hs_state *h;
+	struct saa6752hs_state *h = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	unsigned size;
 	u32 crc;
 	unsigned char localPAT[256];
 	unsigned char localPMT[256];
 
-	h = i2c_get_clientdata(client);
-
 	/* Set video format - must be done first as it resets other settings */
 	set_reg8(client, 0x41, h->video_format);
 
@@ -762,7 +778,7 @@
 	buf[3] = 0x82;
 	buf[4] = 0xB0;
 	buf[5] = buf2[0];
-	switch(h->params.vi_aspect) {
+	switch (h->params.vi_aspect) {
 	case V4L2_MPEG_VIDEO_ASPECT_16x9:
 		buf[6] = buf2[1] | 0x40;
 		break;
@@ -770,7 +786,6 @@
 	default:
 		buf[6] = buf2[1] & 0xBF;
 		break;
-		break;
 	}
 	buf[7] = buf2[2];
 	buf[8] = buf2[3];
@@ -779,81 +794,162 @@
 	return 0;
 }
 
-static int
-saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
 {
-	struct saa6752hs_state *h = i2c_get_clientdata(client);
-	struct v4l2_ext_controls *ctrls = arg;
+	struct saa6752hs_state *h = to_state(sd);
 	struct saa6752hs_mpeg_params params;
-	int err = 0;
 	int i;
 
-	switch (cmd) {
-	case VIDIOC_INT_INIT:
-		/* apply settings and start encoder */
-		saa6752hs_init(client, *(u32 *)arg);
-		break;
-	case VIDIOC_S_EXT_CTRLS:
-		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-			return -EINVAL;
-		/* fall through */
-	case VIDIOC_TRY_EXT_CTRLS:
-	case VIDIOC_G_EXT_CTRLS:
-		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-			return -EINVAL;
-		params = h->params;
-		for (i = 0; i < ctrls->count; i++) {
-			err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, cmd);
-			if (err) {
-				ctrls->error_idx = i;
-				return err;
-			}
+	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	params = h->params;
+	for (i = 0; i < ctrls->count; i++) {
+		int err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, set);
+
+		if (err) {
+			ctrls->error_idx = i;
+			return err;
 		}
+	}
+	if (set)
 		h->params = params;
-		break;
-	case VIDIOC_QUERYCTRL:
-		return saa6752hs_qctrl(h, arg);
-	case VIDIOC_QUERYMENU:
-		return saa6752hs_qmenu(h, arg);
-	case VIDIOC_G_FMT:
-	{
-	   struct v4l2_format *f = arg;
-
-	   if (h->video_format == SAA6752HS_VF_UNKNOWN)
-		   h->video_format = SAA6752HS_VF_D1;
-	   f->fmt.pix.width =
-		   v4l2_format_table[h->video_format].fmt.pix.width;
-	   f->fmt.pix.height =
-		   v4l2_format_table[h->video_format].fmt.pix.height;
-	   break ;
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-
-		saa6752hs_set_subsampling(client, f);
-		break;
-	}
-	case VIDIOC_S_STD:
-		h->standard = *((v4l2_std_id *) arg);
-		break;
-
-	case VIDIOC_DBG_G_CHIP_IDENT:
-		return v4l2_chip_ident_i2c_client(client,
-				arg, h->chip, h->revision);
-
-	default:
-		/* nothing */
-		break;
-	}
-
-	return err;
+	return 0;
 }
 
+static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+	return saa6752hs_do_ext_ctrls(sd, ctrls, 1);
+}
+
+static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+	return saa6752hs_do_ext_ctrls(sd, ctrls, 0);
+}
+
+static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+	struct saa6752hs_state *h = to_state(sd);
+	int i;
+
+	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	for (i = 0; i < ctrls->count; i++) {
+		int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i);
+
+		if (err) {
+			ctrls->error_idx = i;
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	if (h->video_format == SAA6752HS_VF_UNKNOWN)
+		h->video_format = SAA6752HS_VF_D1;
+	f->fmt.pix.width =
+		v4l2_format_table[h->video_format].fmt.pix.width;
+	f->fmt.pix.height =
+		v4l2_format_table[h->video_format].fmt.pix.height;
+	return 0;
+}
+
+static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+	int dist_352, dist_480, dist_720;
+
+	/*
+	  FIXME: translate and round width/height into EMPRESS
+	  subsample type:
+
+	  type   |   PAL   |  NTSC
+	  ---------------------------
+	  SIF    | 352x288 | 352x240
+	  1/2 D1 | 352x576 | 352x480
+	  2/3 D1 | 480x576 | 480x480
+	  D1     | 720x576 | 720x480
+	*/
+
+	dist_352 = abs(f->fmt.pix.width - 352);
+	dist_480 = abs(f->fmt.pix.width - 480);
+	dist_720 = abs(f->fmt.pix.width - 720);
+	if (dist_720 < dist_480) {
+		f->fmt.pix.width = 720;
+		f->fmt.pix.height = 576;
+		h->video_format = SAA6752HS_VF_D1;
+	} else if (dist_480 < dist_352) {
+		f->fmt.pix.width = 480;
+		f->fmt.pix.height = 576;
+		h->video_format = SAA6752HS_VF_2_3_D1;
+	} else {
+		f->fmt.pix.width = 352;
+		if (abs(f->fmt.pix.height - 576) <
+		    abs(f->fmt.pix.height - 288)) {
+			f->fmt.pix.height = 576;
+			h->video_format = SAA6752HS_VF_1_2_D1;
+		} else {
+			f->fmt.pix.height = 288;
+			h->video_format = SAA6752HS_VF_SIF;
+		}
+	}
+	return 0;
+}
+
+static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	h->standard = std;
+	return 0;
+}
+
+static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa6752hs_state *h = to_state(sd);
+
+	return v4l2_chip_ident_i2c_client(client,
+			chip, h->chip, h->revision);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
+	.g_chip_ident = saa6752hs_g_chip_ident,
+	.init = saa6752hs_init,
+	.queryctrl = saa6752hs_queryctrl,
+	.querymenu = saa6752hs_querymenu,
+	.g_ext_ctrls = saa6752hs_g_ext_ctrls,
+	.s_ext_ctrls = saa6752hs_s_ext_ctrls,
+	.try_ext_ctrls = saa6752hs_try_ext_ctrls,
+};
+
+static const struct v4l2_subdev_tuner_ops saa6752hs_tuner_ops = {
+	.s_std = saa6752hs_s_std,
+};
+
+static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
+	.s_fmt = saa6752hs_s_fmt,
+	.g_fmt = saa6752hs_g_fmt,
+};
+
+static const struct v4l2_subdev_ops saa6752hs_ops = {
+	.core = &saa6752hs_core_ops,
+	.tuner = &saa6752hs_tuner_ops,
+	.video = &saa6752hs_video_ops,
+};
+
 static int saa6752hs_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+		const struct i2c_device_id *id)
 {
 	struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+	struct v4l2_subdev *sd;
 	u8 addr = 0x13;
 	u8 data[12];
 
@@ -861,6 +957,8 @@
 			client->addr << 1, client->adapter->name);
 	if (h == NULL)
 		return -ENOMEM;
+	sd = &h->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
 
 	i2c_master_send(client, &addr, 1);
 	i2c_master_recv(client, data, sizeof(data));
@@ -874,14 +972,15 @@
 	}
 	h->params = param_defaults;
 	h->standard = 0; /* Assume 625 input lines */
-
-	i2c_set_clientdata(client, h);
 	return 0;
 }
 
 static int saa6752hs_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
 	return 0;
 }
 
@@ -893,8 +992,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa6752hs",
-	.driverid = I2C_DRIVERID_SAA6752HS,
-	.command = saa6752hs_command,
 	.probe = saa6752hs_probe,
 	.remove = saa6752hs_remove,
 	.id_table = saa6752hs_id,
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index e2febcd..a790a72 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -31,6 +31,7 @@
 #include <media/v4l2-common.h>
 #include <media/tveeprom.h>
 #include "tea5767.h"
+#include "tda18271.h"
 
 /* commly used strings */
 static char name_mute[]    = "mute";
@@ -272,6 +273,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
 
 		.inputs         = {{
 			.name = name_comp1,
@@ -408,6 +410,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.tda9887_conf	= TDA9887_PRESENT,
 		.gpiomask	= 0x820000,
 		.inputs		= {{
@@ -818,6 +821,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.inputs         = {{
 			.name = name_comp1,
 			.vmux = 4,
@@ -977,6 +981,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.inputs         = {{
 			.name = name_comp1,
 			.vmux = 1,
@@ -1699,6 +1704,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.rds_addr 	= 0x10,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
@@ -2364,6 +2370,7 @@
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x21,
 		.inputs		= {{
 			.name   = "Composite 0",
 			.vmux   = 0,
@@ -3291,6 +3298,68 @@
 			.gpio = 0x0200100,
 		},
 	},
+	[SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
+		.name           = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 3,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_SERIAL,
+		.gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x0000100,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0800100, /* GPIO 23 HI for FM */
+		},
+	},
+	[SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = {
+		.name           = "Hauppauge WinTV-HVR1110r3",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 3,
+		.gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x0000100,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0800100, /* GPIO 23 HI for FM */
+		},
+	},
 	[SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
 		.name           = "Terratec Cinergy HT PCMCIA",
 		.audio_clock    = 0x00187de7,
@@ -4070,6 +4139,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = { {
 			.name = name_tv,
@@ -4106,6 +4176,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = { {
 			.name = name_tv,
@@ -4143,6 +4214,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
+		.empress_addr 	= 0x20,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = { {
 			.name = name_tv,
@@ -4323,13 +4395,13 @@
 			 .amux = TV,
 			 .tv   = 1,
 		 }, {
-			 .name = name_comp,
-			 .vmux = 0,
+			 .name = name_comp1,
+			 .vmux = 3,
 			 .amux = LINE1,
 		 }, {
 			 .name = name_svideo,
 			 .vmux = 8,
-			 .amux = LINE1,
+			 .amux = LINE2,
 		 } },
 		 .radio = {
 			 .name = name_radio,
@@ -4421,8 +4493,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		/* no DVB support for now */
-		/* .mpeg           = SAA7134_MPEG_DVB, */
+		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs         = { {
 			.name = name_comp,
 			.vmux = 1,
@@ -4441,8 +4512,7 @@
 		.radio_type     = UNSET,
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
-		/* no DVB support for now */
-		/* .mpeg           = SAA7134_MPEG_DVB, */
+		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs         = { {
 			.name = name_comp,
 			.vmux = 1,
@@ -4611,7 +4681,7 @@
 		.tuner_type     = TUNER_YMEC_TVF_5533MF,
 		.radio_type     = TUNER_TEA5767,
 		.tuner_addr     = ADDR_UNSET,
-		.radio_addr     = ADDR_UNSET,
+		.radio_addr     = 0x60,
 		.gpiomask       = 0x80000700,
 		.inputs = { {
 			.name   = name_tv,
@@ -5405,6 +5475,36 @@
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6706,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6707,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6708,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6709,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x670a,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x153b,
 		.subdevice    = 0x1172,
 		.driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
@@ -5821,8 +5921,8 @@
 }
 
 
-static int saa7134_tda8290_callback(struct saa7134_dev *dev,
-				    int command, int arg)
+static int saa7134_tda8290_827x_callback(struct saa7134_dev *dev,
+					 int command, int arg)
 {
 	u8 sync_control;
 
@@ -5848,6 +5948,65 @@
 	return 0;
 }
 
+static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev,
+						      enum tda18271_mode mode)
+{
+	/* toggle AGC switch through GPIO 26 */
+	switch (mode) {
+	case TDA18271_ANALOG:
+		saa7134_set_gpio(dev, 26, 0);
+		break;
+	case TDA18271_DIGITAL:
+		saa7134_set_gpio(dev, 26, 1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
+					  int command, int arg)
+{
+	int ret = 0;
+
+	switch (command) {
+	case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */
+		switch (dev->board) {
+		case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
+			ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int saa7134_tda8290_callback(struct saa7134_dev *dev,
+				    int command, int arg)
+{
+	int ret;
+
+	switch (dev->board) {
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
+		/* tda8290 + tda18271 */
+		ret = saa7134_tda8290_18271_callback(dev, command, arg);
+		break;
+	default:
+		/* tda8290 + tda827x */
+		ret = saa7134_tda8290_827x_callback(dev, command, arg);
+		break;
+	}
+	return ret;
+}
+
 int saa7134_tuner_callback(void *priv, int component, int command, int arg)
 {
 	struct saa7134_dev *dev = priv;
@@ -5878,11 +6037,16 @@
 	switch (tv.model) {
 	case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */
 	case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
+	case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+	case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
+	case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
 	case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
 	case 67569: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM) */
 	case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */
 	case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
 	case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
+	case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+	case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
 		break;
 	default:
 		printk(KERN_WARNING "%s: warning: "
@@ -6019,6 +6183,11 @@
 		msleep(10);
 		break;
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+		saa7134_set_gpio(dev, 23, 0);
+		msleep(10);
+		saa7134_set_gpio(dev, 23, 1);
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		break;
 	case SAA7134_BOARD_AVERMEDIA_M103:
 		saa7134_set_gpio(dev, 23, 0);
 		msleep(10);
@@ -6054,6 +6223,16 @@
 
 		saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
 		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
+		/* GPIO 26 high for digital, low for analog */
+		saa7134_set_gpio(dev, 26, 0);
+		msleep(1);
+
+		saa7134_set_gpio(dev, 22, 0);
+		msleep(10);
+		saa7134_set_gpio(dev, 22, 1);
+		break;
 	/* i2c remotes */
 	case SAA7134_BOARD_PINNACLE_PCTV_110i:
 	case SAA7134_BOARD_PINNACLE_PCTV_310i:
@@ -6079,15 +6258,15 @@
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
 		break;
-	case SAA7134_BOARD_AVERMEDIA_A700_PRO:
 	case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+		printk("%s: %s: hybrid analog/dvb card\n"
+		       "%s: Sorry, of the analog inputs, only analog s-video and composite "
+		       "are supported for now.\n",
+			dev->name, card(dev).name, dev->name);
+	case SAA7134_BOARD_AVERMEDIA_A700_PRO:
 		/* write windows gpio values */
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
 		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
-		printk("%s: %s: hybrid analog/dvb card\n"
-		       "%s: Sorry, only analog s-video and composite input "
-		       "are supported for now.\n",
-			dev->name, card(dev).name, dev->name);
 		break;
 	}
 	return 0;
@@ -6109,7 +6288,7 @@
 
 		tun_setup.mode_mask = T_RADIO;
 
-		saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+		saa_call_all(dev, tuner, s_type_addr, &tun_setup);
 		mode_mask &= ~T_RADIO;
 	}
 
@@ -6121,7 +6300,7 @@
 
 		tun_setup.mode_mask = mode_mask;
 
-		saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+		saa_call_all(dev, tuner, s_type_addr, &tun_setup);
 	}
 
 	if (dev->tda9887_conf) {
@@ -6130,8 +6309,7 @@
 		tda9887_cfg.tuner = TUNER_TDA9887;
 		tda9887_cfg.priv = &dev->tda9887_conf;
 
-		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
-					 &tda9887_cfg);
+		saa_call_all(dev, tuner, s_config, &tda9887_cfg);
 	}
 
 	if (dev->tuner_type == TUNER_XC2028) {
@@ -6158,7 +6336,7 @@
 		xc2028_cfg.tuner = TUNER_XC2028;
 		xc2028_cfg.priv  = &ctl;
 
-		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+		saa_call_all(dev, tuner, s_config, &xc2028_cfg);
 	}
 }
 
@@ -6168,9 +6346,20 @@
 	unsigned char buf;
 	int board;
 
+	/* Put here the code that enables the chips that are needed
+	   for analog mode and doesn't depend on the tuner attachment.
+	   It is also a good idea to get tuner type from eeprom, etc before
+	   initializing tuner, since we can avoid loading tuner driver
+	   on devices that has TUNER_ABSENT
+	 */
 	switch (dev->board) {
 	case SAA7134_BOARD_BMK_MPEX_NOTUNER:
 	case SAA7134_BOARD_BMK_MPEX_TUNER:
+		/* Checks if the device has a tuner at 0x60 addr
+		   If the device doesn't have a tuner, TUNER_ABSENT
+		   will be used at tuner_type, avoiding loading tuner
+		   without needing it
+		 */
 		dev->i2c_client.addr = 0x60;
 		board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
 			? SAA7134_BOARD_BMK_MPEX_NOTUNER
@@ -6188,11 +6377,15 @@
 		u8 subaddr;
 		u8 data[3];
 		int ret, tuner_t;
-
 		struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1},
 					{.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}};
+
 		subaddr= 0x14;
 		tuner_t = 0;
+
+		/* Retrieve device data from eeprom, checking for the
+		   proper tuner_type.
+		 */
 		ret = i2c_transfer(&dev->i2c_adap, msg, 2);
 		if (ret != 2) {
 			printk(KERN_ERR "EEPROM read failure\n");
@@ -6248,12 +6441,14 @@
 				dev->name, saa7134_boards[dev->board].name);
 			break;
 		}
+		/* break intentionally omitted */
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
 	case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
 	{
 
-		/* The Philips EUROPA based hybrid boards have the tuner connected through
-		 * the channel decoder. We have to make it transparent to find it
+		/* The Philips EUROPA based hybrid boards have the tuner
+		   connected through the channel decoder. We have to make it
+		   transparent to find it
 		 */
 		u8 data[] = { 0x07, 0x02};
 		struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
@@ -6274,21 +6469,15 @@
 		if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
 			dev->tuner_type = TUNER_PHILIPS_TDA8290;
 
-			saa7134_tuner_setup(dev);
-
 			data[2] = 0x68;
 			i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-			/* Tuner setup is handled before I2C transfer.
-			   Due to that, there's no need to do it later
-			 */
-			return 0;
+			break;
 		}
 		i2c_transfer(&dev->i2c_adap, &msg, 1);
 		break;
 	}
-       case SAA7134_BOARD_ASUSTeK_TVFM7135:
-       /* The card below is detected as card=53, but is different */
+	case SAA7134_BOARD_ASUSTeK_TVFM7135:
+	/* The card below is detected as card=53, but is different */
 	       if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
 		       dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
 		       printk(KERN_INFO "%s: P7131 analog only, using "
@@ -6296,6 +6485,10 @@
 		       dev->name, saa7134_boards[dev->board].name);
 	       }
 	       break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
+		hauppauge_eeprom(dev, dev->eedata+0x80);
+		break;
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
 		hauppauge_eeprom(dev, dev->eedata+0x80);
 		/* break intentionally omitted */
@@ -6351,22 +6544,6 @@
 		i2c_transfer(&dev->i2c_adap, &msg, 1);
 		break;
 	}
-	case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
-	case SAA7134_BOARD_KWORLD_ATSC110:
-	{
-		/* enable tuner */
-		int i;
-		static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16,
-					      0x00, 0x14, 0x04, 0x17, 0x00 };
-		dev->i2c_client.addr = 0x0a;
-		for (i = 0; i < 5; i++)
-			if (2 != i2c_master_send(&dev->i2c_client,
-						 &buffer[i*2], 2))
-				printk(KERN_WARNING
-				       "%s: Unable to enable tuner(%i).\n",
-				       dev->name, i);
-		break;
-	}
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
 		/* The T200 and the T200A share the same pci id.  Consequently,
@@ -6375,9 +6552,9 @@
 
 		/* Don't do this if the board was specifically selected with an
 		 * insmod option or if we have the default configuration T200*/
-		if(!dev->autodetected || (dev->eedata[0x41] == 0xd0))
+		if (!dev->autodetected || (dev->eedata[0x41] == 0xd0))
 			break;
-		if(dev->eedata[0x41] == 0x02) {
+		if (dev->eedata[0x41] == 0x02) {
 			/* Reconfigure board  as T200A */
 			dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
 			dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
@@ -6390,6 +6567,58 @@
 			break;
 		}
 		break;
+	case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
+	case SAA7134_BOARD_KWORLD_ATSC110:
+	{
+		struct i2c_msg msg = { .addr = 0x0a, .flags = 0 };
+		int i;
+		static u8 buffer[][2] = {
+			{ 0x10, 0x12 },
+			{ 0x13, 0x04 },
+			{ 0x16, 0x00 },
+			{ 0x14, 0x04 },
+			{ 0x17, 0x00 },
+		};
+
+		for (i = 0; i < ARRAY_SIZE(buffer); i++) {
+			msg.buf = &buffer[i][0];
+			msg.len = ARRAY_SIZE(buffer[0]);
+			if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+				printk(KERN_WARNING
+				       "%s: Unable to enable tuner(%i).\n",
+				       dev->name, i);
+		}
+		break;
+	}
+	} /* switch() */
+
+	/* initialize tuner */
+	if (TUNER_ABSENT != dev->tuner_type) {
+		int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
+
+		/* Note: radio tuner address is always filled in,
+		   so we do not need to probe for a radio tuner device. */
+		if (dev->radio_type != UNSET)
+			v4l2_i2c_new_subdev(&dev->i2c_adap,
+				"tuner", "tuner", dev->radio_addr);
+		if (has_demod)
+			v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		if (dev->tuner_addr == ADDR_UNSET) {
+			enum v4l2_i2c_tuner_type type =
+				has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+
+			v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(type));
+		} else {
+			v4l2_i2c_new_subdev(&dev->i2c_adap,
+				"tuner", "tuner", dev->tuner_addr);
+		}
+	}
+
+	saa7134_tuner_setup(dev);
+
+	switch (dev->board) {
 	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
 	{
 		struct v4l2_priv_tun_config tea5767_cfg;
@@ -6401,12 +6630,10 @@
 		ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
 		tea5767_cfg.tuner = TUNER_TEA5767;
 		tea5767_cfg.priv  = &ctl;
-		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
+		saa_call_all(dev, tuner, s_config, &tea5767_cfg);
 		break;
 	}
 	} /* switch() */
 
-	saa7134_tuner_setup(dev);
-
 	return 0;
 }
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 99221d7..dafa0d8 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -54,13 +54,9 @@
 module_param(gpio_tracking, int, 0644);
 MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
 
-static unsigned int alsa;
+static unsigned int alsa = 1;
 module_param(alsa, int, 0644);
-MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
-
-static unsigned int oss;
-module_param(oss, int, 0644);
-MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
+MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]");
 
 static unsigned int latency = UNSET;
 module_param(latency, int, 0444);
@@ -90,8 +86,10 @@
 MODULE_PARM_DESC(tuner,    "tuner type");
 MODULE_PARM_DESC(card,     "card type");
 
-static DEFINE_MUTEX(devlist_lock);
+DEFINE_MUTEX(saa7134_devlist_lock);
+EXPORT_SYMBOL(saa7134_devlist_lock);
 LIST_HEAD(saa7134_devlist);
+EXPORT_SYMBOL(saa7134_devlist);
 static LIST_HEAD(mops_list);
 static unsigned int saa7134_devcount;
 
@@ -156,10 +154,10 @@
 		request_module("saa7134-empress");
 	if (card_is_dvb(dev))
 		request_module("saa7134-dvb");
-	if (alsa)
-		request_module("saa7134-alsa");
-	if (oss)
-		request_module("saa7134-oss");
+	if (alsa) {
+		if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
+			request_module("saa7134-alsa");
+	}
 }
 
 static void request_submodules(struct saa7134_dev *dev)
@@ -778,7 +776,7 @@
 		return NULL;
 	*vfd = *template;
 	vfd->minor   = -1;
-	vfd->parent  = &dev->pci->dev;
+	vfd->v4l2_dev  = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug   = video_debug;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
@@ -851,6 +849,10 @@
 	if (NULL == dev)
 		return -ENOMEM;
 
+	err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+	if (err)
+		goto fail0;
+
 	/* pci init */
 	dev->pci = pci_dev;
 	if (pci_enable_device(pci_dev)) {
@@ -927,6 +929,8 @@
 	dev->autodetected = card[dev->nr] != dev->board;
 	dev->tuner_type = saa7134_boards[dev->board].tuner_type;
 	dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
+	dev->radio_type = saa7134_boards[dev->board].radio_type;
+	dev->radio_addr = saa7134_boards[dev->board].radio_addr;
 	dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
 	if (UNSET != tuner[dev->nr])
 		dev->tuner_type = tuner[dev->nr];
@@ -971,23 +975,48 @@
 	/* wait a bit, register i2c bus */
 	msleep(100);
 	saa7134_i2c_register(dev);
-
-	/* initialize hardware #2 */
-	if (TUNER_ABSENT != dev->tuner_type)
-		request_module("tuner");
 	saa7134_board_init2(dev);
 
 	saa7134_hwinit2(dev);
 
 	/* load i2c helpers */
 	if (card_is_empress(dev)) {
-		request_module("saa6752hs");
+		struct v4l2_subdev *sd =
+			v4l2_i2c_new_subdev(&dev->i2c_adap,
+				"saa6752hs", "saa6752hs",
+				saa7134_boards[dev->board].empress_addr);
+
+		if (sd)
+			sd->grp_id = GRP_EMPRESS;
+	}
+
+	if (saa7134_boards[dev->board].rds_addr) {
+		unsigned short addrs[2] = { 0, I2C_CLIENT_END };
+		struct v4l2_subdev *sd;
+
+		addrs[0] = saa7134_boards[dev->board].rds_addr;
+		sd = v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "saa6588",
+			    "saa6588", addrs);
+		if (sd)
+			printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
 	}
 
 	request_submodules(dev);
 
 	v4l2_prio_init(&dev->prio);
 
+	mutex_lock(&saa7134_devlist_lock);
+	list_for_each_entry(mops, &mops_list, next)
+		mpeg_ops_attach(mops, dev);
+	list_add_tail(&dev->devlist, &saa7134_devlist);
+	mutex_unlock(&saa7134_devlist_lock);
+
+	/* check for signal */
+	saa7134_irq_video_signalchange(dev);
+
+	if (TUNER_ABSENT != dev->tuner_type)
+		saa_call_all(dev, core, s_standby, 0);
+
 	/* register v4l devices */
 	if (saa7134_no_overlay > 0)
 		printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
@@ -1023,24 +1052,10 @@
 	}
 
 	/* everything worked */
-	pci_set_drvdata(pci_dev,dev);
 	saa7134_devcount++;
 
-	mutex_lock(&devlist_lock);
-	list_for_each_entry(mops, &mops_list, next)
-		mpeg_ops_attach(mops, dev);
-	list_add_tail(&dev->devlist,&saa7134_devlist);
-	mutex_unlock(&devlist_lock);
-
-	/* check for signal */
-	saa7134_irq_video_signalchange(dev);
-
-	if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
+	if (saa7134_dmasound_init && !dev->dmasound.priv_data)
 		saa7134_dmasound_init(dev);
-	}
-
-	if (TUNER_ABSENT != dev->tuner_type)
-		saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
 
 	return 0;
 
@@ -1055,13 +1070,16 @@
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
  fail1:
+	v4l2_device_unregister(&dev->v4l2_dev);
+ fail0:
 	kfree(dev);
 	return err;
 }
 
 static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
 {
-	struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 	struct saa7134_mpeg_ops *mops;
 
 	/* Release DMA sound modules if present */
@@ -1088,11 +1106,11 @@
 	saa7134_hwfini(dev);
 
 	/* unregister */
-	mutex_lock(&devlist_lock);
+	mutex_lock(&saa7134_devlist_lock);
 	list_del(&dev->devlist);
 	list_for_each_entry(mops, &mops_list, next)
 		mpeg_ops_detach(mops, dev);
-	mutex_unlock(&devlist_lock);
+	mutex_unlock(&saa7134_devlist_lock);
 	saa7134_devcount--;
 
 	saa7134_i2c_unregister(dev);
@@ -1113,7 +1131,8 @@
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
 
-	pci_set_drvdata(pci_dev, NULL);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
 
 	/* free memory */
 	kfree(dev);
@@ -1148,8 +1167,8 @@
 
 static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
 {
-
-	struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 
 	/* disable overlay - apps should enable it explicitly on resume*/
 	dev->ovenable = 0;
@@ -1185,7 +1204,8 @@
 
 static int saa7134_resume(struct pci_dev *pci_dev)
 {
-	struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
 	unsigned long flags;
 
 	pci_set_power_state(pci_dev, PCI_D0);
@@ -1247,11 +1267,11 @@
 {
 	struct saa7134_dev *dev;
 
-	mutex_lock(&devlist_lock);
+	mutex_lock(&saa7134_devlist_lock);
 	list_for_each_entry(dev, &saa7134_devlist, devlist)
 		mpeg_ops_attach(ops, dev);
 	list_add_tail(&ops->next,&mops_list);
-	mutex_unlock(&devlist_lock);
+	mutex_unlock(&saa7134_devlist_lock);
 	return 0;
 }
 
@@ -1259,11 +1279,11 @@
 {
 	struct saa7134_dev *dev;
 
-	mutex_lock(&devlist_lock);
+	mutex_lock(&saa7134_devlist_lock);
 	list_del(&ops->next);
 	list_for_each_entry(dev, &saa7134_devlist, devlist)
 		mpeg_ops_detach(ops, dev);
-	mutex_unlock(&devlist_lock);
+	mutex_unlock(&saa7134_devlist_lock);
 }
 
 EXPORT_SYMBOL(saa7134_ts_register);
@@ -1307,8 +1327,6 @@
 /* ----------------------------------------------------------- */
 
 EXPORT_SYMBOL(saa7134_set_gpio);
-EXPORT_SYMBOL(saa7134_i2c_call_clients);
-EXPORT_SYMBOL(saa7134_devlist);
 EXPORT_SYMBOL(saa7134_boards);
 
 /* ----------------- for the DMA sound modules --------------- */
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index b5370b3..4eff1ca 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -48,9 +48,15 @@
 #include "isl6405.h"
 #include "lnbp21.h"
 #include "tuner-simple.h"
+#include "tda18271.h"
+#include "lgdt3305.h"
+#include "tda8290.h"
 
 #include "zl10353.h"
 
+#include "zl10036.h"
+#include "mt312.h"
+
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 
@@ -189,7 +195,7 @@
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
-	saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
+	saa_call_all(dev, tuner, s_frequency, &f);
 	msg.buf = on;
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
@@ -950,6 +956,45 @@
 	.demod_address    = 0x0a,
 };
 
+/* ------------------------------------------------------------------ */
+
+static struct mt312_config avertv_a700_mt312 = {
+	.demod_address = 0x0e,
+	.voltage_inverted = 1,
+};
+
+static struct zl10036_config avertv_a700_tuner = {
+	.tuner_address = 0x60,
+};
+
+static struct lgdt3305_config hcw_lgdt3305_config = {
+	.i2c_addr           = 0x0e,
+	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
+	.tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+	.deny_i2c_rptr      = 1,
+	.spectral_inversion = 1,
+	.qam_if_khz         = 4000,
+	.vsb_if_khz         = 3250,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+	.atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+		      .if_lvl = 1, .rfagc_top = 0x58, },
+	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+		      .if_lvl = 1, .rfagc_top = 0x58, },
+};
+
+static struct tda18271_config hcw_tda18271_config = {
+	.std_map = &hauppauge_tda18271_std_map,
+	.gate    = TDA18271_GATE_ANALOG,
+	.config  = 3,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+	.probe_tuner = TDA829X_DONT_PROBE,
+};
+
 /* ==================================================================
  * Core code
  */
@@ -1076,6 +1121,19 @@
 					 &tda827x_cfg_1) < 0)
 			goto dettach_frontend;
 		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+					       &hcw_lgdt3305_config,
+					       &dev->i2c_adap);
+		if (fe0->dvb.frontend) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
+				   &dev->i2c_adap, 0x4b,
+				   &tda829x_no_probe);
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_adap,
+				   &hcw_tda18271_config);
+		}
+		break;
 	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
 		if (configure_tda827x_fe(dev, &asus_p7131_dual_config,
 					 &tda827x_cfg_0) < 0)
@@ -1376,6 +1434,19 @@
 				   TUNER_PHILIPS_FMD1216ME_MK3);
 		}
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+	case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+		/* Zarlink ZL10313 */
+		fe0->dvb.frontend = dvb_attach(mt312_attach,
+			&avertv_a700_mt312, &dev->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (dvb_attach(zl10036_attach, fe0->dvb.frontend,
+					&avertv_a700_tuner, &dev->i2c_adap) == NULL) {
+				wprintk("%s: No zl10036 found!\n",
+					__func__);
+			}
+		}
+		break;
 	default:
 		wprintk("Huh? unknown DVB card?\n");
 		break;
@@ -1449,7 +1520,7 @@
 		tda9887_cfg.priv  = &on;
 
 		/* otherwise we don't detect the tuner on next insmod */
-		saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tda9887_cfg);
+		saa_call_all(dev, tuner, s_config, &tda9887_cfg);
 	} else if (dev->board == SAA7134_BOARD_MEDION_MD8800_QUADRO) {
 		if ((dev->eedata[2] == 0x07) && use_frontend) {
 			/* turn off the 2nd lnb supply */
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index c9d8beb..9db3472 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -76,7 +76,7 @@
 		break;
 	}
 	ts_reset_encoder(dev);
-	saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes);
+	saa_call_all(dev, core, init, leading_null_bytes);
 	dev->empress_started = 1;
 	return 0;
 }
@@ -234,7 +234,7 @@
 {
 	struct saa7134_dev *dev = file->private_data;
 
-	saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f);
+	saa_call_all(dev, video, g_fmt, f);
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
@@ -247,7 +247,7 @@
 {
 	struct saa7134_dev *dev = file->private_data;
 
-	saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f);
+	saa_call_all(dev, video, s_fmt, f);
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 	f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
@@ -317,7 +317,7 @@
 	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
 		return -EINVAL;
 
-	err = saa7134_i2c_call_saa6752(dev, VIDIOC_S_EXT_CTRLS, ctrls);
+	err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
 	ts_init_encoder(dev);
 
 	return err;
@@ -330,7 +330,7 @@
 
 	if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
 		return -EINVAL;
-	return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls);
+	return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
 }
 
 static int empress_g_ctrl(struct file *file, void *priv,
@@ -352,6 +352,7 @@
 static int empress_queryctrl(struct file *file, void *priv,
 					struct v4l2_queryctrl *c)
 {
+	/* Must be sorted from low to high control ID! */
 	static const u32 user_ctrls[] = {
 		V4L2_CID_USER_CLASS,
 		V4L2_CID_BRIGHTNESS,
@@ -364,6 +365,7 @@
 		0
 	};
 
+	/* Must be sorted from low to high control ID! */
 	static const u32 mpeg_ctrls[] = {
 		V4L2_CID_MPEG_CLASS,
 		V4L2_CID_MPEG_STREAM_TYPE,
@@ -388,10 +390,10 @@
 	if (c->id == 0)
 		return -EINVAL;
 	if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
-		return v4l2_ctrl_query_fill_std(c);
+		return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
 	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
 		return saa7134_queryctrl(file, priv, c);
-	return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYCTRL, c);
+	return saa_call_empress(dev, core, queryctrl, c);
 }
 
 static int empress_querymenu(struct file *file, void *priv,
@@ -401,7 +403,7 @@
 
 	if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
 		return -EINVAL;
-	return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
+	return saa_call_empress(dev, core, querymenu, c);
 }
 
 static int empress_g_chip_ident(struct file *file, void *fh,
@@ -411,14 +413,11 @@
 
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
-	if (dev->mpeg_i2c_client == NULL)
-		return -EINVAL;
 	if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
 	    !strcmp(chip->match.name, "saa6752hs"))
-		return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
-	if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR &&
-	    chip->match.addr == dev->mpeg_i2c_client->addr)
-		return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
+		return saa_call_empress(dev, core, g_chip_ident, chip);
+	if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
+		return saa_call_empress(dev, core, g_chip_ident, chip);
 	return -EINVAL;
 }
 
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 20c1b33..f3e285a 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -255,7 +255,7 @@
 			addr  = msgs[i].addr << 1;
 			if (msgs[i].flags & I2C_M_RD)
 				addr |= 1;
-			if (i > 0 && msgs[i].flags & I2C_M_RD) {
+			if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) {
 				/* workaround for a saa7134 i2c bug
 				 * needed to talk to the mt352 demux
 				 * thanks to pinnacle for the hint */
@@ -327,8 +327,6 @@
 
 	d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
 		client->driver->driver.name, client->addr, client->name);
-	if (client->addr == 0x20 && client->driver && client->driver->command)
-		dev->mpeg_i2c_client = client;
 
 	/* Am I an i2c remote control? */
 
@@ -357,7 +355,6 @@
 
 static struct i2c_adapter saa7134_adap_template = {
 	.owner         = THIS_MODULE,
-	.class         = I2C_CLASS_TV_ANALOG,
 	.name          = "saa7134",
 	.id            = I2C_HW_SAA7134,
 	.algo          = &saa7134_algo,
@@ -421,29 +418,13 @@
 	}
 }
 
-void saa7134_i2c_call_clients(struct saa7134_dev *dev,
-			      unsigned int cmd, void *arg)
-{
-	BUG_ON(NULL == dev->i2c_adap.algo_data);
-	i2c_clients_command(&dev->i2c_adap, cmd, arg);
-}
-
-int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
-					      unsigned int cmd, void *arg)
-{
-	if (dev->mpeg_i2c_client == NULL)
-		return -EINVAL;
-	return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
-								cmd, arg);
-}
-EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752);
-
 int saa7134_i2c_register(struct saa7134_dev *dev)
 {
 	dev->i2c_adap = saa7134_adap_template;
 	dev->i2c_adap.dev.parent = &dev->pci->dev;
 	strcpy(dev->i2c_adap.name,dev->name);
 	dev->i2c_adap.algo_data = dev;
+	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 	i2c_add_adapter(&dev->i2c_adap);
 
 	dev->i2c_client = saa7134_client_template;
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index ef55a59..cc8b923 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -79,8 +79,19 @@
 		saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 
 		/* Start TS stream */
-		saa_writeb(SAA7134_TS_SERIAL0, 0x40);
-		saa_writeb(SAA7134_TS_PARALLEL, 0xEC);
+		switch (saa7134_boards[dev->board].ts_type) {
+		case SAA7134_MPEG_TS_PARALLEL:
+			saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+			saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+			break;
+		case SAA7134_MPEG_TS_SERIAL:
+			saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
+			saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+			saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
+			saa_writeb(SAA7134_TS_SERIAL1, 0x02);
+			break;
+		}
+
 		dev->ts_state = SAA7134_TS_STARTED;
 	}
 
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index a1f7e35..404f70e 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -30,11 +30,7 @@
 #include "saa7134-reg.h"
 #include "saa7134.h"
 #include <media/v4l2-common.h>
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
+#include <media/rds.h>
 
 /* ------------------------------------------------------------------ */
 
@@ -452,6 +448,7 @@
 		.name          = "y offset odd field",
 		.minimum       = 0,
 		.maximum       = 128,
+		.step          = 1,
 		.default_value = 0,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
 	},{
@@ -459,6 +456,7 @@
 		.name          = "y offset even field",
 		.minimum       = 0,
 		.maximum       = 128,
+		.step          = 1,
 		.default_value = 0,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
 	},{
@@ -627,10 +625,10 @@
 	saa7134_set_decoder(dev);
 
 	if (card_in(dev, dev->ctl_input).tv)
-		saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+		saa_call_all(dev, tuner, s_std, dev->tvnorm->id);
 	/* Set the correct norm for the saa6752hs. This function
 	   does nothing if there is no saa6752hs. */
-	saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+	saa_call_empress(dev, tuner, s_std, dev->tvnorm->id);
 }
 
 static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1266,8 +1264,7 @@
 			else
 				dev->tda9887_conf &= ~TDA9887_AUTOMUTE;
 
-			saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
-						 &tda9887_cfg);
+			saa_call_all(dev, tuner, s_config, &tda9887_cfg);
 		}
 		break;
 	}
@@ -1334,7 +1331,7 @@
 	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	int radio = 0;
 
-	lock_kernel();
+	mutex_lock(&saa7134_devlist_lock);
 	list_for_each_entry(dev, &saa7134_devlist, devlist) {
 		if (dev->video_dev && (dev->video_dev->minor == minor))
 			goto found;
@@ -1347,19 +1344,20 @@
 			goto found;
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&saa7134_devlist_lock);
 	return -ENODEV;
- found:
+
+found:
+	mutex_unlock(&saa7134_devlist_lock);
 
 	dprintk("open minor=%d radio=%d type=%s\n",minor,radio,
 		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
 	file->private_data = fh;
 	fh->dev      = dev;
 	fh->radio    = radio;
@@ -1387,12 +1385,11 @@
 	if (fh->radio) {
 		/* switch to radio mode */
 		saa7134_tvaudio_setinput(dev,&card(dev).radio);
-		saa7134_i2c_call_clients(dev,AUDC_SET_RADIO, NULL);
+		saa_call_all(dev, tuner, s_radio);
 	} else {
 		/* switch to video/vbi mode */
 		video_mux(dev,dev->ctl_input);
 	}
-	unlock_kernel();
 	return 0;
 }
 
@@ -1466,6 +1463,7 @@
 {
 	struct saa7134_fh  *fh  = file->private_data;
 	struct saa7134_dev *dev = fh->dev;
+	struct rds_command cmd;
 	unsigned long flags;
 
 	/* turn off overlay */
@@ -1498,7 +1496,9 @@
 	saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
 	saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
 
-	saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
+	saa_call_all(dev, core, s_standby, 0);
+	if (fh->radio)
+		saa_call_all(dev, core, ioctl, RDS_CMD_CLOSE, &cmd);
 
 	/* free stuff */
 	videobuf_mmap_free(&fh->cap);
@@ -1519,6 +1519,37 @@
 	return videobuf_mmap_mapper(saa7134_queue(fh), vma);
 }
 
+static ssize_t radio_read(struct file *file, char __user *data,
+			 size_t count, loff_t *ppos)
+{
+	struct saa7134_fh *fh = file->private_data;
+	struct saa7134_dev *dev = fh->dev;
+	struct rds_command cmd;
+
+	cmd.block_count = count/3;
+	cmd.buffer = data;
+	cmd.instance = file;
+	cmd.result = -ENODEV;
+
+	saa_call_all(dev, core, ioctl, RDS_CMD_READ, &cmd);
+
+	return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+	struct saa7134_fh *fh = file->private_data;
+	struct saa7134_dev *dev = fh->dev;
+	struct rds_command cmd;
+
+	cmd.instance = file;
+	cmd.event_list = wait;
+	cmd.result = -ENODEV;
+	saa_call_all(dev, core, ioctl, RDS_CMD_POLL, &cmd);
+
+	return cmd.result;
+}
+
 /* ------------------------------------------------------------------ */
 
 static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
@@ -2041,7 +2072,7 @@
 	mutex_lock(&dev->lock);
 	dev->ctl_freq = f->frequency;
 
-	saa7134_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);
+	saa_call_all(dev, tuner, s_frequency, f);
 
 	saa7134_tvaudio_do_scan(dev);
 	mutex_unlock(&dev->lock);
@@ -2299,7 +2330,7 @@
 	strcpy(t->name, "Radio");
 	t->type = V4L2_TUNER_RADIO;
 
-	saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
+	saa_call_all(dev, tuner, g_tuner, t);
 	if (dev->input->amux == TV) {
 		t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11);
 		t->rxsubchans = (saa_readb(0x529) & 0x08) ?
@@ -2316,7 +2347,7 @@
 	if (0 != t->index)
 		return -EINVAL;
 
-	saa7134_i2c_call_clients(dev, VIDIOC_S_TUNER, t);
+	saa_call_all(dev, tuner, s_tuner, t);
 	return 0;
 }
 
@@ -2443,8 +2474,10 @@
 static const struct v4l2_file_operations radio_fops = {
 	.owner	  = THIS_MODULE,
 	.open	  = video_open,
+	.read     = radio_read,
 	.release  = video_release,
 	.ioctl	  = video_ioctl2,
+	.poll     = radio_poll,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 14ee265..a2dd326 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -35,6 +35,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
 #include <media/tuner.h>
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
@@ -277,6 +278,8 @@
 #define SAA7134_BOARD_ASUSTeK_TIGER         152
 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
+#define SAA7134_BOARD_HAUPPAUGE_HVR1120     155
+#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3   156
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
@@ -309,6 +312,11 @@
 	SAA7134_MPEG_DVB,
 };
 
+enum saa7134_mpeg_ts_type {
+	SAA7134_MPEG_TS_PARALLEL = 0,
+	SAA7134_MPEG_TS_SERIAL,
+};
+
 struct saa7134_board {
 	char                    *name;
 	unsigned int            audio_clock;
@@ -324,6 +332,8 @@
 	unsigned int		radio_type;
 	unsigned char		tuner_addr;
 	unsigned char		radio_addr;
+	unsigned char		empress_addr;
+	unsigned char		rds_addr;
 
 	unsigned int            tda9887_conf;
 	unsigned int            tuner_config;
@@ -331,6 +341,7 @@
 	/* peripheral I/O */
 	enum saa7134_video_out  video_out;
 	enum saa7134_mpeg_type  mpeg;
+	enum saa7134_mpeg_ts_type ts_type;
 	unsigned int            vid_port_opts;
 };
 
@@ -445,7 +456,6 @@
 	unsigned int               bufsize;
 	struct saa7134_pgtable     pt;
 	struct videobuf_dmabuf     dma;
-	wait_queue_head_t          wq;
 	unsigned int               dma_blk;
 	unsigned int               read_offset;
 	unsigned int               read_count;
@@ -482,6 +492,7 @@
 	struct mutex               lock;
 	spinlock_t                 slock;
 	struct v4l2_prio_state     prio;
+	struct v4l2_device         v4l2_dev;
 	/* workstruct for loading modules */
 	struct work_struct request_module_wk;
 
@@ -572,7 +583,6 @@
 	enum saa7134_ts_status 	   ts_state;
 	unsigned int 		   buff_cnt;
 	struct saa7134_mpeg_ops    *mops;
-	struct i2c_client 	   *mpeg_i2c_client;
 
 	/* SAA7134_MPEG_EMPRESS only */
 	struct video_device        *empress_dev;
@@ -588,6 +598,7 @@
 	int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
 	int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
 #endif
+	void (*gate_ctrl)(struct saa7134_dev *dev, int open);
 };
 
 /* ----------------------------------------------------------- */
@@ -616,10 +627,31 @@
 		V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
 		V4L2_STD_PAL_60)
 
+#define GRP_EMPRESS (1)
+#define saa_call_all(dev, o, f, args...) do {				\
+	if (dev->gate_ctrl)						\
+		dev->gate_ctrl(dev, 1);					\
+	v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args);	\
+	if (dev->gate_ctrl)						\
+		dev->gate_ctrl(dev, 0);					\
+} while (0)
+
+#define saa_call_empress(dev, o, f, args...) ({				\
+	long _rc;							\
+	if (dev->gate_ctrl)						\
+		dev->gate_ctrl(dev, 1);					\
+	_rc = v4l2_device_call_until_err(&(dev)->v4l2_dev,		\
+					 GRP_EMPRESS, o, f , ##args);	\
+	if (dev->gate_ctrl)						\
+		dev->gate_ctrl(dev, 0);					\
+	_rc;								\
+})
+
 /* ----------------------------------------------------------- */
 /* saa7134-core.c                                              */
 
 extern struct list_head  saa7134_devlist;
+extern struct mutex saa7134_devlist_lock;
 extern int saa7134_no_overlay;
 
 void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
@@ -668,10 +700,6 @@
 
 int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
-void saa7134_i2c_call_clients(struct saa7134_dev *dev,
-			      unsigned int cmd, void *arg);
-int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
-			      unsigned int cmd, void *arg);
 
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h
index 2830b5e..9fadb33 100644
--- a/drivers/media/video/saa7146.h
+++ b/drivers/media/video/saa7146.h
@@ -25,8 +25,6 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-#include <linux/videodev.h>
-
 #ifndef O_NONCAP
 #define O_NONCAP	O_TRUNC
 #endif
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
index 88c5e94..25bf230 100644
--- a/drivers/media/video/saa717x.c
+++ b/drivers/media/video/saa717x.c
@@ -931,7 +931,7 @@
 		break;
 
 	case V4L2_CID_HUE:
-		if (ctrl->value < -127 || ctrl->value > 127) {
+		if (ctrl->value < -128 || ctrl->value > 127) {
 			v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
 			return -ERANGE;
 		}
@@ -1380,11 +1380,6 @@
 	return 0;
 }
 
-static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops saa717x_core_ops = {
@@ -1528,10 +1523,7 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa717x",
-	.driverid = I2C_DRIVERID_SAA717X,
-	.command = saa717x_command,
 	.probe = saa717x_probe,
 	.remove = saa717x_remove,
-	.legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
 	.id_table = saa717x_id,
 };
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 6debb65..75747b1 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -30,52 +30,58 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
-#include <linux/video_encoder.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
 MODULE_AUTHOR("Dave Perks");
 MODULE_LICENSE("GPL");
 
-
 static int debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+
 /* ----------------------------------------------------------------------- */
 
 struct saa7185 {
+	struct v4l2_subdev sd;
 	unsigned char reg[128];
 
-	int norm;
-	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
+	v4l2_std_id norm;
 };
 
+static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7185, sd);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static inline int saa7185_read(struct i2c_client *client)
+static inline int saa7185_read(struct v4l2_subdev *sd)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_read_byte(client);
 }
 
-static int saa7185_write(struct i2c_client *client, u8 reg, u8 value)
+static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
-	struct saa7185 *encoder = i2c_get_clientdata(client);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7185 *encoder = to_saa7185(sd);
 
-	v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value);
+	v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
 	encoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static int saa7185_write_block(struct i2c_client *client,
+static int saa7185_write_block(struct v4l2_subdev *sd,
 		const u8 *data, unsigned int len)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7185 *encoder = to_saa7185(sd);
 	int ret = -1;
 	u8 reg;
 
@@ -83,7 +89,6 @@
 	 * the adapter understands raw I2C */
 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		/* do raw I2C, not smbus compatible */
-		struct saa7185 *encoder = i2c_get_clientdata(client);
 		u8 block_data[32];
 		int block_len;
 
@@ -104,7 +109,7 @@
 		/* do some slow I2C emulation kind of thing */
 		while (len >= 2) {
 			reg = *data++;
-			ret = saa7185_write(client, reg, *data++);
+			ret = saa7185_write(sd, reg, *data++);
 			if (ret < 0)
 				break;
 			len -= 2;
@@ -213,133 +218,106 @@
 	0x66, 0x21,		/* FSC3 */
 };
 
-static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
+
+static int saa7185_init(struct v4l2_subdev *sd, u32 val)
 {
-	struct saa7185 *encoder = i2c_get_clientdata(client);
+	struct saa7185 *encoder = to_saa7185(sd);
 
-	switch (cmd) {
+	saa7185_write_block(sd, init_common, sizeof(init_common));
+	if (encoder->norm & V4L2_STD_NTSC)
+		saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
+	else
+		saa7185_write_block(sd, init_pal, sizeof(init_pal));
+	return 0;
+}
+
+static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	if (std & V4L2_STD_NTSC)
+		saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
+	else if (std & V4L2_STD_PAL)
+		saa7185_write_block(sd, init_pal, sizeof(init_pal));
+	else
+		return -EINVAL;
+	encoder->norm = std;
+	return 0;
+}
+
+static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	/* RJ: route->input = 0: input is from SA7111
+	 route->input = 1: input is from ZR36060 */
+
+	switch (route->input) {
 	case 0:
-		saa7185_write_block(client, init_common,
-				    sizeof(init_common));
-		switch (encoder->norm) {
-
-		case VIDEO_MODE_NTSC:
-			saa7185_write_block(client, init_ntsc,
-					    sizeof(init_ntsc));
-			break;
-
-		case VIDEO_MODE_PAL:
-			saa7185_write_block(client, init_pal,
-					    sizeof(init_pal));
-			break;
-		}
+		/* turn off colorbar */
+		saa7185_write(sd, 0x3a, 0x0f);
+		/* Switch RTCE to 1 */
+		saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
+		saa7185_write(sd, 0x6e, 0x01);
 		break;
 
-	case ENCODER_GET_CAPABILITIES:
-	{
-		struct video_encoder_capability *cap = arg;
-
-		cap->flags =
-		    VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC |
-		    VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
-		cap->inputs = 1;
-		cap->outputs = 1;
+	case 1:
+		/* turn off colorbar */
+		saa7185_write(sd, 0x3a, 0x0f);
+		/* Switch RTCE to 0 */
+		saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
+		/* SW: a slight sync problem... */
+		saa7185_write(sd, 0x6e, 0x00);
 		break;
-	}
 
-	case ENCODER_SET_NORM:
-	{
-		int *iarg = arg;
-
-		//saa7185_write_block(client, init_common, sizeof(init_common));
-
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			saa7185_write_block(client, init_ntsc,
-					    sizeof(init_ntsc));
-			break;
-
-		case VIDEO_MODE_PAL:
-			saa7185_write_block(client, init_pal,
-					    sizeof(init_pal));
-			break;
-
-		case VIDEO_MODE_SECAM:
-		default:
-			return -EINVAL;
-		}
-		encoder->norm = *iarg;
+	case 2:
+		/* turn on colorbar */
+		saa7185_write(sd, 0x3a, 0x8f);
+		/* Switch RTCE to 0 */
+		saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
+		/* SW: a slight sync problem... */
+		saa7185_write(sd, 0x6e, 0x01);
 		break;
-	}
-
-	case ENCODER_SET_INPUT:
-	{
-		int *iarg = arg;
-
-		/* RJ: *iarg = 0: input is from SA7111
-		 *iarg = 1: input is from ZR36060 */
-
-		switch (*iarg) {
-		case 0:
-			/* Switch RTCE to 1 */
-			saa7185_write(client, 0x61,
-				      (encoder->reg[0x61] & 0xf7) | 0x08);
-			saa7185_write(client, 0x6e, 0x01);
-			break;
-
-		case 1:
-			/* Switch RTCE to 0 */
-			saa7185_write(client, 0x61,
-				      (encoder->reg[0x61] & 0xf7) | 0x00);
-			/* SW: a slight sync problem... */
-			saa7185_write(client, 0x6e, 0x00);
-			break;
-
-		default:
-			return -EINVAL;
-		}
-		break;
-	}
-
-	case ENCODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-
-	case ENCODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-
-		encoder->enable = !!*iarg;
-		saa7185_write(client, 0x61,
-			      (encoder->reg[0x61] & 0xbf) |
-			      (encoder->enable ? 0x00 : 0x40));
-		break;
-	}
 
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
+static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
+static const struct v4l2_subdev_core_ops saa7185_core_ops = {
+	.g_chip_ident = saa7185_g_chip_ident,
+	.init = saa7185_init,
+};
 
-I2C_CLIENT_INSMOD;
+static const struct v4l2_subdev_video_ops saa7185_video_ops = {
+	.s_std_output = saa7185_s_std_output,
+	.s_routing = saa7185_s_routing,
+};
+
+static const struct v4l2_subdev_ops saa7185_ops = {
+	.core = &saa7185_core_ops,
+	.video = &saa7185_video_ops,
+};
+
+
+/* ----------------------------------------------------------------------- */
 
 static int saa7185_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	int i;
 	struct saa7185 *encoder;
+	struct v4l2_subdev *sd;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -351,28 +329,29 @@
 	encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
 	if (encoder == NULL)
 		return -ENOMEM;
-	encoder->norm = VIDEO_MODE_NTSC;
-	encoder->enable = 1;
-	i2c_set_clientdata(client, encoder);
+	encoder->norm = V4L2_STD_NTSC;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
 
-	i = saa7185_write_block(client, init_common, sizeof(init_common));
+	i = saa7185_write_block(sd, init_common, sizeof(init_common));
 	if (i >= 0)
-		i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc));
+		i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
 	if (i < 0)
-		v4l_dbg(1, debug, client, "init error %d\n", i);
+		v4l2_dbg(1, debug, sd, "init error %d\n", i);
 	else
-		v4l_dbg(1, debug, client, "revision 0x%x\n",
-				saa7185_read(client) >> 5);
+		v4l2_dbg(1, debug, sd, "revision 0x%x\n",
+				saa7185_read(sd) >> 5);
 	return 0;
 }
 
 static int saa7185_remove(struct i2c_client *client)
 {
-	struct saa7185 *encoder = i2c_get_clientdata(client);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa7185 *encoder = to_saa7185(sd);
 
-	saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40);	/* SW: output off is active */
-	//saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */
-
+	v4l2_device_unregister_subdev(sd);
+	/* SW: output off is active */
+	saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
 	kfree(encoder);
 	return 0;
 }
@@ -387,8 +366,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "saa7185",
-	.driverid = I2C_DRIVERID_SAA7185B,
-	.command = saa7185_command,
 	.probe = saa7185_probe,
 	.remove = saa7185_remove,
 	.id_table = saa7185_id,
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index b4018cc..3f523ae 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -19,9 +19,11 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 #include "saa7191.h"
 
@@ -32,6 +34,7 @@
 MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
 MODULE_LICENSE("GPL");
 
+
 // #define SAA7191_DEBUG
 
 #ifdef SAA7191_DEBUG
@@ -44,17 +47,20 @@
 #define SAA7191_SYNC_DELAY	100	/* milliseconds */
 
 struct saa7191 {
-	struct i2c_client *client;
+	struct v4l2_subdev sd;
 
 	/* the register values are stored here as the actual
 	 * I2C-registers are write-only */
 	u8 reg[25];
 
 	int input;
-	int norm;
+	v4l2_std_id norm;
 };
 
-static struct i2c_driver i2c_driver_saa7191;
+static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7191, sd);
+}
 
 static const u8 initseq[] = {
 	0,	/* Subaddress */
@@ -100,15 +106,14 @@
 
 /* SAA7191 register handling */
 
-static u8 saa7191_read_reg(struct i2c_client *client,
-			   u8 reg)
+static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
 {
-	return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
+	return to_saa7191(sd)->reg[reg];
 }
 
-static int saa7191_read_status(struct i2c_client *client,
-			       u8 *value)
+static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int ret;
 
 	ret = i2c_master_recv(client, value, 1);
@@ -121,21 +126,23 @@
 }
 
 
-static int saa7191_write_reg(struct i2c_client *client, u8 reg,
-			     u8 value)
+static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
-	((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	to_saa7191(sd)->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
 /* the first byte of data must be the first subaddress number (register) */
-static int saa7191_write_block(struct i2c_client *client,
+static int saa7191_write_block(struct v4l2_subdev *sd,
 			       u8 length, const u8 *data)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7191 *decoder = to_saa7191(sd);
 	int i;
 	int ret;
 
-	struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
 	for (i = 0; i < (length - 1); i++) {
 		decoder->reg[data[0] + i] = data[i + 1];
 	}
@@ -152,14 +159,15 @@
 
 /* Helper functions */
 
-static int saa7191_set_input(struct i2c_client *client, int input)
+static int saa7191_s_routing(struct v4l2_subdev *sd,
+				const struct v4l2_routing *route)
 {
-	struct saa7191 *decoder = i2c_get_clientdata(client);
-	u8 luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
-	u8 iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+	u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
 	int err;
 
-	switch (input) {
+	switch (route->input) {
 	case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
 		iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
 			  | SAA7191_IOCK_GPSW2);
@@ -175,54 +183,50 @@
 		return -EINVAL;
 	}
 
-	err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
+	err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
 	if (err)
 		return -EIO;
-	err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
+	err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
 	if (err)
 		return -EIO;
 
-	decoder->input = input;
+	decoder->input = route->input;
 
 	return 0;
 }
 
-static int saa7191_set_norm(struct i2c_client *client, int norm)
+static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-	struct saa7191 *decoder = i2c_get_clientdata(client);
-	u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
-	u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
-	u8 chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+	u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
 	int err;
 
-	switch(norm) {
-	case SAA7191_NORM_PAL:
+	if (norm & V4L2_STD_PAL) {
 		stdc &= ~SAA7191_STDC_SECS;
 		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
 		chcv = SAA7191_CHCV_PAL;
-		break;
-	case SAA7191_NORM_NTSC:
+	} else if (norm & V4L2_STD_NTSC) {
 		stdc &= ~SAA7191_STDC_SECS;
 		ctl3 &= ~SAA7191_CTL3_AUFD;
 		ctl3 |= SAA7191_CTL3_FSEL;
 		chcv = SAA7191_CHCV_NTSC;
-		break;
-	case SAA7191_NORM_SECAM:
+	} else if (norm & V4L2_STD_SECAM) {
 		stdc |= SAA7191_STDC_SECS;
 		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
 		chcv = SAA7191_CHCV_PAL;
-		break;
-	default:
+	} else {
 		return -EINVAL;
 	}
 
-	err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
 	if (err)
 		return -EIO;
-	err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
 	if (err)
 		return -EIO;
-	err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
+	err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
 	if (err)
 		return -EIO;
 
@@ -230,19 +234,19 @@
 
 	dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
 		stdc, chcv);
-	dprintk("norm: %d\n", norm);
+	dprintk("norm: %llx\n", norm);
 
 	return 0;
 }
 
-static int saa7191_wait_for_signal(struct i2c_client *client, u8 *status)
+static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
 {
 	int i = 0;
 
 	dprintk("Checking for signal...\n");
 
 	for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
-		if (saa7191_read_status(client, status))
+		if (saa7191_read_status(sd, status))
 			return -EIO;
 
 		if (((*status) & SAA7191_STATUS_HLCK) == 0) {
@@ -258,31 +262,34 @@
 	return -EBUSY;
 }
 
-static int saa7191_autodetect_norm_extended(struct i2c_client *client)
+static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
 {
-	u8 stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
-	u8 ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
+	struct saa7191 *decoder = to_saa7191(sd);
+	u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+	u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
 	u8 status;
+	v4l2_std_id old_norm = decoder->norm;
 	int err = 0;
 
 	dprintk("SAA7191 extended signal auto-detection...\n");
 
+	*norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
 	stdc &= ~SAA7191_STDC_SECS;
 	ctl3 &= ~(SAA7191_CTL3_FSEL);
 
-	err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
+	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
 	if (err) {
 		err = -EIO;
 		goto out;
 	}
-	err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
 	if (err) {
 		err = -EIO;
 		goto out;
 	}
 
 	ctl3 |= SAA7191_CTL3_AUFD;
-	err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
 	if (err) {
 		err = -EIO;
 		goto out;
@@ -290,53 +297,54 @@
 
 	msleep(SAA7191_SYNC_DELAY);
 
-	err = saa7191_wait_for_signal(client, &status);
+	err = saa7191_wait_for_signal(sd, &status);
 	if (err)
 		goto out;
 
 	if (status & SAA7191_STATUS_FIDT) {
 		/* 60Hz signal -> NTSC */
 		dprintk("60Hz signal: NTSC\n");
-		return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+		*norm = V4L2_STD_NTSC;
+		return 0;
 	}
 
 	/* 50Hz signal */
 	dprintk("50Hz signal: Trying PAL...\n");
 
 	/* try PAL first */
-	err = saa7191_set_norm(client, SAA7191_NORM_PAL);
+	err = saa7191_s_std(sd, V4L2_STD_PAL);
 	if (err)
 		goto out;
 
 	msleep(SAA7191_SYNC_DELAY);
 
-	err = saa7191_wait_for_signal(client, &status);
+	err = saa7191_wait_for_signal(sd, &status);
 	if (err)
 		goto out;
 
 	/* not 50Hz ? */
 	if (status & SAA7191_STATUS_FIDT) {
 		dprintk("No 50Hz signal\n");
-		err = -EAGAIN;
-		goto out;
+		saa7191_s_std(sd, old_norm);
+		return -EAGAIN;
 	}
 
 	if (status & SAA7191_STATUS_CODE) {
 		dprintk("PAL\n");
-		return 0;
+		*norm = V4L2_STD_PAL;
+		return saa7191_s_std(sd, old_norm);
 	}
 
 	dprintk("No color detected with PAL - Trying SECAM...\n");
 
 	/* no color detected ? -> try SECAM */
-	err = saa7191_set_norm(client,
-			       SAA7191_NORM_SECAM);
+	err = saa7191_s_std(sd, V4L2_STD_SECAM);
 	if (err)
 		goto out;
 
 	msleep(SAA7191_SYNC_DELAY);
 
-	err = saa7191_wait_for_signal(client, &status);
+	err = saa7191_wait_for_signal(sd, &status);
 	if (err)
 		goto out;
 
@@ -350,32 +358,17 @@
 	if (status & SAA7191_STATUS_CODE) {
 		/* Color detected -> SECAM */
 		dprintk("SECAM\n");
-		return 0;
+		*norm = V4L2_STD_SECAM;
+		return saa7191_s_std(sd, old_norm);
 	}
 
 	dprintk("No color detected with SECAM - Going back to PAL.\n");
 
-	/* still no color detected ?
-	 * -> set norm back to PAL */
-	err = saa7191_set_norm(client,
-			       SAA7191_NORM_PAL);
-	if (err)
-		goto out;
-
 out:
-	ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
-	if (ctl3 & SAA7191_CTL3_AUFD) {
-		ctl3 &= ~(SAA7191_CTL3_AUFD);
-		err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
-		if (err) {
-			err = -EIO;
-		}
-	}
-
-	return err;
+	return saa7191_s_std(sd, old_norm);
 }
 
-static int saa7191_autodetect_norm(struct i2c_client *client)
+static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
 {
 	u8 status;
 
@@ -383,7 +376,7 @@
 
 	dprintk("Reading status...\n");
 
-	if (saa7191_read_status(client, &status))
+	if (saa7191_read_status(sd, &status))
 		return -EIO;
 
 	dprintk("Checking for signal...\n");
@@ -399,26 +392,25 @@
 	if (status & SAA7191_STATUS_FIDT) {
 		/* 60hz signal -> NTSC */
 		dprintk("NTSC\n");
-		return saa7191_set_norm(client, SAA7191_NORM_NTSC);
+		return saa7191_s_std(sd, V4L2_STD_NTSC);
 	} else {
 		/* 50hz signal -> PAL */
 		dprintk("PAL\n");
-		return saa7191_set_norm(client, SAA7191_NORM_PAL);
+		return saa7191_s_std(sd, V4L2_STD_PAL);
 	}
 }
 
-static int saa7191_get_control(struct i2c_client *client,
-			       struct saa7191_control *ctrl)
+static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	u8 reg;
 	int ret = 0;
 
-	switch (ctrl->type) {
+	switch (ctrl->id) {
 	case SAA7191_CONTROL_BANDPASS:
 	case SAA7191_CONTROL_BANDPASS_WEIGHT:
 	case SAA7191_CONTROL_CORING:
-		reg = saa7191_read_reg(client, SAA7191_REG_LUMA);
-		switch (ctrl->type) {
+		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+		switch (ctrl->id) {
 		case SAA7191_CONTROL_BANDPASS:
 			ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
 				>> SAA7191_LUMA_BPSS_SHIFT;
@@ -435,15 +427,15 @@
 		break;
 	case SAA7191_CONTROL_FORCE_COLOUR:
 	case SAA7191_CONTROL_CHROMA_GAIN:
-		reg = saa7191_read_reg(client, SAA7191_REG_GAIN);
-		if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR)
+		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
 			ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
 		else
 			ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
 				>> SAA7191_GAIN_LFIS_SHIFT;
 		break;
-	case SAA7191_CONTROL_HUE:
-		reg = saa7191_read_reg(client, SAA7191_REG_HUEC);
+	case V4L2_CID_HUE:
+		reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
 		if (reg < 0x80)
 			reg += 0x80;
 		else
@@ -451,18 +443,18 @@
 		ctrl->value = (s32)reg;
 		break;
 	case SAA7191_CONTROL_VTRC:
-		reg = saa7191_read_reg(client, SAA7191_REG_STDC);
+		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
 		ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
 		break;
 	case SAA7191_CONTROL_LUMA_DELAY:
-		reg = saa7191_read_reg(client, SAA7191_REG_CTL3);
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
 		ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
 			>> SAA7191_CTL3_YDEL_SHIFT;
 		if (ctrl->value >= 4)
 			ctrl->value -= 8;
 		break;
 	case SAA7191_CONTROL_VNR:
-		reg = saa7191_read_reg(client, SAA7191_REG_CTL4);
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
 		ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
 			>> SAA7191_CTL4_VNOI_SHIFT;
 		break;
@@ -473,18 +465,17 @@
 	return ret;
 }
 
-static int saa7191_set_control(struct i2c_client *client,
-			       struct saa7191_control *ctrl)
+static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	u8 reg;
 	int ret = 0;
 
-	switch (ctrl->type) {
+	switch (ctrl->id) {
 	case SAA7191_CONTROL_BANDPASS:
 	case SAA7191_CONTROL_BANDPASS_WEIGHT:
 	case SAA7191_CONTROL_CORING:
-		reg = saa7191_read_reg(client, SAA7191_REG_LUMA);
-		switch (ctrl->type) {
+		reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+		switch (ctrl->id) {
 		case SAA7191_CONTROL_BANDPASS:
 			reg &= ~SAA7191_LUMA_BPSS_MASK;
 			reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
@@ -501,12 +492,12 @@
 				& SAA7191_LUMA_CORI_MASK;
 			break;
 		}
-		ret = saa7191_write_reg(client, SAA7191_REG_LUMA, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
 		break;
 	case SAA7191_CONTROL_FORCE_COLOUR:
 	case SAA7191_CONTROL_CHROMA_GAIN:
-		reg = saa7191_read_reg(client, SAA7191_REG_GAIN);
-		if (ctrl->type == SAA7191_CONTROL_FORCE_COLOUR) {
+		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
 			if (ctrl->value)
 				reg |= SAA7191_GAIN_COLO;
 			else
@@ -516,41 +507,41 @@
 			reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
 				& SAA7191_GAIN_LFIS_MASK;
 		}
-		ret = saa7191_write_reg(client, SAA7191_REG_GAIN, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
 		break;
-	case SAA7191_CONTROL_HUE:
+	case V4L2_CID_HUE:
 		reg = ctrl->value & 0xff;
 		if (reg < 0x80)
 			reg += 0x80;
 		else
 			reg -= 0x80;
-		ret = saa7191_write_reg(client, SAA7191_REG_HUEC, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
 		break;
 	case SAA7191_CONTROL_VTRC:
-		reg = saa7191_read_reg(client, SAA7191_REG_STDC);
+		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
 		if (ctrl->value)
 			reg |= SAA7191_STDC_VTRC;
 		else
 			reg &= ~SAA7191_STDC_VTRC;
-		ret = saa7191_write_reg(client, SAA7191_REG_STDC, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
 		break;
 	case SAA7191_CONTROL_LUMA_DELAY: {
 		s32 value = ctrl->value;
 		if (value < 0)
 			value += 8;
-		reg = saa7191_read_reg(client, SAA7191_REG_CTL3);
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
 		reg &= ~SAA7191_CTL3_YDEL_MASK;
 		reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
 			& SAA7191_CTL3_YDEL_MASK;
-		ret = saa7191_write_reg(client, SAA7191_REG_CTL3, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
 		break;
 	}
 	case SAA7191_CONTROL_VNR:
-		reg = saa7191_read_reg(client, SAA7191_REG_CTL4);
+		reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
 		reg &= ~SAA7191_CTL4_VNOI_MASK;
 		reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
 			& SAA7191_CTL4_VNOI_MASK;
-		ret = saa7191_write_reg(client, SAA7191_REG_CTL4, reg);
+		ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
 		break;
 	default:
 		ret = -EINVAL;
@@ -561,247 +552,108 @@
 
 /* I2C-interface */
 
-static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
+static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	u8 status_reg;
+	int res = V4L2_IN_ST_NO_SIGNAL;
+
+	if (saa7191_read_status(sd, &status_reg))
+		return -EIO;
+	if ((status_reg & SAA7191_STATUS_HLCK) == 0)
+		res = 0;
+	if (!(status_reg & SAA7191_STATUS_CODE))
+		res |= V4L2_IN_ST_NO_COLOR;
+	*status = res;
+	return 0;
+}
+
+
+static int saa7191_g_chip_ident(struct v4l2_subdev *sd,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa7191_core_ops = {
+	.g_chip_ident = saa7191_g_chip_ident,
+	.g_ctrl = saa7191_g_ctrl,
+	.s_ctrl = saa7191_s_ctrl,
+};
+
+static const struct v4l2_subdev_tuner_ops saa7191_tuner_ops = {
+	.s_std = saa7191_s_std,
+};
+
+static const struct v4l2_subdev_video_ops saa7191_video_ops = {
+	.s_routing = saa7191_s_routing,
+	.querystd = saa7191_querystd,
+	.g_input_status = saa7191_g_input_status,
+};
+
+static const struct v4l2_subdev_ops saa7191_ops = {
+	.core = &saa7191_core_ops,
+	.video = &saa7191_video_ops,
+	.tuner = &saa7191_tuner_ops,
+};
+
+static int saa7191_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
 {
 	int err = 0;
 	struct saa7191 *decoder;
-	struct i2c_client *client;
+	struct v4l2_subdev *sd;
 
-	printk(KERN_INFO "Philips SAA7191 driver version %s\n",
-	       SAA7191_MODULE_VERSION);
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
 
-	client = kzalloc(sizeof(*client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
 	decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
-	if (!decoder) {
-		err = -ENOMEM;
-		goto out_free_client;
-	}
+	if (!decoder)
+		return -ENOMEM;
 
-	client->addr = addr;
-	client->adapter = adap;
-	client->driver = &i2c_driver_saa7191;
-	client->flags = 0;
-	strcpy(client->name, "saa7191 client");
-	i2c_set_clientdata(client, decoder);
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
 
-	decoder->client = client;
-
-	err = i2c_attach_client(client);
-	if (err)
-		goto out_free_decoder;
-
-	err = saa7191_write_block(client, sizeof(initseq), initseq);
+	err = saa7191_write_block(sd, sizeof(initseq), initseq);
 	if (err) {
 		printk(KERN_ERR "SAA7191 initialization failed\n");
-		goto out_detach_client;
+		kfree(decoder);
+		return err;
 	}
 
 	printk(KERN_INFO "SAA7191 initialized\n");
 
 	decoder->input = SAA7191_INPUT_COMPOSITE;
-	decoder->norm = SAA7191_NORM_PAL;
+	decoder->norm = V4L2_STD_PAL;
 
-	err = saa7191_autodetect_norm(client);
-	if (err && (err != -EBUSY)) {
+	err = saa7191_autodetect_norm(sd);
+	if (err && (err != -EBUSY))
 		printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
-	}
-
-	return 0;
-
-out_detach_client:
-	i2c_detach_client(client);
-out_free_decoder:
-	kfree(decoder);
-out_free_client:
-	kfree(client);
-	return err;
-}
-
-static int saa7191_probe(struct i2c_adapter *adap)
-{
-	/* Always connected to VINO */
-	if (adap->id == I2C_HW_SGI_VINO)
-		return saa7191_attach(adap, SAA7191_ADDR, 0);
-	/* Feel free to add probe here :-) */
-	return -ENODEV;
-}
-
-static int saa7191_detach(struct i2c_client *client)
-{
-	struct saa7191 *decoder = i2c_get_clientdata(client);
-
-	i2c_detach_client(client);
-	kfree(decoder);
-	kfree(client);
-	return 0;
-}
-
-static int saa7191_command(struct i2c_client *client, unsigned int cmd,
-			   void *arg)
-{
-	struct saa7191 *decoder = i2c_get_clientdata(client);
-
-	switch (cmd) {
-	case DECODER_GET_CAPABILITIES: {
-		struct video_decoder_capability *cap = arg;
-
-		cap->flags  = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
-			      VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
-		cap->inputs = (client->adapter->id == I2C_HW_SGI_VINO) ? 2 : 1;
-		cap->outputs = 1;
-		break;
-	}
-	case DECODER_GET_STATUS: {
-		int *iarg = arg;
-		u8 status;
-		int res = 0;
-
-		if (saa7191_read_status(client, &status)) {
-			return -EIO;
-		}
-		if ((status & SAA7191_STATUS_HLCK) == 0)
-			res |= DECODER_STATUS_GOOD;
-		if (status & SAA7191_STATUS_CODE)
-			res |= DECODER_STATUS_COLOR;
-		switch (decoder->norm) {
-		case SAA7191_NORM_NTSC:
-			res |= DECODER_STATUS_NTSC;
-			break;
-		case SAA7191_NORM_PAL:
-			res |= DECODER_STATUS_PAL;
-			break;
-		case SAA7191_NORM_SECAM:
-			res |= DECODER_STATUS_SECAM;
-			break;
-		case SAA7191_NORM_AUTO:
-		default:
-			if (status & SAA7191_STATUS_FIDT)
-				res |= DECODER_STATUS_NTSC;
-			else
-				res |= DECODER_STATUS_PAL;
-			break;
-		}
-		*iarg = res;
-		break;
-	}
-	case DECODER_SET_NORM: {
-		int *iarg = arg;
-
-		switch (*iarg) {
-		case VIDEO_MODE_AUTO:
-			return saa7191_autodetect_norm(client);
-		case VIDEO_MODE_PAL:
-			return saa7191_set_norm(client, SAA7191_NORM_PAL);
-		case VIDEO_MODE_NTSC:
-			return saa7191_set_norm(client, SAA7191_NORM_NTSC);
-		case VIDEO_MODE_SECAM:
-			return saa7191_set_norm(client, SAA7191_NORM_SECAM);
-		default:
-			return -EINVAL;
-		}
-		break;
-	}
-	case DECODER_SET_INPUT:	{
-		int *iarg = arg;
-
-		switch (client->adapter->id) {
-		case I2C_HW_SGI_VINO:
-			return saa7191_set_input(client, *iarg);
-		default:
-			if (*iarg != 0)
-				return -EINVAL;
-		}
-		break;
-	}
-	case DECODER_SET_OUTPUT: {
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0)
-			return -EINVAL;
-		break;
-	}
-	case DECODER_ENABLE_OUTPUT: {
-		/* Always enabled */
-		break;
-	}
-	case DECODER_SET_PICTURE: {
-		struct video_picture *pic = arg;
-		unsigned val;
-		int err;
-
-		val = (pic->hue >> 8) - 0x80;
-
-		err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
-		if (err)
-			return -EIO;
-
-		break;
-	}
-	case DECODER_SAA7191_GET_STATUS: {
-		struct saa7191_status *status = arg;
-		u8 status_reg;
-
-		if (saa7191_read_status(client, &status_reg))
-			return -EIO;
-
-		status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
-			? 1 : 0;
-		status->signal_60hz = (status_reg & SAA7191_STATUS_FIDT)
-			? 1 : 0;
-		status->color = (status_reg & SAA7191_STATUS_CODE) ? 1 : 0;
-
-		status->input = decoder->input;
-		status->norm = decoder->norm;
-
-		break;
-	}
-	case DECODER_SAA7191_SET_NORM: {
-		int *norm = arg;
-
-		switch (*norm) {
-		case SAA7191_NORM_AUTO:
-			return saa7191_autodetect_norm(client);
-		case SAA7191_NORM_AUTO_EXT:
-			return saa7191_autodetect_norm_extended(client);
-		default:
-			return saa7191_set_norm(client, *norm);
-		}
-	}
-	case DECODER_SAA7191_GET_CONTROL: {
-		return saa7191_get_control(client, arg);
-	}
-	case DECODER_SAA7191_SET_CONTROL: {
-		return saa7191_set_control(client, arg);
-	}
-	default:
-		return -EINVAL;
-	}
 
 	return 0;
 }
 
-static struct i2c_driver i2c_driver_saa7191 = {
-	.driver = {
-		.name 	= "saa7191",
-	},
-	.id		= I2C_DRIVERID_SAA7191,
-	.attach_adapter = saa7191_probe,
-	.detach_client	= saa7191_detach,
-	.command	= saa7191_command
+static int saa7191_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_saa7191(sd));
+	return 0;
+}
+
+static const struct i2c_device_id saa7191_id[] = {
+	{ "saa7191", 0 },
+	{ }
 };
+MODULE_DEVICE_TABLE(i2c, saa7191_id);
 
-static int saa7191_init(void)
-{
-	return i2c_add_driver(&i2c_driver_saa7191);
-}
-
-static void saa7191_exit(void)
-{
-	i2c_del_driver(&i2c_driver_saa7191);
-}
-
-module_init(saa7191_init);
-module_exit(saa7191_exit);
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "saa7191",
+	.probe = saa7191_probe,
+	.remove = saa7191_remove,
+	.id_table = saa7191_id,
+};
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h
index a2310da..803c74d 100644
--- a/drivers/media/video/saa7191.h
+++ b/drivers/media/video/saa7191.h
@@ -176,11 +176,9 @@
 #define SAA7191_INPUT_COMPOSITE	0
 #define SAA7191_INPUT_SVIDEO	1
 
-#define SAA7191_NORM_AUTO	0
 #define SAA7191_NORM_PAL	1
 #define SAA7191_NORM_NTSC	2
 #define SAA7191_NORM_SECAM	3
-#define SAA7191_NORM_AUTO_EXT	4	/* extended auto-detection */
 
 struct saa7191_status {
 	/* 0=no signal, 1=signal detected */
@@ -232,24 +230,16 @@
 #define SAA7191_VNR_MAX			0x03
 #define SAA7191_VNR_DEFAULT		0x00
 
-#define SAA7191_CONTROL_BANDPASS	0
-#define SAA7191_CONTROL_BANDPASS_WEIGHT	1
-#define SAA7191_CONTROL_CORING		2
-#define SAA7191_CONTROL_FORCE_COLOUR	3	/* boolean */
-#define SAA7191_CONTROL_CHROMA_GAIN	4
-#define SAA7191_CONTROL_HUE		5
-#define SAA7191_CONTROL_VTRC		6	/* boolean */
-#define SAA7191_CONTROL_LUMA_DELAY	7
-#define SAA7191_CONTROL_VNR		8
-
-struct saa7191_control {
-	u8 type;
-	s32 value;
-};
+#define SAA7191_CONTROL_BANDPASS	(V4L2_CID_PRIVATE_BASE + 0)
+#define SAA7191_CONTROL_BANDPASS_WEIGHT	(V4L2_CID_PRIVATE_BASE + 1)
+#define SAA7191_CONTROL_CORING		(V4L2_CID_PRIVATE_BASE + 2)
+#define SAA7191_CONTROL_FORCE_COLOUR	(V4L2_CID_PRIVATE_BASE + 3)
+#define SAA7191_CONTROL_CHROMA_GAIN	(V4L2_CID_PRIVATE_BASE + 4)
+#define SAA7191_CONTROL_VTRC		(V4L2_CID_PRIVATE_BASE + 5)
+#define SAA7191_CONTROL_LUMA_DELAY	(V4L2_CID_PRIVATE_BASE + 6)
+#define SAA7191_CONTROL_VNR		(V4L2_CID_PRIVATE_BASE + 7)
 
 #define	DECODER_SAA7191_GET_STATUS	_IOR('d', 195, struct saa7191_status)
 #define	DECODER_SAA7191_SET_NORM	_IOW('d', 196, int)
-#define	DECODER_SAA7191_GET_CONTROL	_IOR('d', 197, struct saa7191_control)
-#define	DECODER_SAA7191_SET_CONTROL	_IOW('d', 198, struct saa7191_control)
 
 #endif
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index ddcb81d..b5e37a5 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -94,13 +94,37 @@
 	spinlock_t lock;
 	struct list_head capture;
 	struct videobuf_buffer *active;
-	int is_interlace;
+	int is_interlaced;
 
 	struct sh_mobile_ceu_info *pdata;
 
 	const struct soc_camera_data_format *camera_fmt;
 };
 
+static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
+{
+	unsigned long flags;
+
+	flags = SOCAM_MASTER |
+		SOCAM_PCLK_SAMPLE_RISING |
+		SOCAM_HSYNC_ACTIVE_HIGH |
+		SOCAM_HSYNC_ACTIVE_LOW |
+		SOCAM_VSYNC_ACTIVE_HIGH |
+		SOCAM_VSYNC_ACTIVE_LOW |
+		SOCAM_DATA_ACTIVE_HIGH;
+
+	if (pcdev->pdata->flags & SH_CEU_FLAG_USE_8BIT_BUS)
+		flags |= SOCAM_DATAWIDTH_8;
+
+	if (pcdev->pdata->flags & SH_CEU_FLAG_USE_16BIT_BUS)
+		flags |= SOCAM_DATAWIDTH_16;
+
+	if (flags & SOCAM_DATAWIDTH_MASK)
+		return flags;
+
+	return 0;
+}
+
 static void ceu_write(struct sh_mobile_ceu_dev *priv,
 		      unsigned long reg_offs, u32 data)
 {
@@ -150,6 +174,7 @@
 	if (in_interrupt())
 		BUG();
 
+	videobuf_waiton(&buf->vb, 0, 0);
 	videobuf_dma_contig_free(vq, &buf->vb);
 	dev_dbg(&icd->dev, "%s freed\n", __func__);
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
@@ -181,7 +206,7 @@
 
 	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
 	ceu_write(pcdev, CDAYR, phys_addr_top);
-	if (pcdev->is_interlace) {
+	if (pcdev->is_interlaced) {
 		phys_addr_bottom = phys_addr_top + icd->width;
 		ceu_write(pcdev, CDBYR, phys_addr_bottom);
 	}
@@ -193,7 +218,7 @@
 	case V4L2_PIX_FMT_NV61:
 		phys_addr_top += icd->width * icd->height;
 		ceu_write(pcdev, CDACR, phys_addr_top);
-		if (pcdev->is_interlace) {
+		if (pcdev->is_interlaced) {
 			phys_addr_bottom = phys_addr_top + icd->width;
 			ceu_write(pcdev, CDBCR, phys_addr_bottom);
 		}
@@ -396,7 +421,7 @@
 
 	camera_flags = icd->ops->query_bus_param(icd);
 	common_flags = soc_camera_bus_param_compatible(camera_flags,
-						       pcdev->pdata->flags);
+						       make_bus_param(pcdev));
 	if (!common_flags)
 		return -EINVAL;
 
@@ -457,7 +482,7 @@
 	ceu_write(pcdev, CAMCR, value);
 
 	ceu_write(pcdev, CAPCR, 0x00300000);
-	ceu_write(pcdev, CAIFR, (pcdev->is_interlace) ? 0x101 : 0);
+	ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0);
 
 	mdelay(1);
 
@@ -473,7 +498,7 @@
 	}
 
 	height = icd->height;
-	if (pcdev->is_interlace) {
+	if (pcdev->is_interlaced) {
 		height /= 2;
 		cdwdr_width *= 2;
 	}
@@ -517,7 +542,7 @@
 
 	camera_flags = icd->ops->query_bus_param(icd);
 	common_flags = soc_camera_bus_param_compatible(camera_flags,
-						       pcdev->pdata->flags);
+						       make_bus_param(pcdev));
 	if (!common_flags)
 		return -EINVAL;
 
@@ -562,11 +587,29 @@
 	if (ret < 0)
 		return 0;
 
+	/* Beginning of a pass */
+	if (!idx)
+		icd->host_priv = NULL;
+
 	switch (icd->formats[idx].fourcc) {
 	case V4L2_PIX_FMT_UYVY:
 	case V4L2_PIX_FMT_VYUY:
 	case V4L2_PIX_FMT_YUYV:
 	case V4L2_PIX_FMT_YVYU:
+		if (icd->host_priv)
+			goto add_single_format;
+
+		/*
+		 * Our case is simple so far: for any of the above four camera
+		 * formats we add all our four synthesized NV* formats, so,
+		 * just marking the device with a single flag suffices. If
+		 * the format generation rules are more complex, you would have
+		 * to actually hang your already added / counted formats onto
+		 * the host_priv pointer and check whether the format you're
+		 * going to add now is already there.
+		 */
+		icd->host_priv = (void *)sh_mobile_ceu_formats;
+
 		n = ARRAY_SIZE(sh_mobile_ceu_formats);
 		formats += n;
 		for (k = 0; xlate && k < n; k++) {
@@ -579,6 +622,7 @@
 				icd->formats[idx].name);
 		}
 	default:
+add_single_format:
 		/* Generic pass-through */
 		formats++;
 		if (xlate) {
@@ -595,24 +639,30 @@
 	return formats;
 }
 
+static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
+				  struct v4l2_rect *rect)
+{
+	return icd->ops->set_crop(icd, rect);
+}
+
 static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
-				 __u32 pixfmt, struct v4l2_rect *rect)
+				 struct v4l2_format *f)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	__u32 pixfmt = f->fmt.pix.pixelformat;
 	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_format cam_f = *f;
 	int ret;
 
-	if (!pixfmt)
-		return icd->ops->set_fmt(icd, pixfmt, rect);
-
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
 		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
-	ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
+	cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc;
+	ret = icd->ops->set_fmt(icd, &cam_f);
 
 	if (!ret) {
 		icd->buswidth = xlate->buswidth;
@@ -662,13 +712,13 @@
 
 	switch (f->fmt.pix.field) {
 	case V4L2_FIELD_INTERLACED:
-		pcdev->is_interlace = 1;
+		pcdev->is_interlaced = 1;
 		break;
 	case V4L2_FIELD_ANY:
 		f->fmt.pix.field = V4L2_FIELD_NONE;
 		/* fall-through */
 	case V4L2_FIELD_NONE:
-		pcdev->is_interlace = 0;
+		pcdev->is_interlaced = 0;
 		break;
 	default:
 		ret = -EINVAL;
@@ -734,7 +784,8 @@
 				       &sh_mobile_ceu_videobuf_ops,
 				       &ici->dev, &pcdev->lock,
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				       V4L2_FIELD_ANY,
+				       pcdev->is_interlaced ?
+				       V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
 				       sizeof(struct sh_mobile_ceu_buffer),
 				       icd);
 }
@@ -744,6 +795,7 @@
 	.add		= sh_mobile_ceu_add_device,
 	.remove		= sh_mobile_ceu_remove_device,
 	.get_formats	= sh_mobile_ceu_get_formats,
+	.set_crop	= sh_mobile_ceu_set_crop,
 	.set_fmt	= sh_mobile_ceu_set_fmt,
 	.try_fmt	= sh_mobile_ceu_try_fmt,
 	.reqbufs	= sh_mobile_ceu_reqbufs,
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 8cb3457..38a7160 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -96,9 +96,7 @@
 #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
 	{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
-#endif
 	{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
-#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
 	{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
 #endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
@@ -123,7 +121,9 @@
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
 #endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
+#endif
 	{ SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
 	{ }
 };
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index fcb05f0..6d8bfd4 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -30,6 +30,10 @@
 #include <media/videobuf-core.h>
 #include <media/soc_camera.h>
 
+/* Default to VGA resolution */
+#define DEFAULT_WIDTH	640
+#define DEFAULT_HEIGHT	480
+
 static LIST_HEAD(hosts);
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);
@@ -256,6 +260,46 @@
 	vfree(icd->user_formats);
 }
 
+/* Called with .vb_lock held */
+static int soc_camera_set_fmt(struct soc_camera_file *icf,
+			      struct v4l2_format *f)
+{
+	struct soc_camera_device *icd = icf->icd;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int ret;
+
+	/* We always call try_fmt() before set_fmt() or set_crop() */
+	ret = ici->ops->try_fmt(icd, f);
+	if (ret < 0)
+		return ret;
+
+	ret = ici->ops->set_fmt(icd, f);
+	if (ret < 0) {
+		return ret;
+	} else if (!icd->current_fmt ||
+		   icd->current_fmt->fourcc != pix->pixelformat) {
+		dev_err(&ici->dev,
+			"Host driver hasn't set up current format correctly!\n");
+		return -EINVAL;
+	}
+
+	icd->width		= pix->width;
+	icd->height		= pix->height;
+	icf->vb_vidq.field	=
+		icd->field	= pix->field;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
+			 f->type);
+
+	dev_dbg(&icd->dev, "set width: %d height: %d\n",
+		icd->width, icd->height);
+
+	/* set physical bus parameters */
+	return ici->ops->set_bus_param(icd, pix->pixelformat);
+}
+
 static int soc_camera_open(struct file *file)
 {
 	struct video_device *vdev;
@@ -297,14 +341,28 @@
 
 	/* Now we really have to activate the camera */
 	if (icd->use_count == 1) {
-		ret = soc_camera_init_user_formats(icd);
-		if (ret < 0)
-			goto eiufmt;
+		/* Restore parameters before the last close() per V4L2 API */
+		struct v4l2_format f = {
+			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			.fmt.pix = {
+				.width		= icd->width,
+				.height		= icd->height,
+				.field		= icd->field,
+				.pixelformat	= icd->current_fmt->fourcc,
+				.colorspace	= icd->current_fmt->colorspace,
+			},
+		};
+
 		ret = ici->ops->add(icd);
 		if (ret < 0) {
 			dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
 			goto eiciadd;
 		}
+
+		/* Try to configure with default parameters */
+		ret = soc_camera_set_fmt(icf, &f);
+		if (ret < 0)
+			goto esfmt;
 	}
 
 	mutex_unlock(&icd->video_lock);
@@ -316,10 +374,13 @@
 
 	return 0;
 
-	/* First two errors are entered with the .video_lock held */
+	/*
+	 * First three errors are entered with the .video_lock held
+	 * and use_count == 1
+	 */
+esfmt:
+	ici->ops->remove(icd);
 eiciadd:
-	soc_camera_free_user_formats(icd);
-eiufmt:
 	icd->use_count--;
 	mutex_unlock(&icd->video_lock);
 	module_put(ici->ops->owner);
@@ -339,10 +400,9 @@
 
 	mutex_lock(&icd->video_lock);
 	icd->use_count--;
-	if (!icd->use_count) {
+	if (!icd->use_count)
 		ici->ops->remove(icd);
-		soc_camera_free_user_formats(icd);
-	}
+
 	mutex_unlock(&icd->video_lock);
 
 	module_put(icd->ops->owner);
@@ -415,18 +475,10 @@
 {
 	struct soc_camera_file *icf = file->private_data;
 	struct soc_camera_device *icd = icf->icd;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	__u32 pixfmt = pix->pixelformat;
 	int ret;
-	struct v4l2_rect rect;
 
 	WARN_ON(priv != file->private_data);
 
-	ret = soc_camera_try_fmt_vid_cap(file, priv, f);
-	if (ret < 0)
-		return ret;
-
 	mutex_lock(&icf->vb_vidq.vb_lock);
 
 	if (videobuf_queue_is_busy(&icf->vb_vidq)) {
@@ -435,33 +487,7 @@
 		goto unlock;
 	}
 
-	rect.left	= icd->x_current;
-	rect.top	= icd->y_current;
-	rect.width	= pix->width;
-	rect.height	= pix->height;
-	ret = ici->ops->set_fmt(icd, pix->pixelformat, &rect);
-	if (ret < 0) {
-		goto unlock;
-	} else if (!icd->current_fmt ||
-		   icd->current_fmt->fourcc != pixfmt) {
-		dev_err(&ici->dev,
-			"Host driver hasn't set up current format correctly!\n");
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	icd->width		= rect.width;
-	icd->height		= rect.height;
-	icf->vb_vidq.field	= pix->field;
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
-			 f->type);
-
-	dev_dbg(&icd->dev, "set width: %d height: %d\n",
-		icd->width, icd->height);
-
-	/* set physical bus parameters */
-	ret = ici->ops->set_bus_param(icd, pixfmt);
+	ret = soc_camera_set_fmt(icf, f);
 
 unlock:
 	mutex_unlock(&icf->vb_vidq.vb_lock);
@@ -648,8 +674,8 @@
 	a->bounds.height		= icd->height_max;
 	a->defrect.left			= icd->x_min;
 	a->defrect.top			= icd->y_min;
-	a->defrect.width		= 640;
-	a->defrect.height		= 480;
+	a->defrect.width		= DEFAULT_WIDTH;
+	a->defrect.height		= DEFAULT_HEIGHT;
 	a->pixelaspect.numerator	= 1;
 	a->pixelaspect.denominator	= 1;
 
@@ -685,7 +711,7 @@
 	/* Cropping is allowed during a running capture, guard consistency */
 	mutex_lock(&icf->vb_vidq.vb_lock);
 
-	ret = ici->ops->set_fmt(icd, 0, &a->c);
+	ret = ici->ops->set_crop(icd, &a->c);
 	if (!ret) {
 		icd->width	= a->c.width;
 		icd->height	= a->c.height;
@@ -844,9 +870,18 @@
 		qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
 		icd->exposure = qctrl ? qctrl->default_value :
 			(unsigned short)~0;
-	}
-	ici->ops->remove(icd);
 
+		ret = soc_camera_init_user_formats(icd);
+		if (ret < 0)
+			goto eiufmt;
+
+		icd->height	= DEFAULT_HEIGHT;
+		icd->width	= DEFAULT_WIDTH;
+		icd->field	= V4L2_FIELD_ANY;
+	}
+
+eiufmt:
+	ici->ops->remove(icd);
 eiadd:
 	mutex_unlock(&icd->video_lock);
 	module_put(ici->ops->owner);
@@ -865,6 +900,8 @@
 	if (icd->ops->remove)
 		icd->ops->remove(icd);
 
+	soc_camera_free_user_formats(icd);
+
 	return 0;
 }
 
@@ -918,6 +955,7 @@
 	if (!ici || !ici->ops ||
 	    !ici->ops->try_fmt ||
 	    !ici->ops->set_fmt ||
+	    !ici->ops->set_crop ||
 	    !ici->ops->set_bus_param ||
 	    !ici->ops->querycap ||
 	    !ici->ops->init_videobuf ||
@@ -998,6 +1036,7 @@
 	    !icd->ops->release ||
 	    !icd->ops->start_capture ||
 	    !icd->ops->stop_capture ||
+	    !icd->ops->set_crop ||
 	    !icd->ops->set_fmt ||
 	    !icd->ops->try_fmt ||
 	    !icd->ops->query_bus_param ||
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index 013ab06..c486763 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -79,8 +79,14 @@
 	return p->bus_param;
 }
 
+static int soc_camera_platform_set_crop(struct soc_camera_device *icd,
+					struct v4l2_rect *rect)
+{
+	return 0;
+}
+
 static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
-				       __u32 pixfmt, struct v4l2_rect *rect)
+				       struct v4l2_format *f)
 {
 	return 0;
 }
@@ -125,6 +131,7 @@
 	.release		= soc_camera_platform_release,
 	.start_capture		= soc_camera_platform_start_capture,
 	.stop_capture		= soc_camera_platform_stop_capture,
+	.set_crop		= soc_camera_platform_set_crop,
 	.set_fmt		= soc_camera_platform_set_fmt,
 	.try_fmt		= soc_camera_platform_try_fmt,
 	.set_bus_param		= soc_camera_platform_set_bus_param,
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index 26378cf..1a6d39c 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -933,8 +933,6 @@
 static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
 		void *priv, struct v4l2_fmtdesc *fmtd)
 {
-	fmtd->flags = 0;
-
 	switch (fmtd->index) {
 	case 0:
 		fmtd->pixelformat = V4L2_PIX_FMT_RGB565;
@@ -992,7 +990,6 @@
 	pix_format->height = stk_sizes[i].h;
 	pix_format->field = V4L2_FIELD_NONE;
 	pix_format->colorspace = V4L2_COLORSPACE_SRGB;
-	pix_format->priv = 0;
 	pix_format->pixelformat = dev->vsettings.palette;
 	if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
 		pix_format->bytesperline = pix_format->width;
@@ -1115,8 +1112,6 @@
 
 	if (dev == NULL)
 		return -ENODEV;
-	if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 	if (rb->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 	if (is_streaming(dev)
@@ -1139,16 +1134,10 @@
 static int stk_vidioc_querybuf(struct file *filp,
 		void *priv, struct v4l2_buffer *buf)
 {
-	int index;
 	struct stk_camera *dev = priv;
 	struct stk_sio_buffer *sbuf;
 
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	index = buf->index;
-
-	if (index < 0 || index >= dev->n_sbufs)
+	if (buf->index < 0 || buf->index >= dev->n_sbufs)
 		return -EINVAL;
 	sbuf = dev->sio_bufs + buf->index;
 	*buf = sbuf->v4lbuf;
@@ -1161,8 +1150,6 @@
 	struct stk_camera *dev = priv;
 	struct stk_sio_buffer *sbuf;
 	unsigned long flags;
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 
 	if (buf->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
@@ -1189,8 +1176,7 @@
 	unsigned long flags;
 	int ret;
 
-	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
-		|| !is_streaming(dev))
+	if (!is_streaming(dev))
 		return -EINVAL;
 
 	if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))
@@ -1249,16 +1235,10 @@
 static int stk_vidioc_g_parm(struct file *filp,
 		void *priv, struct v4l2_streamparm *sp)
 {
-	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	sp->parm.capture.capability = 0;
-	sp->parm.capture.capturemode = 0;
 	/*FIXME This is not correct */
 	sp->parm.capture.timeperframe.numerator = 1;
 	sp->parm.capture.timeperframe.denominator = 30;
 	sp->parm.capture.readbuffers = 2;
-	sp->parm.capture.extendedmode = 0;
 	return 0;
 }
 
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
index 29991d1..b30c492 100644
--- a/drivers/media/video/tcm825x.c
+++ b/drivers/media/video/tcm825x.c
@@ -50,7 +50,7 @@
 };
 
 /* list of image formats supported by TCM825X sensor */
-const static struct v4l2_fmtdesc tcm825x_formats[] = {
+static const struct v4l2_fmtdesc tcm825x_formats[] = {
 	{
 		.description = "YUYV (YUV 4:2:2), packed",
 		.pixelformat = V4L2_PIX_FMT_UYVY,
@@ -76,15 +76,15 @@
  * TCM825X register configuration for all combinations of pixel format and
  * image size
  */
-const static struct tcm825x_reg subqcif	=	{ 0x20, TCM825X_PICSIZ };
-const static struct tcm825x_reg qcif	=	{ 0x18, TCM825X_PICSIZ };
-const static struct tcm825x_reg cif	=	{ 0x14, TCM825X_PICSIZ };
-const static struct tcm825x_reg qqvga	=	{ 0x0c, TCM825X_PICSIZ };
-const static struct tcm825x_reg qvga	=	{ 0x04, TCM825X_PICSIZ };
-const static struct tcm825x_reg vga	=	{ 0x00, TCM825X_PICSIZ };
+static const struct tcm825x_reg subqcif	=	{ 0x20, TCM825X_PICSIZ };
+static const struct tcm825x_reg qcif	=	{ 0x18, TCM825X_PICSIZ };
+static const struct tcm825x_reg cif	=	{ 0x14, TCM825X_PICSIZ };
+static const struct tcm825x_reg qqvga	=	{ 0x0c, TCM825X_PICSIZ };
+static const struct tcm825x_reg qvga	=	{ 0x04, TCM825X_PICSIZ };
+static const struct tcm825x_reg vga	=	{ 0x00, TCM825X_PICSIZ };
 
-const static struct tcm825x_reg yuv422	=	{ 0x00, TCM825X_PICFMT };
-const static struct tcm825x_reg rgb565	=	{ 0x02, TCM825X_PICFMT };
+static const struct tcm825x_reg yuv422	=	{ 0x00, TCM825X_PICFMT };
+static const struct tcm825x_reg rgb565	=	{ 0x02, TCM825X_PICFMT };
 
 /* Our own specific controls */
 #define V4L2_CID_ALC				V4L2_CID_PRIVATE_BASE
@@ -248,10 +248,10 @@
 };
 
 
-const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
+static const struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
 { &subqcif, &qqvga, &qcif, &qvga, &cif, &vga };
 
-const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
+static const struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
 { &yuv422, &rgb565 };
 
 /*
diff --git a/drivers/media/video/tcm825x.h b/drivers/media/video/tcm825x.h
index 770ebac..5b7e696 100644
--- a/drivers/media/video/tcm825x.h
+++ b/drivers/media/video/tcm825x.h
@@ -188,7 +188,7 @@
 /* Array of image sizes supported by TCM825X.  These must be ordered from
  * smallest image size to largest.
  */
-const static struct capture_size tcm825x_sizes[] = {
+static const struct capture_size tcm825x_sizes[] = {
 	{ 128,  96 }, /* subQCIF */
 	{ 160, 120 }, /* QQVGA */
 	{ 176, 144 }, /* QCIF */
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 0c02058..005f8a4 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -50,7 +50,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/i2c-addr.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 #ifndef VIDEO_AUDIO_BALANCE
 # define VIDEO_AUDIO_BALANCE 32
@@ -69,13 +69,6 @@
 module_param(maxvol, int, S_IRUGO | S_IWUSR);
 
 
-/* Address to scan (I2C address of this chip) */
-static unsigned short normal_i2c[] = {
-	I2C_ADDR_TDA7432 >> 1,
-	I2C_CLIENT_END,
-};
-
-I2C_CLIENT_INSMOD;
 
 /* Structure of address and subaddresses for the tda7432 */
 
@@ -421,21 +414,18 @@
 static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 {
 	switch (qc->id) {
-	case V4L2_CID_AUDIO_MUTE:
 	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
+	case V4L2_CID_AUDIO_MUTE:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill_std(qc);
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 	}
 	return -EINVAL;
 }
 
-static int tda7432_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tda7432_core_ops = {
@@ -498,8 +488,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tda7432",
-	.driverid = I2C_DRIVERID_TDA7432,
-	.command = tda7432_command,
 	.probe = tda7432_probe,
 	.remove = tda7432_remove,
 	.id_table = tda7432_id,
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 6afb705..fe11580 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -30,8 +30,8 @@
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-i2c-drv-legacy.h>
-#include "tda9840.h"
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
 MODULE_DESCRIPTION("tda9840 driver");
@@ -56,11 +56,6 @@
 #define TDA9840_SET_BOTH_R              0x16
 #define TDA9840_SET_EXTERNAL            0x7a
 
-/* addresses to scan, found only at 0x42 (7-Bit) */
-static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END };
-
-/* magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
 
 static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
@@ -137,60 +132,17 @@
 	return 0;
 }
 
-static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static int tda9840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
-	int byte;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	switch (cmd) {
-	case TDA9840_LEVEL_ADJUST:
-		byte = *(int *)arg;
-		v4l2_dbg(1, debug, sd, "TDA9840_LEVEL_ADJUST: %d\n", byte);
-
-		/* check for correct range */
-		if (byte > 25 || byte < -20)
-			return -EINVAL;
-
-		/* calculate actual value to set, see specs, page 18 */
-		byte /= 5;
-		if (0 < byte)
-			byte += 0x8;
-		else
-			byte = -byte;
-		tda9840_write(sd, LEVEL_ADJUST, byte);
-		break;
-
-	case TDA9840_STEREO_ADJUST:
-		byte = *(int *)arg;
-		v4l2_dbg(1, debug, sd, "TDA9840_STEREO_ADJUST: %d\n", byte);
-
-		/* check for correct range */
-		if (byte > 25 || byte < -24)
-			return -EINVAL;
-
-		/* calculate actual value to set */
-		byte /= 5;
-		if (0 < byte)
-			byte += 0x20;
-		else
-			byte = -byte;
-
-		tda9840_write(sd, STEREO_ADJUST, byte);
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TDA9840, 0);
 }
 
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tda9840_core_ops = {
-	.ioctl = tda9840_ioctl,
+	.g_chip_ident = tda9840_g_chip_ident,
 };
 
 static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = {
@@ -209,8 +161,6 @@
 			  const struct i2c_device_id *id)
 {
 	struct v4l2_subdev *sd;
-	int result;
-	int byte;
 
 	/* let's see whether this adapter can support what we need */
 	if (!i2c_check_functionality(client->adapter,
@@ -227,15 +177,9 @@
 	v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
 
 	/* set initial values for level & stereo - adjustment, mode */
-	byte = 0;
-	result = tda9840_ioctl(sd, TDA9840_LEVEL_ADJUST, &byte);
-	result |= tda9840_ioctl(sd, TDA9840_STEREO_ADJUST, &byte);
+	tda9840_write(sd, LEVEL_ADJUST, 0);
+	tda9840_write(sd, STEREO_ADJUST, 0);
 	tda9840_write(sd, SWITCH, TDA9840_SET_STEREO);
-	if (result) {
-		v4l2_dbg(1, debug, sd, "could not initialize tda9840\n");
-		kfree(sd);
-		return -ENODEV;
-	}
 	return 0;
 }
 
@@ -248,12 +192,7 @@
 	return 0;
 }
 
-static int tda9840_legacy_probe(struct i2c_adapter *adapter)
-{
-	/* Let's see whether this is a known adapter we can attach to.
-	   Prevents conflicts with tvaudio.c. */
-	return adapter->id == I2C_HW_SAA7146;
-}
+
 static const struct i2c_device_id tda9840_id[] = {
 	{ "tda9840", 0 },
 	{ }
@@ -262,10 +201,7 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tda9840",
-	.driverid = I2C_DRIVERID_TDA9840,
-	.command = tda9840_command,
 	.probe = tda9840_probe,
 	.remove = tda9840_remove,
-	.legacy_probe = tda9840_legacy_probe,
 	.id_table = tda9840_id,
 };
diff --git a/drivers/media/video/tda9840.h b/drivers/media/video/tda9840.h
deleted file mode 100644
index dc12ae7..0000000
--- a/drivers/media/video/tda9840.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __INCLUDED_TDA9840__
-#define __INCLUDED_TDA9840__
-
-#define	I2C_ADDR_TDA9840		0x42
-
-/* values may range between +2.5 and -2.0;
-   the value has to be multiplied with 10 */
-#define TDA9840_LEVEL_ADJUST	_IOW('v',3,int)
-
-/* values may range between +2.5 and -2.4;
-   the value has to be multiplied with 10 */
-#define TDA9840_STEREO_ADJUST	_IOW('v',4,int)
-
-#endif
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 00c6cbe..24e2b7d 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -28,20 +28,13 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 #include <media/i2c-addr.h>
 
 static int debug; /* insmod parameter */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_LICENSE("GPL");
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] =  {
-    I2C_ADDR_TDA9875 >> 1,
-    I2C_CLIENT_END
-};
-
-I2C_CLIENT_INSMOD;
 
 /* This is a superset of the TDA9875 */
 struct tda9875 {
@@ -313,18 +306,14 @@
 {
 	switch (qc->id) {
 	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill_std(qc);
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 	}
 	return -EINVAL;
 }
 
-static int tda9875_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tda9875_core_ops = {
@@ -401,8 +390,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tda9875",
-	.driverid = I2C_DRIVERID_TDA9875,
-	.command = tda9875_command,
 	.probe = tda9875_probe,
 	.remove = tda9875_remove,
 	.id_table = tda9875_id,
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 7519fd1..d61c56f 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -32,7 +32,8 @@
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 #include "tea6415c.h"
 
 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
@@ -44,25 +45,22 @@
 
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-/* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */
-static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END };
 
-/* magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
-
-/* makes a connection between the input-pin 'i' and the output-pin 'o'
-   for the tea6415c-client 'client' */
-static int switch_matrix(struct i2c_client *client, int i, int o)
+/* makes a connection between the input-pin 'i' and the output-pin 'o' */
+static int tea6415c_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	u8 byte = 0;
+	u32 i = route->input;
+	u32 o = route->output;
 	int ret;
 
-	v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o);
+	v4l2_dbg(1, debug, sd, "i=%d, o=%d\n", i, o);
 
 	/* check if the pins are valid */
 	if (0 == ((1 == i ||  3 == i ||  5 == i ||  6 == i ||  8 == i || 10 == i || 20 == i || 11 == i)
 	      && (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o)))
-		return -1;
+		return -EINVAL;
 
 	/* to understand this, have a look at the tea6415c-specs (p.5) */
 	switch (o) {
@@ -115,37 +113,33 @@
 
 	ret = i2c_smbus_write_byte(client, byte);
 	if (ret) {
-		v4l_dbg(1, debug, client,
+		v4l2_dbg(1, debug, sd,
 			"i2c_smbus_write_byte() failed, ret:%d\n", ret);
 		return -EIO;
 	}
 	return ret;
 }
 
-static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
-	if (cmd == TEA6415C_SWITCH) {
-		struct i2c_client *client = v4l2_get_subdevdata(sd);
-		struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-		return switch_matrix(client, v->in, v->out);
-	}
-	return -ENOIOCTLCMD;
-}
-
-static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0);
 }
 
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tea6415c_core_ops = {
-	.ioctl = tea6415c_ioctl,
+	.g_chip_ident = tea6415c_g_chip_ident,
+};
+
+static const struct v4l2_subdev_video_ops tea6415c_video_ops = {
+	.s_routing = tea6415c_s_routing,
 };
 
 static const struct v4l2_subdev_ops tea6415c_ops = {
 	.core = &tea6415c_core_ops,
+	.video = &tea6415c_video_ops,
 };
 
 /* this function is called by i2c_probe */
@@ -176,12 +170,6 @@
 	return 0;
 }
 
-static int tea6415c_legacy_probe(struct i2c_adapter *adapter)
-{
-	/* Let's see whether this is a known adapter we can attach to.
-	   Prevents conflicts with tvaudio.c. */
-	return adapter->id == I2C_HW_SAA7146;
-}
 
 static const struct i2c_device_id tea6415c_id[] = {
 	{ "tea6415c", 0 },
@@ -191,10 +179,7 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tea6415c",
-	.driverid = I2C_DRIVERID_TEA6415C,
-	.command = tea6415c_command,
 	.probe = tea6415c_probe,
 	.remove = tea6415c_remove,
-	.legacy_probe = tea6415c_legacy_probe,
 	.id_table = tea6415c_id,
 };
diff --git a/drivers/media/video/tea6415c.h b/drivers/media/video/tea6415c.h
index f84ed80..3a47d69 100644
--- a/drivers/media/video/tea6415c.h
+++ b/drivers/media/video/tea6415c.h
@@ -1,10 +1,6 @@
 #ifndef __INCLUDED_TEA6415C__
 #define __INCLUDED_TEA6415C__
 
-/* possible i2c-addresses */
-#define	I2C_TEA6415C_1		0x03
-#define	I2C_TEA6415C_2		0x43
-
 /* the tea6415c's design is quite brain-dead. although there are
    8 inputs and 6 outputs, these aren't enumerated in any way. because
    I don't want to say "connect input pin 20 to output pin 17", I define
@@ -28,12 +24,4 @@
 #define TEA6415C_INPUT7 1
 #define TEA6415C_INPUT8 11
 
-struct tea6415c_multiplex
-{
-	int	in;	/* input-pin */
-	int	out;	/* output-pin */
-};
-
-#define TEA6415C_SWITCH		_IOW('v',1,struct tea6415c_multiplex)
-
 #endif
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 081e74f..3492223 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -32,7 +32,8 @@
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 #include "tea6420.h"
 
 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
@@ -44,24 +45,23 @@
 
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
-/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
-static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
-
-/* magic definition of all other variables and things */
-I2C_CLIENT_INSMOD;
 
 /* make a connection between the input 'i' and the output 'o'
-   with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */
-static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
+   with gain 'g' (note: i = 6 means 'mute') */
+static int tea6420_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i = route->input;
+	int o = route->output & 0xf;
+	int g = (route->output >> 4) & 0xf;
 	u8 byte;
 	int ret;
 
-	v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g);
+	v4l2_dbg(1, debug, sd, "i=%d, o=%d, g=%d\n", i, o, g);
 
 	/* check if the parameters are valid */
 	if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0)
-		return -1;
+		return -EINVAL;
 
 	byte = ((o - 1) << 5);
 	byte |= (i - 1);
@@ -83,37 +83,33 @@
 
 	ret = i2c_smbus_write_byte(client, byte);
 	if (ret) {
-		v4l_dbg(1, debug, client,
+		v4l2_dbg(1, debug, sd,
 			"i2c_smbus_write_byte() failed, ret:%d\n", ret);
 		return -EIO;
 	}
 	return 0;
 }
 
-static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static int tea6420_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
-	if (cmd == TEA6420_SWITCH) {
-		struct i2c_client *client = v4l2_get_subdevdata(sd);
-		struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-		return tea6420_switch(client, a->in, a->out, a->gain);
-	}
-	return -ENOIOCTLCMD;
-}
-
-static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6420, 0);
 }
 
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tea6420_core_ops = {
-	.ioctl = tea6420_ioctl,
+	.g_chip_ident = tea6420_g_chip_ident,
+};
+
+static const struct v4l2_subdev_audio_ops tea6420_audio_ops = {
+	.s_routing = tea6420_s_routing,
 };
 
 static const struct v4l2_subdev_ops tea6420_ops = {
 	.core = &tea6420_core_ops,
+	.audio = &tea6420_audio_ops,
 };
 
 /* this function is called by i2c_probe */
@@ -130,20 +126,24 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
+	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+	v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
+
 	/* set initial values: set "mute"-input to all outputs at gain 0 */
 	err = 0;
 	for (i = 1; i < 5; i++) {
-		err += tea6420_switch(client, 6, i, 0);
+		struct v4l2_routing route;
+
+		route.input = 6;
+		route.output = i;
+		err += tea6420_s_routing(sd, &route);
 	}
 	if (err) {
 		v4l_dbg(1, debug, client, "could not initialize tea6420\n");
 		return -ENODEV;
 	}
-
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
-	if (sd == NULL)
-		return -ENOMEM;
-	v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
 	return 0;
 }
 
@@ -156,12 +156,6 @@
 	return 0;
 }
 
-static int tea6420_legacy_probe(struct i2c_adapter *adapter)
-{
-	/* Let's see whether this is a known adapter we can attach to.
-	   Prevents conflicts with tvaudio.c. */
-	return adapter->id == I2C_HW_SAA7146;
-}
 
 static const struct i2c_device_id tea6420_id[] = {
 	{ "tea6420", 0 },
@@ -171,10 +165,7 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tea6420",
-	.driverid = I2C_DRIVERID_TEA6420,
-	.command = tea6420_command,
 	.probe = tea6420_probe,
 	.remove = tea6420_remove,
-	.legacy_probe = tea6420_legacy_probe,
 	.id_table = tea6420_id,
 };
diff --git a/drivers/media/video/tea6420.h b/drivers/media/video/tea6420.h
index 5ef7c18..4aa3edb 100644
--- a/drivers/media/video/tea6420.h
+++ b/drivers/media/video/tea6420.h
@@ -1,17 +1,24 @@
 #ifndef __INCLUDED_TEA6420__
 #define __INCLUDED_TEA6420__
 
-/* possible addresses */
-#define	I2C_ADDR_TEA6420_1		0x4c
-#define	I2C_ADDR_TEA6420_2		0x4d
+/* input pins */
+#define TEA6420_OUTPUT1 1
+#define TEA6420_OUTPUT2 2
+#define TEA6420_OUTPUT3 3
+#define TEA6420_OUTPUT4 4
 
-struct tea6420_multiplex
-{
-	int	in;	/* input of audio switch */
-	int	out;	/* output of audio switch  */
-	int	gain;	/* gain of connection */
-};
+/* output pins */
+#define TEA6420_INPUT1 1
+#define TEA6420_INPUT2 2
+#define TEA6420_INPUT3 3
+#define TEA6420_INPUT4 4
+#define TEA6420_INPUT5 5
+#define TEA6420_INPUT6 6
 
-#define TEA6420_SWITCH		_IOW('v',1,struct tea6420_multiplex)
+/* gain on the output pins, ORed with the output pin */
+#define TEA6420_GAIN0 0x00
+#define TEA6420_GAIN2 0x20
+#define TEA6420_GAIN4 0x40
+#define TEA6420_GAIN6 0x60
 
 #endif
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
index 5c95ecd..07789c6 100644
--- a/drivers/media/video/tlv320aic23b.c
+++ b/drivers/media/video/tlv320aic23b.c
@@ -31,15 +31,12 @@
 #include <linux/i2c-id.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("tlv320aic23b driver");
 MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
 
@@ -121,11 +118,6 @@
 	return 0;
 }
 
-static int tlv320aic23b_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = {
@@ -208,8 +200,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tlv320aic23b",
-	.driverid = I2C_DRIVERID_TLV320AIC23B,
-	.command = tlv320aic23b_command,
 	.probe = tlv320aic23b_probe,
 	.remove = tlv320aic23b_remove,
 	.id_table = tlv320aic23b_id,
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 30640fb..72d4103 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -364,7 +364,8 @@
 	}
 
 	t->type = type;
-	t->config = new_config;
+	/* prevent invalid config values */
+	t->config = ((new_config >= 0) && (new_config < 256)) ? new_config : 0;
 	if (tuner_callback != NULL) {
 		tuner_dbg("defining GPIO callback\n");
 		t->fe.callback = tuner_callback;
@@ -452,7 +453,8 @@
 		struct dvb_tuner_ops *xc_tuner_ops;
 
 		xc5000_cfg.i2c_address	  = t->i2c->addr;
-		xc5000_cfg.if_khz	  = 5380;
+		/* if_khz will be set when the digital dvb_attach() occurs */
+		xc5000_cfg.if_khz	  = 0;
 		if (!dvb_attach(xc5000_attach,
 				&t->fe, t->i2c->adapter, &xc5000_cfg))
 			goto attach_failed;
@@ -776,8 +778,7 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
-			== -EINVAL)
+	if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL)
 		return 0;
 	if (t->radio_freq)
 		set_freq(client, t->radio_freq);
@@ -791,7 +792,7 @@
 
 	tuner_dbg("Putting tuner to sleep\n");
 
-	if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL)
+	if (check_mode(t, "s_standby") == -EINVAL)
 		return 0;
 	t->mode = T_STANDBY;
 	if (analog_ops->standby)
@@ -799,132 +800,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_VIDEO_ALLOW_V4L1
-static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
-	struct tuner *t = to_tuner(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
-
-	switch (cmd) {
-	case VIDIOCSAUDIO:
-		if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL)
-			return 0;
-		if (check_v4l2(t) == -EINVAL)
-			return 0;
-
-		/* Should be implemented, since bttv calls it */
-		tuner_dbg("VIDIOCSAUDIO not implemented.\n");
-		break;
-	case VIDIOCSCHAN:
-		{
-			static const v4l2_std_id map[] = {
-				[VIDEO_MODE_PAL] = V4L2_STD_PAL,
-				[VIDEO_MODE_NTSC] = V4L2_STD_NTSC_M,
-				[VIDEO_MODE_SECAM] = V4L2_STD_SECAM,
-				[4 /* bttv */ ] = V4L2_STD_PAL_M,
-				[5 /* bttv */ ] = V4L2_STD_PAL_N,
-				[6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
-			};
-			struct video_channel *vc = arg;
-
-			if (check_v4l2(t) == -EINVAL)
-				return 0;
-
-			if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL)
-				return 0;
-
-			if (vc->norm < ARRAY_SIZE(map))
-				t->std = map[vc->norm];
-			tuner_fixup_std(t);
-			if (t->tv_freq)
-				set_tv_freq(client, t->tv_freq);
-			return 0;
-		}
-	case VIDIOCSFREQ:
-		{
-			unsigned long *v = arg;
-
-			if (check_mode(t, "VIDIOCSFREQ") == -EINVAL)
-				return 0;
-			if (check_v4l2(t) == -EINVAL)
-				return 0;
-
-			set_freq(client, *v);
-			return 0;
-		}
-	case VIDIOCGTUNER:
-		{
-			struct video_tuner *vt = arg;
-
-			if (check_mode(t, "VIDIOCGTUNER") == -EINVAL)
-				return 0;
-			if (check_v4l2(t) == -EINVAL)
-				return 0;
-
-			if (V4L2_TUNER_RADIO == t->mode) {
-				if (fe_tuner_ops->get_status) {
-					u32 tuner_status;
-
-					fe_tuner_ops->get_status(&t->fe, &tuner_status);
-					if (tuner_status & TUNER_STATUS_STEREO)
-						vt->flags |= VIDEO_TUNER_STEREO_ON;
-					else
-						vt->flags &= ~VIDEO_TUNER_STEREO_ON;
-				} else {
-					if (analog_ops->is_stereo) {
-						if (analog_ops->is_stereo(&t->fe))
-							vt->flags |=
-								VIDEO_TUNER_STEREO_ON;
-						else
-							vt->flags &=
-								~VIDEO_TUNER_STEREO_ON;
-					}
-				}
-				if (analog_ops->has_signal)
-					vt->signal =
-						analog_ops->has_signal(&t->fe);
-
-				vt->flags |= VIDEO_TUNER_LOW;	/* Allow freqs at 62.5 Hz */
-
-				vt->rangelow = radio_range[0] * 16000;
-				vt->rangehigh = radio_range[1] * 16000;
-
-			} else {
-				vt->rangelow = tv_range[0] * 16;
-				vt->rangehigh = tv_range[1] * 16;
-			}
-
-			return 0;
-		}
-	case VIDIOCGAUDIO:
-		{
-			struct video_audio *va = arg;
-
-			if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL)
-				return 0;
-			if (check_v4l2(t) == -EINVAL)
-				return 0;
-
-			if (V4L2_TUNER_RADIO == t->mode) {
-				if (fe_tuner_ops->get_status) {
-					u32 tuner_status;
-
-					fe_tuner_ops->get_status(&t->fe, &tuner_status);
-					va->mode = (tuner_status & TUNER_STATUS_STEREO)
-					    ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
-				} else if (analog_ops->is_stereo)
-					va->mode = analog_ops->is_stereo(&t->fe)
-					    ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
-			}
-			return 0;
-		}
-	}
-	return -ENOIOCTLCMD;
-}
-#endif
-
 static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg)
 {
 	struct tuner *t = to_tuner(sd);
@@ -950,8 +825,7 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD")
-			== -EINVAL)
+	if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL)
 		return 0;
 
 	switch_v4l2();
@@ -968,8 +842,7 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, f->type, "VIDIOC_S_FREQUENCY")
-			== -EINVAL)
+	if (set_mode(client, t, f->type, "s_frequency") == -EINVAL)
 		return 0;
 	switch_v4l2();
 	set_freq(client, f->frequency);
@@ -982,7 +855,7 @@
 	struct tuner *t = to_tuner(sd);
 	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
 
-	if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL)
+	if (check_mode(t, "g_frequency") == -EINVAL)
 		return 0;
 	switch_v4l2();
 	f->type = t->mode;
@@ -1006,7 +879,7 @@
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
 
-	if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL)
+	if (check_mode(t, "g_tuner") == -EINVAL)
 		return 0;
 	switch_v4l2();
 
@@ -1055,7 +928,7 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL)
+	if (check_mode(t, "s_tuner") == -EINVAL)
 		return 0;
 
 	switch_v4l2();
@@ -1112,9 +985,6 @@
 static const struct v4l2_subdev_core_ops tuner_core_ops = {
 	.log_status = tuner_log_status,
 	.s_standby = tuner_s_standby,
-#ifdef CONFIG_VIDEO_ALLOW_V4L1
-	.ioctl = tuner_ioctl,
-#endif
 };
 
 static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = {
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 076ed5b..226bf35 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -26,7 +26,7 @@
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
@@ -1047,6 +1047,116 @@
 	return 0;
 }
 
+/* ---------------------------------------------------------------------- */
+/* audio chip description - defines+functions for tda9875                 */
+/* The TDA9875 is made by Philips Semiconductor
+ * http://www.semiconductors.philips.com
+ * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator
+ *
+ */
+
+/* subaddresses for TDA9875 */
+#define TDA9875_MUT         0x12  /*General mute  (value --> 0b11001100*/
+#define TDA9875_CFG         0x01  /* Config register (value --> 0b00000000 */
+#define TDA9875_DACOS       0x13  /*DAC i/o select (ADC) 0b0000100*/
+#define TDA9875_LOSR        0x16  /*Line output select regirter 0b0100 0001*/
+
+#define TDA9875_CH1V        0x0c  /*Channel 1 volume (mute)*/
+#define TDA9875_CH2V        0x0d  /*Channel 2 volume (mute)*/
+#define TDA9875_SC1         0x14  /*SCART 1 in (mono)*/
+#define TDA9875_SC2         0x15  /*SCART 2 in (mono)*/
+
+#define TDA9875_ADCIS       0x17  /*ADC input select (mono) 0b0110 000*/
+#define TDA9875_AER         0x19  /*Audio effect (AVL+Pseudo) 0b0000 0110*/
+#define TDA9875_MCS         0x18  /*Main channel select (DAC) 0b0000100*/
+#define TDA9875_MVL         0x1a  /* Main volume gauche */
+#define TDA9875_MVR         0x1b  /* Main volume droite */
+#define TDA9875_MBA         0x1d  /* Main Basse */
+#define TDA9875_MTR         0x1e  /* Main treble */
+#define TDA9875_ACS         0x1f  /* Auxilary channel select (FM) 0b0000000*/
+#define TDA9875_AVL         0x20  /* Auxilary volume gauche */
+#define TDA9875_AVR         0x21  /* Auxilary volume droite */
+#define TDA9875_ABA         0x22  /* Auxilary Basse */
+#define TDA9875_ATR         0x23  /* Auxilary treble */
+
+#define TDA9875_MSR         0x02  /* Monitor select register */
+#define TDA9875_C1MSB       0x03  /* Carrier 1 (FM) frequency register MSB */
+#define TDA9875_C1MIB       0x04  /* Carrier 1 (FM) frequency register (16-8]b */
+#define TDA9875_C1LSB       0x05  /* Carrier 1 (FM) frequency register LSB */
+#define TDA9875_C2MSB       0x06  /* Carrier 2 (nicam) frequency register MSB */
+#define TDA9875_C2MIB       0x07  /* Carrier 2 (nicam) frequency register (16-8]b */
+#define TDA9875_C2LSB       0x08  /* Carrier 2 (nicam) frequency register LSB */
+#define TDA9875_DCR         0x09  /* Demodulateur configuration regirter*/
+#define TDA9875_DEEM        0x0a  /* FM de-emphasis regirter*/
+#define TDA9875_FMAT        0x0b  /* FM Matrix regirter*/
+
+/* values */
+#define TDA9875_MUTE_ON	    0xff /* general mute */
+#define TDA9875_MUTE_OFF    0xcc /* general no mute */
+
+static int tda9875_initialize(struct CHIPSTATE *chip)
+{
+	chip_write(chip, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/
+	chip_write(chip, TDA9875_MSR, 0x03);    /* Monitor 0b00000XXX*/
+	chip_write(chip, TDA9875_C1MSB, 0x00);  /*Car1(FM) MSB XMHz*/
+	chip_write(chip, TDA9875_C1MIB, 0x00);  /*Car1(FM) MIB XMHz*/
+	chip_write(chip, TDA9875_C1LSB, 0x00);  /*Car1(FM) LSB XMHz*/
+	chip_write(chip, TDA9875_C2MSB, 0x00);  /*Car2(NICAM) MSB XMHz*/
+	chip_write(chip, TDA9875_C2MIB, 0x00);  /*Car2(NICAM) MIB XMHz*/
+	chip_write(chip, TDA9875_C2LSB, 0x00);  /*Car2(NICAM) LSB XMHz*/
+	chip_write(chip, TDA9875_DCR, 0x00);    /*Demod config 0x00*/
+	chip_write(chip, TDA9875_DEEM, 0x44);   /*DE-Emph 0b0100 0100*/
+	chip_write(chip, TDA9875_FMAT, 0x00);   /*FM Matrix reg 0x00*/
+	chip_write(chip, TDA9875_SC1, 0x00);    /* SCART 1 (SC1)*/
+	chip_write(chip, TDA9875_SC2, 0x01);    /* SCART 2 (sc2)*/
+
+	chip_write(chip, TDA9875_CH1V, 0x10);  /* Channel volume 1 mute*/
+	chip_write(chip, TDA9875_CH2V, 0x10);  /* Channel volume 2 mute */
+	chip_write(chip, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/
+	chip_write(chip, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/
+	chip_write(chip, TDA9875_LOSR, 0x00);  /* line out (in:mono)*/
+	chip_write(chip, TDA9875_AER, 0x00);   /*06 Effect (AVL+PSEUDO) */
+	chip_write(chip, TDA9875_MCS, 0x44);   /* Main ch select (DAC) */
+	chip_write(chip, TDA9875_MVL, 0x03);   /* Vol Main left 10dB */
+	chip_write(chip, TDA9875_MVR, 0x03);   /* Vol Main right 10dB*/
+	chip_write(chip, TDA9875_MBA, 0x00);   /* Main Bass Main 0dB*/
+	chip_write(chip, TDA9875_MTR, 0x00);   /* Main Treble Main 0dB*/
+	chip_write(chip, TDA9875_ACS, 0x44);   /* Aux chan select (dac)*/
+	chip_write(chip, TDA9875_AVL, 0x00);   /* Vol Aux left 0dB*/
+	chip_write(chip, TDA9875_AVR, 0x00);   /* Vol Aux right 0dB*/
+	chip_write(chip, TDA9875_ABA, 0x00);   /* Aux Bass Main 0dB*/
+	chip_write(chip, TDA9875_ATR, 0x00);   /* Aux Aigus Main 0dB*/
+
+	chip_write(chip, TDA9875_MUT, 0xcc);   /* General mute  */
+	return 0;
+}
+
+static int tda9875_volume(int val) { return (unsigned char)(val / 602 - 84); }
+static int tda9875_bass(int val) { return (unsigned char)(max(-12, val / 2115 - 15)); }
+static int tda9875_treble(int val) { return (unsigned char)(val / 2622 - 12); }
+
+/* ----------------------------------------------------------------------- */
+
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tda9875_checkit(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int dic, rev;
+
+	dic = chip_read2(chip, 254);
+	rev = chip_read2(chip, 255);
+
+	if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */
+		v4l2_info(sd, "found tda9875%s rev. %d.\n",
+			dic == 0 ? "" : "A", rev);
+		return 1;
+	}
+	return 0;
+}
 
 /* ---------------------------------------------------------------------- */
 /* audio chip descriptions - defines+functions for tea6420                */
@@ -1280,6 +1390,7 @@
 static int tda9855  = 1;
 static int tda9873  = 1;
 static int tda9874a = 1;
+static int tda9875  = 1;
 static int tea6300;	/* default 0 - address clash with msp34xx */
 static int tea6320;	/* default 0 - address clash with msp34xx */
 static int tea6420  = 1;
@@ -1292,6 +1403,7 @@
 module_param(tda9855, int, 0444);
 module_param(tda9873, int, 0444);
 module_param(tda9874a, int, 0444);
+module_param(tda9875, int, 0444);
 module_param(tea6300, int, 0444);
 module_param(tea6320, int, 0444);
 module_param(tea6420, int, 0444);
@@ -1349,6 +1461,26 @@
 		.setmode    = tda9874a_setmode,
 	},
 	{
+		.name       = "tda9875",
+		.insmodopt  = &tda9875,
+		.addr_lo    = I2C_ADDR_TDA9875 >> 1,
+		.addr_hi    = I2C_ADDR_TDA9875 >> 1,
+		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,
+
+		/* callbacks */
+		.initialize = tda9875_initialize,
+		.checkit    = tda9875_checkit,
+		.volfunc    = tda9875_volume,
+		.bassfunc   = tda9875_bass,
+		.treblefunc = tda9875_treble,
+		.leftreg    = TDA9875_MVL,
+		.rightreg   = TDA9875_MVR,
+		.bassreg    = TDA9875_MBA,
+		.treblereg  = TDA9875_MTR,
+		.leftinit   = 58880,
+		.rightinit  = 58880,
+	},
+	{
 		.name       = "tda9850",
 		.insmodopt  = &tda9850,
 		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
@@ -1511,6 +1643,8 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
+		if (!(desc->flags & CHIP_HAS_INPUTSEL))
+			break;
 		ctrl->value=chip->muted;
 		return 0;
 	case V4L2_CID_AUDIO_VOLUME:
@@ -1552,6 +1686,9 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
+		if (!(desc->flags & CHIP_HAS_INPUTSEL))
+			break;
+
 		if (ctrl->value < 0 || ctrl->value >= 2)
 			return -ERANGE;
 		chip->muted = ctrl->value;
@@ -1636,21 +1773,26 @@
 
 	switch (qc->id) {
 	case V4L2_CID_AUDIO_MUTE:
+		if (desc->flags & CHIP_HAS_INPUTSEL)
+			return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
+		if (desc->flags & CHIP_HAS_VOLUME)
+			return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880);
+		break;
 	case V4L2_CID_AUDIO_BALANCE:
-		if (!(desc->flags & CHIP_HAS_VOLUME))
-			return -EINVAL;
+		if (desc->flags & CHIP_HAS_VOLUME)
+			return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 		break;
 	case V4L2_CID_AUDIO_BASS:
 	case V4L2_CID_AUDIO_TREBLE:
-		if (!(desc->flags & CHIP_HAS_BASSTREBLE))
-			return -EINVAL;
+		if (desc->flags & CHIP_HAS_BASSTREBLE)
+			return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
 		break;
 	default:
-		return -EINVAL;
+		break;
 	}
-	return v4l2_ctrl_query_fill_std(qc);
+	return -EINVAL;
 }
 
 static int tvaudio_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *rt)
@@ -1658,7 +1800,9 @@
 	struct CHIPSTATE *chip = to_state(sd);
 	struct CHIPDESC *desc = chip->desc;
 
-	if (!(desc->flags & CHIP_HAS_INPUTSEL) || rt->input >= 4)
+	if (!(desc->flags & CHIP_HAS_INPUTSEL))
+		return 0;
+	if (rt->input >= 4)
 		return -EINVAL;
 	/* There are four inputs: tuner, radio, extern and intern. */
 	chip->input = rt->input;
@@ -1675,8 +1819,11 @@
 	struct CHIPDESC *desc = chip->desc;
 	int mode = 0;
 
+	if (!desc->setmode)
+		return 0;
 	if (chip->radio)
 		return 0;
+
 	switch (vt->audmode) {
 	case V4L2_TUNER_MODE_MONO:
 	case V4L2_TUNER_MODE_STEREO:
@@ -1692,7 +1839,7 @@
 	}
 	chip->audmode = vt->audmode;
 
-	if (desc->setmode && mode) {
+	if (mode) {
 		chip->watch_stereo = 0;
 		/* del_timer(&chip->wt); */
 		chip->mode = mode;
@@ -1707,15 +1854,17 @@
 	struct CHIPDESC *desc = chip->desc;
 	int mode = V4L2_TUNER_MODE_MONO;
 
+	if (!desc->getmode)
+		return 0;
 	if (chip->radio)
 		return 0;
+
 	vt->audmode = chip->audmode;
 	vt->rxsubchans = 0;
 	vt->capability = V4L2_TUNER_CAP_STEREO |
 		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
 
-	if (desc->getmode)
-		mode = desc->getmode(chip);
+	mode = desc->getmode(chip);
 
 	if (mode & V4L2_TUNER_MODE_MONO)
 		vt->rxsubchans |= V4L2_TUNER_SUB_MONO;
@@ -1901,6 +2050,7 @@
 	}
 
 	chip->thread = NULL;
+	init_timer(&chip->wt);
 	if (desc->flags & CHIP_NEED_CHECKMODE) {
 		if (!desc->getmode || !desc->setmode) {
 			/* This shouldn't be happen. Warn user, but keep working
@@ -1910,7 +2060,6 @@
 			return 0;
 		}
 		/* start async thread */
-		init_timer(&chip->wt);
 		chip->wt.function = chip_thread_wake;
 		chip->wt.data     = (unsigned long)chip;
 		chip->thread = kthread_run(chip_thread, chip, client->name);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 78277ab..e24a38c 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -261,7 +261,12 @@
 	{ TUNER_ABSENT,        		"MaxLinear MXL5005_v2"},
 	{ TUNER_PHILIPS_TDA8290, 	"Philips 18271_8295"},
 	/* 150-159 */
-	{ TUNER_ABSENT,                 "Xceive XC5000"},
+	{ TUNER_XC5000,                 "Xceive XC5000"},
+	{ TUNER_ABSENT,                 "Xceive XC3028L"},
+	{ TUNER_ABSENT,                 "NXP 18271C2_716x"},
+	{ TUNER_ABSENT,                 "Xceive XC4000"},
+	{ TUNER_ABSENT,                 "Dibcom 7070"},
+	{ TUNER_PHILIPS_TDA8290,        "NXP 18271C2"},
 };
 
 /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c
index 8e23aa5..4262e60 100644
--- a/drivers/media/video/tvp514x.c
+++ b/drivers/media/video/tvp514x.c
@@ -86,9 +86,12 @@
 	struct v4l2_standard standard;
 };
 
+static struct tvp514x_reg tvp514x_reg_list_default[0x40];
 /**
- * struct tvp514x_decoded - TVP5146/47 decoder object
+ * struct tvp514x_decoder - TVP5146/47 decoder object
  * @v4l2_int_device: Slave handle
+ * @tvp514x_slave: Slave pointer which is used by @v4l2_int_device
+ * @tvp514x_regs: copy of hw's regs with preset values.
  * @pdata: Board specific
  * @client: I2C client data
  * @id: Entry from I2C table
@@ -103,7 +106,9 @@
  * @route: input and output routing at chip level
  */
 struct tvp514x_decoder {
-	struct v4l2_int_device *v4l2_int_device;
+	struct v4l2_int_device v4l2_int_device;
+	struct v4l2_int_slave tvp514x_slave;
+	struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)];
 	const struct tvp514x_platform_data *pdata;
 	struct i2c_client *client;
 
@@ -124,7 +129,7 @@
 };
 
 /* TVP514x default register values */
-static struct tvp514x_reg tvp514x_reg_list[] = {
+static struct tvp514x_reg tvp514x_reg_list_default[] = {
 	{TOK_WRITE, REG_INPUT_SEL, 0x05},	/* Composite selected */
 	{TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F},
 	{TOK_WRITE, REG_VIDEO_STD, 0x00},	/* Auto mode */
@@ -422,7 +427,7 @@
 
 	/* common register initialization */
 	err =
-	    tvp514x_write_regs(decoder->client, tvp514x_reg_list);
+	    tvp514x_write_regs(decoder->client, decoder->tvp514x_regs);
 	if (err)
 		return err;
 
@@ -580,7 +585,8 @@
 		return err;
 
 	decoder->current_std = i;
-	tvp514x_reg_list[REG_VIDEO_STD].val = decoder->std_list[i].video_std;
+	decoder->tvp514x_regs[REG_VIDEO_STD].val =
+		decoder->std_list[i].video_std;
 
 	v4l_dbg(1, debug, decoder->client, "Standard set to: %s",
 			decoder->std_list[i].standard.name);
@@ -625,8 +631,8 @@
 	if (err)
 		return err;
 
-	tvp514x_reg_list[REG_INPUT_SEL].val = input_sel;
-	tvp514x_reg_list[REG_OUTPUT_FORMATTER1].val = output_sel;
+	decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
+	decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
 
 	/* Clear status */
 	msleep(LOCK_RETRY_DELAY);
@@ -686,7 +692,7 @@
 			break;	/* Input detected */
 	}
 
-	if ((current_std == STD_INVALID) || (try_count < 0))
+	if ((current_std == STD_INVALID) || (try_count <= 0))
 		return -EINVAL;
 
 	decoder->current_std = current_std;
@@ -719,10 +725,9 @@
 
 	switch (qctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		/* Brightness supported is same as standard one (0-255),
-		 * so make use of standard API provided.
+		/* Brightness supported is (0-255),
 		 */
-		err = v4l2_ctrl_query_fill_std(qctrl);
+		err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
 		break;
 	case V4L2_CID_CONTRAST:
 	case V4L2_CID_SATURATION:
@@ -779,16 +784,16 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = tvp514x_reg_list[REG_BRIGHTNESS].val;
+		ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val;
 		break;
 	case V4L2_CID_CONTRAST:
-		ctrl->value = tvp514x_reg_list[REG_CONTRAST].val;
+		ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val;
 		break;
 	case V4L2_CID_SATURATION:
-		ctrl->value = tvp514x_reg_list[REG_SATURATION].val;
+		ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val;
 		break;
 	case V4L2_CID_HUE:
-		ctrl->value = tvp514x_reg_list[REG_HUE].val;
+		ctrl->value = decoder->tvp514x_regs[REG_HUE].val;
 		if (ctrl->value == 0x7F)
 			ctrl->value = 180;
 		else if (ctrl->value == 0x80)
@@ -798,7 +803,7 @@
 
 		break;
 	case V4L2_CID_AUTOGAIN:
-		ctrl->value = tvp514x_reg_list[REG_AFE_GAIN_CTRL].val;
+		ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val;
 		if ((ctrl->value & 0x3) == 3)
 			ctrl->value = 1;
 		else
@@ -848,7 +853,7 @@
 				value);
 		if (err)
 			return err;
-		tvp514x_reg_list[REG_BRIGHTNESS].val = value;
+		decoder->tvp514x_regs[REG_BRIGHTNESS].val = value;
 		break;
 	case V4L2_CID_CONTRAST:
 		if (ctrl->value < 0 || ctrl->value > 255) {
@@ -861,7 +866,7 @@
 				value);
 		if (err)
 			return err;
-		tvp514x_reg_list[REG_CONTRAST].val = value;
+		decoder->tvp514x_regs[REG_CONTRAST].val = value;
 		break;
 	case V4L2_CID_SATURATION:
 		if (ctrl->value < 0 || ctrl->value > 255) {
@@ -874,7 +879,7 @@
 				value);
 		if (err)
 			return err;
-		tvp514x_reg_list[REG_SATURATION].val = value;
+		decoder->tvp514x_regs[REG_SATURATION].val = value;
 		break;
 	case V4L2_CID_HUE:
 		if (value == 180)
@@ -893,7 +898,7 @@
 				value);
 		if (err)
 			return err;
-		tvp514x_reg_list[REG_HUE].val = value;
+		decoder->tvp514x_regs[REG_HUE].val = value;
 		break;
 	case V4L2_CID_AUTOGAIN:
 		if (value == 1)
@@ -910,7 +915,7 @@
 				value);
 		if (err)
 			return err;
-		tvp514x_reg_list[REG_AFE_GAIN_CTRL].val = value;
+		decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value;
 		break;
 	default:
 		v4l_err(decoder->client,
@@ -1275,7 +1280,7 @@
 	struct tvp514x_decoder *decoder = s->priv;
 
 	/* Set default standard to auto */
-	tvp514x_reg_list[REG_VIDEO_STD].val =
+	decoder->tvp514x_regs[REG_VIDEO_STD].val =
 	    VIDEO_STD_AUTO_SWITCH_BIT;
 
 	return tvp514x_configure(decoder);
@@ -1344,11 +1349,6 @@
 		(v4l2_int_ioctl_func *) ioctl_s_routing},
 };
 
-static struct v4l2_int_slave tvp514x_slave = {
-	.ioctls = tvp514x_ioctl_desc,
-	.num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc),
-};
-
 static struct tvp514x_decoder tvp514x_dev = {
 	.state = STATE_NOT_DETECTED,
 
@@ -1369,17 +1369,15 @@
 	.current_std = STD_NTSC_MJ,
 	.std_list = tvp514x_std_list,
 	.num_stds = ARRAY_SIZE(tvp514x_std_list),
-
-};
-
-static struct v4l2_int_device tvp514x_int_device = {
-	.module = THIS_MODULE,
-	.name = TVP514X_MODULE_NAME,
-	.priv = &tvp514x_dev,
-	.type = v4l2_int_type_slave,
-	.u = {
-	      .slave = &tvp514x_slave,
-	      },
+	.v4l2_int_device = {
+		.module = THIS_MODULE,
+		.name = TVP514X_MODULE_NAME,
+		.type = v4l2_int_type_slave,
+	},
+	.tvp514x_slave = {
+		.ioctls = tvp514x_ioctl_desc,
+		.num_ioctls = ARRAY_SIZE(tvp514x_ioctl_desc),
+	},
 };
 
 /**
@@ -1392,26 +1390,37 @@
 static int
 tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct tvp514x_decoder *decoder = &tvp514x_dev;
+	struct tvp514x_decoder *decoder;
 	int err;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
 
-	decoder->pdata = client->dev.platform_data;
-	if (!decoder->pdata) {
+	decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+
+	if (!client->dev.platform_data) {
 		v4l_err(client, "No platform data!!\n");
-		return -ENODEV;
+		err = -ENODEV;
+		goto out_free;
 	}
+
+	*decoder = tvp514x_dev;
+	decoder->v4l2_int_device.priv = decoder;
+	decoder->pdata = client->dev.platform_data;
+	decoder->v4l2_int_device.u.slave = &decoder->tvp514x_slave;
+	memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default,
+			sizeof(tvp514x_reg_list_default));
 	/*
 	 * Fetch platform specific data, and configure the
 	 * tvp514x_reg_list[] accordingly. Since this is one
 	 * time configuration, no need to preserve.
 	 */
-	tvp514x_reg_list[REG_OUTPUT_FORMATTER2].val |=
+	decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |=
 			(decoder->pdata->clk_polarity << 1);
-	tvp514x_reg_list[REG_SYNC_CONTROL].val |=
+	decoder->tvp514x_regs[REG_SYNC_CONTROL].val |=
 			((decoder->pdata->hs_polarity << 2) |
 			(decoder->pdata->vs_polarity << 3));
 	/*
@@ -1419,23 +1428,27 @@
 	 */
 	decoder->id = (struct i2c_device_id *)id;
 	/* Attach to Master */
-	strcpy(tvp514x_int_device.u.slave->attach_to, decoder->pdata->master);
-	decoder->v4l2_int_device = &tvp514x_int_device;
+	strcpy(decoder->v4l2_int_device.u.slave->attach_to,
+			decoder->pdata->master);
 	decoder->client = client;
 	i2c_set_clientdata(client, decoder);
 
 	/* Register with V4L2 layer as slave device */
-	err = v4l2_int_device_register(decoder->v4l2_int_device);
+	err = v4l2_int_device_register(&decoder->v4l2_int_device);
 	if (err) {
 		i2c_set_clientdata(client, NULL);
 		v4l_err(client,
 			"Unable to register to v4l2. Err[%d]\n", err);
+		goto out_free;
 
 	} else
 		v4l_info(client, "Registered to v4l2 master %s!!\n",
 				decoder->pdata->master);
-
 	return 0;
+
+out_free:
+	kfree(decoder);
+	return err;
 }
 
 /**
@@ -1452,9 +1465,9 @@
 	if (!client->adapter)
 		return -ENODEV;	/* our client isn't attached */
 
-	v4l2_int_device_unregister(decoder->v4l2_int_device);
+	v4l2_int_device_unregister(&decoder->v4l2_int_device);
 	i2c_set_clientdata(client, NULL);
-
+	kfree(decoder);
 	return 0;
 }
 /*
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 2cd64ef..3a5a95f 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -8,7 +8,6 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <linux/delay.h>
-#include <linux/video_decoder.h>
 #include <media/v4l2-device.h>
 #include <media/tvp5150.h>
 #include <media/v4l2-i2c-drv-legacy.h>
@@ -632,7 +631,7 @@
 	const struct i2c_vbi_ram_value *regs = vbi_ram_default;
 	int line;
 
-	v4l2_dbg(1, debug, sd, "VIDIOC_G_SLICED_VBI_CAP\n");
+	v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n");
 	memset(cap, 0, sizeof *cap);
 
 	while (regs->reg != (u16)-1 ) {
@@ -831,7 +830,7 @@
 
 static int tvp5150_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	v4l2_dbg(1, debug, sd, "VIDIOC_G_CTRL called\n");
+	v4l2_dbg(1, debug, sd, "g_ctrl called\n");
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -861,7 +860,7 @@
 		if (ctrl->value < tvp5150_qctrl[i].minimum ||
 		    ctrl->value > tvp5150_qctrl[i].maximum)
 			return -ERANGE;
-		v4l2_dbg(1, debug, sd, "VIDIOC_S_CTRL: id=%d, value=%d\n",
+		v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
 					ctrl->id, ctrl->value);
 		break;
 	}
@@ -1015,7 +1014,7 @@
 {
 	int i;
 
-	v4l2_dbg(1, debug, sd, "VIDIOC_QUERYCTRL called\n");
+	v4l2_dbg(1, debug, sd, "queryctrl called\n");
 
 	for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++)
 		if (qc->id && qc->id == tvp5150_qctrl[i].id) {
@@ -1126,7 +1125,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "tvp5150",
-	.driverid = I2C_DRIVERID_TVP5150,
 	.command = tvp5150_command,
 	.probe = tvp5150_probe,
 	.remove = tvp5150_remove,
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 52c0357..a399476 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -460,9 +460,11 @@
 			   u8 mask, u8 set)
 {
 	s32 val = i2c_smbus_read_byte_data(client, command);
+	if (val < 0)
+		return val;
 
 	val &= ~mask;
-	val |=  set;
+	val |= set & mask;
 
 	return i2c_smbus_write_byte_data(client, command, val);
 }
@@ -639,8 +641,8 @@
 }
 #endif
 
-static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt,
-			      struct v4l2_rect *rect)
+static int tw9910_set_crop(struct soc_camera_device *icd,
+			   struct v4l2_rect *rect)
 {
 	struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
 	int                 ret  = -EINVAL;
@@ -731,8 +733,33 @@
 	return ret;
 }
 
+static int tw9910_set_fmt(struct soc_camera_device *icd,
+			  struct v4l2_format *f)
+{
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_rect rect = {
+		.left	= icd->x_current,
+		.top	= icd->y_current,
+		.width	= pix->width,
+		.height	= pix->height,
+	};
+	int i;
+
+	/*
+	 * check color format
+	 */
+	for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++)
+		if (pix->pixelformat == tw9910_color_fmt[i].fourcc)
+			break;
+
+	if (i == ARRAY_SIZE(tw9910_color_fmt))
+		return -EINVAL;
+
+	return tw9910_set_crop(icd, &rect);
+}
+
 static int tw9910_try_fmt(struct soc_camera_device *icd,
-			      struct v4l2_format *f)
+			  struct v4l2_format *f)
 {
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	const struct tw9910_scale_ctrl *scale;
@@ -820,6 +847,7 @@
 	.release		= tw9910_release,
 	.start_capture		= tw9910_start_capture,
 	.stop_capture		= tw9910_stop_capture,
+	.set_crop		= tw9910_set_crop,
 	.set_fmt		= tw9910_set_fmt,
 	.try_fmt		= tw9910_try_fmt,
 	.set_bus_param		= tw9910_set_bus_param,
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
index f4522bb..c0ac651 100644
--- a/drivers/media/video/upd64031a.c
+++ b/drivers/media/video/upd64031a.c
@@ -187,11 +187,6 @@
 }
 #endif
 
-static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops upd64031a_core_ops = {
@@ -267,8 +262,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "upd64031a",
-	.driverid = I2C_DRIVERID_UPD64031A,
-	.command = upd64031a_command,
 	.probe = upd64031a_probe,
 	.remove = upd64031a_remove,
 	.id_table = upd64031a_id,
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
index a5fb74b..410c915 100644
--- a/drivers/media/video/upd64083.c
+++ b/drivers/media/video/upd64083.c
@@ -164,11 +164,6 @@
 	return 0;
 }
 
-static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops upd64083_core_ops = {
@@ -239,8 +234,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "upd64083",
-	.driverid = I2C_DRIVERID_UPD64083,
-	.command = upd64083_command,
 	.probe = upd64083_probe,
 	.remove = upd64083_remove,
 	.id_table = upd64083_id,
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 2f11063..8d73979 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -191,7 +191,7 @@
 {
 	int err;
 	const struct ihex_binrec *rec;
-	const struct firmware *fw;
+	const struct firmware *uninitialized_var(fw);
 
 	err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
 	if (err) {
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 9e4f506..a0feb1c 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -36,7 +36,6 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 #include <linux/videodev2.h>
-#include <linux/video_decoder.h>
 #include <linux/i2c.h>
 
 #include <media/saa7115.h>
@@ -381,8 +380,9 @@
 	usbvision->scratch = vmalloc_32(scratch_buf_size);
 	scratch_reset(usbvision);
 	if(usbvision->scratch == NULL) {
-		err("%s: unable to allocate %d bytes for scratch",
-		    __func__, scratch_buf_size);
+		dev_err(&usbvision->dev->dev,
+			"%s: unable to allocate %d bytes for scratch\n",
+				__func__, scratch_buf_size);
 		return -ENOMEM;
 	}
 	return 0;
@@ -491,8 +491,9 @@
 	int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
 	usbvision->IntraFrameBuffer = vmalloc_32(IFB_size);
 	if (usbvision->IntraFrameBuffer == NULL) {
-		err("%s: unable to allocate %d for compr. frame buffer",
-		    __func__, IFB_size);
+		dev_err(&usbvision->dev->dev,
+			"%s: unable to allocate %d for compr. frame buffer\n",
+				__func__, IFB_size);
 		return -ENOMEM;
 	}
 	return 0;
@@ -1514,8 +1515,9 @@
 	errCode = usb_submit_urb (urb, GFP_ATOMIC);
 
 	if(errCode) {
-		err("%s: usb_submit_urb failed: error %d",
-		    __func__, errCode);
+		dev_err(&usbvision->dev->dev,
+			"%s: usb_submit_urb failed: error %d\n",
+				__func__, errCode);
 	}
 
 	return;
@@ -1546,7 +1548,8 @@
 				0, (__u16) reg, buffer, 1, HZ);
 
 	if (errCode < 0) {
-		err("%s: failed: error %d", __func__, errCode);
+		dev_err(&usbvision->dev->dev,
+			"%s: failed: error %d\n", __func__, errCode);
 		return errCode;
 	}
 	return buffer[0];
@@ -1574,7 +1577,8 @@
 				USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
 
 	if (errCode < 0) {
-		err("%s: failed: error %d", __func__, errCode);
+		dev_err(&usbvision->dev->dev,
+			"%s: failed: error %d\n", __func__, errCode);
 	}
 	return errCode;
 }
@@ -1850,7 +1854,8 @@
 				 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
 
 		if (errCode < 0) {
-			err("%s failed: error %d", __func__, errCode);
+			dev_err(&usbvision->dev->dev,
+				"%s failed: error %d\n", __func__, errCode);
 			return errCode;
 		}
 		usbvision->curwidth = usbvision->stretch_width * UsbWidth;
@@ -2236,7 +2241,7 @@
 			     (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
 
 	if (rc < 0) {
-		err("%sERROR=%d", __func__, rc);
+		dev_err(&usbvision->dev->dev, "%sERROR=%d\n", __func__, rc);
 		return rc;
 	}
 
@@ -2432,8 +2437,9 @@
 		PDEBUG(DBG_FUNC,"setting alternate %d with wMaxPacketSize=%u", dev->ifaceAlt,dev->isocPacketSize);
 		errCode = usb_set_interface(dev->dev, dev->iface, dev->ifaceAlt);
 		if (errCode < 0) {
-			err ("cannot change alternate number to %d (error=%i)",
-							dev->ifaceAlt, errCode);
+			dev_err(&dev->dev->dev,
+				"cannot change alternate number to %d (error=%i)\n",
+					dev->ifaceAlt, errCode);
 			return errCode;
 		}
 	}
@@ -2484,7 +2490,8 @@
 
 		urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
 		if (urb == NULL) {
-			err("%s: usb_alloc_urb() failed", __func__);
+			dev_err(&usbvision->dev->dev,
+				"%s: usb_alloc_urb() failed\n", __func__);
 			return -ENOMEM;
 		}
 		usbvision->sbuf[bufIdx].urb = urb;
@@ -2496,7 +2503,7 @@
 		urb->dev = dev;
 		urb->context = usbvision;
 		urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
-		urb->transfer_flags = URB_ISO_ASAP;
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		urb->interval = 1;
 		urb->transfer_buffer = usbvision->sbuf[bufIdx].data;
 		urb->complete = usbvision_isocIrq;
@@ -2516,8 +2523,9 @@
 			errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
 						 GFP_KERNEL);
 		if (errCode) {
-			err("%s: usb_submit_urb(%d) failed: error %d",
-			    __func__, bufIdx, errCode);
+			dev_err(&usbvision->dev->dev,
+				"%s: usb_submit_urb(%d) failed: error %d\n",
+					__func__, bufIdx, errCode);
 		}
 	}
 
@@ -2566,8 +2574,9 @@
 		errCode = usb_set_interface(usbvision->dev, usbvision->iface,
 					    usbvision->ifaceAlt);
 		if (errCode < 0) {
-			err("%s: usb_set_interface() failed: error %d",
-			    __func__, errCode);
+			dev_err(&usbvision->dev->dev,
+				"%s: usb_set_interface() failed: error %d\n",
+					__func__, errCode);
 			usbvision->last_error = errCode;
 		}
 		regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
@@ -2623,7 +2632,7 @@
 	}
 	route.input = mode[channel];
 	route.output = 0;
-	call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route);
+	call_all(usbvision, video, s_routing, &route);
 	usbvision_set_audio(usbvision, audio[channel]);
 	return 0;
 }
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 6b66ae4..dd2f8f2 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -119,7 +119,8 @@
 		/* try extended address code... */
 		ret = try_write_address(i2c_adap, addr, retries);
 		if (ret != 1) {
-			err("died at extended address code, while writing");
+			dev_err(&i2c_adap->dev,
+				"died at extended address code,	while writing\n");
 			return -EREMOTEIO;
 		}
 		add[0] = addr;
@@ -128,7 +129,8 @@
 			addr |= 0x01;
 			ret = try_read_address(i2c_adap, addr, retries);
 			if (ret != 1) {
-				err("died at extended address code, while reading");
+				dev_err(&i2c_adap->dev,
+					"died at extended address code, while reading\n");
 				return -EREMOTEIO;
 			}
 		}
@@ -200,72 +202,78 @@
 };
 
 
-/*
- * registering functions to load algorithms at runtime
- */
-static int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap)
-{
-	PDEBUG(DBG_I2C, "I2C   debugging is enabled [i2c]");
-	PDEBUG(DBG_I2C, "ALGO   debugging is enabled [i2c]");
-
-	/* register new adapter to i2c module... */
-
-	adap->algo = &usbvision_algo;
-
-	adap->timeout = 100;	/* default values, should       */
-	adap->retries = 3;	/* be replaced by defines       */
-
-	i2c_add_adapter(adap);
-
-	PDEBUG(DBG_I2C,"i2c bus for %s registered", adap->name);
-
-	return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 /* usbvision specific I2C functions                                        */
 /* ----------------------------------------------------------------------- */
 static struct i2c_adapter i2c_adap_template;
-static struct i2c_client i2c_client_template;
 
 int usbvision_i2c_register(struct usb_usbvision *usbvision)
 {
+	static unsigned short saa711x_addrs[] = {
+		0x4a >> 1, 0x48 >> 1,	/* SAA7111, SAA7111A and SAA7113 */
+		0x42 >> 1, 0x40 >> 1,	/* SAA7114, SAA7115 and SAA7118 */
+		I2C_CLIENT_END };
+
 	memcpy(&usbvision->i2c_adap, &i2c_adap_template,
 	       sizeof(struct i2c_adapter));
-	memcpy(&usbvision->i2c_client, &i2c_client_template,
-	       sizeof(struct i2c_client));
 
 	sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
 		" #%d", usbvision->vdev->num);
 	PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
 	usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
 
-	i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
-	i2c_set_clientdata(&usbvision->i2c_client, usbvision);
-
-	usbvision->i2c_client.adapter = &usbvision->i2c_adap;
+	i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev);
 
 	if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
 		printk(KERN_ERR "usbvision_register: can't write reg\n");
 		return -EBUSY;
 	}
 
-#ifdef CONFIG_MODULES
+	PDEBUG(DBG_I2C, "I2C   debugging is enabled [i2c]");
+	PDEBUG(DBG_I2C, "ALGO   debugging is enabled [i2c]");
+
+	/* register new adapter to i2c module... */
+
+	usbvision->i2c_adap.algo = &usbvision_algo;
+
+	usbvision->i2c_adap.timeout = 100;	/* default values, should       */
+	usbvision->i2c_adap.retries = 3;	/* be replaced by defines       */
+
+	i2c_add_adapter(&usbvision->i2c_adap);
+
+	PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name);
+
 	/* Request the load of the i2c modules we need */
 	switch (usbvision_device_data[usbvision->DevModel].Codec) {
 	case CODEC_SAA7113:
-		request_module("saa7115");
-		break;
 	case CODEC_SAA7111:
-		request_module("saa7115");
+		v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "saa7115",
+				"saa7115_auto", saa711x_addrs);
 		break;
 	}
 	if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
-		request_module("tuner");
-	}
-#endif
+		struct v4l2_subdev *sd;
+		enum v4l2_i2c_tuner_type type;
+		struct tuner_setup tun_setup;
 
-	return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap);
+		sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		/* depending on whether we found a demod or not, select
+		   the tuner type. */
+		type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+
+		sd = v4l2_i2c_new_probed_subdev(&usbvision->i2c_adap, "tuner",
+				"tuner", v4l2_i2c_tuner_addrs(type));
+
+		if (usbvision->tuner_type != -1) {
+			tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+			tun_setup.type = usbvision->tuner_type;
+			tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+			call_all(usbvision, tuner, s_type_addr, &tun_setup);
+		}
+	}
+
+	return 0;
 }
 
 int usbvision_i2c_unregister(struct usb_usbvision *usbvision)
@@ -278,67 +286,6 @@
 	return 0;
 }
 
-void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,
-		      void *arg)
-{
-	i2c_clients_command(&usbvision->i2c_adap, cmd, arg);
-}
-
-static int attach_inform(struct i2c_client *client)
-{
-	struct usb_usbvision *usbvision;
-
-	usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
-
-	switch (client->addr << 1) {
-		case 0x42 << 1:
-		case 0x43 << 1:
-		case 0x4a << 1:
-		case 0x4b << 1:
-			PDEBUG(DBG_I2C,"attach_inform: tda9887 detected.");
-			break;
-		case 0x42:
-			PDEBUG(DBG_I2C,"attach_inform: saa7114 detected.");
-			break;
-		case 0x4a:
-			PDEBUG(DBG_I2C,"attach_inform: saa7113 detected.");
-			break;
-		case 0x48:
-			PDEBUG(DBG_I2C,"attach_inform: saa7111 detected.");
-			break;
-		case 0xa0:
-			PDEBUG(DBG_I2C,"attach_inform: eeprom detected.");
-			break;
-
-		default:
-			{
-				struct tuner_setup tun_setup;
-
-				PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1);
-				usbvision->tuner_addr = client->addr;
-
-				if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) {
-					tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-					tun_setup.type = usbvision->tuner_type;
-					tun_setup.addr = usbvision->tuner_addr;
-					call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
-				}
-			}
-			break;
-	}
-	return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
-	struct usb_usbvision *usbvision;
-
-	usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
-
-	PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name);
-	return 0;
-}
-
 static int
 usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
 		     char *buf, short len)
@@ -511,14 +458,6 @@
 static struct i2c_adapter i2c_adap_template = {
 	.owner = THIS_MODULE,
 	.name              = "usbvision",
-	.id                = I2C_HW_B_BT848, /* FIXME */
-	.client_register   = attach_inform,
-	.client_unregister = detach_inform,
-	.class		   = I2C_CLASS_TV_ANALOG,
-};
-
-static struct i2c_client i2c_client_template = {
-	.name		= "usbvision internal",
 };
 
 /*
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 2622de0..fa62a2f 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -59,7 +59,6 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 #include <linux/videodev2.h>
-#include <linux/video_decoder.h>
 #include <linux/i2c.h>
 
 #include <media/saa7115.h>
@@ -212,7 +211,7 @@
 	ctrl.id = V4L2_CID_HUE;
 	ctrl.value = 0;
 	if(usbvision->user)
-		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
 static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
@@ -227,7 +226,7 @@
 	ctrl.id = V4L2_CID_CONTRAST;
 	ctrl.value = 0;
 	if(usbvision->user)
-		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
 static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
@@ -242,7 +241,7 @@
 	ctrl.id = V4L2_CID_BRIGHTNESS;
 	ctrl.value = 0;
 	if(usbvision->user)
-		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
 static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
@@ -257,7 +256,7 @@
 	ctrl.id = V4L2_CID_SATURATION;
 	ctrl.value = 0;
 	if(usbvision->user)
-		call_i2c_clients(usbvision, VIDIOC_G_CTRL, &ctrl);
+		call_all(usbvision, core, g_ctrl, &ctrl);
 	return sprintf(buf, "%d\n", ctrl.value);
 }
 static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
@@ -329,7 +328,7 @@
 			return;
 	} while (0);
 
-	err("%s error: %d\n", __func__, res);
+	dev_err(&vdev->dev, "%s error: %d\n", __func__, res);
 }
 
 static void usbvision_remove_sysfs(struct video_device *vdev)
@@ -487,8 +486,9 @@
 	/* NT100x has a 8-bit register space */
 	errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
 	if (errCode < 0) {
-		err("%s: VIDIOC_DBG_G_REGISTER failed: error %d",
-		    __func__, errCode);
+		dev_err(&usbvision->vdev->dev,
+			"%s: VIDIOC_DBG_G_REGISTER failed: error %d\n",
+				__func__, errCode);
 		return errCode;
 	}
 	reg->val = errCode;
@@ -507,8 +507,9 @@
 	/* NT100x has a 8-bit register space */
 	errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
 	if (errCode < 0) {
-		err("%s: VIDIOC_DBG_S_REGISTER failed: error %d",
-		    __func__, errCode);
+		dev_err(&usbvision->vdev->dev,
+			"%s: VIDIOC_DBG_S_REGISTER failed: error %d\n",
+				__func__, errCode);
 		return errCode;
 	}
 	return 0;
@@ -524,8 +525,7 @@
 	strlcpy(vc->card,
 		usbvision_device_data[usbvision->DevModel].ModelString,
 		sizeof(vc->card));
-	strlcpy(vc->bus_info, dev_name(&usbvision->dev->dev),
-		sizeof(vc->bus_info));
+	usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
 	vc->version = USBVISION_DRIVER_VERSION;
 	vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_AUDIO |
@@ -621,8 +621,7 @@
 	usbvision->tvnormId=*id;
 
 	mutex_lock(&usbvision->lock);
-	call_i2c_clients(usbvision, VIDIOC_S_STD,
-			 &usbvision->tvnormId);
+	call_all(usbvision, tuner, s_std, usbvision->tvnormId);
 	mutex_unlock(&usbvision->lock);
 	/* propagate the change to the decoder */
 	usbvision_muxsel(usbvision, usbvision->ctl_input);
@@ -644,7 +643,7 @@
 		strcpy(vt->name, "Television");
 	}
 	/* Let clients fill in the remainder of this struct */
-	call_i2c_clients(usbvision,VIDIOC_G_TUNER,vt);
+	call_all(usbvision, tuner, g_tuner, vt);
 
 	return 0;
 }
@@ -658,7 +657,7 @@
 	if (!usbvision->have_tuner || vt->index)
 		return -EINVAL;
 	/* let clients handle this */
-	call_i2c_clients(usbvision,VIDIOC_S_TUNER,vt);
+	call_all(usbvision, tuner, s_tuner, vt);
 
 	return 0;
 }
@@ -689,7 +688,7 @@
 		return -EINVAL;
 
 	usbvision->freq = freq->frequency;
-	call_i2c_clients(usbvision, VIDIOC_S_FREQUENCY, freq);
+	call_all(usbvision, tuner, s_frequency, freq);
 
 	return 0;
 }
@@ -698,7 +697,6 @@
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
-	memset(a,0,sizeof(*a));
 	if(usbvision->radio) {
 		strcpy(a->name,"Radio");
 	} else {
@@ -722,12 +720,8 @@
 			    struct v4l2_queryctrl *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int id=ctrl->id;
 
-	memset(ctrl,0,sizeof(*ctrl));
-	ctrl->id=id;
-
-	call_i2c_clients(usbvision, VIDIOC_QUERYCTRL, ctrl);
+	call_all(usbvision, core, queryctrl, ctrl);
 
 	if (!ctrl->type)
 		return -EINVAL;
@@ -739,7 +733,7 @@
 				struct v4l2_control *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
+	call_all(usbvision, core, g_ctrl, ctrl);
 
 	return 0;
 }
@@ -748,7 +742,7 @@
 				struct v4l2_control *ctrl)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
+	call_all(usbvision, core, s_ctrl, ctrl);
 
 	return 0;
 }
@@ -763,8 +757,7 @@
 
 	/* Check input validity:
 	   the user must do a VIDEO CAPTURE and MMAP method. */
-	if((vr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-	   (vr->memory != V4L2_MEMORY_MMAP))
+	if (vr->memory != V4L2_MEMORY_MMAP)
 		return -EINVAL;
 
 	if(usbvision->streaming == Stream_On) {
@@ -789,9 +782,6 @@
 
 	/* FIXME : must control
 	   that buffers are mapped (VIDIOC_REQBUFS has been called) */
-	if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
-		return -EINVAL;
-	}
 	if(vb->index>=usbvision->num_frames)  {
 		return -EINVAL;
 	}
@@ -825,9 +815,6 @@
 	unsigned long lock_flags;
 
 	/* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */
-	if(vb->type != V4L2_CAP_VIDEO_CAPTURE) {
-		return -EINVAL;
-	}
 	if(vb->index>=usbvision->num_frames)  {
 		return -EINVAL;
 	}
@@ -862,9 +849,6 @@
 	struct usbvision_frame *f;
 	unsigned long lock_flags;
 
-	if (vb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
 	if (list_empty(&(usbvision->outqueue))) {
 		if (usbvision->streaming == Stream_Idle)
 			return -EINVAL;
@@ -899,10 +883,9 @@
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
 	usbvision->streaming = Stream_On;
-	call_i2c_clients(usbvision,VIDIOC_STREAMON , &b);
+	call_all(usbvision, video, s_stream, 1);
 
 	return 0;
 }
@@ -911,7 +894,6 @@
 			    void *priv, enum v4l2_buf_type type)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
-	int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
 	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -919,7 +901,7 @@
 	if(usbvision->streaming == Stream_On) {
 		usbvision_stream_interrupt(usbvision);
 		/* Stop all video streamings */
-		call_i2c_clients(usbvision,VIDIOC_STREAMOFF , &b);
+		call_all(usbvision, video, s_stream, 0);
 	}
 	usbvision_empty_framequeues(usbvision);
 
@@ -932,11 +914,8 @@
 	if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
 		return -EINVAL;
 	}
-	vfd->flags = 0;
-	vfd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	strcpy(vfd->description,usbvision_v4l2_format[vfd->index].desc);
 	vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
-	memset(vfd->reserved, 0, sizeof(vfd->reserved));
 	return 0;
 }
 
@@ -1042,7 +1021,7 @@
 	if(usbvision->streaming != Stream_On) {
 		/* no stream is running, make it running ! */
 		usbvision->streaming = Stream_On;
-		call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL);
+		call_all(usbvision, video, s_stream, 1);
 	}
 
 	/* Then, enqueue as many frames as possible
@@ -1189,7 +1168,9 @@
 	mutex_lock(&usbvision->lock);
 
 	if (usbvision->user) {
-		err("%s: Someone tried to open an already opened USBVision Radio!", __func__);
+		dev_err(&usbvision->rdev->dev,
+			"%s: Someone tried to open an already opened USBVision Radio!\n",
+				__func__);
 		errCode = -EBUSY;
 	}
 	else {
@@ -1211,7 +1192,7 @@
 
 		// If so far no errors then we shall start the radio
 		usbvision->radio = 1;
-		call_i2c_clients(usbvision,AUDC_SET_RADIO,&usbvision->tuner_type);
+		call_all(usbvision, tuner, s_radio);
 		usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
 		usbvision->user++;
 	}
@@ -1413,7 +1394,8 @@
 	struct video_device *vdev;
 
 	if (usb_dev == NULL) {
-		err("%s: usbvision->dev is not set", __func__);
+		dev_err(&usbvision->dev->dev,
+			"%s: usbvision->dev is not set\n", __func__);
 		return NULL;
 	}
 
@@ -1423,7 +1405,7 @@
 	}
 	*vdev = *vdev_template;
 //	vdev->minor   = -1;
-	vdev->parent  = &usb_dev->dev;
+	vdev->v4l2_dev = &usbvision->v4l2_dev;
 	snprintf(vdev->name, sizeof(vdev->name), "%s", name);
 	video_set_drvdata(vdev, usbvision);
 	return vdev;
@@ -1524,7 +1506,9 @@
 	return 0;
 
  err_exit:
-	err("USBVision[%d]: video_register_device() failed", usbvision->nr);
+	dev_err(&usbvision->dev->dev,
+		"USBVision[%d]: video_register_device() failed\n",
+			usbvision->nr);
 	usbvision_unregister_video(usbvision);
 	return -1;
 }
@@ -1542,33 +1526,30 @@
 {
 	struct usb_usbvision *usbvision;
 
-	if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) ==
-	    NULL) {
-		goto err_exit;
-	}
+	usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL);
+	if (usbvision == NULL)
+		return NULL;
 
 	usbvision->dev = dev;
+	if (v4l2_device_register(&dev->dev, &usbvision->v4l2_dev))
+		goto err_free;
 
 	mutex_init(&usbvision->lock);	/* available */
 
 	// prepare control urb for control messages during interrupts
 	usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
-	if (usbvision->ctrlUrb == NULL) {
-		goto err_exit;
-	}
+	if (usbvision->ctrlUrb == NULL)
+		goto err_unreg;
 	init_waitqueue_head(&usbvision->ctrlUrb_wq);
 
 	usbvision_init_powerOffTimer(usbvision);
 
 	return usbvision;
 
-err_exit:
-	if (usbvision && usbvision->ctrlUrb) {
-		usb_free_urb(usbvision->ctrlUrb);
-	}
-	if (usbvision) {
-		kfree(usbvision);
-	}
+err_unreg:
+	v4l2_device_unregister(&usbvision->v4l2_dev);
+err_free:
+	kfree(usbvision);
 	return NULL;
 }
 
@@ -1598,6 +1579,7 @@
 		usb_free_urb(usbvision->ctrlUrb);
 	}
 
+	v4l2_device_unregister(&usbvision->v4l2_dev);
 	kfree(usbvision);
 
 	PDEBUG(DBG_PROBE, "success");
@@ -1675,20 +1657,20 @@
 	}
 	endpoint = &interface->endpoint[1].desc;
 	if (!usb_endpoint_xfer_isoc(endpoint)) {
-		err("%s: interface %d. has non-ISO endpoint!",
+		dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
 		    __func__, ifnum);
-		err("%s: Endpoint attributes %d",
+		dev_err(&intf->dev, "%s: Endpoint attributes %d",
 		    __func__, endpoint->bmAttributes);
 		return -ENODEV;
 	}
 	if (usb_endpoint_dir_out(endpoint)) {
-		err("%s: interface %d. has ISO OUT endpoint!",
+		dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n",
 		    __func__, ifnum);
 		return -ENODEV;
 	}
 
 	if ((usbvision = usbvision_alloc(dev)) == NULL) {
-		err("%s: couldn't allocate USBVision struct", __func__);
+		dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -1711,7 +1693,7 @@
 	usbvision->alt_max_pkt_size = kmalloc(32*
 					      usbvision->num_alt,GFP_KERNEL);
 	if (usbvision->alt_max_pkt_size == NULL) {
-		err("usbvision: out of memory!\n");
+		dev_err(&intf->dev, "usbvision: out of memory!\n");
 		mutex_unlock(&usbvision->lock);
 		return -ENOMEM;
 	}
@@ -1733,8 +1715,6 @@
 		usbvision->tuner_type = usbvision_device_data[model].TunerType;
 	}
 
-	usbvision->tuner_addr = ADDR_UNSET;
-
 	usbvision->DevModel = model;
 	usbvision->remove_pending = 0;
 	usbvision->iface = ifnum;
@@ -1772,7 +1752,8 @@
 	PDEBUG(DBG_PROBE, "");
 
 	if (usbvision == NULL) {
-		err("%s: usb_get_intfdata() failed", __func__);
+		dev_err(&usbvision->dev->dev,
+			"%s: usb_get_intfdata() failed\n", __func__);
 		return;
 	}
 	usb_set_intfdata (intf, NULL);
@@ -1782,6 +1763,8 @@
 	// At this time we ask to cancel outstanding URBs
 	usbvision_stop_isoc(usbvision);
 
+	v4l2_device_disconnect(&usbvision->v4l2_dev);
+
 	if (usbvision->power) {
 		usbvision_i2c_unregister(usbvision);
 		usbvision_power_off(usbvision);
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index 20d7ec6..f8d7458 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -6,7 +6,7 @@
  *                         Dwaine Garden <dwainegarden@rogers.com>
  *
  *
- * Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list
+ * Report problems to v4l MailingList: linux-media@vger.kernel.org
  *
  * This module is part of usbvision driver project.
  * Updates to driver completed by Dwaine P. Garden
@@ -35,7 +35,7 @@
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/tuner.h>
 #include <linux/videodev2.h>
 
@@ -357,13 +357,13 @@
 extern struct usb_device_id usbvision_table[];
 
 struct usb_usbvision {
+	struct v4l2_device v4l2_dev;
 	struct video_device *vdev;         				/* Video Device */
 	struct video_device *rdev;               			/* Radio Device */
 	struct video_device *vbi; 					/* VBI Device   */
 
 	/* i2c Declaration Section*/
 	struct i2c_adapter i2c_adap;
-	struct i2c_client i2c_client;
 
 	struct urb *ctrlUrb;
 	unsigned char ctrlUrbBuffer[8];
@@ -374,7 +374,6 @@
 	/* configuration part */
 	int have_tuner;
 	int tuner_type;
-	int tuner_addr;
 	int bridgeType;							// NT1003, NT1004, NT1005
 	int radio;
 	int video_inputs;						// # of inputs
@@ -464,6 +463,8 @@
 	int ComprBlockTypes[4];
 };
 
+#define call_all(usbvision, o, f, args...) \
+	v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args)
 
 /* --------------------------------------------------------------- */
 /* defined in usbvision-i2c.c                                      */
@@ -475,7 +476,6 @@
 /* ----------------------------------------------------------------------- */
 int usbvision_i2c_register(struct usb_usbvision *usbvision);
 int usbvision_i2c_unregister(struct usb_usbvision *usbvision);
-void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg);
 
 /* defined in usbvision-core.c                                      */
 int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index d2576f6..0d7e38d 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -786,7 +786,7 @@
 	memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
 	v4l2_ctrl->id = mapping->id;
 	v4l2_ctrl->type = mapping->v4l2_type;
-	strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
+	strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
 	v4l2_ctrl->flags = 0;
 
 	if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR))
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index b128732..399412d 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -314,7 +314,7 @@
 		fmtdesc = uvc_format_by_guid(&buffer[5]);
 
 		if (fmtdesc != NULL) {
-			strncpy(format->name, fmtdesc->name,
+			strlcpy(format->name, fmtdesc->name,
 				sizeof format->name);
 			format->fcc = fmtdesc->fcc;
 		} else {
@@ -345,7 +345,7 @@
 			return -EINVAL;
 		}
 
-		strncpy(format->name, "MJPEG", sizeof format->name);
+		strlcpy(format->name, "MJPEG", sizeof format->name);
 		format->fcc = V4L2_PIX_FMT_MJPEG;
 		format->flags = UVC_FMT_FLAG_COMPRESSED;
 		format->bpp = 0;
@@ -363,13 +363,13 @@
 
 		switch (buffer[8] & 0x7f) {
 		case 0:
-			strncpy(format->name, "SD-DV", sizeof format->name);
+			strlcpy(format->name, "SD-DV", sizeof format->name);
 			break;
 		case 1:
-			strncpy(format->name, "SDL-DV", sizeof format->name);
+			strlcpy(format->name, "SDL-DV", sizeof format->name);
 			break;
 		case 2:
-			strncpy(format->name, "HD-DV", sizeof format->name);
+			strlcpy(format->name, "HD-DV", sizeof format->name);
 			break;
 		default:
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
@@ -379,7 +379,7 @@
 			return -EINVAL;
 		}
 
-		strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
+		strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
 			sizeof format->name);
 
 		format->fcc = V4L2_PIX_FMT_DV;
@@ -1526,7 +1526,7 @@
 	vdev->minor = -1;
 	vdev->fops = &uvc_fops;
 	vdev->release = video_device_release;
-	strncpy(vdev->name, dev->name, sizeof vdev->name);
+	strlcpy(vdev->name, dev->name, sizeof vdev->name);
 
 	/* Set the driver data before calling video_register_device, otherwise
 	 * uvc_v4l2_open might race us.
@@ -1621,7 +1621,7 @@
 	dev->quirks = id->driver_info | uvc_quirks_param;
 
 	if (udev->product != NULL)
-		strncpy(dev->name, udev->product, sizeof dev->name);
+		strlcpy(dev->name, udev->product, sizeof dev->name);
 	else
 		snprintf(dev->name, sizeof dev->name,
 			"UVC Camera (%04x:%04x)",
@@ -1833,6 +1833,15 @@
 	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0 },
+	/* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x058f,
+	  .idProduct		= 0x3820,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
 	/* Apple Built-In iSight */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1852,6 +1861,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
+	/* ViMicro */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_VENDOR
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x0ac8,
+	  .idProduct		= 0x0000,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_FIX_BANDWIDTH },
 	/* MT6227 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1879,7 +1897,7 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
-	/* Asus F9SG */
+	/* Syntek (Asus F9SG) */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
 	  .idVendor		= 0x174f,
@@ -1897,6 +1915,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
+	/* Syntek (JAOtech Smart Terminal) */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x174f,
+	  .idProduct		= 0x8a34,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
 	/* Lenovo Thinkpad SL500 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
index c705f24..21d8712 100644
--- a/drivers/media/video/uvc/uvc_status.c
+++ b/drivers/media/video/uvc/uvc_status.c
@@ -24,26 +24,19 @@
 #ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
 static int uvc_input_init(struct uvc_device *dev)
 {
-	struct usb_device *udev = dev->udev;
 	struct input_dev *input;
-	char *phys = NULL;
 	int ret;
 
 	input = input_allocate_device();
 	if (input == NULL)
 		return -ENOMEM;
 
-	phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath),
-			GFP_KERNEL);
-	if (phys == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath);
+	usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
+	strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
 
 	input->name = dev->name;
-	input->phys = phys;
-	usb_to_input_id(udev, &input->id);
+	input->phys = dev->input_phys;
+	usb_to_input_id(dev->udev, &input->id);
 	input->dev.parent = &dev->intf->dev;
 
 	__set_bit(EV_KEY, input->evbit);
@@ -57,7 +50,6 @@
 
 error:
 	input_free_device(input);
-	kfree(phys);
 	return ret;
 }
 
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index d681519..2a80caa 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -55,7 +55,7 @@
 		return -EINVAL;
 
 	menu_info = &mapping->menu_info[query_menu->index];
-	strncpy(query_menu->name, menu_info->name, 32);
+	strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
 	return 0;
 }
 
@@ -486,10 +486,10 @@
 		struct v4l2_capability *cap = arg;
 
 		memset(cap, 0, sizeof *cap);
-		strncpy(cap->driver, "uvcvideo", sizeof cap->driver);
-		strncpy(cap->card, vdev->name, 32);
-		strncpy(cap->bus_info, video->dev->udev->bus->bus_name,
-			sizeof cap->bus_info);
+		strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
+		strlcpy(cap->card, vdev->name, sizeof cap->card);
+		usb_make_path(video->dev->udev,
+			      cap->bus_info, sizeof(cap->bus_info));
 		cap->version = DRIVER_VERSION_NUMBER;
 		if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
@@ -620,7 +620,7 @@
 
 		memset(input, 0, sizeof *input);
 		input->index = index;
-		strncpy(input->name, iterm->name, sizeof input->name);
+		strlcpy(input->name, iterm->name, sizeof input->name);
 		if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA)
 			input->type = V4L2_INPUT_TYPE_CAMERA;
 		break;
@@ -673,16 +673,22 @@
 	{
 		struct v4l2_fmtdesc *fmt = arg;
 		struct uvc_format *format;
+		enum v4l2_buf_type type = fmt->type;
+		__u32 index = fmt->index;
 
 		if (fmt->type != video->streaming->type ||
 		    fmt->index >= video->streaming->nformats)
 			return -EINVAL;
 
+		memset(fmt, 0, sizeof(*fmt));
+		fmt->index = index;
+		fmt->type = type;
+
 		format = &video->streaming->format[fmt->index];
 		fmt->flags = 0;
 		if (format->flags & UVC_FMT_FLAG_COMPRESSED)
 			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-		strncpy(fmt->description, format->name,
+		strlcpy(fmt->description, format->name,
 			sizeof fmt->description);
 		fmt->description[sizeof fmt->description - 1] = 0;
 		fmt->pixelformat = format->fcc;
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 9bc4705..a95e173 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -61,7 +61,7 @@
 	return 0;
 }
 
-static void uvc_fixup_buffer_size(struct uvc_video_device *video,
+static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
 	struct uvc_streaming_control *ctrl)
 {
 	struct uvc_format *format;
@@ -84,6 +84,31 @@
 	      video->dev->uvc_version < 0x0110))
 		ctrl->dwMaxVideoFrameSize =
 			frame->dwMaxVideoFrameBufferSize;
+
+	if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
+	    video->streaming->intf->num_altsetting > 1) {
+		u32 interval;
+		u32 bandwidth;
+
+		interval = (ctrl->dwFrameInterval > 100000)
+			 ? ctrl->dwFrameInterval
+			 : frame->dwFrameInterval[0];
+
+		/* Compute a bandwidth estimation by multiplying the frame
+		 * size by the number of video frames per second, divide the
+		 * result by the number of USB frames (or micro-frames for
+		 * high-speed devices) per second and add the UVC header size
+		 * (assumed to be 12 bytes long).
+		 */
+		bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
+		bandwidth *= 10000000 / interval + 1;
+		bandwidth /= 1000;
+		if (video->dev->udev->speed == USB_SPEED_HIGH)
+			bandwidth /= 8;
+		bandwidth += 12;
+
+		ctrl->dwMaxPayloadTransferSize = bandwidth;
+	}
 }
 
 static int uvc_get_video_ctrl(struct uvc_video_device *video,
@@ -158,10 +183,11 @@
 		ctrl->bMaxVersion = 0;
 	}
 
-	/* Some broken devices return a null or wrong dwMaxVideoFrameSize.
-	 * Try to get the value from the format and frame descriptors.
+	/* Some broken devices return null or wrong dwMaxVideoFrameSize and
+	 * dwMaxPayloadTransferSize fields. Try to get the value from the
+	 * format and frame descriptors.
 	 */
-	uvc_fixup_buffer_size(video, ctrl);
+	uvc_fixup_video_ctrl(video, ctrl);
 	ret = 0;
 
 out:
@@ -540,6 +566,9 @@
 	u8 *mem;
 	int len, ret;
 
+	if (urb->actual_length == 0)
+		return;
+
 	mem = urb->transfer_buffer;
 	len = urb->actual_length;
 	video->bulk.payload_size += len;
@@ -699,27 +728,47 @@
  * already allocated when resuming from suspend, in which case it will
  * return without touching the buffers.
  *
- * Return 0 on success or -ENOMEM when out of memory.
+ * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the
+ * system is too low on memory try successively smaller numbers of packets
+ * until allocation succeeds.
+ *
+ * Return the number of allocated packets on success or 0 when out of memory.
  */
 static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
-	unsigned int size)
+	unsigned int size, unsigned int psize, gfp_t gfp_flags)
 {
+	unsigned int npackets;
 	unsigned int i;
 
 	/* Buffers are already allocated, bail out. */
 	if (video->urb_size)
 		return 0;
 
-	for (i = 0; i < UVC_URBS; ++i) {
-		video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
-			size, GFP_KERNEL, &video->urb_dma[i]);
-		if (video->urb_buffer[i] == NULL) {
-			uvc_free_urb_buffers(video);
-			return -ENOMEM;
+	/* Compute the number of packets. Bulk endpoints might transfer UVC
+	 * payloads accross multiple URBs.
+	 */
+	npackets = DIV_ROUND_UP(size, psize);
+	if (npackets > UVC_MAX_PACKETS)
+		npackets = UVC_MAX_PACKETS;
+
+	/* Retry allocations until one succeed. */
+	for (; npackets > 1; npackets /= 2) {
+		for (i = 0; i < UVC_URBS; ++i) {
+			video->urb_buffer[i] = usb_buffer_alloc(
+				video->dev->udev, psize * npackets,
+				gfp_flags | __GFP_NOWARN, &video->urb_dma[i]);
+			if (!video->urb_buffer[i]) {
+				uvc_free_urb_buffers(video);
+				break;
+			}
+		}
+
+		if (i == UVC_URBS) {
+			video->urb_size = psize * npackets;
+			return npackets;
 		}
 	}
 
-	video->urb_size = size;
 	return 0;
 }
 
@@ -753,29 +802,19 @@
 {
 	struct urb *urb;
 	unsigned int npackets, i, j;
-	__u16 psize;
-	__u32 size;
+	u16 psize;
+	u32 size;
 
-	/* Compute the number of isochronous packets to allocate by dividing
-	 * the maximum video frame size by the packet size. Limit the result
-	 * to UVC_MAX_ISO_PACKETS.
-	 */
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize);
 	psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-
 	size = video->streaming->ctrl.dwMaxVideoFrameSize;
-	if (size > UVC_MAX_FRAME_SIZE)
-		return -EINVAL;
 
-	npackets = DIV_ROUND_UP(size, psize);
-	if (npackets > UVC_MAX_ISO_PACKETS)
-		npackets = UVC_MAX_ISO_PACKETS;
+	npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+	if (npackets == 0)
+		return -ENOMEM;
 
 	size = npackets * psize;
 
-	if (uvc_alloc_urb_buffers(video, size) < 0)
-		return -ENOMEM;
-
 	for (i = 0; i < UVC_URBS; ++i) {
 		urb = usb_alloc_urb(npackets, gfp_flags);
 		if (urb == NULL) {
@@ -814,25 +853,20 @@
 	struct usb_host_endpoint *ep, gfp_t gfp_flags)
 {
 	struct urb *urb;
-	unsigned int pipe, i;
-	__u16 psize;
-	__u32 size;
+	unsigned int npackets, pipe, i;
+	u16 psize;
+	u32 size;
 
-	/* Compute the bulk URB size. Some devices set the maximum payload
-	 * size to a value too high for memory-constrained devices. We must
-	 * then transfer the payload accross multiple URBs. To be consistant
-	 * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk
-	 * URB.
-	 */
 	psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
 	size = video->streaming->ctrl.dwMaxPayloadTransferSize;
 	video->bulk.max_payload_size = size;
-	if (size > psize * UVC_MAX_ISO_PACKETS)
-		size = psize * UVC_MAX_ISO_PACKETS;
 
-	if (uvc_alloc_urb_buffers(video, size) < 0)
+	npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags);
+	if (npackets == 0)
 		return -ENOMEM;
 
+	size = npackets * psize;
+
 	if (usb_endpoint_dir_in(&ep->desc))
 		pipe = usb_rcvbulkpipe(video->dev->udev,
 				       ep->desc.bEndpointAddress);
@@ -1021,11 +1055,20 @@
 	 */
 	usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
 
-	/* Some webcams don't suport GET_DEF requests on the probe control. We
-	 * fall back to GET_CUR if GET_DEF fails.
+	/* Set the streaming probe control with default streaming parameters
+	 * retrieved from the device. Webcams that don't suport GET_DEF
+	 * requests on the probe control will just keep their current streaming
+	 * parameters.
 	 */
-	if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
-	    (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+	if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0)
+		uvc_set_video_ctrl(video, probe, 1);
+
+	/* Initialize the streaming parameters with the probe control current
+	 * value. This makes sure SET_CUR requests on the streaming commit
+	 * control will always use values retrieved from a successful GET_CUR
+	 * request on the probe control, as required by the UVC specification.
+	 */
+	if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
 		return ret;
 
 	/* Check if the default format descriptor exists. Use the first
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 027947e..e5014e6 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -296,10 +296,8 @@
 
 /* Number of isochronous URBs. */
 #define UVC_URBS		5
-/* Maximum number of packets per isochronous URB. */
-#define UVC_MAX_ISO_PACKETS	40
-/* Maximum frame size in bytes, for sanity checking. */
-#define UVC_MAX_FRAME_SIZE	(16*1024*1024)
+/* Maximum number of packets per URB. */
+#define UVC_MAX_PACKETS		32
 /* Maximum number of video buffers. */
 #define UVC_MAX_VIDEO_BUFFERS	32
 /* Maximum status buffer size in bytes of interrupt URB. */
@@ -316,6 +314,7 @@
 #define UVC_QUIRK_STREAM_NO_FID		0x00000010
 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
 #define UVC_QUIRK_PRUNE_CONTROLS	0x00000040
+#define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
@@ -649,6 +648,7 @@
 	struct urb *int_urb;
 	__u8 *status;
 	struct input_dev *input;
+	char input_phys[64];
 
 	/* Video Streaming interfaces */
 	struct list_head streaming;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b8f2be8..1da8cb8 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -334,6 +334,12 @@
 		"Aperture Priority Mode",
 		NULL
 	};
+	static const char *colorfx[] = {
+		"None",
+		"Black & White",
+		"Sepia",
+		NULL
+	};
 
 	switch (id) {
 		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -370,6 +376,8 @@
 			return camera_power_line_frequency;
 		case V4L2_CID_EXPOSURE_AUTO:
 			return camera_exposure_auto;
+		case V4L2_CID_COLORFX:
+			return colorfx;
 		default:
 			return NULL;
 	}
@@ -382,16 +390,16 @@
 	switch (id) {
 	/* USER controls */
 	case V4L2_CID_USER_CLASS: 		return "User Controls";
-	case V4L2_CID_AUDIO_VOLUME: 		return "Volume";
-	case V4L2_CID_AUDIO_MUTE: 		return "Mute";
-	case V4L2_CID_AUDIO_BALANCE: 		return "Balance";
-	case V4L2_CID_AUDIO_BASS: 		return "Bass";
-	case V4L2_CID_AUDIO_TREBLE: 		return "Treble";
-	case V4L2_CID_AUDIO_LOUDNESS: 		return "Loudness";
 	case V4L2_CID_BRIGHTNESS: 		return "Brightness";
 	case V4L2_CID_CONTRAST: 		return "Contrast";
 	case V4L2_CID_SATURATION: 		return "Saturation";
 	case V4L2_CID_HUE: 			return "Hue";
+	case V4L2_CID_AUDIO_VOLUME: 		return "Volume";
+	case V4L2_CID_AUDIO_BALANCE: 		return "Balance";
+	case V4L2_CID_AUDIO_BASS: 		return "Bass";
+	case V4L2_CID_AUDIO_TREBLE: 		return "Treble";
+	case V4L2_CID_AUDIO_MUTE: 		return "Mute";
+	case V4L2_CID_AUDIO_LOUDNESS: 		return "Loudness";
 	case V4L2_CID_BLACK_LEVEL:		return "Black Level";
 	case V4L2_CID_AUTO_WHITE_BALANCE:	return "White Balance, Automatic";
 	case V4L2_CID_DO_WHITE_BALANCE:		return "Do White Balance";
@@ -412,6 +420,7 @@
 	case V4L2_CID_BACKLIGHT_COMPENSATION:	return "Backlight Compensation";
 	case V4L2_CID_CHROMA_AGC:		return "Chroma AGC";
 	case V4L2_CID_COLOR_KILLER:		return "Color Killer";
+	case V4L2_CID_COLORFX:			return "Color Effects";
 
 	/* MPEG controls */
 	case V4L2_CID_MPEG_CLASS: 		return "MPEG Encoder Controls";
@@ -490,16 +499,25 @@
 	case V4L2_CID_HFLIP:
 	case V4L2_CID_VFLIP:
 	case V4L2_CID_HUE_AUTO:
+	case V4L2_CID_CHROMA_AGC:
+	case V4L2_CID_COLOR_KILLER:
 	case V4L2_CID_MPEG_AUDIO_MUTE:
 	case V4L2_CID_MPEG_VIDEO_MUTE:
 	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
 	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
 	case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
+	case V4L2_CID_FOCUS_AUTO:
 	case V4L2_CID_PRIVACY:
 		qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
 		min = 0;
 		max = step = 1;
 		break;
+	case V4L2_CID_PAN_RESET:
+	case V4L2_CID_TILT_RESET:
+		qctrl->type = V4L2_CTRL_TYPE_BUTTON;
+		qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+		min = max = step = def = 0;
+		break;
 	case V4L2_CID_POWER_LINE_FREQUENCY:
 	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
 	case V4L2_CID_MPEG_AUDIO_ENCODING:
@@ -517,6 +535,7 @@
 	case V4L2_CID_MPEG_STREAM_TYPE:
 	case V4L2_CID_MPEG_STREAM_VBI_FMT:
 	case V4L2_CID_EXPOSURE_AUTO:
+	case V4L2_CID_COLORFX:
 		qctrl->type = V4L2_CTRL_TYPE_MENU;
 		step = 1;
 		break;
@@ -547,161 +566,29 @@
 	case V4L2_CID_CONTRAST:
 	case V4L2_CID_SATURATION:
 	case V4L2_CID_HUE:
+	case V4L2_CID_RED_BALANCE:
+	case V4L2_CID_BLUE_BALANCE:
+	case V4L2_CID_GAMMA:
+	case V4L2_CID_SHARPNESS:
 		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 		break;
+	case V4L2_CID_PAN_RELATIVE:
+	case V4L2_CID_TILT_RELATIVE:
+	case V4L2_CID_FOCUS_RELATIVE:
+	case V4L2_CID_ZOOM_RELATIVE:
+		qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+		break;
 	}
 	qctrl->minimum = min;
 	qctrl->maximum = max;
 	qctrl->step = step;
 	qctrl->default_value = def;
 	qctrl->reserved[0] = qctrl->reserved[1] = 0;
-	snprintf(qctrl->name, sizeof(qctrl->name), name);
+	strlcpy(qctrl->name, name, sizeof(qctrl->name));
 	return 0;
 }
 EXPORT_SYMBOL(v4l2_ctrl_query_fill);
 
-/* Fill in a struct v4l2_queryctrl with standard values based on
-   the control ID. */
-int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
-{
-	switch (qctrl->id) {
-	/* USER controls */
-	case V4L2_CID_USER_CLASS:
-	case V4L2_CID_MPEG_CLASS:
-		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880);
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_LOUDNESS:
-		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768);
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0);
-
-	/* MPEG controls */
-	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
-				V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
-				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
-	case V4L2_CID_MPEG_AUDIO_ENCODING:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_ENCODING_LAYER_1,
-				V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
-				V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
-	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_L1_BITRATE_32K,
-				V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1,
-				V4L2_MPEG_AUDIO_L1_BITRATE_256K);
-	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_L2_BITRATE_32K,
-				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
-				V4L2_MPEG_AUDIO_L2_BITRATE_224K);
-	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_L3_BITRATE_32K,
-				V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1,
-				V4L2_MPEG_AUDIO_L3_BITRATE_192K);
-	case V4L2_CID_MPEG_AUDIO_AAC_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000);
-	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_AC3_BITRATE_32K,
-				V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1,
-				V4L2_MPEG_AUDIO_AC3_BITRATE_384K);
-	case V4L2_CID_MPEG_AUDIO_MODE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_MODE_STEREO,
-				V4L2_MPEG_AUDIO_MODE_MONO, 1,
-				V4L2_MPEG_AUDIO_MODE_STEREO);
-	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
-				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
-				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
-	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_EMPHASIS_NONE,
-				V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
-				V4L2_MPEG_AUDIO_EMPHASIS_NONE);
-	case V4L2_CID_MPEG_AUDIO_CRC:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_AUDIO_CRC_NONE,
-				V4L2_MPEG_AUDIO_CRC_CRC16, 1,
-				V4L2_MPEG_AUDIO_CRC_NONE);
-	case V4L2_CID_MPEG_AUDIO_MUTE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
-	case V4L2_CID_MPEG_VIDEO_ENCODING:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
-				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-	case V4L2_CID_MPEG_VIDEO_ASPECT:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_VIDEO_ASPECT_1x1,
-				V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
-				V4L2_MPEG_VIDEO_ASPECT_4x3);
-	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-		return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12);
-	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
-	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
-		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
-	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
-				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-	case V4L2_CID_MPEG_VIDEO_BITRATE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
-	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
-	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
-		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
-	case V4L2_CID_MPEG_VIDEO_MUTE:
-		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
-	case V4L2_CID_MPEG_VIDEO_MUTE_YUV:  /* Init YUV (really YCbCr) to black */
-		return v4l2_ctrl_query_fill(qctrl, 0, 0xffffff, 1, 0x008080);
-	case V4L2_CID_MPEG_STREAM_TYPE:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
-				V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
-				V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
-	case V4L2_CID_MPEG_STREAM_PID_PMT:
-		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
-	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
-	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
-	case V4L2_CID_MPEG_STREAM_PID_PCR:
-		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
-	case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO:
-		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
-	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO:
-		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
-	case V4L2_CID_MPEG_STREAM_VBI_FMT:
-		return v4l2_ctrl_query_fill(qctrl,
-				V4L2_MPEG_STREAM_VBI_FMT_NONE,
-				V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
-				V4L2_MPEG_STREAM_VBI_FMT_NONE);
-	default:
-		return -EINVAL;
-	}
-}
-EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
-
 /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
    the menu. The qctrl pointer may be NULL, in which case it is ignored.
    If menu_items is NULL, then the menu items are retrieved using
@@ -720,7 +607,7 @@
 	for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
 	if (menu_items[i] == NULL || menu_items[i][0] == '\0')
 		return -EINVAL;
-	snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]);
+	strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name));
 	return 0;
 }
 EXPORT_SYMBOL(v4l2_ctrl_query_menu);
@@ -737,8 +624,8 @@
 		return -EINVAL;
 	while (*ids != V4L2_CTRL_MENU_IDS_END) {
 		if (*ids++ == qmenu->index) {
-			snprintf(qmenu->name, sizeof(qmenu->name),
-				       menu_items[qmenu->index]);
+			strlcpy(qmenu->name, menu_items[qmenu->index],
+					sizeof(qmenu->name));
 			return 0;
 		}
 	}
@@ -749,7 +636,7 @@
 /* ctrl_classes points to an array of u32 pointers, the last element is
    a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
    Each array must be sorted low to high and belong to the same control
-   class. The array of u32 pointer must also be sorted, from low class IDs
+   class. The array of u32 pointers must also be sorted, from low class IDs
    to high class IDs.
 
    This function returns the first ID that follows after the given ID.
@@ -910,10 +797,10 @@
 	struct i2c_board_info info;
 
 	BUG_ON(!dev);
-#ifdef MODULE
+
 	if (module_name)
 		request_module(module_name);
-#endif
+
 	/* Setup the i2c board info with the device type and
 	   the device address. */
 	memset(&info, 0, sizeof(info));
@@ -927,11 +814,11 @@
 	   We need better support from the kernel so that we
 	   can easily wait for the load to finish. */
 	if (client == NULL || client->driver == NULL)
-		return NULL;
+		goto error;
 
 	/* Lock the module so we can safely get the v4l2_subdev pointer */
 	if (!try_module_get(client->driver->driver.owner))
-		return NULL;
+		goto error;
 	sd = i2c_get_clientdata(client);
 
 	/* Register with the v4l2_device which increases the module's
@@ -940,8 +827,13 @@
 		sd = NULL;
 	/* Decrease the module use count to match the first try_module_get. */
 	module_put(client->driver->driver.owner);
-	return sd;
 
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (client && sd == NULL)
+		i2c_unregister_device(client);
+	return sd;
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
 
@@ -958,10 +850,10 @@
 	struct i2c_board_info info;
 
 	BUG_ON(!dev);
-#ifdef MODULE
+
 	if (module_name)
 		request_module(module_name);
-#endif
+
 	/* Setup the i2c board info with the device type and
 	   the device address. */
 	memset(&info, 0, sizeof(info));
@@ -974,11 +866,11 @@
 	   We need better support from the kernel so that we
 	   can easily wait for the load to finish. */
 	if (client == NULL || client->driver == NULL)
-		return NULL;
+		goto error;
 
 	/* Lock the module so we can safely get the v4l2_subdev pointer */
 	if (!try_module_get(client->driver->driver.owner))
-		return NULL;
+		goto error;
 	sd = i2c_get_clientdata(client);
 
 	/* Register with the v4l2_device which increases the module's
@@ -987,8 +879,59 @@
 		sd = NULL;
 	/* Decrease the module use count to match the first try_module_get. */
 	module_put(client->driver->driver.owner);
+
+error:
+	/* If we have a client but no subdev, then something went wrong and
+	   we must unregister the client. */
+	if (client && sd == NULL)
+		i2c_unregister_device(client);
 	return sd;
 }
 EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev);
 
+/* Return i2c client address of v4l2_subdev. */
+unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return client ? client->addr : I2C_CLIENT_END;
+}
+EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr);
+
+/* Return a list of I2C tuner addresses to probe. Use only if the tuner
+   addresses are unknown. */
+const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
+{
+	static const unsigned short radio_addrs[] = {
+#if defined(CONFIG_MEDIA_TUNER_TEA5761) || defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE)
+		0x10,
+#endif
+		0x60,
+		I2C_CLIENT_END
+	};
+	static const unsigned short demod_addrs[] = {
+		0x42, 0x43, 0x4a, 0x4b,
+		I2C_CLIENT_END
+	};
+	static const unsigned short tv_addrs[] = {
+		0x42, 0x43, 0x4a, 0x4b,		/* tda8290 */
+		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+		I2C_CLIENT_END
+	};
+
+	switch (type) {
+	case ADDRS_RADIO:
+		return radio_addrs;
+	case ADDRS_DEMOD:
+		return demod_addrs;
+	case ADDRS_TV:
+		return tv_addrs;
+	case ADDRS_TV_WITH_DEMOD:
+		return tv_addrs + 4;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
+
 #endif
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 110376b..0056b11 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -1047,7 +1047,6 @@
 	case VIDIOC_DBG_S_REGISTER:
 	case VIDIOC_DBG_G_REGISTER:
 	case VIDIOC_DBG_G_CHIP_IDENT:
-	case VIDIOC_G_CHIP_IDENT_OLD:
 	case VIDIOC_S_HW_FREQ_SEEK:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 13f87c2..91228b3 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -198,6 +198,23 @@
 	return vdev->fops->unlocked_ioctl(filp, cmd, arg);
 }
 
+#ifdef CONFIG_MMU
+#define v4l2_get_unmapped_area NULL
+#else
+static unsigned long v4l2_get_unmapped_area(struct file *filp,
+		unsigned long addr, unsigned long len, unsigned long pgoff,
+		unsigned long flags)
+{
+	struct video_device *vdev = video_devdata(filp);
+
+	if (!vdev->fops->get_unmapped_area)
+		return -ENOSYS;
+	if (video_is_unregistered(vdev))
+		return -ENODEV;
+	return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags);
+}
+#endif
+
 static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 {
 	struct video_device *vdev = video_devdata(filp);
@@ -250,6 +267,7 @@
 	.read = v4l2_read,
 	.write = v4l2_write,
 	.open = v4l2_open,
+	.get_unmapped_area = v4l2_get_unmapped_area,
 	.mmap = v4l2_mmap,
 	.unlocked_ioctl = v4l2_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
@@ -265,6 +283,7 @@
 	.read = v4l2_read,
 	.write = v4l2_write,
 	.open = v4l2_open,
+	.get_unmapped_area = v4l2_get_unmapped_area,
 	.mmap = v4l2_mmap,
 	.ioctl = v4l2_ioctl,
 #ifdef CONFIG_COMPAT
@@ -288,37 +307,38 @@
  */
 static int get_index(struct video_device *vdev, int num)
 {
-	u32 used = 0;
-	const int max_index = sizeof(used) * 8 - 1;
+	/* This can be static since this function is called with the global
+	   videodev_lock held. */
+	static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES);
 	int i;
 
-	/* Currently a single v4l driver instance cannot create more than
-	   32 devices.
-	   Increase to u64 or an array of u32 if more are needed. */
-	if (num > max_index) {
+	if (num >= VIDEO_NUM_DEVICES) {
 		printk(KERN_ERR "videodev: %s num is too large\n", __func__);
 		return -EINVAL;
 	}
 
-	/* Some drivers do not set the parent. In that case always return 0. */
+	/* Some drivers do not set the parent. In that case always return
+	   num or 0. */
 	if (vdev->parent == NULL)
-		return 0;
+		return num >= 0 ? num : 0;
+
+	bitmap_zero(used, VIDEO_NUM_DEVICES);
 
 	for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
 		if (video_device[i] != NULL &&
 		    video_device[i]->parent == vdev->parent) {
-			used |= 1 << video_device[i]->index;
+			set_bit(video_device[i]->index, used);
 		}
 	}
 
 	if (num >= 0) {
-		if (used & (1 << num))
+		if (test_bit(num, used))
 			return -ENFILE;
 		return num;
 	}
 
-	i = ffz(used);
-	return i > max_index ? -ENFILE : i;
+	i = find_first_zero_bit(used, VIDEO_NUM_DEVICES);
+	return i == VIDEO_NUM_DEVICES ? -ENFILE : i;
 }
 
 int video_register_device(struct video_device *vdev, int type, int nr)
@@ -365,12 +385,11 @@
 
 	/* A minor value of -1 marks this video device as never
 	   having been registered */
-	if (vdev)
-		vdev->minor = -1;
+	vdev->minor = -1;
 
 	/* the release callback MUST be present */
-	WARN_ON(!vdev || !vdev->release);
-	if (!vdev || !vdev->release)
+	WARN_ON(!vdev->release);
+	if (!vdev->release)
 		return -EINVAL;
 
 	/* Part 1: check device type */
@@ -395,7 +414,7 @@
 
 	vdev->vfl_type = type;
 	vdev->cdev = NULL;
-	if (vdev->v4l2_dev)
+	if (vdev->v4l2_dev && vdev->v4l2_dev->dev)
 		vdev->parent = vdev->v4l2_dev->dev;
 
 	/* Part 2: find a free minor, kernel number and device index. */
@@ -582,6 +601,7 @@
 MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR);
 
 
 /*
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 8a4b74f..94aa485 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -26,48 +26,66 @@
 
 int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 {
-	if (dev == NULL || v4l2_dev == NULL)
+	if (v4l2_dev == NULL)
 		return -EINVAL;
-	/* Warn if we apparently re-register a device */
-	WARN_ON(dev_get_drvdata(dev) != NULL);
+
 	INIT_LIST_HEAD(&v4l2_dev->subdevs);
 	spin_lock_init(&v4l2_dev->lock);
 	v4l2_dev->dev = dev;
-	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
+	if (dev == NULL) {
+		/* If dev == NULL, then name must be filled in by the caller */
+		WARN_ON(!v4l2_dev->name[0]);
+		return 0;
+	}
+
+	/* Set name to driver name + device name if it is empty. */
+	if (!v4l2_dev->name[0])
+		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
 			dev->driver->name, dev_name(dev));
+	if (dev_get_drvdata(dev))
+		v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n");
 	dev_set_drvdata(dev, v4l2_dev);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register);
 
+void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
+{
+	if (v4l2_dev->dev) {
+		dev_set_drvdata(v4l2_dev->dev, NULL);
+		v4l2_dev->dev = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
+
 void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
 {
 	struct v4l2_subdev *sd, *next;
 
-	if (v4l2_dev == NULL || v4l2_dev->dev == NULL)
+	if (v4l2_dev == NULL)
 		return;
-	dev_set_drvdata(v4l2_dev->dev, NULL);
-	/* unregister subdevs */
+	v4l2_device_disconnect(v4l2_dev);
+
+	/* Unregister subdevs */
 	list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list)
 		v4l2_device_unregister_subdev(sd);
-
-	v4l2_dev->dev = NULL;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister);
 
-int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd)
+int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+						struct v4l2_subdev *sd)
 {
 	/* Check for valid input */
-	if (dev == NULL || sd == NULL || !sd->name[0])
+	if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
 		return -EINVAL;
 	/* Warn if we apparently re-register a subdev */
-	WARN_ON(sd->dev != NULL);
+	WARN_ON(sd->v4l2_dev != NULL);
 	if (!try_module_get(sd->owner))
 		return -ENODEV;
-	sd->dev = dev;
-	spin_lock(&dev->lock);
-	list_add_tail(&sd->list, &dev->subdevs);
-	spin_unlock(&dev->lock);
+	sd->v4l2_dev = v4l2_dev;
+	spin_lock(&v4l2_dev->lock);
+	list_add_tail(&sd->list, &v4l2_dev->subdevs);
+	spin_unlock(&v4l2_dev->lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
@@ -75,12 +93,12 @@
 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 {
 	/* return if it isn't registered */
-	if (sd == NULL || sd->dev == NULL)
+	if (sd == NULL || sd->v4l2_dev == NULL)
 		return;
-	spin_lock(&sd->dev->lock);
+	spin_lock(&sd->v4l2_dev->lock);
 	list_del(&sd->list);
-	spin_unlock(&sd->dev->lock);
-	sd->dev = NULL;
+	spin_unlock(&sd->v4l2_dev->lock);
+	sd->v4l2_dev = NULL;
 	module_put(sd->owner);
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 52d687b..f41c6f5 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 
 #define __OLD_VIDIOC_ /* To allow fixing old calls */
+#include <linux/videodev.h>
 #include <linux/videodev2.h>
 
 #ifdef CONFIG_VIDEO_V4L1
@@ -24,7 +25,7 @@
 #endif
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/video_decoder.h>
+#include <media/v4l2-chip-ident.h>
 
 #define dbgarg(cmd, fmt, arg...) \
 		do {							\
@@ -100,25 +101,27 @@
 }
 EXPORT_SYMBOL(v4l2_norm_to_name);
 
+/* Returns frame period for the given standard */
+void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
+{
+	if (id & V4L2_STD_525_60) {
+		frameperiod->numerator = 1001;
+		frameperiod->denominator = 30000;
+	} else {
+		frameperiod->numerator = 1;
+		frameperiod->denominator = 25;
+	}
+}
+EXPORT_SYMBOL(v4l2_video_std_frame_period);
+
 /* Fill in the fields of a v4l2_standard structure according to the
    'id' and 'transmission' parameters.  Returns negative on error.  */
 int v4l2_video_std_construct(struct v4l2_standard *vs,
 			     int id, const char *name)
 {
-	u32 index = vs->index;
-
-	memset(vs, 0, sizeof(struct v4l2_standard));
-	vs->index = index;
-	vs->id    = id;
-	if (id & V4L2_STD_525_60) {
-		vs->frameperiod.numerator = 1001;
-		vs->frameperiod.denominator = 30000;
-		vs->framelines = 525;
-	} else {
-		vs->frameperiod.numerator = 1;
-		vs->frameperiod.denominator = 25;
-		vs->framelines = 625;
-	}
+	vs->id = id;
+	v4l2_video_std_frame_period(id, &vs->frameperiod);
+	vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
 	strlcpy(vs->name, name, sizeof(vs->name));
 	return 0;
 }
@@ -273,19 +276,6 @@
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
 static const char *v4l2_int_ioctls[] = {
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	[_IOC_NR(DECODER_GET_CAPABILITIES)]    = "DECODER_GET_CAPABILITIES",
-	[_IOC_NR(DECODER_GET_STATUS)]          = "DECODER_GET_STATUS",
-	[_IOC_NR(DECODER_SET_NORM)]            = "DECODER_SET_NORM",
-	[_IOC_NR(DECODER_SET_INPUT)]           = "DECODER_SET_INPUT",
-	[_IOC_NR(DECODER_SET_OUTPUT)]          = "DECODER_SET_OUTPUT",
-	[_IOC_NR(DECODER_ENABLE_OUTPUT)]       = "DECODER_ENABLE_OUTPUT",
-	[_IOC_NR(DECODER_SET_PICTURE)]         = "DECODER_SET_PICTURE",
-	[_IOC_NR(DECODER_SET_GPIO)]            = "DECODER_SET_GPIO",
-	[_IOC_NR(DECODER_INIT)]                = "DECODER_INIT",
-	[_IOC_NR(DECODER_SET_VBI_BYPASS)]      = "DECODER_SET_VBI_BYPASS",
-	[_IOC_NR(DECODER_DUMP)]                = "DECODER_DUMP",
-#endif
 	[_IOC_NR(AUDC_SET_RADIO)]              = "AUDC_SET_RADIO",
 
 	[_IOC_NR(TUNER_SET_TYPE_ADDR)]         = "TUNER_SET_TYPE_ADDR",
@@ -654,8 +644,6 @@
 	if (cmd == VIDIOCGMBUF) {
 		struct video_mbuf *p = arg;
 
-		memset(p, 0, sizeof(*p));
-
 		if (!ops->vidiocgmbuf)
 			return ret;
 		ret = ops->vidiocgmbuf(file, fh, p);
@@ -682,7 +670,6 @@
 	case VIDIOC_QUERYCAP:
 	{
 		struct v4l2_capability *cap = (struct v4l2_capability *)arg;
-		memset(cap, 0, sizeof(*cap));
 
 		if (!ops->vidioc_querycap)
 			break;
@@ -725,16 +712,8 @@
 	case VIDIOC_ENUM_FMT:
 	{
 		struct v4l2_fmtdesc *f = arg;
-		enum v4l2_buf_type type;
-		unsigned int index;
 
-		index = f->index;
-		type  = f->type;
-		memset(f, 0, sizeof(*f));
-		f->index = index;
-		f->type  = type;
-
-		switch (type) {
+		switch (f->type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 			if (ops->vidioc_enum_fmt_vid_cap)
 				ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
@@ -771,8 +750,6 @@
 	{
 		struct v4l2_format *f = (struct v4l2_format *)arg;
 
-		memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data));
-
 		/* FIXME: Should be one dump per type */
 		dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
 
@@ -1088,7 +1065,6 @@
 			return -EINVAL;
 
 		v4l2_video_std_construct(p, curr_id, descr);
-		p->index = index;
 
 		dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
 				"framelines=%d\n", p->index,
@@ -1153,12 +1129,9 @@
 	case VIDIOC_ENUMINPUT:
 	{
 		struct v4l2_input *p = arg;
-		int i = p->index;
 
 		if (!ops->vidioc_enum_input)
 			break;
-		memset(p, 0, sizeof(*p));
-		p->index = i;
 
 		ret = ops->vidioc_enum_input(file, fh, p);
 		if (!ret)
@@ -1197,12 +1170,9 @@
 	case VIDIOC_ENUMOUTPUT:
 	{
 		struct v4l2_output *p = arg;
-		int i = p->index;
 
 		if (!ops->vidioc_enum_output)
 			break;
-		memset(p, 0, sizeof(*p));
-		p->index = i;
 
 		ret = ops->vidioc_enum_output(file, fh, p);
 		if (!ret)
@@ -1378,13 +1348,10 @@
 	case VIDIOC_G_AUDIO:
 	{
 		struct v4l2_audio *p = arg;
-		__u32 index = p->index;
 
 		if (!ops->vidioc_g_audio)
 			break;
 
-		memset(p, 0, sizeof(*p));
-		p->index = index;
 		ret = ops->vidioc_g_audio(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
@@ -1426,7 +1393,7 @@
 
 		if (!ops->vidioc_g_audout)
 			break;
-		dbgarg(cmd, "Enum for index=%d\n", p->index);
+
 		ret = ops->vidioc_g_audout(file, fh, p);
 		if (!ret)
 			dbgarg2("index=%d, name=%s, capability=%d, "
@@ -1479,15 +1446,10 @@
 	case VIDIOC_G_CROP:
 	{
 		struct v4l2_crop *p = arg;
-		__u32 type;
 
 		if (!ops->vidioc_g_crop)
 			break;
 
-		type = p->type;
-		memset(p, 0, sizeof(*p));
-		p->type = type;
-
 		dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
 		ret = ops->vidioc_g_crop(file, fh, p);
 		if (!ret)
@@ -1508,16 +1470,11 @@
 	case VIDIOC_CROPCAP:
 	{
 		struct v4l2_cropcap *p = arg;
-		__u32 type;
 
 		/*FIXME: Should also show v4l2_fract pixelaspect */
 		if (!ops->vidioc_cropcap)
 			break;
 
-		type = p->type;
-		memset(p, 0, sizeof(*p));
-		p->type = type;
-
 		dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
 		ret = ops->vidioc_cropcap(file, fh, p);
 		if (!ret) {
@@ -1533,8 +1490,6 @@
 		if (!ops->vidioc_g_jpegcomp)
 			break;
 
-		memset(p, 0, sizeof(*p));
-
 		ret = ops->vidioc_g_jpegcomp(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "quality=%d, APPn=%d, "
@@ -1575,7 +1530,6 @@
 
 		if (!ops->vidioc_encoder_cmd)
 			break;
-		memset(&p->raw, 0, sizeof(p->raw));
 		ret = ops->vidioc_encoder_cmd(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1587,7 +1541,6 @@
 
 		if (!ops->vidioc_try_encoder_cmd)
 			break;
-		memset(&p->raw, 0, sizeof(p->raw));
 		ret = ops->vidioc_try_encoder_cmd(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1596,23 +1549,18 @@
 	case VIDIOC_G_PARM:
 	{
 		struct v4l2_streamparm *p = arg;
-		__u32 type = p->type;
-
-		memset(p, 0, sizeof(*p));
-		p->type = type;
 
 		if (ops->vidioc_g_parm) {
+			ret = check_fmt(ops, p->type);
+			if (ret)
+				break;
 			ret = ops->vidioc_g_parm(file, fh, p);
 		} else {
-			struct v4l2_standard s;
-
 			if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 				return -EINVAL;
 
-			v4l2_video_std_construct(&s, vfd->current_norm,
-						 v4l2_norm_to_name(vfd->current_norm));
-
-			p->parm.capture.timeperframe = s.frameperiod;
+			v4l2_video_std_frame_period(vfd->current_norm,
+						    &p->parm.capture.timeperframe);
 			ret = 0;
 		}
 
@@ -1625,6 +1573,10 @@
 
 		if (!ops->vidioc_s_parm)
 			break;
+		ret = check_fmt(ops, p->type);
+		if (ret)
+			break;
+
 		dbgarg(cmd, "type=%d\n", p->type);
 		ret = ops->vidioc_s_parm(file, fh, p);
 		break;
@@ -1632,14 +1584,10 @@
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *p = arg;
-		__u32 index = p->index;
 
 		if (!ops->vidioc_g_tuner)
 			break;
 
-		memset(p, 0, sizeof(*p));
-		p->index = index;
-
 		ret = ops->vidioc_g_tuner(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1676,8 +1624,6 @@
 		if (!ops->vidioc_g_frequency)
 			break;
 
-		memset(p->reserved, 0, sizeof(p->reserved));
-
 		ret = ops->vidioc_g_frequency(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
@@ -1698,12 +1644,13 @@
 	case VIDIOC_G_SLICED_VBI_CAP:
 	{
 		struct v4l2_sliced_vbi_cap *p = arg;
-		__u32 type = p->type;
 
 		if (!ops->vidioc_g_sliced_vbi_cap)
 			break;
-		memset(p, 0, sizeof(*p));
-		p->type = type;
+
+		/* Clear up to type, everything after type is zerod already */
+		memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
+
 		dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
 		ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
 		if (!ret)
@@ -1745,16 +1692,13 @@
 
 		if (!ops->vidioc_g_chip_ident)
 			break;
+		p->ident = V4L2_IDENT_NONE;
+		p->revision = 0;
 		ret = ops->vidioc_g_chip_ident(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
 		break;
 	}
-	case VIDIOC_G_CHIP_IDENT_OLD:
-		printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n");
-		printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n");
-		return -EINVAL;
-
 	case VIDIOC_S_HW_FREQ_SEEK:
 	{
 		struct v4l2_hw_freq_seek *p = arg;
@@ -1774,8 +1718,6 @@
 		if (!ops->vidioc_enum_framesizes)
 			break;
 
-		memset(p, 0, sizeof(*p));
-
 		ret = ops->vidioc_enum_framesizes(file, fh, p);
 		dbgarg(cmd,
 			"index=%d, pixelformat=%d, type=%d ",
@@ -1807,8 +1749,6 @@
 		if (!ops->vidioc_enum_frameintervals)
 			break;
 
-		memset(p, 0, sizeof(*p));
-
 		ret = ops->vidioc_enum_frameintervals(file, fh, p);
 		dbgarg(cmd,
 			"index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
@@ -1857,6 +1797,45 @@
 	return ret;
 }
 
+/* In some cases, only a few fields are used as input, i.e. when the app sets
+ * "index" and then the driver fills in the rest of the structure for the thing
+ * with that index.  We only need to copy up the first non-input field.  */
+static unsigned long cmd_input_size(unsigned int cmd)
+{
+	/* Size of structure up to and including 'field' */
+#define CMDINSIZE(cmd, type, field) 				\
+	case VIDIOC_##cmd: 					\
+		return offsetof(struct v4l2_##type, field) + 	\
+			sizeof(((struct v4l2_##type *)0)->field);
+
+	switch (cmd) {
+		CMDINSIZE(ENUM_FMT,		fmtdesc,	type);
+		CMDINSIZE(G_FMT,		format,		type);
+		CMDINSIZE(QUERYBUF,		buffer,		type);
+		CMDINSIZE(G_PARM,		streamparm,	type);
+		CMDINSIZE(ENUMSTD,		standard,	index);
+		CMDINSIZE(ENUMINPUT,		input,		index);
+		CMDINSIZE(G_CTRL,		control,	id);
+		CMDINSIZE(G_TUNER,		tuner,		index);
+		CMDINSIZE(QUERYCTRL,		queryctrl,	id);
+		CMDINSIZE(QUERYMENU,		querymenu,	index);
+		CMDINSIZE(ENUMOUTPUT,		output,		index);
+		CMDINSIZE(G_MODULATOR,		modulator,	index);
+		CMDINSIZE(G_FREQUENCY,		frequency,	tuner);
+		CMDINSIZE(CROPCAP,		cropcap,	type);
+		CMDINSIZE(G_CROP,		crop,		type);
+		CMDINSIZE(ENUMAUDIO,		audio, 		index);
+		CMDINSIZE(ENUMAUDOUT,		audioout, 	index);
+		CMDINSIZE(ENCODER_CMD,		encoder_cmd,	flags);
+		CMDINSIZE(TRY_ENCODER_CMD,	encoder_cmd,	flags);
+		CMDINSIZE(G_SLICED_VBI_CAP,	sliced_vbi_cap,	type);
+		CMDINSIZE(ENUM_FRAMESIZES,	frmsizeenum,	pixel_format);
+		CMDINSIZE(ENUM_FRAMEINTERVALS,	frmivalenum,	height);
+	default:
+		return _IOC_SIZE(cmd);
+	}
+}
+
 long video_ioctl2(struct file *file,
 	       unsigned int cmd, unsigned long arg)
 {
@@ -1875,13 +1854,7 @@
 		       cmd == VIDIOC_TRY_EXT_CTRLS);
 
 	/*  Copy arguments into temp kernel buffer  */
-	switch (_IOC_DIR(cmd)) {
-	case _IOC_NONE:
-		parg = NULL;
-		break;
-	case _IOC_READ:
-	case _IOC_WRITE:
-	case (_IOC_WRITE | _IOC_READ):
+	if (_IOC_DIR(cmd) != _IOC_NONE) {
 		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
 			parg = sbuf;
 		} else {
@@ -1893,10 +1866,19 @@
 		}
 
 		err = -EFAULT;
-		if (_IOC_DIR(cmd) & _IOC_WRITE)
-			if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+		if (_IOC_DIR(cmd) & _IOC_WRITE) {
+			unsigned long n = cmd_input_size(cmd);
+
+			if (copy_from_user(parg, (void __user *)arg, n))
 				goto out;
-		break;
+
+			/* zero out anything we don't copy from userspace */
+			if (n < _IOC_SIZE(cmd))
+				memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
+		} else {
+			/* read-only ioctl */
+			memset(parg, 0, _IOC_SIZE(cmd));
+		}
 	}
 
 	if (is_ext_ctrl) {
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 2120880..dc88167 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -33,6 +33,12 @@
 		return v4l2_subdev_call(sd, core, g_ctrl, arg);
 	case VIDIOC_S_CTRL:
 		return v4l2_subdev_call(sd, core, s_ctrl, arg);
+	case VIDIOC_G_EXT_CTRLS:
+		return v4l2_subdev_call(sd, core, g_ext_ctrls, arg);
+	case VIDIOC_S_EXT_CTRLS:
+		return v4l2_subdev_call(sd, core, s_ext_ctrls, arg);
+	case VIDIOC_TRY_EXT_CTRLS:
+		return v4l2_subdev_call(sd, core, try_ext_ctrls, arg);
 	case VIDIOC_QUERYMENU:
 		return v4l2_subdev_call(sd, core, querymenu, arg);
 	case VIDIOC_LOG_STATUS:
@@ -92,16 +98,28 @@
 		return v4l2_subdev_call(sd, video, g_vbi_data, arg);
 	case VIDIOC_G_SLICED_VBI_CAP:
 		return v4l2_subdev_call(sd, video, g_sliced_vbi_cap, arg);
+	case VIDIOC_ENUM_FMT:
+		return v4l2_subdev_call(sd, video, enum_fmt, arg);
+	case VIDIOC_TRY_FMT:
+		return v4l2_subdev_call(sd, video, try_fmt, arg);
 	case VIDIOC_S_FMT:
 		return v4l2_subdev_call(sd, video, s_fmt, arg);
 	case VIDIOC_G_FMT:
 		return v4l2_subdev_call(sd, video, g_fmt, arg);
 	case VIDIOC_INT_S_STD_OUTPUT:
 		return v4l2_subdev_call(sd, video, s_std_output, *(v4l2_std_id *)arg);
+	case VIDIOC_QUERYSTD:
+		return v4l2_subdev_call(sd, video, querystd, arg);
+	case VIDIOC_INT_G_INPUT_STATUS:
+		return v4l2_subdev_call(sd, video, g_input_status, arg);
 	case VIDIOC_STREAMON:
 		return v4l2_subdev_call(sd, video, s_stream, 1);
 	case VIDIOC_STREAMOFF:
 		return v4l2_subdev_call(sd, video, s_stream, 0);
+	case VIDIOC_S_PARM:
+		return v4l2_subdev_call(sd, video, s_parm, arg);
+	case VIDIOC_G_PARM:
+		return v4l2_subdev_call(sd, video, g_parm, arg);
 
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index 31944b1..6109fb5 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -400,7 +400,7 @@
 	   So, it should free memory only if the memory were allocated for
 	   read() operation.
 	 */
-	if ((buf->memory != V4L2_MEMORY_USERPTR) || !buf->baddr)
+	if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
 		return;
 
 	if (!mem)
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
index be65a2f..30ae30f 100644
--- a/drivers/media/video/videobuf-vmalloc.c
+++ b/drivers/media/video/videobuf-vmalloc.c
@@ -425,7 +425,7 @@
 	   So, it should free memory only if the memory were allocated for
 	   read() operation.
 	 */
-	if ((buf->memory != V4L2_MEMORY_USERPTR) || (buf->baddr == 0))
+	if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
 		return;
 
 	if (!mem)
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 88bf845..8da4dd1 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -8,6 +8,12 @@
  *
  * Based on the previous version of the driver for 2.4 kernels by:
  * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this conversion is untested! Please contact the linux-media
+ * mailinglist if you can test this, together with the test results.
  */
 
 /*
@@ -33,12 +39,10 @@
 #include <linux/kmod.h>
 
 #include <linux/i2c.h>
-#include <linux/i2c-algo-sgi.h>
 
 #include <linux/videodev2.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/video_decoder.h>
 #include <linux/mutex.h>
 
 #include <asm/paccess.h>
@@ -139,13 +143,23 @@
 #define VINO_DATA_NORM_PAL		1
 #define VINO_DATA_NORM_SECAM		2
 #define VINO_DATA_NORM_D1		3
-/* The following are special entries that can be used to
- * autodetect the norm. */
-#define VINO_DATA_NORM_AUTO		0xfe
-#define VINO_DATA_NORM_AUTO_EXT		0xff
 
 #define VINO_DATA_NORM_COUNT		4
 
+/* I2C controller flags */
+#define SGI_I2C_FORCE_IDLE		(0 << 0)
+#define SGI_I2C_NOT_IDLE		(1 << 0)
+#define SGI_I2C_WRITE			(0 << 1)
+#define SGI_I2C_READ			(1 << 1)
+#define SGI_I2C_RELEASE_BUS		(0 << 2)
+#define SGI_I2C_HOLD_BUS		(1 << 2)
+#define SGI_I2C_XFER_DONE		(0 << 4)
+#define SGI_I2C_XFER_BUSY		(1 << 4)
+#define SGI_I2C_ACK			(0 << 5)
+#define SGI_I2C_NACK			(1 << 5)
+#define SGI_I2C_BUS_OK			(0 << 7)
+#define SGI_I2C_BUS_ERR			(1 << 7)
+
 /* Internal data structure definitions */
 
 struct vino_input {
@@ -289,22 +303,20 @@
 	struct vino_interrupt_data int_data;
 
 	/* V4L support */
-	struct video_device *v4l_device;
-};
-
-struct vino_client {
-	/* the channel which owns this client:
-	 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
-	unsigned int owner;
-	struct i2c_client *driver;
+	struct video_device *vdev;
 };
 
 struct vino_settings {
+	struct v4l2_device v4l2_dev;
 	struct vino_channel_settings a;
 	struct vino_channel_settings b;
 
-	struct vino_client decoder;
-	struct vino_client camera;
+	/* the channel which owns this client:
+	 * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+	unsigned int decoder_owner;
+	struct v4l2_subdev *decoder;
+	unsigned int camera_owner;
+	struct v4l2_subdev *camera;
 
 	/* a lock for vino register access */
 	spinlock_t vino_lock;
@@ -344,11 +356,16 @@
 
 static struct vino_settings *vino_drvdata;
 
+#define camera_call(o, f, args...) \
+	v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
+#define decoder_call(o, f, args...) \
+	v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
+
 static const char *vino_driver_name = "vino";
 static const char *vino_driver_description = "SGI VINO";
 static const char *vino_bus_name = "GIO64 bus";
-static const char *vino_v4l_device_name_a = "SGI VINO Channel A";
-static const char *vino_v4l_device_name_b = "SGI VINO Channel B";
+static const char *vino_vdev_name_a = "SGI VINO Channel A";
+static const char *vino_vdev_name_b = "SGI VINO Channel B";
 
 static void vino_capture_tasklet(unsigned long channel);
 
@@ -360,11 +377,11 @@
 		.name		= "Composite",
 		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
 		| V4L2_STD_SECAM,
-	},{
+	}, {
 		.name		= "S-Video",
 		.std		= V4L2_STD_NTSC | V4L2_STD_PAL
 		| V4L2_STD_SECAM,
-	},{
+	}, {
 		.name		= "D1/IndyCam",
 		.std		= V4L2_STD_NTSC,
 	}
@@ -376,17 +393,17 @@
 		.bpp		= 1,
 		.pixelformat	= V4L2_PIX_FMT_GREY,
 		.colorspace	= V4L2_COLORSPACE_SMPTE170M,
-	},{
+	}, {
 		.description	= "8-bit dithered RGB 3-3-2",
 		.bpp		= 1,
 		.pixelformat	= V4L2_PIX_FMT_RGB332,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
-	},{
+	}, {
 		.description	= "32-bit RGB",
 		.bpp		= 4,
 		.pixelformat	= V4L2_PIX_FMT_RGB32,
 		.colorspace	= V4L2_COLORSPACE_SRGB,
-	},{
+	}, {
 		.description	= "YUV 4:2:2",
 		.bpp		= 2,
 		.pixelformat	= V4L2_PIX_FMT_YUYV, // XXX: swapped?
@@ -417,7 +434,7 @@
 			+ VINO_NTSC_HEIGHT / 2 - 1,
 			.right	= VINO_NTSC_WIDTH,
 		},
-	},{
+	}, {
 		.description	= "PAL",
 		.std		= V4L2_STD_PAL,
 		.fps_min	= 5,
@@ -439,7 +456,7 @@
 			+ VINO_PAL_HEIGHT / 2 - 1,
 			.right	= VINO_PAL_WIDTH,
 		},
-	},{
+	}, {
 		.description	= "SECAM",
 		.std		= V4L2_STD_SECAM,
 		.fps_min	= 5,
@@ -461,7 +478,7 @@
 			+ VINO_PAL_HEIGHT / 2 - 1,
 			.right	= VINO_PAL_WIDTH,
 		},
-	},{
+	}, {
 		.description	= "NTSC/D1",
 		.std		= V4L2_STD_NTSC,
 		.fps_min	= 6,
@@ -497,9 +514,7 @@
 		.maximum = 1,
 		.step = 1,
 		.default_value = INDYCAM_AGC_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_AGC, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_AUTO_WHITE_BALANCE,
 		.type = V4L2_CTRL_TYPE_BOOLEAN,
 		.name = "Automatic White Balance",
@@ -507,9 +522,7 @@
 		.maximum = 1,
 		.step = 1,
 		.default_value = INDYCAM_AWB_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_AWB, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_GAIN,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Gain",
@@ -517,29 +530,23 @@
 		.maximum = INDYCAM_GAIN_MAX,
 		.step = 1,
 		.default_value = INDYCAM_GAIN_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_GAIN, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE,
+	}, {
+		.id = INDYCAM_CONTROL_RED_SATURATION,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Red Saturation",
 		.minimum = INDYCAM_RED_SATURATION_MIN,
 		.maximum = INDYCAM_RED_SATURATION_MAX,
 		.step = 1,
 		.default_value = INDYCAM_RED_SATURATION_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_RED_SATURATION, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 1,
+	}, {
+		.id = INDYCAM_CONTROL_BLUE_SATURATION,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Blue Saturation",
 		.minimum = INDYCAM_BLUE_SATURATION_MIN,
 		.maximum = INDYCAM_BLUE_SATURATION_MAX,
 		.step = 1,
 		.default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_BLUE_SATURATION, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_RED_BALANCE,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Red Balance",
@@ -547,9 +554,7 @@
 		.maximum = INDYCAM_RED_BALANCE_MAX,
 		.step = 1,
 		.default_value = INDYCAM_RED_BALANCE_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_RED_BALANCE, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_BLUE_BALANCE,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Blue Balance",
@@ -557,9 +562,7 @@
 		.maximum = INDYCAM_BLUE_BALANCE_MAX,
 		.step = 1,
 		.default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_BLUE_BALANCE, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_EXPOSURE,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Shutter Control",
@@ -567,9 +570,7 @@
 		.maximum = INDYCAM_SHUTTER_MAX,
 		.step = 1,
 		.default_value = INDYCAM_SHUTTER_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_SHUTTER, 0 },
-	},{
+	}, {
 		.id = V4L2_CID_GAMMA,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Gamma",
@@ -577,8 +578,6 @@
 		.maximum = INDYCAM_GAMMA_MAX,
 		.step = 1,
 		.default_value = INDYCAM_GAMMA_DEFAULT,
-		.flags = 0,
-		.reserved = { INDYCAM_CONTROL_GAMMA, 0 },
 	}
 };
 
@@ -593,209 +592,73 @@
 		.maximum = SAA7191_HUE_MAX,
 		.step = 1,
 		.default_value = SAA7191_HUE_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_HUE, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE,
+	}, {
+		.id = SAA7191_CONTROL_BANDPASS,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Luminance Bandpass",
 		.minimum = SAA7191_BANDPASS_MIN,
 		.maximum = SAA7191_BANDPASS_MAX,
 		.step = 1,
 		.default_value = SAA7191_BANDPASS_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_BANDPASS, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 1,
+	}, {
+		.id = SAA7191_CONTROL_BANDPASS_WEIGHT,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Luminance Bandpass Weight",
 		.minimum = SAA7191_BANDPASS_WEIGHT_MIN,
 		.maximum = SAA7191_BANDPASS_WEIGHT_MAX,
 		.step = 1,
 		.default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_BANDPASS_WEIGHT, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 2,
+	}, {
+		.id = SAA7191_CONTROL_CORING,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "HF Luminance Coring",
 		.minimum = SAA7191_CORING_MIN,
 		.maximum = SAA7191_CORING_MAX,
 		.step = 1,
 		.default_value = SAA7191_CORING_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_CORING, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 3,
+	}, {
+		.id = SAA7191_CONTROL_FORCE_COLOUR,
 		.type = V4L2_CTRL_TYPE_BOOLEAN,
 		.name = "Force Colour",
 		.minimum = SAA7191_FORCE_COLOUR_MIN,
 		.maximum = SAA7191_FORCE_COLOUR_MAX,
 		.step = 1,
 		.default_value = SAA7191_FORCE_COLOUR_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_FORCE_COLOUR, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 4,
+	}, {
+		.id = SAA7191_CONTROL_CHROMA_GAIN,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Chrominance Gain Control",
 		.minimum = SAA7191_CHROMA_GAIN_MIN,
 		.maximum = SAA7191_CHROMA_GAIN_MAX,
 		.step = 1,
 		.default_value = SAA7191_CHROMA_GAIN_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_CHROMA_GAIN, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 5,
+	}, {
+		.id = SAA7191_CONTROL_VTRC,
 		.type = V4L2_CTRL_TYPE_BOOLEAN,
 		.name = "VTR Time Constant",
 		.minimum = SAA7191_VTRC_MIN,
 		.maximum = SAA7191_VTRC_MAX,
 		.step = 1,
 		.default_value = SAA7191_VTRC_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_VTRC, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 6,
+	}, {
+		.id = SAA7191_CONTROL_LUMA_DELAY,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Luminance Delay Compensation",
 		.minimum = SAA7191_LUMA_DELAY_MIN,
 		.maximum = SAA7191_LUMA_DELAY_MAX,
 		.step = 1,
 		.default_value = SAA7191_LUMA_DELAY_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_LUMA_DELAY, 0 },
-	},{
-		.id = V4L2_CID_PRIVATE_BASE + 7,
+	}, {
+		.id = SAA7191_CONTROL_VNR,
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.name = "Vertical Noise Reduction",
 		.minimum = SAA7191_VNR_MIN,
 		.maximum = SAA7191_VNR_MAX,
 		.step = 1,
 		.default_value = SAA7191_VNR_DEFAULT,
-		.flags = 0,
-		.reserved = { SAA7191_CONTROL_VNR, 0 },
 	}
 };
 
-/* VINO I2C bus functions */
-
-unsigned i2c_vino_getctrl(void *data)
-{
-	return vino->i2c_control;
-}
-
-void i2c_vino_setctrl(void *data, unsigned val)
-{
-	vino->i2c_control = val;
-}
-
-unsigned i2c_vino_rdata(void *data)
-{
-	return vino->i2c_data;
-}
-
-void i2c_vino_wdata(void *data, unsigned val)
-{
-	vino->i2c_data = val;
-}
-
-static struct i2c_algo_sgi_data i2c_sgi_vino_data =
-{
-	.getctrl = &i2c_vino_getctrl,
-	.setctrl = &i2c_vino_setctrl,
-	.rdata   = &i2c_vino_rdata,
-	.wdata   = &i2c_vino_wdata,
-	.xfer_timeout = 200,
-	.ack_timeout  = 1000,
-};
-
-/*
- * There are two possible clients on VINO I2C bus, so we limit usage only
- * to them.
- */
-static int i2c_vino_client_reg(struct i2c_client *client)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	switch (client->driver->id) {
-	case I2C_DRIVERID_SAA7191:
-		if (vino_drvdata->decoder.driver)
-			ret = -EBUSY;
-		else
-			vino_drvdata->decoder.driver = client;
-		break;
-	case I2C_DRIVERID_INDYCAM:
-		if (vino_drvdata->camera.driver)
-			ret = -EBUSY;
-		else
-			vino_drvdata->camera.driver = client;
-		break;
-	default:
-		ret = -ENODEV;
-	}
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return ret;
-}
-
-static int i2c_vino_client_unreg(struct i2c_client *client)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	if (client == vino_drvdata->decoder.driver) {
-		if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL)
-			ret = -EBUSY;
-		else
-			vino_drvdata->decoder.driver = NULL;
-	} else if (client == vino_drvdata->camera.driver) {
-		if (vino_drvdata->camera.owner != VINO_NO_CHANNEL)
-			ret = -EBUSY;
-		else
-			vino_drvdata->camera.driver = NULL;
-	}
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return ret;
-}
-
-static struct i2c_adapter vino_i2c_adapter =
-{
-	.name			= "VINO I2C bus",
-	.id			= I2C_HW_SGI_VINO,
-	.algo_data		= &i2c_sgi_vino_data,
-	.client_register	= &i2c_vino_client_reg,
-	.client_unregister	= &i2c_vino_client_unreg,
-};
-
-static int vino_i2c_add_bus(void)
-{
-	return i2c_sgi_add_bus(&vino_i2c_adapter);
-}
-
-static int vino_i2c_del_bus(void)
-{
-	return i2c_del_adapter(&vino_i2c_adapter);
-}
-
-static int i2c_camera_command(unsigned int cmd, void *arg)
-{
-	return vino_drvdata->camera.driver->
-		driver->command(vino_drvdata->camera.driver,
-				cmd, arg);
-}
-
-static int i2c_decoder_command(unsigned int cmd, void *arg)
-{
-	return vino_drvdata->decoder.driver->
-		driver->command(vino_drvdata->decoder.driver,
-				cmd, arg);
-}
-
 /* VINO framebuffer/DMA descriptor management */
 
 static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
@@ -1741,6 +1604,184 @@
 	vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
 }
 
+/* VINO I2C bus functions */
+
+struct i2c_algo_sgi_data {
+	void *data;	/* private data for lowlevel routines */
+	unsigned (*getctrl)(void *data);
+	void (*setctrl)(void *data, unsigned val);
+	unsigned (*rdata)(void *data);
+	void (*wdata)(void *data, unsigned val);
+
+	int xfer_timeout;
+	int ack_timeout;
+};
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	for (i = 0; i < adap->xfer_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	if (wait_xfer_done(adap))
+		return -ETIMEDOUT;
+	for (i = 0; i < adap->ack_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+	int i;
+
+	adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
+	for (i = 0; i < adap->xfer_timeout; i++) {
+		if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
+			goto out;
+		udelay(1);
+	}
+	return -ETIMEDOUT;
+out:
+	if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
+		return -EIO;
+	return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+		      int rd)
+{
+	if (rd)
+		adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
+	/* Check if bus is idle, eventually force it to do so */
+	if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
+		if (force_idle(adap))
+			return -EIO;
+	/* Write out the i2c chip address and specify operation */
+	adap->setctrl(adap->data,
+		      SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+	if (rd)
+		addr |= 1;
+	adap->wdata(adap->data, addr);
+	if (wait_ack(adap))
+		return -EIO;
+	return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+		    unsigned int len)
+{
+	int i;
+
+	adap->setctrl(adap->data,
+		      SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+	for (i = 0; i < len; i++) {
+		if (wait_xfer_done(adap))
+			return -EIO;
+		buf[i] = adap->rdata(adap->data);
+	}
+	adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+	return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+		     unsigned int len)
+{
+	int i;
+
+	/* We are already in write state */
+	for (i = 0; i < len; i++) {
+		adap->wdata(adap->data, buf[i]);
+		if (wait_ack(adap))
+			return -EIO;
+	}
+	return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+		    int num)
+{
+	struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+	struct i2c_msg *p;
+	int i, err = 0;
+
+	for (i = 0; !err && i < num; i++) {
+		p = &msgs[i];
+		err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+		if (err || !p->len)
+			continue;
+		if (p->flags & I2C_M_RD)
+			err = i2c_read(adap, p->buf, p->len);
+		else
+			err = i2c_write(adap, p->buf, p->len);
+	}
+
+	return (err < 0) ? err : i;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm sgi_algo = {
+	.master_xfer	= sgi_xfer,
+	.functionality	= sgi_func,
+};
+
+static unsigned i2c_vino_getctrl(void *data)
+{
+	return vino->i2c_control;
+}
+
+static void i2c_vino_setctrl(void *data, unsigned val)
+{
+	vino->i2c_control = val;
+}
+
+static unsigned i2c_vino_rdata(void *data)
+{
+	return vino->i2c_data;
+}
+
+static void i2c_vino_wdata(void *data, unsigned val)
+{
+	vino->i2c_data = val;
+}
+
+static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
+	.getctrl = &i2c_vino_getctrl,
+	.setctrl = &i2c_vino_setctrl,
+	.rdata   = &i2c_vino_rdata,
+	.wdata   = &i2c_vino_wdata,
+	.xfer_timeout = 200,
+	.ack_timeout  = 1000,
+};
+
+static struct i2c_adapter vino_i2c_adapter = {
+	.name			= "VINO I2C bus",
+	.id			= I2C_HW_SGI_VINO,
+	.algo			= &sgi_algo,
+	.algo_data		= &i2c_sgi_vino_data,
+	.owner 			= THIS_MODULE,
+};
+
 /*
  * Prepare VINO for DMA transfer...
  * (execute only with vino_lock and input_lock locked)
@@ -2490,86 +2531,15 @@
 	}
 }
 
-static int vino_get_saa7191_norm(unsigned int data_norm)
-{
-	switch (data_norm) {
-	case VINO_DATA_NORM_AUTO:
-		return SAA7191_NORM_AUTO;
-	case VINO_DATA_NORM_AUTO_EXT:
-		return SAA7191_NORM_AUTO_EXT;
-	case VINO_DATA_NORM_PAL:
-		return SAA7191_NORM_PAL;
-	case VINO_DATA_NORM_NTSC:
-		return SAA7191_NORM_NTSC;
-	case VINO_DATA_NORM_SECAM:
-		return SAA7191_NORM_SECAM;
-	default:
-		printk(KERN_ERR "VINO: vino_get_saa7191_norm(): "
-		       "invalid norm!\n");
-		return -1;
-	}
-}
-
-static int vino_get_from_saa7191_norm(int saa7191_norm)
-{
-	switch (saa7191_norm) {
-	case SAA7191_NORM_PAL:
-		return VINO_DATA_NORM_PAL;
-	case SAA7191_NORM_NTSC:
-		return VINO_DATA_NORM_NTSC;
-	case SAA7191_NORM_SECAM:
-		return VINO_DATA_NORM_SECAM;
-	default:
-		printk(KERN_ERR "VINO: vino_get_from_saa7191_norm(): "
-		       "invalid norm!\n");
-		return VINO_DATA_NORM_NONE;
-	}
-}
-
-static int vino_saa7191_set_norm(unsigned int *data_norm)
-{
-	int saa7191_norm, new_data_norm;
-	int err = 0;
-
-	saa7191_norm = vino_get_saa7191_norm(*data_norm);
-
-	err = i2c_decoder_command(DECODER_SAA7191_SET_NORM,
-				  &saa7191_norm);
-	if (err)
-		goto out;
-
-	if ((*data_norm == VINO_DATA_NORM_AUTO)
-	    || (*data_norm == VINO_DATA_NORM_AUTO_EXT)) {
-		struct saa7191_status status;
-
-		err = i2c_decoder_command(DECODER_SAA7191_GET_STATUS,
-					  &status);
-		if (err)
-			goto out;
-
-		new_data_norm =
-			vino_get_from_saa7191_norm(status.norm);
-		if (new_data_norm == VINO_DATA_NORM_NONE) {
-			err = -EINVAL;
-			goto out;
-		}
-
-		*data_norm = (unsigned int)new_data_norm;
-	}
-
-out:
-	return err;
-}
-
 /* execute with input_lock locked */
 static int vino_is_input_owner(struct vino_channel_settings *vcs)
 {
 	switch(vcs->input) {
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO:
-		return (vino_drvdata->decoder.owner == vcs->channel);
+		return vino_drvdata->decoder_owner == vcs->channel;
 	case VINO_INPUT_D1:
-		return (vino_drvdata->camera.owner == vcs->channel);
+		return vino_drvdata->camera_owner == vcs->channel;
 	default:
 		return 0;
 	}
@@ -2585,23 +2555,22 @@
 	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
 
 	/* First try D1 and then SAA7191 */
-	if (vino_drvdata->camera.driver
-	    && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) {
-		i2c_use_client(vino_drvdata->camera.driver);
-		vino_drvdata->camera.owner = vcs->channel;
+	if (vino_drvdata->camera
+	    && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
+		vino_drvdata->camera_owner = vcs->channel;
 		vcs->input = VINO_INPUT_D1;
 		vcs->data_norm = VINO_DATA_NORM_D1;
-	} else if (vino_drvdata->decoder.driver
-		   && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) {
-		int input, data_norm;
-		int saa7191_input;
+	} else if (vino_drvdata->decoder
+		   && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
+		int input;
+		int data_norm;
+		v4l2_std_id norm;
+		struct v4l2_routing route = { 0, 0 };
 
-		i2c_use_client(vino_drvdata->decoder.driver);
 		input = VINO_INPUT_COMPOSITE;
 
-		saa7191_input = vino_get_saa7191_input(input);
-		ret = i2c_decoder_command(DECODER_SET_INPUT,
-					  &saa7191_input);
+		route.input = vino_get_saa7191_input(input);
+		ret = decoder_call(video, s_routing, &route);
 		if (ret) {
 			ret = -EINVAL;
 			goto out;
@@ -2612,12 +2581,15 @@
 		/* Don't hold spinlocks while auto-detecting norm
 		 * as it may take a while... */
 
-		data_norm = VINO_DATA_NORM_AUTO_EXT;
-
-		ret = vino_saa7191_set_norm(&data_norm);
-		if ((ret == -EBUSY) || (ret == -EAGAIN)) {
-			data_norm = VINO_DATA_NORM_PAL;
-			ret = vino_saa7191_set_norm(&data_norm);
+		ret = decoder_call(video, querystd, &norm);
+		if (!ret) {
+			for (data_norm = 0; data_norm < 3; data_norm++) {
+				if (vino_data_norms[data_norm].std & norm)
+					break;
+			}
+			if (data_norm == 3)
+				data_norm = VINO_DATA_NORM_PAL;
+			ret = decoder_call(tuner, s_std, norm);
 		}
 
 		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
@@ -2627,7 +2599,7 @@
 			goto out;
 		}
 
-		vino_drvdata->decoder.owner = vcs->channel;
+		vino_drvdata->decoder_owner = vcs->channel;
 
 		vcs->input = input;
 		vcs->data_norm = data_norm;
@@ -2672,25 +2644,24 @@
 	switch (input) {
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO:
-		if (!vino_drvdata->decoder.driver) {
+		if (!vino_drvdata->decoder) {
 			ret = -EINVAL;
 			goto out;
 		}
 
-		if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) {
-			i2c_use_client(vino_drvdata->decoder.driver);
-			vino_drvdata->decoder.owner = vcs->channel;
+		if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
+			vino_drvdata->decoder_owner = vcs->channel;
 		}
 
-		if (vino_drvdata->decoder.owner == vcs->channel) {
+		if (vino_drvdata->decoder_owner == vcs->channel) {
 			int data_norm;
-			int saa7191_input;
+			v4l2_std_id norm;
+			struct v4l2_routing route = { 0, 0 };
 
-			saa7191_input = vino_get_saa7191_input(input);
-			ret = i2c_decoder_command(DECODER_SET_INPUT,
-						  &saa7191_input);
+			route.input = vino_get_saa7191_input(input);
+			ret = decoder_call(video, s_routing, &route);
 			if (ret) {
-				vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
 				ret = -EINVAL;
 				goto out;
 			}
@@ -2700,18 +2671,21 @@
 			/* Don't hold spinlocks while auto-detecting norm
 			 * as it may take a while... */
 
-			data_norm = VINO_DATA_NORM_AUTO_EXT;
-
-			ret = vino_saa7191_set_norm(&data_norm);
-			if ((ret  == -EBUSY) || (ret == -EAGAIN)) {
-				data_norm = VINO_DATA_NORM_PAL;
-				ret = vino_saa7191_set_norm(&data_norm);
+			ret = decoder_call(video, querystd, &norm);
+			if (!ret) {
+				for (data_norm = 0; data_norm < 3; data_norm++) {
+					if (vino_data_norms[data_norm].std & norm)
+						break;
+				}
+				if (data_norm == 3)
+					data_norm = VINO_DATA_NORM_PAL;
+				ret = decoder_call(tuner, s_std, norm);
 			}
 
 			spin_lock_irqsave(&vino_drvdata->input_lock, flags);
 
 			if (ret) {
-				vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
 				ret = -EINVAL;
 				goto out;
 			}
@@ -2728,37 +2702,31 @@
 			vcs->data_norm = vcs2->data_norm;
 		}
 
-		if (vino_drvdata->camera.owner == vcs->channel) {
+		if (vino_drvdata->camera_owner == vcs->channel) {
 			/* Transfer the ownership or release the input */
 			if (vcs2->input == VINO_INPUT_D1) {
-				vino_drvdata->camera.owner = vcs2->channel;
+				vino_drvdata->camera_owner = vcs2->channel;
 			} else {
-				i2c_release_client(vino_drvdata->
-						   camera.driver);
-				vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+				vino_drvdata->camera_owner = VINO_NO_CHANNEL;
 			}
 		}
 		break;
 	case VINO_INPUT_D1:
-		if (!vino_drvdata->camera.driver) {
+		if (!vino_drvdata->camera) {
 			ret = -EINVAL;
 			goto out;
 		}
 
-		if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) {
-			i2c_use_client(vino_drvdata->camera.driver);
-			vino_drvdata->camera.owner = vcs->channel;
-		}
+		if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
+			vino_drvdata->camera_owner = vcs->channel;
 
-		if (vino_drvdata->decoder.owner == vcs->channel) {
+		if (vino_drvdata->decoder_owner == vcs->channel) {
 			/* Transfer the ownership or release the input */
 			if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
 				 (vcs2->input == VINO_INPUT_SVIDEO)) {
-				vino_drvdata->decoder.owner = vcs2->channel;
+				vino_drvdata->decoder_owner = vcs2->channel;
 			} else {
-				i2c_release_client(vino_drvdata->
-						   decoder.driver);
-				vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+				vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
 			}
 		}
 
@@ -2795,20 +2763,18 @@
 	/* Release ownership of the channel
 	 * and if the other channel takes input from
 	 * the same source, transfer the ownership */
-	if (vino_drvdata->camera.owner == vcs->channel) {
+	if (vino_drvdata->camera_owner == vcs->channel) {
 		if (vcs2->input == VINO_INPUT_D1) {
-			vino_drvdata->camera.owner = vcs2->channel;
+			vino_drvdata->camera_owner = vcs2->channel;
 		} else {
-			i2c_release_client(vino_drvdata->camera.driver);
-			vino_drvdata->camera.owner = VINO_NO_CHANNEL;
+			vino_drvdata->camera_owner = VINO_NO_CHANNEL;
 		}
-	} else if (vino_drvdata->decoder.owner == vcs->channel) {
+	} else if (vino_drvdata->decoder_owner == vcs->channel) {
 		if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
 			 (vcs2->input == VINO_INPUT_SVIDEO)) {
-			vino_drvdata->decoder.owner = vcs2->channel;
+			vino_drvdata->decoder_owner = vcs2->channel;
 		} else {
-			i2c_release_client(vino_drvdata->decoder.driver);
-			vino_drvdata->decoder.owner = VINO_NO_CHANNEL;
+			vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
 		}
 	}
 	vcs->input = VINO_INPUT_NONE;
@@ -2829,18 +2795,16 @@
 	switch (vcs->input) {
 	case VINO_INPUT_D1:
 		/* only one "norm" supported */
-		if ((data_norm != VINO_DATA_NORM_D1)
-		    && (data_norm != VINO_DATA_NORM_AUTO)
-		    && (data_norm != VINO_DATA_NORM_AUTO_EXT))
+		if (data_norm != VINO_DATA_NORM_D1)
 			return -EINVAL;
 		break;
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO: {
+		v4l2_std_id norm;
+
 		if ((data_norm != VINO_DATA_NORM_PAL)
 		    && (data_norm != VINO_DATA_NORM_NTSC)
-		    && (data_norm != VINO_DATA_NORM_SECAM)
-		    && (data_norm != VINO_DATA_NORM_AUTO)
-		    && (data_norm != VINO_DATA_NORM_AUTO_EXT))
+		    && (data_norm != VINO_DATA_NORM_SECAM))
 			return -EINVAL;
 
 		spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
@@ -2848,7 +2812,8 @@
 		/* Don't hold spinlocks while setting norm
 		 * as it may take a while... */
 
-		err = vino_saa7191_set_norm(&data_norm);
+		norm = vino_data_norms[data_norm].std;
+		err = decoder_call(tuner, s_std, norm);
 
 		spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
 
@@ -2884,41 +2849,13 @@
 	return VINO_DATA_FMT_NONE;
 }
 
-static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index)
-{
-	int data_norm = VINO_DATA_NORM_NONE;
-	unsigned long flags;
-
-	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	switch(vcs->input) {
-	case VINO_INPUT_COMPOSITE:
-	case VINO_INPUT_SVIDEO:
-		if (index == 0) {
-			data_norm = VINO_DATA_NORM_PAL;
-		} else if (index == 1) {
-			data_norm = VINO_DATA_NORM_NTSC;
-		} else if (index == 2) {
-			data_norm = VINO_DATA_NORM_SECAM;
-		}
-		break;
-	case VINO_INPUT_D1:
-		if (index == 0) {
-			data_norm = VINO_DATA_NORM_D1;
-		}
-		break;
-	}
-	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-	return data_norm;
-}
-
-static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index)
+static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
 {
 	int input = VINO_INPUT_NONE;
 	unsigned long flags;
 
 	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-	if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+	if (vino_drvdata->decoder && vino_drvdata->camera) {
 		switch (index) {
 		case 0:
 			input = VINO_INPUT_COMPOSITE;
@@ -2930,7 +2867,7 @@
 			input = VINO_INPUT_D1;
 			break;
 		}
-	} else if (vino_drvdata->decoder.driver) {
+	} else if (vino_drvdata->decoder) {
 		switch (index) {
 		case 0:
 			input = VINO_INPUT_COMPOSITE;
@@ -2939,7 +2876,7 @@
 			input = VINO_INPUT_SVIDEO;
 			break;
 		}
-	} else if (vino_drvdata->camera.driver) {
+	} else if (vino_drvdata->camera) {
 		switch (index) {
 		case 0:
 			input = VINO_INPUT_D1;
@@ -2957,7 +2894,7 @@
 	__u32 index = 0;
 	// FIXME: detect when no inputs available
 
-	if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) {
+	if (vino_drvdata->decoder && vino_drvdata->camera) {
 		switch (vcs->input) {
 		case VINO_INPUT_COMPOSITE:
 			index = 0;
@@ -2969,7 +2906,7 @@
 			index = 2;
 			break;
 		}
-	} else if (vino_drvdata->decoder.driver) {
+	} else if (vino_drvdata->decoder) {
 		switch (vcs->input) {
 		case VINO_INPUT_COMPOSITE:
 			index = 0;
@@ -2978,7 +2915,7 @@
 			index = 1;
 			break;
 		}
-	} else if (vino_drvdata->camera.driver) {
+	} else if (vino_drvdata->camera) {
 		switch (vcs->input) {
 		case VINO_INPUT_D1:
 			index = 0;
@@ -2991,7 +2928,8 @@
 
 /* V4L2 ioctls */
 
-static void vino_v4l2_querycap(struct v4l2_capability *cap)
+static int vino_querycap(struct file *file, void *__fh,
+		struct v4l2_capability *cap)
 {
 	memset(cap, 0, sizeof(struct v4l2_capability));
 
@@ -3003,16 +2941,18 @@
 		V4L2_CAP_VIDEO_CAPTURE |
 		V4L2_CAP_STREAMING;
 	// V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+	return 0;
 }
 
-static int vino_v4l2_enuminput(struct vino_channel_settings *vcs,
+static int vino_enum_input(struct file *file, void *__fh,
 			       struct v4l2_input *i)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	__u32 index = i->index;
 	int input;
 	dprintk("requested index = %d\n", index);
 
-	input = vino_enum_input(vcs, index);
+	input = vino_int_enum_input(vcs, index);
 	if (input == VINO_INPUT_NONE)
 		return -EINVAL;
 
@@ -3023,20 +2963,15 @@
 	i->std = vino_inputs[input].std;
 	strcpy(i->name, vino_inputs[input].name);
 
-	if ((input == VINO_INPUT_COMPOSITE)
-	    || (input == VINO_INPUT_SVIDEO)) {
-		struct saa7191_status status;
-		i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
-		i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL;
-		i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR;
-	}
-
+	if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
+		decoder_call(video, g_input_status, &i->status);
 	return 0;
 }
 
-static int vino_v4l2_g_input(struct vino_channel_settings *vcs,
+static int vino_g_input(struct file *file, void *__fh,
 			     unsigned int *i)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	__u32 index;
 	int input;
 	unsigned long flags;
@@ -3057,52 +2992,24 @@
 	return 0;
 }
 
-static int vino_v4l2_s_input(struct vino_channel_settings *vcs,
-			     unsigned int *i)
+static int vino_s_input(struct file *file, void *__fh,
+			     unsigned int i)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	int input;
-	dprintk("requested input = %d\n", *i);
+	dprintk("requested input = %d\n", i);
 
-	input = vino_enum_input(vcs, *i);
+	input = vino_int_enum_input(vcs, i);
 	if (input == VINO_INPUT_NONE)
 		return -EINVAL;
 
 	return vino_set_input(vcs, input);
 }
 
-static int vino_v4l2_enumstd(struct vino_channel_settings *vcs,
-			     struct v4l2_standard *s)
-{
-	int index = s->index;
-	int data_norm;
-
-	data_norm = vino_enum_data_norm(vcs, index);
-	dprintk("standard index = %d\n", index);
-
-	if (data_norm == VINO_DATA_NORM_NONE)
-		return -EINVAL;
-
-	dprintk("standard name = %s\n",
-	       vino_data_norms[data_norm].description);
-
-	memset(s, 0, sizeof(struct v4l2_standard));
-	s->index = index;
-
-	s->id = vino_data_norms[data_norm].std;
-	s->frameperiod.numerator = 1;
-	s->frameperiod.denominator =
-		vino_data_norms[data_norm].fps_max;
-	s->framelines =
-		vino_data_norms[data_norm].framelines;
-	strcpy(s->name,
-	       vino_data_norms[data_norm].description);
-
-	return 0;
-}
-
-static int vino_v4l2_querystd(struct vino_channel_settings *vcs,
+static int vino_querystd(struct file *file, void *__fh,
 			      v4l2_std_id *std)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 	int err = 0;
 
@@ -3114,19 +3021,7 @@
 		break;
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO: {
-		struct saa7191_status status;
-
-		i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status);
-
-		if (status.signal) {
-			if (status.signal_60hz) {
-				*std = V4L2_STD_NTSC;
-			} else {
-				*std = V4L2_STD_PAL | V4L2_STD_SECAM;
-			}
-		} else {
-			*std = vino_inputs[vcs->input].std;
-		}
+		decoder_call(video, querystd, std);
 		break;
 	}
 	default:
@@ -3138,9 +3033,10 @@
 	return err;
 }
 
-static int vino_v4l2_g_std(struct vino_channel_settings *vcs,
+static int vino_g_std(struct file *file, void *__fh,
 			   v4l2_std_id *std)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 
 	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
@@ -3153,9 +3049,10 @@
 	return 0;
 }
 
-static int vino_v4l2_s_std(struct vino_channel_settings *vcs,
+static int vino_s_std(struct file *file, void *__fh,
 			   v4l2_std_id *std)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 	int ret = 0;
 
@@ -3176,12 +3073,7 @@
 		if (vcs->input == VINO_INPUT_D1)
 			goto out;
 
-		if (((*std) & V4L2_STD_PAL)
-		    && ((*std) & V4L2_STD_NTSC)
-		    && ((*std) & V4L2_STD_SECAM)) {
-			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_AUTO_EXT,
-						 &flags);
-		} else if ((*std) & V4L2_STD_PAL) {
+		if ((*std) & V4L2_STD_PAL) {
 			ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
 						 &flags);
 		} else if ((*std) & V4L2_STD_NTSC) {
@@ -3207,185 +3099,144 @@
 	return ret;
 }
 
-static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs,
+static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
 			      struct v4l2_fmtdesc *fd)
 {
-	enum v4l2_buf_type type = fd->type;
-	int index = fd->index;
-	dprintk("format index = %d\n", index);
+	dprintk("format index = %d\n", fd->index);
 
-	switch (fd->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		if ((fd->index < 0) ||
-		    (fd->index >= VINO_DATA_FMT_COUNT))
-			return -EINVAL;
-		dprintk("format name = %s\n",
-		       vino_data_formats[index].description);
-
-		memset(fd, 0, sizeof(struct v4l2_fmtdesc));
-		fd->index = index;
-		fd->type = type;
-		fd->pixelformat = vino_data_formats[index].pixelformat;
-		strcpy(fd->description, vino_data_formats[index].description);
-		break;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
+	if (fd->index >= VINO_DATA_FMT_COUNT)
 		return -EINVAL;
-	}
+	dprintk("format name = %s\n", vino_data_formats[fd->index].description);
 
+	fd->pixelformat = vino_data_formats[fd->index].pixelformat;
+	strcpy(fd->description, vino_data_formats[fd->index].description);
 	return 0;
 }
 
-static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs,
+static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
 			     struct v4l2_format *f)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	struct vino_channel_settings tempvcs;
 	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
 
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct v4l2_pix_format *pf = &f->fmt.pix;
+	dprintk("requested: w = %d, h = %d\n",
+			pf->width, pf->height);
 
-		dprintk("requested: w = %d, h = %d\n",
-		       pf->width, pf->height);
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-		memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-		tempvcs.data_format = vino_find_data_format(pf->pixelformat);
-		if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
-			tempvcs.data_format = VINO_DATA_FMT_GREY;
-			pf->pixelformat =
-				vino_data_formats[tempvcs.data_format].
-				pixelformat;
-		}
-
-		/* data format must be set before clipping/scaling */
-		vino_set_scaling(&tempvcs, pf->width, pf->height);
-
-		dprintk("data format = %s\n",
-		       vino_data_formats[tempvcs.data_format].description);
-
-		pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
-			tempvcs.decimation;
-		pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
-			tempvcs.decimation;
-
-		pf->field = V4L2_FIELD_INTERLACED;
-		pf->bytesperline = tempvcs.line_size;
-		pf->sizeimage = tempvcs.line_size *
-			(tempvcs.clipping.bottom - tempvcs.clipping.top) /
-			tempvcs.decimation;
-		pf->colorspace =
-			vino_data_formats[tempvcs.data_format].colorspace;
-
-		pf->priv = 0;
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs,
-			   struct v4l2_format *f)
-{
-	unsigned long flags;
-
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct v4l2_pix_format *pf = &f->fmt.pix;
-
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		pf->width = (vcs->clipping.right - vcs->clipping.left) /
-			vcs->decimation;
-		pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
-			vcs->decimation;
+	tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+	if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+		tempvcs.data_format = VINO_DATA_FMT_GREY;
 		pf->pixelformat =
-			vino_data_formats[vcs->data_format].pixelformat;
-
-		pf->field = V4L2_FIELD_INTERLACED;
-		pf->bytesperline = vcs->line_size;
-		pf->sizeimage = vcs->line_size *
-			(vcs->clipping.bottom - vcs->clipping.top) /
-			vcs->decimation;
-		pf->colorspace =
-			vino_data_formats[vcs->data_format].colorspace;
-
-		pf->priv = 0;
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
+			vino_data_formats[tempvcs.data_format].
+			pixelformat;
 	}
 
+	/* data format must be set before clipping/scaling */
+	vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+	dprintk("data format = %s\n",
+			vino_data_formats[tempvcs.data_format].description);
+
+	pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+		tempvcs.decimation;
+	pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+		tempvcs.decimation;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = tempvcs.line_size;
+	pf->sizeimage = tempvcs.line_size *
+		(tempvcs.clipping.bottom - tempvcs.clipping.top) /
+		tempvcs.decimation;
+	pf->colorspace =
+		vino_data_formats[tempvcs.data_format].colorspace;
+
+	pf->priv = 0;
 	return 0;
 }
 
-static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs,
+static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
 			   struct v4l2_format *f)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
+
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+	pf->width = (vcs->clipping.right - vcs->clipping.left) /
+		vcs->decimation;
+	pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->pixelformat =
+		vino_data_formats[vcs->data_format].pixelformat;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = vcs->line_size;
+	pf->sizeimage = vcs->line_size *
+		(vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->colorspace =
+		vino_data_formats[vcs->data_format].colorspace;
+
+	pf->priv = 0;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+	return 0;
+}
+
+static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
+			   struct v4l2_format *f)
+{
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	int data_format;
 	unsigned long flags;
+	struct v4l2_pix_format *pf = &f->fmt.pix;
 
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct v4l2_pix_format *pf = &f->fmt.pix;
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
 
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	data_format = vino_find_data_format(pf->pixelformat);
 
-		data_format = vino_find_data_format(pf->pixelformat);
-
-		if (data_format == VINO_DATA_FMT_NONE) {
-			vcs->data_format = VINO_DATA_FMT_GREY;
-			pf->pixelformat =
-				vino_data_formats[vcs->data_format].
-				pixelformat;
-		} else {
-			vcs->data_format = data_format;
-		}
-
-		/* data format must be set before clipping/scaling */
-		vino_set_scaling(vcs, pf->width, pf->height);
-
-		dprintk("data format = %s\n",
-		       vino_data_formats[vcs->data_format].description);
-
-		pf->width = vcs->clipping.right - vcs->clipping.left;
-		pf->height = vcs->clipping.bottom - vcs->clipping.top;
-
-		pf->field = V4L2_FIELD_INTERLACED;
-		pf->bytesperline = vcs->line_size;
-		pf->sizeimage = vcs->line_size *
-			(vcs->clipping.bottom - vcs->clipping.top) /
-			vcs->decimation;
-		pf->colorspace =
-			vino_data_formats[vcs->data_format].colorspace;
-
-		pf->priv = 0;
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
+	if (data_format == VINO_DATA_FMT_NONE) {
+		vcs->data_format = VINO_DATA_FMT_GREY;
+		pf->pixelformat =
+			vino_data_formats[vcs->data_format].
+			pixelformat;
+	} else {
+		vcs->data_format = data_format;
 	}
 
+	/* data format must be set before clipping/scaling */
+	vino_set_scaling(vcs, pf->width, pf->height);
+
+	dprintk("data format = %s\n",
+	       vino_data_formats[vcs->data_format].description);
+
+	pf->width = vcs->clipping.right - vcs->clipping.left;
+	pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+	pf->field = V4L2_FIELD_INTERLACED;
+	pf->bytesperline = vcs->line_size;
+	pf->sizeimage = vcs->line_size *
+		(vcs->clipping.bottom - vcs->clipping.top) /
+		vcs->decimation;
+	pf->colorspace =
+		vino_data_formats[vcs->data_format].colorspace;
+
+	pf->priv = 0;
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 	return 0;
 }
 
-static int vino_v4l2_cropcap(struct vino_channel_settings *vcs,
+static int vino_cropcap(struct file *file, void *__fh,
 			     struct v4l2_cropcap *ccap)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	const struct vino_data_norm *norm;
 	unsigned long flags;
 
@@ -3415,9 +3266,10 @@
 	return 0;
 }
 
-static int vino_v4l2_g_crop(struct vino_channel_settings *vcs,
+static int vino_g_crop(struct file *file, void *__fh,
 			    struct v4l2_crop *c)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 
 	switch (c->type) {
@@ -3439,9 +3291,10 @@
 	return 0;
 }
 
-static int vino_v4l2_s_crop(struct vino_channel_settings *vcs,
+static int vino_s_crop(struct file *file, void *__fh,
 			    struct v4l2_crop *c)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 
 	switch (c->type) {
@@ -3461,108 +3314,83 @@
 	return 0;
 }
 
-static int vino_v4l2_g_parm(struct vino_channel_settings *vcs,
+static int vino_g_parm(struct file *file, void *__fh,
 			    struct v4l2_streamparm *sp)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
 
-	switch (sp->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct v4l2_captureparm *cp = &sp->parm.capture;
-		memset(cp, 0, sizeof(struct v4l2_captureparm));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = 1;
 
-		cp->capability = V4L2_CAP_TIMEPERFRAME;
-		cp->timeperframe.numerator = 1;
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
 
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+	cp->timeperframe.denominator = vcs->fps;
 
-		cp->timeperframe.denominator = vcs->fps;
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-		// TODO: cp->readbuffers = xxx;
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
+	/* TODO: cp->readbuffers = xxx; */
 
 	return 0;
 }
 
-static int vino_v4l2_s_parm(struct vino_channel_settings *vcs,
+static int vino_s_parm(struct file *file, void *__fh,
 			    struct v4l2_streamparm *sp)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
+	struct v4l2_captureparm *cp = &sp->parm.capture;
 
-	switch (sp->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct v4l2_captureparm *cp = &sp->parm.capture;
+	spin_lock_irqsave(&vino_drvdata->input_lock, flags);
 
-		spin_lock_irqsave(&vino_drvdata->input_lock, flags);
-
-		if ((cp->timeperframe.numerator == 0) ||
-		    (cp->timeperframe.denominator == 0)) {
-			/* reset framerate */
-			vino_set_default_framerate(vcs);
-		} else {
-			vino_set_framerate(vcs, cp->timeperframe.denominator /
-					   cp->timeperframe.numerator);
-		}
-
-		spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
-
-		// TODO: set buffers according to cp->readbuffers
-		break;
+	if ((cp->timeperframe.numerator == 0) ||
+	    (cp->timeperframe.denominator == 0)) {
+		/* reset framerate */
+		vino_set_default_framerate(vcs);
+	} else {
+		vino_set_framerate(vcs, cp->timeperframe.denominator /
+				   cp->timeperframe.numerator);
 	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
-	}
+
+	spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
 
 	return 0;
 }
 
-static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs,
+static int vino_reqbufs(struct file *file, void *__fh,
 			     struct v4l2_requestbuffers *rb)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
+
 	if (vcs->reading)
 		return -EBUSY;
 
-	switch (rb->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		// TODO: check queue type
-		if (rb->memory != V4L2_MEMORY_MMAP) {
-			dprintk("type not mmap\n");
-			return -EINVAL;
+	/* TODO: check queue type */
+	if (rb->memory != V4L2_MEMORY_MMAP) {
+		dprintk("type not mmap\n");
+		return -EINVAL;
+	}
+
+	dprintk("count = %d\n", rb->count);
+	if (rb->count > 0) {
+		if (vino_is_capturing(vcs)) {
+			dprintk("busy, capturing\n");
+			return -EBUSY;
 		}
 
-		dprintk("count = %d\n", rb->count);
-		if (rb->count > 0) {
-			if (vino_is_capturing(vcs)) {
-				dprintk("busy, capturing\n");
-				return -EBUSY;
-			}
-
-			if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
-				dprintk("busy, buffers still mapped\n");
-				return -EBUSY;
-			} else {
-				vcs->streaming = 0;
-				vino_queue_free(&vcs->fb_queue);
-				vino_queue_init(&vcs->fb_queue, &rb->count);
-			}
+		if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+			dprintk("busy, buffers still mapped\n");
+			return -EBUSY;
 		} else {
 			vcs->streaming = 0;
-			vino_capture_stop(vcs);
 			vino_queue_free(&vcs->fb_queue);
+			vino_queue_init(&vcs->fb_queue, &rb->count);
 		}
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
-		return -EINVAL;
+	} else {
+		vcs->streaming = 0;
+		vino_capture_stop(vcs);
+		vino_queue_free(&vcs->fb_queue);
 	}
 
 	return 0;
@@ -3606,156 +3434,135 @@
 		fb->id, fb->size, fb->data_size, fb->offset);
 }
 
-static int vino_v4l2_querybuf(struct vino_channel_settings *vcs,
+static int vino_querybuf(struct file *file, void *__fh,
 			      struct v4l2_buffer *b)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	struct vino_framebuffer *fb;
+
 	if (vcs->reading)
 		return -EBUSY;
 
-	switch (b->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct vino_framebuffer *fb;
-
-		// TODO: check queue type
-		if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
-			dprintk("invalid index = %d\n",
-			       b->index);
-			return -EINVAL;
-		}
-
-		fb = vino_queue_get_buffer(&vcs->fb_queue,
-					   b->index);
-		if (fb == NULL) {
-			dprintk("vino_queue_get_buffer() failed");
-			return -EINVAL;
-		}
-
-		vino_v4l2_get_buffer_status(vcs, fb, b);
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
+	/* TODO: check queue type */
+	if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+		dprintk("invalid index = %d\n",
+		       b->index);
 		return -EINVAL;
 	}
 
+	fb = vino_queue_get_buffer(&vcs->fb_queue,
+				   b->index);
+	if (fb == NULL) {
+		dprintk("vino_queue_get_buffer() failed");
+		return -EINVAL;
+	}
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
 	return 0;
 }
 
-static int vino_v4l2_qbuf(struct vino_channel_settings *vcs,
+static int vino_qbuf(struct file *file, void *__fh,
 			  struct v4l2_buffer *b)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	struct vino_framebuffer *fb;
+	int ret;
+
 	if (vcs->reading)
 		return -EBUSY;
 
-	switch (b->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct vino_framebuffer *fb;
-		int ret;
-
-		// TODO: check queue type
-		if (b->memory != V4L2_MEMORY_MMAP) {
-			dprintk("type not mmap\n");
-			return -EINVAL;
-		}
-
-		fb = vino_capture_enqueue(vcs, b->index);
-		if (fb == NULL)
-			return -EINVAL;
-
-		vino_v4l2_get_buffer_status(vcs, fb, b);
-
-		if (vcs->streaming) {
-			ret = vino_capture_next(vcs, 1);
-			if (ret)
-				return ret;
-		}
-		break;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
+	/* TODO: check queue type */
+	if (b->memory != V4L2_MEMORY_MMAP) {
+		dprintk("type not mmap\n");
 		return -EINVAL;
 	}
 
+	fb = vino_capture_enqueue(vcs, b->index);
+	if (fb == NULL)
+		return -EINVAL;
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
+	if (vcs->streaming) {
+		ret = vino_capture_next(vcs, 1);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
-static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs,
-			   struct v4l2_buffer *b,
-			   unsigned int nonblocking)
+static int vino_dqbuf(struct file *file, void *__fh,
+			   struct v4l2_buffer *b)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
+	unsigned int nonblocking = file->f_flags & O_NONBLOCK;
+	struct vino_framebuffer *fb;
+	unsigned int incoming, outgoing;
+	int err;
+
 	if (vcs->reading)
 		return -EBUSY;
 
-	switch (b->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
-		struct vino_framebuffer *fb;
-		unsigned int incoming, outgoing;
-		int err;
+	/* TODO: check queue type */
 
-		// TODO: check queue type
+	err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+	if (err) {
+		dprintk("vino_queue_get_incoming() failed\n");
+		return -EINVAL;
+	}
+	err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+	if (err) {
+		dprintk("vino_queue_get_outgoing() failed\n");
+		return -EINVAL;
+	}
 
-		err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
-		if (err) {
-			dprintk("vino_queue_get_incoming() failed\n");
+	dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+	if (outgoing == 0) {
+		if (incoming == 0) {
+			dprintk("no incoming or outgoing buffers\n");
 			return -EINVAL;
 		}
-		err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
-		if (err) {
-			dprintk("vino_queue_get_outgoing() failed\n");
-			return -EINVAL;
+		if (nonblocking) {
+			dprintk("non-blocking I/O was selected and "
+				"there are no buffers to dequeue\n");
+			return -EAGAIN;
 		}
 
-		dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
-
-		if (outgoing == 0) {
-			if (incoming == 0) {
-				dprintk("no incoming or outgoing buffers\n");
-				return -EINVAL;
-			}
-			if (nonblocking) {
-				dprintk("non-blocking I/O was selected and "
-					"there are no buffers to dequeue\n");
-				return -EAGAIN;
-			}
-
+		err = vino_wait_for_frame(vcs);
+		if (err) {
 			err = vino_wait_for_frame(vcs);
 			if (err) {
-				err = vino_wait_for_frame(vcs);
-				if (err) {
-					/* interrupted or
-					 * no frames captured because
-					 * of frame skipping */
-					// vino_capture_failed(vcs);
-					return -EIO;
-				}
+				/* interrupted or no frames captured because of
+				 * frame skipping */
+				/* vino_capture_failed(vcs); */
+				return -EIO;
 			}
 		}
-
-		fb = vino_queue_remove(&vcs->fb_queue, &b->index);
-		if (fb == NULL) {
-			dprintk("vino_queue_remove() failed\n");
-			return -EINVAL;
-		}
-
-		err = vino_check_buffer(vcs, fb);
-
-		vino_v4l2_get_buffer_status(vcs, fb, b);
-
-		if (err)
-			return -EIO;
-
-		break;
 	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-	default:
+
+	fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+	if (fb == NULL) {
+		dprintk("vino_queue_remove() failed\n");
 		return -EINVAL;
 	}
 
+	err = vino_check_buffer(vcs, fb);
+
+	vino_v4l2_get_buffer_status(vcs, fb, b);
+
+	if (err)
+		return -EIO;
+
 	return 0;
 }
 
-static int vino_v4l2_streamon(struct vino_channel_settings *vcs)
+static int vino_streamon(struct file *file, void *__fh,
+		enum v4l2_buf_type i)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned int incoming;
 	int ret;
 	if (vcs->reading)
@@ -3792,8 +3599,10 @@
 	return 0;
 }
 
-static int vino_v4l2_streamoff(struct vino_channel_settings *vcs)
+static int vino_streamoff(struct file *file, void *__fh,
+		enum v4l2_buf_type i)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	if (vcs->reading)
 		return -EBUSY;
 
@@ -3806,9 +3615,10 @@
 	return 0;
 }
 
-static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs,
+static int vino_queryctrl(struct file *file, void *__fh,
 			       struct v4l2_queryctrl *queryctrl)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 	int i;
 	int err = 0;
@@ -3855,9 +3665,10 @@
 	return err;
 }
 
-static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs,
+static int vino_g_ctrl(struct file *file, void *__fh,
 			    struct v4l2_control *control)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 	int i;
 	int err = 0;
@@ -3866,56 +3677,38 @@
 
 	switch (vcs->input) {
 	case VINO_INPUT_D1: {
-		struct indycam_control indycam_ctrl;
-
+		err = -EINVAL;
 		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
-			if (vino_indycam_v4l2_controls[i].id ==
-			    control->id) {
-				goto found1;
+			if (vino_indycam_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
 			}
 		}
 
-		err = -EINVAL;
-		goto out;
-
-found1:
-		indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0];
-
-		err = i2c_camera_command(DECODER_INDYCAM_GET_CONTROL,
-					 &indycam_ctrl);
-		if (err) {
-			err = -EINVAL;
+		if (err)
 			goto out;
-		}
 
-		control->value = indycam_ctrl.value;
+		err = camera_call(core, g_ctrl, control);
+		if (err)
+			err = -EINVAL;
 		break;
 	}
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO: {
-		struct saa7191_control saa7191_ctrl;
-
+		err = -EINVAL;
 		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
-			if (vino_saa7191_v4l2_controls[i].id ==
-			    control->id) {
-				goto found2;
+			if (vino_saa7191_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
 			}
 		}
 
-		err = -EINVAL;
-		goto out;
-
-found2:
-		saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0];
-
-		err = i2c_decoder_command(DECODER_SAA7191_GET_CONTROL,
-					  &saa7191_ctrl);
-		if (err) {
-			err = -EINVAL;
+		if (err)
 			goto out;
-		}
 
-		control->value = saa7191_ctrl.value;
+		err = decoder_call(core, g_ctrl, control);
+		if (err)
+			err = -EINVAL;
 		break;
 	}
 	default:
@@ -3928,9 +3721,10 @@
 	return err;
 }
 
-static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs,
+static int vino_s_ctrl(struct file *file, void *__fh,
 			    struct v4l2_control *control)
 {
+	struct vino_channel_settings *vcs = video_drvdata(file);
 	unsigned long flags;
 	int i;
 	int err = 0;
@@ -3944,65 +3738,43 @@
 
 	switch (vcs->input) {
 	case VINO_INPUT_D1: {
-		struct indycam_control indycam_ctrl;
-
+		err = -EINVAL;
 		for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
-			if (vino_indycam_v4l2_controls[i].id ==
-			    control->id) {
-				if ((control->value >=
-				     vino_indycam_v4l2_controls[i].minimum)
-				    && (control->value <=
-					vino_indycam_v4l2_controls[i].
-					maximum)) {
-					goto found1;
-				} else {
-					err = -ERANGE;
-					goto out;
-				}
+			if (vino_indycam_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
 			}
 		}
-
-		err = -EINVAL;
-		goto out;
-
-found1:
-		indycam_ctrl.type = vino_indycam_v4l2_controls[i].reserved[0];
-		indycam_ctrl.value = control->value;
-
-		err = i2c_camera_command(DECODER_INDYCAM_SET_CONTROL,
-					 &indycam_ctrl);
+		if (err)
+			goto out;
+		if (control->value < vino_indycam_v4l2_controls[i].minimum ||
+		    control->value > vino_indycam_v4l2_controls[i].maximum) {
+			err = -ERANGE;
+			goto out;
+		}
+		err = camera_call(core, s_ctrl, control);
 		if (err)
 			err = -EINVAL;
 		break;
 	}
 	case VINO_INPUT_COMPOSITE:
 	case VINO_INPUT_SVIDEO: {
-		struct saa7191_control saa7191_ctrl;
-
+		err = -EINVAL;
 		for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
-			if (vino_saa7191_v4l2_controls[i].id ==
-			    control->id) {
-				if ((control->value >=
-				     vino_saa7191_v4l2_controls[i].minimum)
-				    && (control->value <=
-					vino_saa7191_v4l2_controls[i].
-					maximum)) {
-					goto found2;
-				} else {
-					err = -ERANGE;
-					goto out;
-				}
+			if (vino_saa7191_v4l2_controls[i].id == control->id) {
+				err = 0;
+				break;
 			}
 		}
-		err = -EINVAL;
-		goto out;
+		if (err)
+			goto out;
+		if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
+		    control->value > vino_saa7191_v4l2_controls[i].maximum) {
+			err = -ERANGE;
+			goto out;
+		}
 
-found2:
-		saa7191_ctrl.type = vino_saa7191_v4l2_controls[i].reserved[0];
-		saa7191_ctrl.value = control->value;
-
-		err = i2c_decoder_command(DECODER_SAA7191_SET_CONTROL,
-					  &saa7191_ctrl);
+		err = decoder_call(core, s_ctrl, control);
 		if (err)
 			err = -EINVAL;
 		break;
@@ -4233,116 +4005,9 @@
 		ret = POLLIN | POLLRDNORM;
 
 error:
-
 	return ret;
 }
 
-static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-	struct vino_channel_settings *vcs = video_drvdata(file);
-
-#ifdef VINO_DEBUG
-	switch (_IOC_TYPE(cmd)) {
-	case 'v':
-		dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd);
-		break;
-	case 'V':
-		dprintk("ioctl(): V4L2 %s (0x%08x)\n",
-			v4l2_ioctl_names[_IOC_NR(cmd)], cmd);
-		break;
-	default:
-		dprintk("ioctl(): unsupported command 0x%08x\n", cmd);
-	}
-#endif
-
-	switch (cmd) {
-	/* V4L2 interface */
-	case VIDIOC_QUERYCAP: {
-		vino_v4l2_querycap(arg);
-		break;
-	}
-	case VIDIOC_ENUMINPUT: {
-		return vino_v4l2_enuminput(vcs, arg);
-	}
-	case VIDIOC_G_INPUT: {
-		return vino_v4l2_g_input(vcs, arg);
-	}
-	case VIDIOC_S_INPUT: {
-		return vino_v4l2_s_input(vcs, arg);
-	}
-	case VIDIOC_ENUMSTD: {
-		return vino_v4l2_enumstd(vcs, arg);
-	}
-	case VIDIOC_QUERYSTD: {
-		return vino_v4l2_querystd(vcs, arg);
-	}
-	case VIDIOC_G_STD: {
-		return vino_v4l2_g_std(vcs, arg);
-	}
-	case VIDIOC_S_STD: {
-		return vino_v4l2_s_std(vcs, arg);
-	}
-	case VIDIOC_ENUM_FMT: {
-		return vino_v4l2_enum_fmt(vcs, arg);
-	}
-	case VIDIOC_TRY_FMT: {
-		return vino_v4l2_try_fmt(vcs, arg);
-	}
-	case VIDIOC_G_FMT: {
-		return vino_v4l2_g_fmt(vcs, arg);
-	}
-	case VIDIOC_S_FMT: {
-		return vino_v4l2_s_fmt(vcs, arg);
-	}
-	case VIDIOC_CROPCAP: {
-		return vino_v4l2_cropcap(vcs, arg);
-	}
-	case VIDIOC_G_CROP: {
-		return vino_v4l2_g_crop(vcs, arg);
-	}
-	case VIDIOC_S_CROP: {
-		return vino_v4l2_s_crop(vcs, arg);
-	}
-	case VIDIOC_G_PARM: {
-		return vino_v4l2_g_parm(vcs, arg);
-	}
-	case VIDIOC_S_PARM: {
-		return vino_v4l2_s_parm(vcs, arg);
-	}
-	case VIDIOC_REQBUFS: {
-		return vino_v4l2_reqbufs(vcs, arg);
-	}
-	case VIDIOC_QUERYBUF: {
-		return vino_v4l2_querybuf(vcs, arg);
-	}
-	case VIDIOC_QBUF: {
-		return vino_v4l2_qbuf(vcs, arg);
-	}
-	case VIDIOC_DQBUF: {
-		return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK);
-	}
-	case VIDIOC_STREAMON: {
-		return vino_v4l2_streamon(vcs);
-	}
-	case VIDIOC_STREAMOFF: {
-		return vino_v4l2_streamoff(vcs);
-	}
-	case VIDIOC_QUERYCTRL: {
-		return vino_v4l2_queryctrl(vcs, arg);
-	}
-	case VIDIOC_G_CTRL: {
-		return vino_v4l2_g_ctrl(vcs, arg);
-	}
-	case VIDIOC_S_CTRL: {
-		return vino_v4l2_s_ctrl(vcs, arg);
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	return 0;
-}
-
 static long vino_ioctl(struct file *file,
 		      unsigned int cmd, unsigned long arg)
 {
@@ -4352,7 +4017,7 @@
 	if (mutex_lock_interruptible(&vcs->mutex))
 		return -EINTR;
 
-	ret = video_usercopy(file, cmd, arg, vino_do_ioctl);
+	ret = video_ioctl2(file, cmd, arg);
 
 	mutex_unlock(&vcs->mutex);
 
@@ -4364,45 +4029,75 @@
 /* __initdata */
 static int vino_init_stage;
 
+const struct v4l2_ioctl_ops vino_ioctl_ops = {
+	.vidioc_enum_fmt_vid_cap     = vino_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 	     = vino_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  	     = vino_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap	     = vino_try_fmt_vid_cap,
+	.vidioc_querycap    	     = vino_querycap,
+	.vidioc_enum_input   	     = vino_enum_input,
+	.vidioc_g_input      	     = vino_g_input,
+	.vidioc_s_input      	     = vino_s_input,
+	.vidioc_g_std 		     = vino_g_std,
+	.vidioc_s_std 		     = vino_s_std,
+	.vidioc_querystd             = vino_querystd,
+	.vidioc_cropcap      	     = vino_cropcap,
+	.vidioc_s_crop       	     = vino_s_crop,
+	.vidioc_g_crop       	     = vino_g_crop,
+	.vidioc_s_parm 		     = vino_s_parm,
+	.vidioc_g_parm 		     = vino_g_parm,
+	.vidioc_reqbufs              = vino_reqbufs,
+	.vidioc_querybuf             = vino_querybuf,
+	.vidioc_qbuf                 = vino_qbuf,
+	.vidioc_dqbuf                = vino_dqbuf,
+	.vidioc_streamon             = vino_streamon,
+	.vidioc_streamoff            = vino_streamoff,
+	.vidioc_queryctrl            = vino_queryctrl,
+	.vidioc_g_ctrl               = vino_g_ctrl,
+	.vidioc_s_ctrl               = vino_s_ctrl,
+};
+
 static const struct v4l2_file_operations vino_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vino_open,
 	.release	= vino_close,
-	.ioctl		= vino_ioctl,
+	.unlocked_ioctl	= vino_ioctl,
 	.mmap		= vino_mmap,
 	.poll		= vino_poll,
 };
 
-static struct video_device v4l_device_template = {
+static struct video_device vdev_template = {
 	.name		= "NOT SET",
 	.fops		= &vino_fops,
+	.ioctl_ops 	= &vino_ioctl_ops,
+	.tvnorms 	= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
 	.minor		= -1,
 };
 
 static void vino_module_cleanup(int stage)
 {
 	switch(stage) {
+	case 11:
+		video_unregister_device(vino_drvdata->b.vdev);
+		vino_drvdata->b.vdev = NULL;
 	case 10:
-		video_unregister_device(vino_drvdata->b.v4l_device);
-		vino_drvdata->b.v4l_device = NULL;
+		video_unregister_device(vino_drvdata->a.vdev);
+		vino_drvdata->a.vdev = NULL;
 	case 9:
-		video_unregister_device(vino_drvdata->a.v4l_device);
-		vino_drvdata->a.v4l_device = NULL;
+		i2c_del_adapter(&vino_i2c_adapter);
 	case 8:
-		vino_i2c_del_bus();
-	case 7:
 		free_irq(SGI_VINO_IRQ, NULL);
+	case 7:
+		if (vino_drvdata->b.vdev) {
+			video_device_release(vino_drvdata->b.vdev);
+			vino_drvdata->b.vdev = NULL;
+		}
 	case 6:
-		if (vino_drvdata->b.v4l_device) {
-			video_device_release(vino_drvdata->b.v4l_device);
-			vino_drvdata->b.v4l_device = NULL;
+		if (vino_drvdata->a.vdev) {
+			video_device_release(vino_drvdata->a.vdev);
+			vino_drvdata->a.vdev = NULL;
 		}
 	case 5:
-		if (vino_drvdata->a.v4l_device) {
-			video_device_release(vino_drvdata->a.v4l_device);
-			vino_drvdata->a.v4l_device = NULL;
-		}
-	case 4:
 		/* all entries in dma_cpu dummy table have the same address */
 		dma_unmap_single(NULL,
 				 vino_drvdata->dummy_desc_table.dma_cpu[0],
@@ -4412,8 +4107,10 @@
 				  (void *)vino_drvdata->
 				  dummy_desc_table.dma_cpu,
 				  vino_drvdata->dummy_desc_table.dma);
-	case 3:
+	case 4:
 		free_page(vino_drvdata->dummy_page);
+	case 3:
+		v4l2_device_unregister(&vino_drvdata->v4l2_dev);
 	case 2:
 		kfree(vino_drvdata);
 	case 1:
@@ -4468,6 +4165,7 @@
 static int vino_init(void)
 {
 	dma_addr_t dma_dummy_address;
+	int err;
 	int i;
 
 	vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
@@ -4476,6 +4174,12 @@
 		return -ENOMEM;
 	}
 	vino_init_stage++;
+	strlcpy(vino_drvdata->v4l2_dev.name, "vino",
+			sizeof(vino_drvdata->v4l2_dev.name));
+	err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
+	if (err)
+		return err;
+	vino_init_stage++;
 
 	/* create a dummy dma descriptor */
 	vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -4542,25 +4246,27 @@
 	spin_lock_init(&vcs->fb_queue.queue_lock);
 	init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
 
-	vcs->v4l_device = video_device_alloc();
-	if (!vcs->v4l_device) {
+	vcs->vdev = video_device_alloc();
+	if (!vcs->vdev) {
 		vino_module_cleanup(vino_init_stage);
 		return -ENOMEM;
 	}
 	vino_init_stage++;
 
-	memcpy(vcs->v4l_device, &v4l_device_template,
+	memcpy(vcs->vdev, &vdev_template,
 	       sizeof(struct video_device));
-	strcpy(vcs->v4l_device->name, name);
-	vcs->v4l_device->release = video_device_release;
+	strcpy(vcs->vdev->name, name);
+	vcs->vdev->release = video_device_release;
+	vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
 
-	video_set_drvdata(vcs->v4l_device, vcs);
+	video_set_drvdata(vcs->vdev, vcs);
 
 	return 0;
 }
 
 static int __init vino_module_init(void)
 {
+	unsigned short addr[] = { 0, I2C_CLIENT_END };
 	int ret;
 
 	printk(KERN_INFO "SGI VINO driver version %s\n",
@@ -4580,12 +4286,12 @@
 	spin_lock_init(&vino_drvdata->input_lock);
 
 	ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
-				    vino_v4l_device_name_a);
+				    vino_vdev_name_a);
 	if (ret)
 		return ret;
 
 	ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
-				    vino_v4l_device_name_b);
+				    vino_vdev_name_b);
 	if (ret)
 		return ret;
 
@@ -4601,15 +4307,16 @@
 	}
 	vino_init_stage++;
 
-	ret = vino_i2c_add_bus();
+	ret = i2c_add_adapter(&vino_i2c_adapter);
 	if (ret) {
 		printk(KERN_ERR "VINO I2C bus registration failed\n");
 		vino_module_cleanup(vino_init_stage);
 		return ret;
 	}
+	i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
 	vino_init_stage++;
 
-	ret = video_register_device(vino_drvdata->a.v4l_device,
+	ret = video_register_device(vino_drvdata->a.vdev,
 				    VFL_TYPE_GRABBER, -1);
 	if (ret < 0) {
 		printk(KERN_ERR "VINO channel A Video4Linux-device "
@@ -4619,7 +4326,7 @@
 	}
 	vino_init_stage++;
 
-	ret = video_register_device(vino_drvdata->b.v4l_device,
+	ret = video_register_device(vino_drvdata->b.vdev,
 				    VFL_TYPE_GRABBER, -1);
 	if (ret < 0) {
 		printk(KERN_ERR "VINO channel B Video4Linux-device "
@@ -4629,10 +4336,12 @@
 	}
 	vino_init_stage++;
 
-#ifdef MODULE
-	request_module("saa7191");
-	request_module("indycam");
-#endif
+	addr[0] = 0x45;
+	vino_drvdata->decoder = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
+			"saa7191", "saa7191", addr);
+	addr[0] = 0x2b;
+	vino_drvdata->camera = v4l2_i2c_new_probed_subdev(&vino_i2c_adapter,
+			"indycam", "indycam", addr);
 
 	dprintk("init complete!\n");
 
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 81d5aa5..fbfefae 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -28,17 +28,14 @@
 #include <linux/mutex.h>
 #include <linux/videodev2.h>
 #include <linux/dma-mapping.h>
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-/* Include V4L1 specific functions. Should be removed soon */
-#include <linux/videodev.h>
-#endif
 #include <linux/interrupt.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/kthread.h>
 #include <linux/highmem.h>
 #include <linux/freezer.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include "font.h"
 
 #define VIVI_MODULE_NAME "vivi"
 
@@ -47,18 +44,32 @@
 #define WAKE_DENOMINATOR 1001
 #define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
 
-#include "font.h"
-
 #define VIVI_MAJOR_VERSION 0
-#define VIVI_MINOR_VERSION 5
+#define VIVI_MINOR_VERSION 6
 #define VIVI_RELEASE 0
 #define VIVI_VERSION \
 	KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
 
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;	/* Video memory limit, in Mb */
-static int video_nr = -1;		/* /dev/videoN, -1 for autodetect */
-static int n_devs = 1;			/* Number of virtual devices */
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+
+static unsigned n_devs = 1;
+module_param(n_devs, uint, 0644);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
+
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit, uint, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
 
 /* supported controls */
 static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -69,7 +80,7 @@
 		.maximum       = 65535,
 		.step          = 65535/100,
 		.default_value = 65535,
-		.flags         = 0,
+		.flags         = V4L2_CTRL_FLAG_SLIDER,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
 	}, {
 		.id            = V4L2_CID_BRIGHTNESS,
@@ -79,7 +90,7 @@
 		.maximum       = 255,
 		.step          = 1,
 		.default_value = 127,
-		.flags         = 0,
+		.flags         = V4L2_CTRL_FLAG_SLIDER,
 	}, {
 		.id            = V4L2_CID_CONTRAST,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
@@ -88,7 +99,7 @@
 		.maximum       = 255,
 		.step          = 0x1,
 		.default_value = 0x10,
-		.flags         = 0,
+		.flags         = V4L2_CTRL_FLAG_SLIDER,
 	}, {
 		.id            = V4L2_CID_SATURATION,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
@@ -97,7 +108,7 @@
 		.maximum       = 255,
 		.step          = 0x1,
 		.default_value = 127,
-		.flags         = 0,
+		.flags         = V4L2_CTRL_FLAG_SLIDER,
 	}, {
 		.id            = V4L2_CID_HUE,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
@@ -106,17 +117,12 @@
 		.maximum       = 127,
 		.step          = 0x1,
 		.default_value = 0,
-		.flags         = 0,
+		.flags         = V4L2_CTRL_FLAG_SLIDER,
 	}
 };
 
-static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
-
-#define dprintk(dev, level, fmt, arg...)				\
-	do {								\
-		if (dev->vfd->debug >= (level))				\
-			printk(KERN_DEBUG "vivi: " fmt , ## arg);	\
-	} while (0)
+#define dprintk(dev, level, fmt, arg...) \
+	v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
 
 /* ------------------------------------------------------------------
 	Basic structures
@@ -206,6 +212,7 @@
 
 struct vivi_dev {
 	struct list_head           vivi_devlist;
+	struct v4l2_device 	   v4l2_dev;
 
 	spinlock_t                 slock;
 	struct mutex		   mutex;
@@ -223,6 +230,12 @@
 	char                       timestr[13];
 
 	int			   mv_count;	/* Controls bars movement */
+
+	/* Input Number */
+	int			   input;
+
+	/* Control 'registers' */
+	int 			   qctl_regs[ARRAY_SIZE(vivi_qctrl)];
 };
 
 struct vivi_fh {
@@ -235,6 +248,7 @@
 
 	enum v4l2_buf_type         type;
 	unsigned char              bars[8][3];
+	int			   input; 	/* Input Number on bars */
 };
 
 /* ------------------------------------------------------------------
@@ -254,18 +268,72 @@
 	BLACK,
 };
 
-static u8 bars[8][3] = {
 	/* R   G   B */
-	{204, 204, 204},  /* white */
-	{208, 208,   0},  /* ambar */
-	{  0, 206, 206},  /* cyan */
-	{  0, 239,   0},  /* green */
-	{239,   0, 239},  /* magenta */
-	{205,   0,   0},  /* red */
-	{  0,   0, 255},  /* blue */
-	{  0,   0,   0},  /* black */
+#define COLOR_WHITE	{204, 204, 204}
+#define COLOR_AMBAR	{208, 208,   0}
+#define COLOR_CIAN	{  0, 206, 206}
+#define	COLOR_GREEN	{  0, 239,   0}
+#define COLOR_MAGENTA	{239,   0, 239}
+#define COLOR_RED	{205,   0,   0}
+#define COLOR_BLUE	{  0,   0, 255}
+#define COLOR_BLACK	{  0,   0,   0}
+
+struct bar_std {
+	u8 bar[8][3];
 };
 
+/* Maximum number of bars are 10 - otherwise, the input print code
+   should be modified */
+static struct bar_std bars[] = {
+	{	/* Standard ITU-R color bar sequence */
+		{
+			COLOR_WHITE,
+			COLOR_AMBAR,
+			COLOR_CIAN,
+			COLOR_GREEN,
+			COLOR_MAGENTA,
+			COLOR_RED,
+			COLOR_BLUE,
+			COLOR_BLACK,
+		}
+	}, {
+		{
+			COLOR_WHITE,
+			COLOR_AMBAR,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_AMBAR,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_AMBAR,
+		}
+	}, {
+		{
+			COLOR_WHITE,
+			COLOR_CIAN,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_CIAN,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_CIAN,
+		}
+	}, {
+		{
+			COLOR_WHITE,
+			COLOR_GREEN,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_GREEN,
+			COLOR_BLACK,
+			COLOR_WHITE,
+			COLOR_GREEN,
+		}
+	},
+};
+
+#define NUM_INPUTS ARRAY_SIZE(bars)
+
 #define TO_Y(r, g, b) \
 	(((16829 * r + 33039 * g + 6416 * b  + 32768) >> 16) + 16)
 /* RGB to  V(Cr) Color transform */
@@ -275,9 +343,10 @@
 #define TO_U(r, g, b) \
 	(((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
 
-#define TSTAMP_MIN_Y 24
-#define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
-#define TSTAMP_MIN_X 64
+#define TSTAMP_MIN_Y	24
+#define TSTAMP_MAX_Y	(TSTAMP_MIN_Y + 15)
+#define TSTAMP_INPUT_X	10
+#define TSTAMP_MIN_X	(54 + TSTAMP_INPUT_X)
 
 static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
 {
@@ -392,9 +461,29 @@
 		pos += 4; /* only 16 bpp supported for now */
 	}
 
-	/* Checks if it is possible to show timestamp */
+	/* Prints input entry number */
+
+	/* Checks if it is possible to input number */
 	if (TSTAMP_MAX_Y >= hmax)
 		goto end;
+
+	if (TSTAMP_INPUT_X + strlen(timestr) >= wmax)
+		goto end;
+
+	if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) {
+		chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y];
+		pos = TSTAMP_INPUT_X;
+		for (i = 0; i < 7; i++) {
+			/* Draw white font on black background */
+			if (chr & 1 << (7 - i))
+				gen_twopix(fh, basep + pos, WHITE);
+			else
+				gen_twopix(fh, basep + pos, BLACK);
+			pos += 2;
+		}
+	}
+
+	/* Checks if it is possible to show timestamp */
 	if (TSTAMP_MIN_X + strlen(timestr) >= wmax)
 		goto end;
 
@@ -577,7 +666,7 @@
 	dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
 
 	if (IS_ERR(dma_q->kthread)) {
-		printk(KERN_ERR "vivi: kernel_thread() failed\n");
+		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
 		return PTR_ERR(dma_q->kthread);
 	}
 	/* Wakes thread */
@@ -720,8 +809,12 @@
 static int vidioc_querycap(struct file *file, void  *priv,
 					struct v4l2_capability *cap)
 {
+	struct vivi_fh  *fh  = priv;
+	struct vivi_dev *dev = fh->dev;
+
 	strcpy(cap->driver, "vivi");
 	strcpy(cap->card, "vivi");
+	strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
 	cap->version = VIVI_VERSION;
 	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE |
 				V4L2_CAP_STREAMING     |
@@ -807,38 +900,19 @@
 	return 0;
 }
 
-/*FIXME: This seems to be generic enough to be at videodev2 */
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *f)
+/* precalculate color bar values to speed up rendering */
+static void precalculate_bars(struct vivi_fh *fh)
 {
-	struct vivi_fh  *fh = priv;
-	struct videobuf_queue *q = &fh->vb_vidq;
+	struct vivi_dev *dev = fh->dev;
 	unsigned char r, g, b;
 	int k, is_yuv;
 
-	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
-	if (ret < 0)
-		return (ret);
+	fh->input = dev->input;
 
-	mutex_lock(&q->vb_lock);
-
-	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-		dprintk(fh->dev, 1, "%s queue busy\n", __func__);
-		ret = -EBUSY;
-		goto out;
-	}
-
-	fh->fmt           = get_format(f);
-	fh->width         = f->fmt.pix.width;
-	fh->height        = f->fmt.pix.height;
-	fh->vb_vidq.field = f->fmt.pix.field;
-	fh->type          = f->type;
-
-	/* precalculate color bar values to speed up rendering */
 	for (k = 0; k < 8; k++) {
-		r = bars[k][0];
-		g = bars[k][1];
-		b = bars[k][2];
+		r = bars[fh->input].bar[k][0];
+		g = bars[fh->input].bar[k][1];
+		b = bars[fh->input].bar[k][2];
 		is_yuv = 0;
 
 		switch (fh->fmt->fourcc) {
@@ -871,11 +945,40 @@
 		}
 	}
 
+}
+
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct vivi_fh *fh = priv;
+	struct videobuf_queue *q = &fh->vb_vidq;
+
+	int ret = vidioc_try_fmt_vid_cap(file, fh, f);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&q->vb_lock);
+
+	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+		dprintk(fh->dev, 1, "%s queue busy\n", __func__);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	fh->fmt           = get_format(f);
+	fh->width         = f->fmt.pix.width;
+	fh->height        = f->fmt.pix.height;
+	fh->vb_vidq.field = f->fmt.pix.field;
+	fh->type          = f->type;
+
+	precalculate_bars(fh);
+
 	ret = 0;
 out:
 	mutex_unlock(&q->vb_lock);
 
-	return (ret);
+	return ret;
 }
 
 static int vidioc_reqbufs(struct file *file, void *priv,
@@ -950,27 +1053,36 @@
 static int vidioc_enum_input(struct file *file, void *priv,
 				struct v4l2_input *inp)
 {
-	if (inp->index != 0)
+	if (inp->index >= NUM_INPUTS)
 		return -EINVAL;
 
 	inp->type = V4L2_INPUT_TYPE_CAMERA;
 	inp->std = V4L2_STD_525_60;
-	strcpy(inp->name, "Camera");
+	sprintf(inp->name, "Camera %u", inp->index);
 
 	return (0);
 }
 
 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
-	*i = 0;
+	struct vivi_fh *fh = priv;
+	struct vivi_dev *dev = fh->dev;
+
+	*i = dev->input;
 
 	return (0);
 }
 static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
-	if (i > 0)
+	struct vivi_fh *fh = priv;
+	struct vivi_dev *dev = fh->dev;
+
+	if (i >= NUM_INPUTS)
 		return -EINVAL;
 
+	dev->input = i;
+	precalculate_bars(fh);
+
 	return (0);
 }
 
@@ -993,12 +1105,14 @@
 static int vidioc_g_ctrl(struct file *file, void *priv,
 			 struct v4l2_control *ctrl)
 {
+	struct vivi_fh *fh = priv;
+	struct vivi_dev *dev = fh->dev;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
 		if (ctrl->id == vivi_qctrl[i].id) {
-			ctrl->value = qctl_regs[i];
-			return (0);
+			ctrl->value = dev->qctl_regs[i];
+			return 0;
 		}
 
 	return -EINVAL;
@@ -1006,16 +1120,18 @@
 static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
+	struct vivi_fh *fh = priv;
+	struct vivi_dev *dev = fh->dev;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
 		if (ctrl->id == vivi_qctrl[i].id) {
-			if (ctrl->value < vivi_qctrl[i].minimum
-			    || ctrl->value > vivi_qctrl[i].maximum) {
-					return (-ERANGE);
-				}
-			qctl_regs[i] = ctrl->value;
-			return (0);
+			if (ctrl->value < vivi_qctrl[i].minimum ||
+			    ctrl->value > vivi_qctrl[i].maximum) {
+				return -ERANGE;
+			}
+			dev->qctl_regs[i] = ctrl->value;
+			return 0;
 		}
 	return -EINVAL;
 }
@@ -1026,32 +1142,20 @@
 
 static int vivi_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct vivi_dev *dev;
+	struct vivi_dev *dev = video_drvdata(file);
 	struct vivi_fh *fh = NULL;
-	int i;
 	int retval = 0;
 
-	printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
-
-	lock_kernel();
-	list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
-		if (dev->vfd->minor == minor)
-			goto found;
-	unlock_kernel();
-	return -ENODEV;
-
-found:
 	mutex_lock(&dev->mutex);
 	dev->users++;
 
 	if (dev->users > 1) {
 		dev->users--;
-		retval = -EBUSY;
-		goto unlock;
+		mutex_unlock(&dev->mutex);
+		return -EBUSY;
 	}
 
-	dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
+	dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
 		v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
 	/* allocate + initialize per filehandle data */
@@ -1059,14 +1163,11 @@
 	if (NULL == fh) {
 		dev->users--;
 		retval = -ENOMEM;
-		goto unlock;
 	}
-unlock:
 	mutex_unlock(&dev->mutex);
-	if (retval) {
-		unlock_kernel();
+
+	if (retval)
 		return retval;
-	}
 
 	file->private_data = fh;
 	fh->dev      = dev;
@@ -1076,10 +1177,6 @@
 	fh->width    = 640;
 	fh->height   = 480;
 
-	/* Put all controls at a sane state */
-	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-		qctl_regs[i] = vivi_qctrl[i].default_value;
-
 	/* Resets frame counters */
 	dev->h = 0;
 	dev->m = 0;
@@ -1095,7 +1192,6 @@
 			sizeof(struct vivi_buffer), fh);
 
 	vivi_start_thread(fh);
-	unlock_kernel();
 
 	return 0;
 }
@@ -1151,32 +1247,6 @@
 	return 0;
 }
 
-static int vivi_release(void)
-{
-	struct vivi_dev *dev;
-	struct list_head *list;
-
-	while (!list_empty(&vivi_devlist)) {
-		list = vivi_devlist.next;
-		list_del(list);
-		dev = list_entry(list, struct vivi_dev, vivi_devlist);
-
-		if (-1 != dev->vfd->minor) {
-			printk(KERN_INFO "%s: unregistering /dev/video%d\n",
-				VIVI_MODULE_NAME, dev->vfd->num);
-			video_unregister_device(dev->vfd);
-		} else {
-			printk(KERN_INFO "%s: releasing /dev/video%d\n",
-				VIVI_MODULE_NAME, dev->vfd->num);
-			video_device_release(dev->vfd);
-		}
-
-		kfree(dev);
-	}
-
-	return 0;
-}
-
 static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct vivi_fh  *fh = file->private_data;
@@ -1239,87 +1309,130 @@
 	.tvnorms              = V4L2_STD_525_60,
 	.current_norm         = V4L2_STD_NTSC_M,
 };
+
 /* -----------------------------------------------------------------
 	Initialization and module stuff
    ------------------------------------------------------------------*/
 
+static int vivi_release(void)
+{
+	struct vivi_dev *dev;
+	struct list_head *list;
+
+	while (!list_empty(&vivi_devlist)) {
+		list = vivi_devlist.next;
+		list_del(list);
+		dev = list_entry(list, struct vivi_dev, vivi_devlist);
+
+		v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
+			dev->vfd->num);
+		video_unregister_device(dev->vfd);
+		v4l2_device_unregister(&dev->v4l2_dev);
+		kfree(dev);
+	}
+
+	return 0;
+}
+
+static int __init vivi_create_instance(int inst)
+{
+	struct vivi_dev *dev;
+	struct video_device *vfd;
+	int ret, i;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+			"%s-%03d", VIVI_MODULE_NAME, inst);
+	ret = v4l2_device_register(NULL, &dev->v4l2_dev);
+	if (ret)
+		goto free_dev;
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&dev->vidq.active);
+	init_waitqueue_head(&dev->vidq.wq);
+
+	/* initialize locks */
+	spin_lock_init(&dev->slock);
+	mutex_init(&dev->mutex);
+
+	ret = -ENOMEM;
+	vfd = video_device_alloc();
+	if (!vfd)
+		goto unreg_dev;
+
+	*vfd = vivi_template;
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+	if (ret < 0)
+		goto rel_vdev;
+
+	video_set_drvdata(vfd, dev);
+
+	/* Set all controls to their default value. */
+	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+		dev->qctl_regs[i] = vivi_qctrl[i].default_value;
+
+	/* Now that everything is fine, let's add it to device list */
+	list_add_tail(&dev->vivi_devlist, &vivi_devlist);
+
+	snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
+			vivi_template.name, vfd->num);
+
+	if (video_nr >= 0)
+		video_nr++;
+
+	dev->vfd = vfd;
+	v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
+			vfd->num);
+	return 0;
+
+rel_vdev:
+	video_device_release(vfd);
+unreg_dev:
+	v4l2_device_unregister(&dev->v4l2_dev);
+free_dev:
+	kfree(dev);
+	return ret;
+}
+
 /* This routine allocates from 1 to n_devs virtual drivers.
 
    The real maximum number of virtual drivers will depend on how many drivers
    will succeed. This is limited to the maximum number of devices that
-   videodev supports. Since there are 64 minors for video grabbers, this is
-   currently the theoretical maximum limit. However, a further limit does
-   exist at videodev that forbids any driver to register more than 32 video
-   grabbers.
+   videodev supports, which is equal to VIDEO_NUM_DEVICES.
  */
 static int __init vivi_init(void)
 {
-	int ret = -ENOMEM, i;
-	struct vivi_dev *dev;
-	struct video_device *vfd;
+	int ret = 0, i;
 
 	if (n_devs <= 0)
 		n_devs = 1;
 
 	for (i = 0; i < n_devs; i++) {
-		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-		if (!dev)
-			break;
-
-		/* init video dma queues */
-		INIT_LIST_HEAD(&dev->vidq.active);
-		init_waitqueue_head(&dev->vidq.wq);
-
-		/* initialize locks */
-		spin_lock_init(&dev->slock);
-		mutex_init(&dev->mutex);
-
-		vfd = video_device_alloc();
-		if (!vfd) {
-			kfree(dev);
-			break;
-		}
-
-		*vfd = vivi_template;
-
-		ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-		if (ret < 0) {
-			video_device_release(vfd);
-			kfree(dev);
-
-			/* If some registers succeeded, keep driver */
+		ret = vivi_create_instance(i);
+		if (ret) {
+			/* If some instantiations succeeded, keep driver */
 			if (i)
 				ret = 0;
-
 			break;
 		}
-
-		/* Now that everything is fine, let's add it to device list */
-		list_add_tail(&dev->vivi_devlist, &vivi_devlist);
-
-		snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
-			 vivi_template.name, vfd->minor);
-
-		if (video_nr >= 0)
-			video_nr++;
-
-		dev->vfd = vfd;
-		printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
-			VIVI_MODULE_NAME, vfd->num);
 	}
 
 	if (ret < 0) {
-		vivi_release();
 		printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
-	} else {
-		printk(KERN_INFO "Video Technology Magazine Virtual Video "
+		return ret;
+	}
+
+	printk(KERN_INFO "Video Technology Magazine Virtual Video "
 			"Capture Board ver %u.%u.%u successfully loaded.\n",
 			(VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
 			VIVI_VERSION & 0xFF);
 
-		/* n_devs will reflect the actual number of allocated devices */
-		n_devs = i;
-	}
+	/* n_devs will reflect the actual number of allocated devices */
+	n_devs = i;
 
 	return ret;
 }
@@ -1331,19 +1444,3 @@
 
 module_init(vivi_init);
 module_exit(vivi_exit);
-
-MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
-MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
-MODULE_LICENSE("Dual BSD/GPL");
-
-module_param(video_nr, uint, 0444);
-MODULE_PARM_DESC(video_nr, "video iminor start number");
-
-module_param(n_devs, uint, 0444);
-MODULE_PARM_DESC(n_devs, "number of video devices to create");
-
-module_param_named(debug, vivi_template.debug, int, 0444);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c
index 5d73f66..42e23a4 100644
--- a/drivers/media/video/vp27smpx.c
+++ b/drivers/media/video/vp27smpx.c
@@ -129,11 +129,6 @@
 	return 0;
 }
 
-static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops vp27smpx_core_ops = {
@@ -206,8 +201,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "vp27smpx",
-	.driverid = I2C_DRIVERID_VP27SMPX,
-	.command = vp27smpx_command,
 	.probe = vp27smpx_probe,
 	.remove = vp27smpx_remove,
 	.id_table = vp27smpx_id,
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 67aa0db..2fa7e8b 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -24,10 +24,10 @@
 #include <linux/types.h>
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-i2c-drv-legacy.h>
-#include <linux/videodev.h>
-#include <linux/video_decoder.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
 MODULE_AUTHOR("Laurent Pinchart");
@@ -37,14 +37,17 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
+
 #define VPX_TIMEOUT_COUNT  10
 
 /* ----------------------------------------------------------------------- */
 
 struct vpx3220 {
+	struct v4l2_subdev sd;
 	unsigned char reg[255];
 
-	int norm;
+	v4l2_std_id norm;
+	int ident;
 	int input;
 	int enable;
 	int bright;
@@ -53,30 +56,38 @@
 	int sat;
 };
 
+static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct vpx3220, sd);
+}
+
 static char *inputs[] = { "internal", "composite", "svideo" };
 
 /* ----------------------------------------------------------------------- */
 
-static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value)
+static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct vpx3220 *decoder = i2c_get_clientdata(client);
 
 	decoder->reg[reg] = value;
 	return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-static inline int vpx3220_read(struct i2c_client *client, u8 reg)
+static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int vpx3220_fp_status(struct i2c_client *client)
+static int vpx3220_fp_status(struct v4l2_subdev *sd)
 {
 	unsigned char status;
 	unsigned int i;
 
 	for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
-		status = vpx3220_read(client, 0x29);
+		status = vpx3220_read(sd, 0x29);
 
 		if (!(status & 4))
 			return 0;
@@ -90,57 +101,60 @@
 	return -1;
 }
 
-static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data)
+static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
 	/* Write the 16-bit address to the FPWR register */
 	if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
-		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
 		return -1;
 	}
 
-	if (vpx3220_fp_status(client) < 0)
+	if (vpx3220_fp_status(sd) < 0)
 		return -1;
 
 	/* Write the 16-bit data to the FPDAT register */
 	if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
-		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
 		return -1;
 	}
 
 	return 0;
 }
 
-static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr)
+static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr)
 {
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	s16 data;
 
 	/* Write the 16-bit address to the FPRD register */
 	if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
-		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
 		return -1;
 	}
 
-	if (vpx3220_fp_status(client) < 0)
+	if (vpx3220_fp_status(sd) < 0)
 		return -1;
 
 	/* Read the 16-bit data from the FPDAT register */
 	data = i2c_smbus_read_word_data(client, 0x28);
 	if (data == -1) {
-		v4l_dbg(1, debug, client, "%s: failed\n", __func__);
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
 		return -1;
 	}
 
 	return swab16(data);
 }
 
-static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
+static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
 {
 	u8 reg;
 	int ret = -1;
 
 	while (len >= 2) {
 		reg = *data++;
-		ret = vpx3220_write(client, reg, *data++);
+		ret = vpx3220_write(sd, reg, *data++);
 		if (ret < 0)
 			break;
 		len -= 2;
@@ -149,7 +163,7 @@
 	return ret;
 }
 
-static int vpx3220_write_fp_block(struct i2c_client *client,
+static int vpx3220_write_fp_block(struct v4l2_subdev *sd,
 		const u16 *data, unsigned int len)
 {
 	u8 reg;
@@ -157,7 +171,7 @@
 
 	while (len > 1) {
 		reg = *data++;
-		ret |= vpx3220_fp_write(client, reg, *data++);
+		ret |= vpx3220_fp_write(sd, reg, *data++);
 		len -= 2;
 	}
 
@@ -259,276 +273,277 @@
 	0x4b, 0x298,		/* PLL gain */
 };
 
-static void vpx3220_dump_i2c(struct i2c_client *client)
-{
-	int len = sizeof(init_common);
-	const unsigned char *data = init_common;
 
-	while (len > 1) {
-		v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
-			*data, vpx3220_read(client, *data));
-		data += 2;
-		len -= 2;
-	}
+static int vpx3220_init(struct v4l2_subdev *sd, u32 val)
+{
+	struct vpx3220 *decoder = to_vpx3220(sd);
+
+	vpx3220_write_block(sd, init_common, sizeof(init_common));
+	vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
+	if (decoder->norm & V4L2_STD_NTSC)
+		vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
+	else if (decoder->norm & V4L2_STD_PAL)
+		vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
+	else if (decoder->norm & V4L2_STD_SECAM)
+		vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
+	else
+		vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
+	return 0;
 }
 
-static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
+static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
 {
-	struct vpx3220 *decoder = i2c_get_clientdata(client);
+	int res = V4L2_IN_ST_NO_SIGNAL, status;
+	v4l2_std_id std = 0;
 
-	switch (cmd) {
-	case 0:
-	{
-		vpx3220_write_block(client, init_common,
-				    sizeof(init_common));
-		vpx3220_write_fp_block(client, init_fp,
-				       sizeof(init_fp) >> 1);
-		switch (decoder->norm) {
-		case VIDEO_MODE_NTSC:
-			vpx3220_write_fp_block(client, init_ntsc,
-					       sizeof(init_ntsc) >> 1);
+	status = vpx3220_fp_read(sd, 0x0f3);
+
+	v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status);
+
+	if (status < 0)
+		return status;
+
+	if ((status & 0x20) == 0) {
+		res = 0;
+
+		switch (status & 0x18) {
+		case 0x00:
+		case 0x10:
+		case 0x14:
+		case 0x18:
+			std = V4L2_STD_PAL;
 			break;
 
-		case VIDEO_MODE_PAL:
-			vpx3220_write_fp_block(client, init_pal,
-					       sizeof(init_pal) >> 1);
-			break;
-		case VIDEO_MODE_SECAM:
-			vpx3220_write_fp_block(client, init_secam,
-					       sizeof(init_secam) >> 1);
-			break;
-		default:
-			vpx3220_write_fp_block(client, init_pal,
-					       sizeof(init_pal) >> 1);
-			break;
-		}
-		break;
-	}
-
-	case DECODER_DUMP:
-	{
-		vpx3220_dump_i2c(client);
-		break;
-	}
-
-	case DECODER_GET_CAPABILITIES:
-	{
-		struct video_decoder_capability *cap = arg;
-
-		v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
-
-		cap->flags = VIDEO_DECODER_PAL |
-			     VIDEO_DECODER_NTSC |
-			     VIDEO_DECODER_SECAM |
-			     VIDEO_DECODER_AUTO |
-			     VIDEO_DECODER_CCIR;
-		cap->inputs = 3;
-		cap->outputs = 1;
-		break;
-	}
-
-	case DECODER_GET_STATUS:
-	{
-		int res = 0, status;
-
-		v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n");
-
-		status = vpx3220_fp_read(client, 0x0f3);
-
-		v4l_dbg(1, debug, client, "status: 0x%04x\n", status);
-
-		if (status < 0)
-			return status;
-
-		if ((status & 0x20) == 0) {
-			res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
-
-			switch (status & 0x18) {
-			case 0x00:
-			case 0x10:
-			case 0x14:
-			case 0x18:
-				res |= DECODER_STATUS_PAL;
-				break;
-
-			case 0x08:
-				res |= DECODER_STATUS_SECAM;
-				break;
-
-			case 0x04:
-			case 0x0c:
-			case 0x1c:
-				res |= DECODER_STATUS_NTSC;
-				break;
-			}
-		}
-
-		*(int *) arg = res;
-		break;
-	}
-
-	case DECODER_SET_NORM:
-	{
-		int *iarg = arg, data;
-		int temp_input;
-
-		/* Here we back up the input selection because it gets
-		   overwritten when we fill the registers with the
-		   choosen video norm */
-		temp_input = vpx3220_fp_read(client, 0xf2);
-
-		v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg);
-		switch (*iarg) {
-		case VIDEO_MODE_NTSC:
-			vpx3220_write_fp_block(client, init_ntsc,
-					       sizeof(init_ntsc) >> 1);
-			v4l_dbg(1, debug, client, "norm switched to NTSC\n");
+		case 0x08:
+			std = V4L2_STD_SECAM;
 			break;
 
-		case VIDEO_MODE_PAL:
-			vpx3220_write_fp_block(client, init_pal,
-					       sizeof(init_pal) >> 1);
-			v4l_dbg(1, debug, client, "norm switched to PAL\n");
+		case 0x04:
+		case 0x0c:
+		case 0x1c:
+			std = V4L2_STD_NTSC;
 			break;
-
-		case VIDEO_MODE_SECAM:
-			vpx3220_write_fp_block(client, init_secam,
-					       sizeof(init_secam) >> 1);
-			v4l_dbg(1, debug, client, "norm switched to SECAM\n");
-			break;
-
-		case VIDEO_MODE_AUTO:
-			/* FIXME This is only preliminary support */
-			data = vpx3220_fp_read(client, 0xf2) & 0x20;
-			vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
-			v4l_dbg(1, debug, client, "norm switched to AUTO\n");
-			break;
-
-		default:
-			return -EINVAL;
 		}
-		decoder->norm = *iarg;
+	}
+	if (pstd)
+		*pstd = std;
+	if (pstatus)
+		*pstatus = status;
+	return 0;
+}
 
-		/* And here we set the backed up video input again */
-		vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
-		udelay(10);
-		break;
+static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	v4l2_dbg(1, debug, sd, "querystd\n");
+	return vpx3220_status(sd, NULL, std);
+}
+
+static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	v4l2_dbg(1, debug, sd, "g_input_status\n");
+	return vpx3220_status(sd, status, NULL);
+}
+
+static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct vpx3220 *decoder = to_vpx3220(sd);
+	int temp_input;
+
+	/* Here we back up the input selection because it gets
+	   overwritten when we fill the registers with the
+	   choosen video norm */
+	temp_input = vpx3220_fp_read(sd, 0xf2);
+
+	v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std);
+	if (std & V4L2_STD_NTSC) {
+		vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
+		v4l2_dbg(1, debug, sd, "norm switched to NTSC\n");
+	} else if (std & V4L2_STD_PAL) {
+		vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
+		v4l2_dbg(1, debug, sd, "norm switched to PAL\n");
+	} else if (std & V4L2_STD_SECAM) {
+		vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
+		v4l2_dbg(1, debug, sd, "norm switched to SECAM\n");
+	} else {
+		return -EINVAL;
 	}
 
-	case DECODER_SET_INPUT:
-	{
-		int *iarg = arg, data;
+	decoder->norm = std;
 
-		/* RJ:  *iarg = 0: ST8 (PCTV) input
-		 *iarg = 1: COMPOSITE  input
-		 *iarg = 2: SVHS       input  */
+	/* And here we set the backed up video input again */
+	vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010);
+	udelay(10);
+	return 0;
+}
 
-		const int input[3][2] = {
-			{0x0c, 0},
-			{0x0d, 0},
-			{0x0e, 1}
-		};
+static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
+{
+	int data;
 
-		if (*iarg < 0 || *iarg > 2)
-			return -EINVAL;
+	/* RJ:   route->input = 0: ST8 (PCTV) input
+		 route->input = 1: COMPOSITE  input
+		 route->input = 2: SVHS       input  */
 
-		v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]);
+	const int input[3][2] = {
+		{0x0c, 0},
+		{0x0d, 0},
+		{0x0e, 1}
+	};
 
-		vpx3220_write(client, 0x33, input[*iarg][0]);
+	if (route->input < 0 || route->input > 2)
+		return -EINVAL;
 
-		data = vpx3220_fp_read(client, 0xf2) & ~(0x0020);
-		if (data < 0)
-			return data;
-		/* 0x0010 is required to latch the setting */
-		vpx3220_fp_write(client, 0xf2,
-				 data | (input[*iarg][1] << 5) | 0x0010);
+	v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[route->input]);
 
-		udelay(10);
+	vpx3220_write(sd, 0x33, input[route->input][0]);
+
+	data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020);
+	if (data < 0)
+		return data;
+	/* 0x0010 is required to latch the setting */
+	vpx3220_fp_write(sd, 0xf2,
+			data | (input[route->input][1] << 5) | 0x0010);
+
+	udelay(10);
+	return 0;
+}
+
+static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	v4l2_dbg(1, debug, sd, "s_stream %s\n", enable ? "on" : "off");
+
+	vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00));
+	return 0;
+}
+
+static int vpx3220_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	case V4L2_CID_BRIGHTNESS:
+		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
 		break;
-	}
 
-	case DECODER_SET_OUTPUT:
-	{
-		int *iarg = arg;
-
-		/* not much choice of outputs */
-		if (*iarg != 0) {
-			return -EINVAL;
-		}
+	case V4L2_CID_CONTRAST:
+		v4l2_ctrl_query_fill(qc, 0, 63, 1, 32);
 		break;
-	}
 
-	case DECODER_ENABLE_OUTPUT:
-	{
-		int *iarg = arg;
-
-		v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg);
-
-		vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
+	case V4L2_CID_SATURATION:
+		v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048);
 		break;
-	}
 
-	case DECODER_SET_PICTURE:
-	{
-		struct video_picture *pic = arg;
-
-		if (decoder->bright != pic->brightness) {
-			/* We want -128 to 128 we get 0-65535 */
-			decoder->bright = pic->brightness;
-			vpx3220_write(client, 0xe6,
-				      (decoder->bright - 32768) >> 8);
-		}
-		if (decoder->contrast != pic->contrast) {
-			/* We want 0 to 64 we get 0-65535 */
-			/* Bit 7 and 8 is for noise shaping */
-			decoder->contrast = pic->contrast;
-			vpx3220_write(client, 0xe7,
-				      (decoder->contrast >> 10) + 192);
-		}
-		if (decoder->sat != pic->colour) {
-			/* We want 0 to 4096 we get 0-65535 */
-			decoder->sat = pic->colour;
-			vpx3220_fp_write(client, 0xa0,
-					 decoder->sat >> 4);
-		}
-		if (decoder->hue != pic->hue) {
-			/* We want -512 to 512 we get 0-65535 */
-			decoder->hue = pic->hue;
-			vpx3220_fp_write(client, 0x1c,
-					 ((decoder->hue - 32768) >> 6) & 0xFFF);
-		}
+	case V4L2_CID_HUE:
+		v4l2_ctrl_query_fill(qc, -512, 511, 1, 0);
 		break;
-	}
 
 	default:
 		return -EINVAL;
 	}
-
 	return 0;
 }
 
-static int vpx3220_init_client(struct i2c_client *client)
+static int vpx3220_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
-	vpx3220_write_block(client, init_common, sizeof(init_common));
-	vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1);
-	/* Default to PAL */
-	vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1);
+	struct vpx3220 *decoder = to_vpx3220(sd);
 
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctrl->value = decoder->bright;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctrl->value = decoder->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctrl->value = decoder->sat;
+		break;
+	case V4L2_CID_HUE:
+		ctrl->value = decoder->hue;
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
 
+static int vpx3220_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct vpx3220 *decoder = to_vpx3220(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (decoder->bright != ctrl->value) {
+			decoder->bright = ctrl->value;
+			vpx3220_write(sd, 0xe6, decoder->bright);
+		}
+		break;
+	case V4L2_CID_CONTRAST:
+		if (decoder->contrast != ctrl->value) {
+			/* Bit 7 and 8 is for noise shaping */
+			decoder->contrast = ctrl->value;
+			vpx3220_write(sd, 0xe7, decoder->contrast + 192);
+		}
+		break;
+	case V4L2_CID_SATURATION:
+		if (decoder->sat != ctrl->value) {
+			decoder->sat = ctrl->value;
+			vpx3220_fp_write(sd, 0xa0, decoder->sat);
+		}
+		break;
+	case V4L2_CID_HUE:
+		if (decoder->hue != ctrl->value) {
+			decoder->hue = ctrl->value;
+			vpx3220_fp_write(sd, 0x1c, decoder->hue);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct vpx3220 *decoder = to_vpx3220(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
+	.g_chip_ident = vpx3220_g_chip_ident,
+	.init = vpx3220_init,
+	.g_ctrl = vpx3220_g_ctrl,
+	.s_ctrl = vpx3220_s_ctrl,
+	.queryctrl = vpx3220_queryctrl,
+};
+
+static const struct v4l2_subdev_tuner_ops vpx3220_tuner_ops = {
+	.s_std = vpx3220_s_std,
+};
+
+static const struct v4l2_subdev_video_ops vpx3220_video_ops = {
+	.s_routing = vpx3220_s_routing,
+	.s_stream = vpx3220_s_stream,
+	.querystd = vpx3220_querystd,
+	.g_input_status = vpx3220_g_input_status,
+};
+
+static const struct v4l2_subdev_ops vpx3220_ops = {
+	.core = &vpx3220_core_ops,
+	.tuner = &vpx3220_tuner_ops,
+	.video = &vpx3220_video_ops,
+};
+
 /* -----------------------------------------------------------------------
  * Client management code
  */
 
-static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static int vpx3220_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct vpx3220 *decoder;
+	struct v4l2_subdev *sd;
 	const char *name = NULL;
 	u8 ver;
 	u16 pn;
@@ -541,18 +556,20 @@
 	decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
 	if (decoder == NULL)
 		return -ENOMEM;
-	decoder->norm = VIDEO_MODE_PAL;
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &vpx3220_ops);
+	decoder->norm = V4L2_STD_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
 	decoder->bright = 32768;
 	decoder->contrast = 32768;
 	decoder->hue = 32768;
 	decoder->sat = 32768;
-	i2c_set_clientdata(client, decoder);
 
 	ver = i2c_smbus_read_byte_data(client, 0x00);
 	pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
 		i2c_smbus_read_byte_data(client, 0x01);
+	decoder->ident = V4L2_IDENT_VPX3220A;
 	if (ver == 0xec) {
 		switch (pn) {
 		case 0x4680:
@@ -560,26 +577,34 @@
 			break;
 		case 0x4260:
 			name = "vpx3216b";
+			decoder->ident = V4L2_IDENT_VPX3216B;
 			break;
 		case 0x4280:
 			name = "vpx3214c";
+			decoder->ident = V4L2_IDENT_VPX3214C;
 			break;
 		}
 	}
 	if (name)
-		v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+		v4l2_info(sd, "%s found @ 0x%x (%s)\n", name,
 			client->addr << 1, client->adapter->name);
 	else
-		v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n",
+		v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n",
 			ver, pn, client->addr << 1, client->adapter->name);
 
-	vpx3220_init_client(client);
+	vpx3220_write_block(sd, init_common, sizeof(init_common));
+	vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
+	/* Default to PAL */
+	vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
 	return 0;
 }
 
 static int vpx3220_remove(struct i2c_client *client)
 {
-	kfree(i2c_get_clientdata(client));
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_vpx3220(sd));
 	return 0;
 }
 
@@ -593,8 +618,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "vpx3220",
-	.driverid = I2C_DRIVERID_VPX3220,
-	.command = vpx3220_command,
 	.probe = vpx3220_probe,
 	.remove = vpx3220_remove,
 	.id_table = vpx3220_id,
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 038ff32..dcade61 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -57,7 +57,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/videodev2.h>
+#include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <linux/parport.h>
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 105a832..3b08bc4 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -42,6 +42,7 @@
 #include <asm/page.h>
 #include <asm/uaccess.h>
 #include <linux/page-flags.h>
+#include <linux/videodev.h>
 #include <media/v4l2-ioctl.h>
 
 #include "w9968cf.h"
@@ -68,7 +69,6 @@
 MODULE_LICENSE(W9968CF_MODULE_LICENSE);
 MODULE_SUPPORTED_DEVICE("Video");
 
-static int ovmod_load = W9968CF_OVMOD_LOAD;
 static unsigned short simcams = W9968CF_SIMCAMS;
 static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
 static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
@@ -111,9 +111,6 @@
 
 static unsigned int param_nv[24]; /* number of values per parameter */
 
-#ifdef CONFIG_MODULES
-module_param(ovmod_load, bool, 0644);
-#endif
 module_param(simcams, ushort, 0644);
 module_param_array(video_nr, short, &param_nv[0], 0444);
 module_param_array(packet_size, uint, &param_nv[1], 0444);
@@ -144,18 +141,6 @@
 module_param(specific_debug, bool, 0644);
 #endif
 
-#ifdef CONFIG_MODULES
-MODULE_PARM_DESC(ovmod_load,
-		 "\n<0|1> Automatic 'ovcamchip' module loading."
-		 "\n0 disabled, 1 enabled."
-		 "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
-		 "\nmodule in the system, according to its configuration, and"
-		 "\nattempts to load that module automatically. This action is"
-		 "\nperformed once as soon as the 'w9968cf' module is loaded"
-		 "\ninto memory."
-		 "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
-		 "\n");
-#endif
 MODULE_PARM_DESC(simcams,
 		 "\n<n> Number of cameras allowed to stream simultaneously."
 		 "\nn may vary from 0 to "
@@ -443,8 +428,6 @@
 				  unsigned short flags, char read_write,
 				  u8 command, int size, union i2c_smbus_data*);
 static u32 w9968cf_i2c_func(struct i2c_adapter*);
-static int w9968cf_i2c_attach_inform(struct i2c_client*);
-static int w9968cf_i2c_detach_inform(struct i2c_client*);
 
 /* Memory management */
 static void* rvmalloc(unsigned long size);
@@ -1443,19 +1426,11 @@
 		       unsigned short flags, char read_write, u8 command,
 		       int size, union i2c_smbus_data *data)
 {
-	struct w9968cf_device* cam = i2c_get_adapdata(adapter);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
+	struct w9968cf_device *cam = to_cam(v4l2_dev);
 	u8 i;
 	int err = 0;
 
-	switch (addr) {
-		case OV6xx0_SID:
-		case OV7xx0_SID:
-			break;
-		default:
-			DBG(4, "Rejected slave ID 0x%04X", addr)
-			return -EINVAL;
-	}
-
 	if (size == I2C_SMBUS_BYTE) {
 		/* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */
 		addr <<= 1;
@@ -1463,8 +1438,17 @@
 		if (read_write == I2C_SMBUS_WRITE)
 			err = w9968cf_i2c_adap_write_byte(cam, addr, command);
 		else if (read_write == I2C_SMBUS_READ)
-			err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte);
-
+			for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
+				err = w9968cf_i2c_adap_read_byte(cam, addr,
+							 &data->byte);
+				if (err) {
+					if (w9968cf_smbus_refresh_bus(cam)) {
+						err = -EIO;
+						break;
+					}
+				} else
+					break;
+			}
 	} else if (size == I2C_SMBUS_BYTE_DATA) {
 		addr <<= 1;
 
@@ -1491,7 +1475,6 @@
 		DBG(4, "Unsupported I2C transfer mode (%d)", size)
 		return -EINVAL;
 	}
-
 	return err;
 }
 
@@ -1504,44 +1487,6 @@
 }
 
 
-static int w9968cf_i2c_attach_inform(struct i2c_client* client)
-{
-	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-	int id = client->driver->id, err = 0;
-
-	if (id == I2C_DRIVERID_OVCAMCHIP) {
-		cam->sensor_client = client;
-		err = w9968cf_sensor_init(cam);
-		if (err) {
-			cam->sensor_client = NULL;
-			return err;
-		}
-	} else {
-		DBG(4, "Rejected client [%s] with driver [%s]",
-		    client->name, client->driver->driver.name)
-		return -EINVAL;
-	}
-
-	DBG(5, "I2C attach client [%s] with driver [%s]",
-	    client->name, client->driver->driver.name)
-
-	return 0;
-}
-
-
-static int w9968cf_i2c_detach_inform(struct i2c_client* client)
-{
-	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-
-	if (cam->sensor_client == client)
-		cam->sensor_client = NULL;
-
-	DBG(5, "I2C detach client [%s]", client->name)
-
-	return 0;
-}
-
-
 static int w9968cf_i2c_init(struct w9968cf_device* cam)
 {
 	int err = 0;
@@ -1554,15 +1499,13 @@
 	static struct i2c_adapter adap = {
 		.id =                I2C_HW_SMBUS_W9968CF,
 		.owner =             THIS_MODULE,
-		.client_register =   w9968cf_i2c_attach_inform,
-		.client_unregister = w9968cf_i2c_detach_inform,
 		.algo =              &algo,
 	};
 
 	memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
 	strcpy(cam->i2c_adapter.name, "w9968cf");
 	cam->i2c_adapter.dev.parent = &cam->usbdev->dev;
-	i2c_set_adapdata(&cam->i2c_adapter, cam);
+	i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev);
 
 	DBG(6, "Registering I2C adapter with kernel...")
 
@@ -2165,13 +2108,9 @@
 static int
 w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
 {
-	struct i2c_client* c = cam->sensor_client;
-	int rc = 0;
+	int rc;
 
-	if (!c || !c->driver || !c->driver->command)
-		return -EINVAL;
-
-	rc = c->driver->command(c, cmd, arg);
+	rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg);
 	/* The I2C driver returns -EPERM on non-supported controls */
 	return (rc < 0 && rc != -EPERM) ? rc : 0;
 }
@@ -2346,7 +2285,7 @@
 		goto error;
 
 	/* NOTE: Make sure width and height are a multiple of 16 */
-	switch (cam->sensor_client->addr) {
+	switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) {
 		case OV6xx0_SID:
 			cam->maxwidth = 352;
 			cam->maxheight = 288;
@@ -2651,6 +2590,7 @@
 	w9968cf_deallocate_memory(cam);
 	kfree(cam->control_buffer);
 	kfree(cam->data_buffer);
+	v4l2_device_unregister(&cam->v4l2_dev);
 
 	mutex_unlock(&w9968cf_devlist_mutex);
 }
@@ -3480,6 +3420,11 @@
 	struct list_head* ptr;
 	u8 sc = 0; /* number of simultaneous cameras */
 	static unsigned short dev_nr; /* 0 - we are handling device number n */
+	static unsigned short addrs[] = {
+		OV7xx0_SID,
+		OV6xx0_SID,
+		I2C_CLIENT_END
+	};
 
 	if (le16_to_cpu(udev->descriptor.idVendor)  == winbond_id_table[0].idVendor &&
 	    le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
@@ -3495,12 +3440,14 @@
 	if (!cam)
 		return -ENOMEM;
 
+	err = v4l2_device_register(&udev->dev, &cam->v4l2_dev);
+	if (err)
+		goto fail0;
+
 	mutex_init(&cam->dev_mutex);
 	mutex_lock(&cam->dev_mutex);
 
 	cam->usbdev = udev;
-	/* NOTE: a local copy is used to avoid possible race conditions */
-	memcpy(&cam->dev, &udev->dev, sizeof(struct device));
 
 	DBG(2, "%s detected", symbolic(camlist, mod_id))
 
@@ -3549,7 +3496,7 @@
 	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
 	video_set_drvdata(cam->v4ldev, cam);
-	cam->v4ldev->parent = &cam->dev;
+	cam->v4ldev->v4l2_dev = &cam->v4l2_dev;
 
 	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
 				    video_nr[dev_nr]);
@@ -3576,9 +3523,13 @@
 	w9968cf_turn_on_led(cam);
 
 	w9968cf_i2c_init(cam);
+	cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter,
+			"ovcamchip", "ovcamchip", addrs);
 
 	usb_set_intfdata(intf, cam);
 	mutex_unlock(&cam->dev_mutex);
+
+	err = w9968cf_sensor_init(cam);
 	return 0;
 
 fail: /* Free unused memory */
@@ -3587,6 +3538,8 @@
 	if (cam->v4ldev)
 		video_device_release(cam->v4ldev);
 	mutex_unlock(&cam->dev_mutex);
+	v4l2_device_unregister(&cam->v4l2_dev);
+fail0:
 	kfree(cam);
 	return err;
 }
@@ -3597,15 +3550,16 @@
 	struct w9968cf_device* cam =
 	   (struct w9968cf_device*)usb_get_intfdata(intf);
 
-	down_write(&w9968cf_disconnect);
-
 	if (cam) {
+		down_write(&w9968cf_disconnect);
 		/* Prevent concurrent accesses to data */
 		mutex_lock(&cam->dev_mutex);
 
 		cam->disconnected = 1;
 
-		DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id))
+		DBG(2, "Disconnecting %s...", symbolic(camlist, cam->id));
+
+		v4l2_device_disconnect(&cam->v4l2_dev);
 
 		wake_up_interruptible_all(&cam->open);
 
@@ -3621,12 +3575,12 @@
 			w9968cf_release_resources(cam);
 
 		mutex_unlock(&cam->dev_mutex);
+		up_write(&w9968cf_disconnect);
 
-		if (!cam->users)
+		if (!cam->users) {
 			kfree(cam);
+		}
 	}
-
-	up_write(&w9968cf_disconnect);
 }
 
 
@@ -3650,9 +3604,6 @@
 	KDBG(2, W9968CF_MODULE_NAME" "W9968CF_MODULE_VERSION)
 	KDBG(3, W9968CF_MODULE_AUTHOR)
 
-	if (ovmod_load)
-		request_module("ovcamchip");
-
 	if ((err = usb_register(&w9968cf_usb_driver)))
 		return err;
 
diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h
index 30032e1..fdfc6a4 100644
--- a/drivers/media/video/w9968cf.h
+++ b/drivers/media/video/w9968cf.h
@@ -33,6 +33,7 @@
 #include <linux/rwsem.h>
 #include <linux/mutex.h>
 
+#include <media/v4l2-device.h>
 #include <media/ovcamchip.h>
 
 #include "w9968cf_vpp.h"
@@ -42,7 +43,6 @@
  * Default values                                                           *
  ****************************************************************************/
 
-#define W9968CF_OVMOD_LOAD      1  /* automatic 'ovcamchip' module loading */
 #define W9968CF_VPPMOD_LOAD     1  /* automatic 'w9968cf-vpp' module loading */
 
 /* Comment/uncomment the following line to enable/disable debugging messages */
@@ -195,10 +195,9 @@
 
 /* Main device driver structure */
 struct w9968cf_device {
-	struct device dev; /* device structure */
-
 	enum w9968cf_model_id id;   /* private device identifier */
 
+	struct v4l2_device v4l2_dev;
 	struct video_device* v4ldev; /* -> V4L structure */
 	struct list_head v4llist;    /* entry of the list of V4L cameras */
 
@@ -265,7 +264,7 @@
 
 	/* I2C interface to kernel */
 	struct i2c_adapter i2c_adapter;
-	struct i2c_client* sensor_client;
+	struct v4l2_subdev *sensor_sd;
 
 	/* Locks */
 	struct mutex dev_mutex,    /* for probe, disconnect,open and close */
@@ -277,6 +276,11 @@
 	char command[16]; /* name of the program holding the device */
 };
 
+static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev);
+}
+
 
 /****************************************************************************
  * Macros for debugging                                                     *
@@ -291,14 +295,14 @@
 	if ( ((specific_debug) && (debug == (level))) ||                      \
 	     ((!specific_debug) && (debug >= (level))) ) {                    \
 		if ((level) == 1)                                             \
-			dev_err(&cam->dev, fmt "\n", ## args);                \
+			v4l2_err(&cam->v4l2_dev, fmt "\n", ## args);          \
 		else if ((level) == 2 || (level) == 3)                        \
-			dev_info(&cam->dev, fmt "\n", ## args);               \
+			v4l2_info(&cam->v4l2_dev, fmt "\n", ## args);         \
 		else if ((level) == 4)                                        \
-			dev_warn(&cam->dev, fmt "\n", ## args);               \
+			v4l2_warn(&cam->v4l2_dev, fmt "\n", ## args);         \
 		else if ((level) >= 5)                                        \
-			dev_info(&cam->dev, "[%s:%d] " fmt "\n",              \
-				 __func__, __LINE__ , ## args);           \
+			v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n",        \
+				 __func__, __LINE__ , ## args);               \
 	}                                                                     \
 }
 /* For generic kernel (not device specific) messages */
@@ -321,7 +325,7 @@
 
 #undef PDBG
 #define PDBG(fmt, args...)                                                    \
-dev_info(&cam->dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
+v4l2_info(&cam->v4l2_dev, "[%s:%d] " fmt "\n", __func__, __LINE__ , ## args);
 
 #undef PDBGG
 #define PDBGG(fmt, args...) do {;} while(0); /* nothing: it's a placeholder */
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index f2864d5..b572ce2 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -252,11 +252,6 @@
 	return 0;
 }
 
-static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops wm8739_core_ops = {
@@ -343,8 +338,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "wm8739",
-	.driverid = I2C_DRIVERID_WM8739,
-	.command = wm8739_command,
 	.probe = wm8739_probe,
 	.remove = wm8739_remove,
 	.id_table = wm8739_id,
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 53fcd4284..eddf11a 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -34,15 +34,12 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/v4l2-i2c-drv-legacy.h>
+#include <media/v4l2-i2c-drv.h>
 
 MODULE_DESCRIPTION("wm8775 driver");
 MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
 MODULE_LICENSE("GPL");
 
-static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
 
 
 /* ----------------------------------------------------------------------- */
@@ -161,11 +158,6 @@
 	return 0;
 }
 
-static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg)
-{
-	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
-}
-
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops wm8775_core_ops = {
@@ -268,8 +260,6 @@
 
 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 	.name = "wm8775",
-	.driverid = I2C_DRIVERID_WM8775,
-	.command = wm8775_command,
 	.probe = wm8775_probe,
 	.remove = wm8775_remove,
 	.id_table = wm8775_id,
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index b0cd49c..3a408de 100644
--- a/drivers/media/video/zc0301/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -58,12 +58,20 @@
 	.idProduct = (prod),                                                  \
 	.bInterfaceClass = (intclass)
 
+#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
 	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
 	{ ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */           \
 	{ }                                                                   \
 };
+#else
+#define ZC0301_ID_TABLE                                                       \
+static const struct usb_device_id zc0301_id_table[] =  {                      \
+	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
+	{ }                                                                   \
+};
+#endif
 
 /*****************************************************************************/
 
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig
index 8666e19..fd4120e 100644
--- a/drivers/media/video/zoran/Kconfig
+++ b/drivers/media/video/zoran/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_ZORAN
 	tristate "Zoran ZR36057/36067 Video For Linux"
-	depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
+	depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS
 	help
 	  Say Y for support for MJPEG capture cards based on the Zoran
 	  36057/36067 PCI controller chipset. This includes the Iomega
@@ -32,7 +32,7 @@
 config VIDEO_ZORAN_BUZ
 	tristate "Iomega Buz support"
 	depends on VIDEO_ZORAN_ZR36060
-	select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
 	help
 	  Support for the Iomega Buz MJPEG capture/playback card.
@@ -58,7 +58,7 @@
 config VIDEO_ZORAN_LML33R10
 	tristate "Linux Media Labs LML33R10 support"
 	depends on VIDEO_ZORAN_ZR36060
-	select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
+	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
 	help
 	  support for the Linux Media Labs LML33R10 MJPEG capture/playback
@@ -66,7 +66,7 @@
 
 config VIDEO_ZORAN_AVS6EYES
 	tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
-	depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
+	depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL
 	select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO
 	select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h
index 97a3bbe..5c27b25 100644
--- a/drivers/media/video/zoran/videocodec.h
+++ b/drivers/media/video/zoran/videocodec.h
@@ -97,7 +97,7 @@
 	       available) - it returns 0 if the mode is possible
    set_size -> this fn-ref. sets the norm and image size for
 	       compression/decompression (returns 0 on success)
-	       the norm param is defined in videodev.h (VIDEO_MODE_*)
+	       the norm param is defined in videodev2.h (V4L2_STD_*)
 
    additional setup may be available, too - but the codec should work with
    some default values even without this
@@ -144,9 +144,8 @@
 #ifndef __LINUX_VIDEOCODEC_H
 #define __LINUX_VIDEOCODEC_H
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 
-//should be in videodev.h ??? (VID_DO_....)
 #define CODEC_DO_COMPRESSION 0
 #define CODEC_DO_EXPANSION   1
 
@@ -237,10 +236,6 @@
 	__u32 width, height;	/* Area to capture */
 	__u16 decimation;	/* Decimation divider */
 	__u16 flags;		/* Flags for capture */
-/* flags are the same as in struct video_capture - see videodev.h:
-#define VIDEO_CAPTURE_ODD		0
-#define VIDEO_CAPTURE_EVEN		1
-*/
 	__u16 quality;		/* quality of the video */
 };
 
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
index e873a91..afecf32 100644
--- a/drivers/media/video/zoran/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
@@ -31,6 +31,8 @@
 #ifndef _BUZ_H_
 #define _BUZ_H_
 
+#include <media/v4l2-device.h>
+
 struct zoran_requestbuffers {
 	unsigned long count;	/* Number of buffers for MJPEG grabbing */
 	unsigned long size;	/* Size PER BUFFER in bytes */
@@ -170,7 +172,7 @@
 #endif
 #define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
 
-#define MAX_KMALLOC_MEM (128*1024)
+#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME)
 
 #include "zr36057.h"
 
@@ -240,9 +242,6 @@
 
 struct zoran_format {
 	char *name;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	int palette;
-#endif
 	__u32 fourcc;
 	int colorspace;
 	int depth;
@@ -283,21 +282,21 @@
 	int count;
 };
 
-struct zoran_jpg_buffer {
+struct zoran_buffer {
 	struct zoran_mapping *map;
-	__le32 *frag_tab;		/* addresses of frag table */
-	u32 frag_tab_bus;	/* same value cached to save time in ISR */
-	enum zoran_buffer_state state;	/* non-zero if corresponding buffer is in use in grab queue */
-	struct zoran_sync bs;	/* DONE: info to return to application */
-};
-
-struct zoran_v4l_buffer {
-	struct zoran_mapping *map;
-	char *fbuffer;		/* virtual  address of frame buffer */
-	unsigned long fbuffer_phys;	/* physical address of frame buffer */
-	unsigned long fbuffer_bus;	/* bus      address of frame buffer */
-	enum zoran_buffer_state state;	/* state: unused/pending/done */
-	struct zoran_sync bs;	/* DONE: info to return to application */
+	enum zoran_buffer_state state;	/* state: unused/pending/dma/done */
+	struct zoran_sync bs;		/* DONE: info to return to application */
+	union {
+		struct {
+			__le32 *frag_tab;	/* addresses of frag table */
+			u32 frag_tab_bus;	/* same value cached to save time in ISR */
+		} jpg;
+		struct {
+			char *fbuffer;		/* virtual address of frame buffer */
+			unsigned long fbuffer_phys;/* physical address of frame buffer */
+			unsigned long fbuffer_bus;/* bus address of frame buffer */
+		} v4l;
+	};
 };
 
 enum zoran_lock_activity {
@@ -307,21 +306,13 @@
 };
 
 /* buffer collections */
-struct zoran_jpg_struct {
+struct zoran_buffer_col {
 	enum zoran_lock_activity active;	/* feature currently in use? */
-	struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME];	/* buffers */
-	int num_buffers, buffer_size;
+	unsigned int num_buffers, buffer_size;
+	struct zoran_buffer buffer[MAX_FRAME];	/* buffers */
 	u8 allocated;		/* Flag if buffers are allocated  */
-	u8 ready_to_be_freed;	/* hack - see zoran_driver.c */
 	u8 need_contiguous;	/* Flag if contiguous buffers are needed */
-};
-
-struct zoran_v4l_struct {
-	enum zoran_lock_activity active;	/* feature currently in use? */
-	struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME];	/* buffers */
-	int num_buffers, buffer_size;
-	u8 allocated;		/* Flag if buffers are allocated  */
-	u8 ready_to_be_freed;	/* hack - see zoran_driver.c */
+	/* only applies to jpg buffers, raw buffers are always contiguous */
 };
 
 struct zoran;
@@ -330,23 +321,27 @@
 struct zoran_fh {
 	struct zoran *zr;
 
-	enum zoran_map_mode map_mode;	/* Flag which bufferset will map by next mmap() */
+	enum zoran_map_mode map_mode;		/* Flag which bufferset will map by next mmap() */
 
 	struct zoran_overlay_settings overlay_settings;
-	u32 *overlay_mask;	/* overlay mask */
-	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
+	u32 *overlay_mask;			/* overlay mask */
+	enum zoran_lock_activity overlay_active;/* feature currently in use? */
+
+	struct zoran_buffer_col buffers;	/* buffers' info */
 
 	struct zoran_v4l_settings v4l_settings;	/* structure with a lot of things to play with */
-	struct zoran_v4l_struct v4l_buffers;	/* V4L buffers' info */
-
 	struct zoran_jpg_settings jpg_settings;	/* structure with a lot of things to play with */
-	struct zoran_jpg_struct jpg_buffers;	/* MJPEG buffers' info */
 };
 
 struct card_info {
 	enum card_type type;
 	char name[32];
-	u16 i2c_decoder, i2c_encoder;			/* I2C types */
+	const char *i2c_decoder;	/* i2c decoder device */
+	const char *mod_decoder;	/* i2c decoder module */
+	const unsigned short *addrs_decoder;
+	const char *i2c_encoder;	/* i2c encoder device */
+	const char *mod_encoder;	/* i2c encoder module */
+	const unsigned short *addrs_encoder;
 	u16 video_vfe, video_codec;			/* videocodec types */
 	u16 audio_chip;					/* audio type */
 
@@ -356,7 +351,7 @@
 		char name[32];
 	} input[BUZ_MAX_INPUT];
 
-	int norms;
+	v4l2_std_id norms;
 	struct tvnorm *tvn[3];	/* supported TV norms */
 
 	u32 jpeg_int;		/* JPEG interrupt */
@@ -377,14 +372,15 @@
 };
 
 struct zoran {
+	struct v4l2_device v4l2_dev;
 	struct video_device *video_dev;
 
 	struct i2c_adapter i2c_adapter;	/* */
 	struct i2c_algo_bit_data i2c_algo;	/* */
 	u32 i2cbr;
 
-	struct i2c_client *decoder;	/* video decoder i2c client */
-	struct i2c_client *encoder;	/* video encoder i2c client */
+	struct v4l2_subdev *decoder;	/* video decoder sub-device */
+	struct v4l2_subdev *encoder;	/* video encoder sub-device */
 
 	struct videocodec *codec;	/* video codec */
 	struct videocodec *vfe;	/* video front end */
@@ -405,9 +401,15 @@
 	spinlock_t spinlock;	/* Spinlock */
 
 	/* Video for Linux parameters */
-	int input, norm;	/* card's norm and input - norm=VIDEO_MODE_* */
-	int hue, saturation, contrast, brightness;	/* Current picture params */
-	struct video_buffer buffer;	/* Current buffer params */
+	int input;	/* card's norm and input - norm=VIDEO_MODE_* */
+	v4l2_std_id norm;
+
+	/* Current buffer params */
+	void    *vbuf_base;
+	int     vbuf_height, vbuf_width;
+	int     vbuf_depth;
+	int     vbuf_bytesperline;
+
 	struct zoran_overlay_settings overlay_settings;
 	u32 *overlay_mask;	/* overlay mask */
 	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
@@ -427,7 +429,7 @@
 	unsigned long v4l_pend_tail;
 	unsigned long v4l_sync_tail;
 	int v4l_pend[V4L_MAX_FRAME];
-	struct zoran_v4l_struct v4l_buffers;	/* V4L buffers' info */
+	struct zoran_buffer_col v4l_buffers;	/* V4L buffers' info */
 
 	/* Buz MJPEG parameters */
 	enum zoran_codec_mode codec_mode;	/* status of codec */
@@ -454,7 +456,7 @@
 	int jpg_pend[BUZ_MAX_FRAME];
 
 	/* array indexed by frame number */
-	struct zoran_jpg_struct jpg_buffers;	/* MJPEG buffers' info */
+	struct zoran_buffer_col jpg_buffers;	/* MJPEG buffers' info */
 
 	/* Additional stuff for testing */
 #ifdef CONFIG_PROC_FS
@@ -488,6 +490,11 @@
 	wait_queue_head_t test_q;
 };
 
+static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct zoran, v4l2_dev);
+}
+
 /* There was something called _ALPHA_BUZ that used the PCI address instead of
  * the kernel iomapped address for btread/btwrite.  */
 #define btwrite(dat,adr)    writel((dat), zr->zr36057_mem+(adr))
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index 5d2f090..f91bba4 100644
--- a/drivers/media/video/zoran/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -38,8 +38,7 @@
 #include <linux/proc_fs.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
+#include <linux/videodev2.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/kmod.h>
@@ -47,11 +46,10 @@
 
 #include <linux/pci.h>
 #include <linux/interrupt.h>
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
 #include <linux/mutex.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
+#include <media/v4l2-common.h>
+#include <media/bt819.h>
 
 #include "videocodec.h"
 #include "zoran.h"
@@ -108,25 +106,8 @@
 module_param_array(video_nr, int, NULL, 0444);
 MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
 
-/*
-   Number and size of grab buffers for Video 4 Linux
-   The vast majority of applications should not need more than 2,
-   the very popular BTTV driver actually does ONLY have 2.
-   Time sensitive applications might need more, the maximum
-   is VIDEO_MAX_FRAME (defined in <linux/videodev.h>).
-
-   The size is set so that the maximum possible request
-   can be satisfied. Decrease  it, if bigphys_area alloc'd
-   memory is low. If you don't have the bigphys_area patch,
-   set it to 128 KB. Will you allow only to grab small
-   images with V4L, but that's better than nothing.
-
-   v4l_bufsize has to be given in KB !
-
-*/
-
-int v4l_nbufs = 2;
-int v4l_bufsize = 128;		/* Everybody should be able to work with this setting */
+int v4l_nbufs = 4;
+int v4l_bufsize = 864;		/* Everybody should be able to work with this setting */
 module_param(v4l_nbufs, int, 0644);
 MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
 module_param(v4l_bufsize, int, 0644);
@@ -273,7 +254,7 @@
 static void
 dc10_init (struct zoran *zr)
 {
-	dprintk(3, KERN_DEBUG "%s: dc10_init()\n", ZR_DEVNAME(zr));
+	dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
 
 	/* Pixel clock selection */
 	GPIO(zr, 4, 0);
@@ -285,13 +266,13 @@
 static void
 dc10plus_init (struct zoran *zr)
 {
-	dprintk(3, KERN_DEBUG "%s: dc10plus_init()\n", ZR_DEVNAME(zr));
+	dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
 }
 
 static void
 buz_init (struct zoran *zr)
 {
-	dprintk(3, KERN_DEBUG "%s: buz_init()\n", ZR_DEVNAME(zr));
+	dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
 
 	/* some stuff from Iomega */
 	pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
@@ -302,7 +283,7 @@
 static void
 lml33_init (struct zoran *zr)
 {
-	dprintk(3, KERN_DEBUG "%s: lml33_init()\n", ZR_DEVNAME(zr));
+	dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
 
 	GPIO(zr, 2, 1);		// Set Composite input/output
 }
@@ -332,50 +313,6 @@
 }
 
 static char *
-i2cid_to_modulename (u16 i2c_id)
-{
-	char *name = NULL;
-
-	switch (i2c_id) {
-	case I2C_DRIVERID_SAA7110:
-		name = "saa7110";
-		break;
-	case I2C_DRIVERID_SAA7111A:
-		name = "saa7111";
-		break;
-	case I2C_DRIVERID_SAA7114:
-		name = "saa7114";
-		break;
-	case I2C_DRIVERID_SAA7185B:
-		name = "saa7185";
-		break;
-	case I2C_DRIVERID_ADV7170:
-		name = "adv7170";
-		break;
-	case I2C_DRIVERID_ADV7175:
-		name = "adv7175";
-		break;
-	case I2C_DRIVERID_BT819:
-		name = "bt819";
-		break;
-	case I2C_DRIVERID_BT856:
-		name = "bt856";
-		break;
-	case I2C_DRIVERID_BT866:
-		name = "bt866";
-		break;
-	case I2C_DRIVERID_VPX3220:
-		name = "vpx3220";
-		break;
-	case I2C_DRIVERID_KS0127:
-		name = "ks0127";
-		break;
-	}
-
-	return name;
-}
-
-static char *
 codecid_to_modulename (u16 codecid)
 {
 	char *name = NULL;
@@ -425,11 +362,24 @@
 static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
 static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
 
+static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END };
+static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END };
+static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END };
+static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END };
+static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END };
+static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END };
+static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END };
+static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END };
+
 static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
 	{
 		.type = DC10_old,
 		.name = "DC10(old)",
-		.i2c_decoder = I2C_DRIVERID_VPX3220,
+		.i2c_decoder = "vpx3220a",
+		.mod_decoder = "vpx3220",
+		.addrs_decoder = vpx3220_addrs,
 		.video_codec = CODEC_TYPE_ZR36050,
 		.video_vfe = CODEC_TYPE_ZR36016,
 
@@ -439,7 +389,7 @@
 			{ 2, "S-Video" },
 			{ 0, "Internal/comp" }
 		},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 			&f50sqpixel_dc10,
 			&f60sqpixel_dc10,
@@ -457,8 +407,12 @@
 	}, {
 		.type = DC10_new,
 		.name = "DC10(new)",
-		.i2c_decoder = I2C_DRIVERID_SAA7110,
-		.i2c_encoder = I2C_DRIVERID_ADV7175,
+		.i2c_decoder = "saa7110",
+		.mod_decoder = "saa7110",
+		.addrs_decoder = saa7110_addrs,
+		.i2c_encoder = "adv7175",
+		.mod_encoder = "adv7175",
+		.addrs_encoder = adv717x_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 3,
@@ -467,7 +421,7 @@
 				{ 7, "S-Video" },
 				{ 5, "Internal/comp" }
 			},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 				&f50sqpixel,
 				&f60sqpixel,
@@ -484,8 +438,12 @@
 	}, {
 		.type = DC10plus,
 		.name = "DC10plus",
-		.i2c_decoder = I2C_DRIVERID_SAA7110,
-		.i2c_encoder = I2C_DRIVERID_ADV7175,
+		.i2c_decoder = "saa7110",
+		.mod_decoder = "saa7110",
+		.addrs_decoder = saa7110_addrs,
+		.i2c_encoder = "adv7175",
+		.mod_encoder = "adv7175",
+		.addrs_encoder = adv717x_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 3,
@@ -494,7 +452,7 @@
 			{ 7, "S-Video" },
 			{ 5, "Internal/comp" }
 		},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 			&f50sqpixel,
 			&f60sqpixel,
@@ -512,8 +470,12 @@
 	}, {
 		.type = DC30,
 		.name = "DC30",
-		.i2c_decoder = I2C_DRIVERID_VPX3220,
-		.i2c_encoder = I2C_DRIVERID_ADV7175,
+		.i2c_decoder = "vpx3220a",
+		.mod_decoder = "vpx3220",
+		.addrs_decoder = vpx3220_addrs,
+		.i2c_encoder = "adv7175",
+		.mod_encoder = "adv7175",
+		.addrs_encoder = adv717x_addrs,
 		.video_codec = CODEC_TYPE_ZR36050,
 		.video_vfe = CODEC_TYPE_ZR36016,
 
@@ -523,7 +485,7 @@
 			{ 2, "S-Video" },
 			{ 0, "Internal/comp" }
 		},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 			&f50sqpixel_dc10,
 			&f60sqpixel_dc10,
@@ -541,8 +503,12 @@
 	}, {
 		.type = DC30plus,
 		.name = "DC30plus",
-		.i2c_decoder = I2C_DRIVERID_VPX3220,
-		.i2c_encoder = I2C_DRIVERID_ADV7175,
+		.i2c_decoder = "vpx3220a",
+		.mod_decoder = "vpx3220",
+		.addrs_decoder = vpx3220_addrs,
+		.i2c_encoder = "adv7175",
+		.mod_encoder = "adv7175",
+		.addrs_encoder = adv717x_addrs,
 		.video_codec = CODEC_TYPE_ZR36050,
 		.video_vfe = CODEC_TYPE_ZR36016,
 
@@ -552,7 +518,7 @@
 			{ 2, "S-Video" },
 			{ 0, "Internal/comp" }
 		},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 			&f50sqpixel_dc10,
 			&f60sqpixel_dc10,
@@ -570,8 +536,12 @@
 	}, {
 		.type = LML33,
 		.name = "LML33",
-		.i2c_decoder = I2C_DRIVERID_BT819,
-		.i2c_encoder = I2C_DRIVERID_BT856,
+		.i2c_decoder = "bt819a",
+		.mod_decoder = "bt819",
+		.addrs_decoder = bt819_addrs,
+		.i2c_encoder = "bt856",
+		.mod_encoder = "bt856",
+		.addrs_encoder = bt856_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 2,
@@ -579,7 +549,7 @@
 			{ 0, "Composite" },
 			{ 7, "S-Video" }
 		},
-		.norms = 2,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
 		.tvn = {
 			&f50ccir601_lml33,
 			&f60ccir601_lml33,
@@ -597,8 +567,12 @@
 	}, {
 		.type = LML33R10,
 		.name = "LML33R10",
-		.i2c_decoder = I2C_DRIVERID_SAA7114,
-		.i2c_encoder = I2C_DRIVERID_ADV7170,
+		.i2c_decoder = "saa7114",
+		.mod_decoder = "saa7115",
+		.addrs_decoder = saa7114_addrs,
+		.i2c_encoder = "adv7170",
+		.mod_encoder = "adv7170",
+		.addrs_encoder = adv717x_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 2,
@@ -606,7 +580,7 @@
 			{ 0, "Composite" },
 			{ 7, "S-Video" }
 		},
-		.norms = 2,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
 		.tvn = {
 			&f50ccir601_lm33r10,
 			&f60ccir601_lm33r10,
@@ -624,8 +598,12 @@
 	}, {
 		.type = BUZ,
 		.name = "Buz",
-		.i2c_decoder = I2C_DRIVERID_SAA7111A,
-		.i2c_encoder = I2C_DRIVERID_SAA7185B,
+		.i2c_decoder = "saa7111",
+		.mod_decoder = "saa7115",
+		.addrs_decoder = saa7111_addrs,
+		.i2c_encoder = "saa7185",
+		.mod_encoder = "saa7185",
+		.addrs_encoder = saa7185_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 2,
@@ -633,7 +611,7 @@
 			{ 3, "Composite" },
 			{ 7, "S-Video" }
 		},
-		.norms = 3,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
 		.tvn = {
 			&f50ccir601,
 			&f60ccir601,
@@ -653,8 +631,12 @@
 		.name = "6-Eyes",
 		/* AverMedia chose not to brand the 6-Eyes. Thus it
 		   can't be autodetected, and requires card=x. */
-		.i2c_decoder = I2C_DRIVERID_KS0127,
-		.i2c_encoder = I2C_DRIVERID_BT866,
+		.i2c_decoder = "ks0127",
+		.mod_decoder = "ks0127",
+		.addrs_decoder = ks0127_addrs,
+		.i2c_encoder = "bt866",
+		.mod_encoder = "bt866",
+		.addrs_encoder = bt866_addrs,
 		.video_codec = CODEC_TYPE_ZR36060,
 
 		.inputs = 10,
@@ -670,7 +652,7 @@
 			{10, "S-Video 3" },
 			{15, "YCbCr" }
 		},
-		.norms = 2,
+		.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
 		.tvn = {
 			&f50ccir601_avs6eyes,
 			&f60ccir601_avs6eyes,
@@ -735,69 +717,6 @@
 	btwrite(zr->i2cbr, ZR36057_I2CBR);
 }
 
-static int
-zoran_i2c_client_register (struct i2c_client *client)
-{
-	struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
-	int res = 0;
-
-	dprintk(2,
-		KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n",
-		ZR_DEVNAME(zr), client->driver->id);
-
-	mutex_lock(&zr->resource_lock);
-
-	if (zr->user > 0) {
-		/* we're already busy, so we keep a reference to
-		 * them... Could do a lot of stuff here, but this
-		 * is easiest. (Did I ever mention I'm a lazy ass?)
-		 */
-		res = -EBUSY;
-		goto clientreg_unlock_and_return;
-	}
-
-	if (client->driver->id == zr->card.i2c_decoder)
-		zr->decoder = client;
-	else if (client->driver->id == zr->card.i2c_encoder)
-		zr->encoder = client;
-	else {
-		res = -ENODEV;
-		goto clientreg_unlock_and_return;
-	}
-
-clientreg_unlock_and_return:
-	mutex_unlock(&zr->resource_lock);
-
-	return res;
-}
-
-static int
-zoran_i2c_client_unregister (struct i2c_client *client)
-{
-	struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
-	int res = 0;
-
-	dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr));
-
-	mutex_lock(&zr->resource_lock);
-
-	if (zr->user > 0) {
-		res = -EBUSY;
-		goto clientunreg_unlock_and_return;
-	}
-
-	/* try to locate it */
-	if (client == zr->encoder) {
-		zr->encoder = NULL;
-	} else if (client == zr->decoder) {
-		zr->decoder = NULL;
-		snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id);
-	}
-clientunreg_unlock_and_return:
-	mutex_unlock(&zr->resource_lock);
-	return res;
-}
-
 static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
 	.setsda = zoran_i2c_setsda,
 	.setscl = zoran_i2c_setscl,
@@ -813,13 +732,10 @@
 	memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
 	       sizeof(struct i2c_algo_bit_data));
 	zr->i2c_algo.data = zr;
-	zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG;
 	zr->i2c_adapter.id = I2C_HW_B_ZR36067;
-	zr->i2c_adapter.client_register = zoran_i2c_client_register;
-	zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
 	strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
 		sizeof(zr->i2c_adapter.name));
-	i2c_set_adapdata(&zr->i2c_adapter, zr);
+	i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev);
 	zr->i2c_adapter.algo_data = &zr->i2c_algo;
 	zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
 	return i2c_bit_add_bus(&zr->i2c_adapter);
@@ -835,19 +751,20 @@
 
 int
 zoran_check_jpg_settings (struct zoran              *zr,
-			  struct zoran_jpg_settings *settings)
+			  struct zoran_jpg_settings *settings,
+			  int try)
 {
 	int err = 0, err0 = 0;
 
 	dprintk(4,
 		KERN_DEBUG
-		"%s: check_jpg_settings() - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
-		ZR_DEVNAME(zr), settings->decimation, settings->HorDcm,
+		"%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
+		ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm,
 		settings->VerDcm, settings->TmpDcm);
 	dprintk(4,
 		KERN_DEBUG
-		"%s: check_jpg_settings() - x: %d, y: %d, w: %d, y: %d\n",
-		ZR_DEVNAME(zr), settings->img_x, settings->img_y,
+		"%s: %s - x: %d, y: %d, w: %d, y: %d\n",
+		ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y,
 		settings->img_width, settings->img_height);
 	/* Check decimation, set default values for decimation = 1, 2, 4 */
 	switch (settings->decimation) {
@@ -879,8 +796,8 @@
 		if (zr->card.type == DC10_new) {
 			dprintk(1,
 				KERN_DEBUG
-				"%s: check_jpg_settings() - HDec by 4 is not supported on the DC10\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - HDec by 4 is not supported on the DC10\n",
+				ZR_DEVNAME(zr), __func__);
 			err0++;
 			break;
 		}
@@ -900,50 +817,73 @@
 		/* We have to check the data the user has set */
 
 		if (settings->HorDcm != 1 && settings->HorDcm != 2 &&
-		    (zr->card.type == DC10_new || settings->HorDcm != 4))
+		    (zr->card.type == DC10_new || settings->HorDcm != 4)) {
+			settings->HorDcm = clamp(settings->HorDcm, 1, 2);
 			err0++;
-		if (settings->VerDcm != 1 && settings->VerDcm != 2)
+		}
+		if (settings->VerDcm != 1 && settings->VerDcm != 2) {
+			settings->VerDcm = clamp(settings->VerDcm, 1, 2);
 			err0++;
-		if (settings->TmpDcm != 1 && settings->TmpDcm != 2)
+		}
+		if (settings->TmpDcm != 1 && settings->TmpDcm != 2) {
+			settings->TmpDcm = clamp(settings->TmpDcm, 1, 2);
 			err0++;
+		}
 		if (settings->field_per_buff != 1 &&
-		    settings->field_per_buff != 2)
+		    settings->field_per_buff != 2) {
+			settings->field_per_buff = clamp(settings->field_per_buff, 1, 2);
 			err0++;
-		if (settings->img_x < 0)
+		}
+		if (settings->img_x < 0) {
+			settings->img_x = 0;
 			err0++;
-		if (settings->img_y < 0)
+		}
+		if (settings->img_y < 0) {
+			settings->img_y = 0;
 			err0++;
-		if (settings->img_width < 0)
+		}
+		if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) {
+			settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH);
 			err0++;
-		if (settings->img_height < 0)
+		}
+		if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) {
+			settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2);
 			err0++;
-		if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH)
+		}
+		if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) {
+			settings->img_x = BUZ_MAX_WIDTH - settings->img_width;
 			err0++;
-		if (settings->img_y + settings->img_height >
-		    BUZ_MAX_HEIGHT / 2)
+		}
+		if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) {
+			settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height;
 			err0++;
-		if (settings->HorDcm && settings->VerDcm) {
-			if (settings->img_width %
-			    (16 * settings->HorDcm) != 0)
-				err0++;
-			if (settings->img_height %
-			    (8 * settings->VerDcm) != 0)
-				err0++;
+		}
+		if (settings->img_width % (16 * settings->HorDcm) != 0) {
+			settings->img_width -= settings->img_width % (16 * settings->HorDcm);
+			if (settings->img_width == 0)
+				settings->img_width = 16 * settings->HorDcm;
+			err0++;
+		}
+		if (settings->img_height % (8 * settings->VerDcm) != 0) {
+			settings->img_height -= settings->img_height % (8 * settings->VerDcm);
+			if (settings->img_height == 0)
+				settings->img_height = 8 * settings->VerDcm;
+			err0++;
 		}
 
-		if (err0) {
+		if (!try && err0) {
 			dprintk(1,
 				KERN_ERR
-				"%s: check_jpg_settings() - error in params for decimation = 0\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - error in params for decimation = 0\n",
+				ZR_DEVNAME(zr), __func__);
 			err++;
 		}
 		break;
 	default:
 		dprintk(1,
 			KERN_ERR
-			"%s: check_jpg_settings() - decimation = %d, must be 0, 1, 2 or 4\n",
-			ZR_DEVNAME(zr), settings->decimation);
+			"%s: %s - decimation = %d, must be 0, 1, 2 or 4\n",
+			ZR_DEVNAME(zr), __func__, settings->decimation);
 		err++;
 		break;
 	}
@@ -1021,12 +961,10 @@
 	       sizeof(zr->jpg_settings.jpg_comp.COM_data));
 	zr->jpg_settings.jpg_comp.jpeg_markers =
 	    JPEG_MARKER_DHT | JPEG_MARKER_DQT;
-	i = zoran_check_jpg_settings(zr, &zr->jpg_settings);
+	i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
 	if (i)
-		dprintk(1,
-			KERN_ERR
-			"%s: zoran_open_init_params() internal error\n",
-			ZR_DEVNAME(zr));
+		dprintk(1, KERN_ERR "%s: %s internal error\n",
+			ZR_DEVNAME(zr), __func__);
 
 	clear_interrupt_counters(zr);
 	zr->testing = 0;
@@ -1062,13 +1000,11 @@
 zr36057_init (struct zoran *zr)
 {
 	int j, err;
-	int two = 2;
-	int zero = 0;
 
 	dprintk(1,
 		KERN_INFO
-		"%s: zr36057_init() - initializing card[%d], zr=%p\n",
-		ZR_DEVNAME(zr), zr->id, zr);
+		"%s: %s - initializing card[%d], zr=%p\n",
+		ZR_DEVNAME(zr), __func__, zr->id, zr);
 
 	/* default setup of all parameters which will persist between opens */
 	zr->user = 0;
@@ -1079,24 +1015,32 @@
 	zr->jpg_buffers.allocated = 0;
 	zr->v4l_buffers.allocated = 0;
 
-	zr->buffer.base = (void *) vidmem;
-	zr->buffer.width = 0;
-	zr->buffer.height = 0;
-	zr->buffer.depth = 0;
-	zr->buffer.bytesperline = 0;
+	zr->vbuf_base = (void *) vidmem;
+	zr->vbuf_width = 0;
+	zr->vbuf_height = 0;
+	zr->vbuf_depth = 0;
+	zr->vbuf_bytesperline = 0;
 
 	/* Avoid nonsense settings from user for default input/norm */
-	if (default_norm < VIDEO_MODE_PAL &&
-	    default_norm > VIDEO_MODE_SECAM)
-		default_norm = VIDEO_MODE_PAL;
-	zr->norm = default_norm;
-	if (!(zr->timing = zr->card.tvn[zr->norm])) {
+	if (default_norm < 0 && default_norm > 2)
+		default_norm = 0;
+	if (default_norm == 0) {
+		zr->norm = V4L2_STD_PAL;
+		zr->timing = zr->card.tvn[0];
+	} else if (default_norm == 1) {
+		zr->norm = V4L2_STD_NTSC;
+		zr->timing = zr->card.tvn[1];
+	} else {
+		zr->norm = V4L2_STD_SECAM;
+		zr->timing = zr->card.tvn[2];
+	}
+	if (zr->timing == NULL) {
 		dprintk(1,
 			KERN_WARNING
-			"%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n",
-			ZR_DEVNAME(zr));
-		zr->norm = VIDEO_MODE_PAL;
-		zr->timing = zr->card.tvn[zr->norm];
+			"%s: %s - default TV standard not supported by hardware. PAL will be used.\n",
+			ZR_DEVNAME(zr), __func__);
+		zr->norm = V4L2_STD_PAL;
+		zr->timing = zr->card.tvn[0];
 	}
 
 	if (default_input > zr->card.inputs-1) {
@@ -1108,12 +1052,6 @@
 	}
 	zr->input = default_input;
 
-	/* Should the following be reset at every open ? */
-	zr->hue = 32768;
-	zr->contrast = 32768;
-	zr->saturation = 32768;
-	zr->brightness = 32768;
-
 	/* default setup (will be repeated at every open) */
 	zoran_open_init_params(zr);
 
@@ -1124,8 +1062,8 @@
 	if (!zr->stat_com || !zr->video_dev) {
 		dprintk(1,
 			KERN_ERR
-			"%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - kmalloc (STAT_COM) failed\n",
+			ZR_DEVNAME(zr), __func__);
 		err = -ENOMEM;
 		goto exit_free;
 	}
@@ -1137,6 +1075,7 @@
 	 *   Now add the template and register the device unit.
 	 */
 	memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
+	zr->video_dev->parent = &zr->pci_dev->dev;
 	strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
 	err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
 	if (err < 0)
@@ -1148,8 +1087,10 @@
 		detect_guest_activity(zr);
 	test_interrupts(zr);
 	if (!pass_through) {
-		decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
-		encoder_command(zr, ENCODER_SET_INPUT, &two);
+		struct v4l2_routing route = { 2, 0 };
+
+		decoder_call(zr, video, s_stream, 0);
+		encoder_call(zr, video, s_routing, &route);
 	}
 
 	zr->zoran_proc = NULL;
@@ -1164,7 +1105,8 @@
 
 static void __devexit zoran_remove(struct pci_dev *pdev)
 {
-	struct zoran *zr = pci_get_drvdata(pdev);
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+	struct zoran *zr = to_zoran(v4l2_dev);
 
 	if (!zr->initialized)
 		goto exit_free;
@@ -1197,7 +1139,7 @@
 	pci_disable_device(zr->pci_dev);
 	video_unregister_device(zr->video_dev);
 exit_free:
-	pci_set_drvdata(pdev, NULL);
+	v4l2_device_unregister(&zr->v4l2_dev);
 	kfree(zr);
 }
 
@@ -1215,10 +1157,8 @@
 
 	m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL);
 	if (!m) {
-		dprintk(1,
-			KERN_ERR
-			"%s: zoran_setup_videocodec() - no memory\n",
-			ZR_DEVNAME(zr));
+		dprintk(1, KERN_ERR "%s: %s - no memory\n",
+			ZR_DEVNAME(zr), __func__);
 		return m;
 	}
 
@@ -1256,6 +1196,18 @@
 	return m;
 }
 
+static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct zoran *zr = to_zoran(sd->v4l2_dev);
+
+	/* Bt819 needs to reset its FIFO buffer using #FRST pin and
+	   LML33 card uses GPIO(7) for that. */
+	if (cmd == BT819_FIFO_RESET_LOW)
+		GPIO(zr, 7, 0);
+	else if (cmd == BT819_FIFO_RESET_HIGH)
+		GPIO(zr, 7, 1);
+}
+
 /*
  *   Scan for a Buz card (actually for the PCI controller ZR36057),
  *   request the irq and map the io memory
@@ -1269,34 +1221,33 @@
 	struct videocodec_master *master_vfe = NULL;
 	struct videocodec_master *master_codec = NULL;
 	int card_num;
-	char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name;
+	char *codec_name, *vfe_name;
 	unsigned int nr;
 
 
 	nr = zoran_num++;
 	if (nr >= BUZ_MAX) {
-		dprintk(1,
-			KERN_ERR
-			"%s: driver limited to %d card(s) maximum\n",
+		dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n",
 			ZORAN_NAME, BUZ_MAX);
 		return -ENOENT;
 	}
 
 	zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
 	if (!zr) {
-		dprintk(1,
-			KERN_ERR
-			"%s: find_zr36057() - kzalloc failed\n",
-			ZORAN_NAME);
+		dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n",
+			ZORAN_NAME, __func__);
 		return -ENOMEM;
 	}
+	zr->v4l2_dev.notify = zoran_subdev_notify;
+	if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev))
+		goto zr_free_mem;
 	zr->pci_dev = pdev;
 	zr->id = nr;
 	snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
 	spin_lock_init(&zr->spinlock);
 	mutex_init(&zr->resource_lock);
 	if (pci_enable_device(pdev))
-		goto zr_free_mem;
+		goto zr_unreg;
 	pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision);
 
 	dprintk(1,
@@ -1323,7 +1274,7 @@
 				KERN_ERR
 				"%s: It is not possible to auto-detect ZR36057 based cards\n",
 				ZR_DEVNAME(zr));
-			goto zr_free_mem;
+			goto zr_unreg;
 		}
 
 		card_num = ent->driver_data;
@@ -1332,7 +1283,7 @@
 				KERN_ERR
 				"%s: Unknown card, try specifying card=X module parameter\n",
 				ZR_DEVNAME(zr));
-			goto zr_free_mem;
+			goto zr_unreg;
 		}
 		dprintk(3,
 			KERN_DEBUG
@@ -1345,7 +1296,7 @@
 				KERN_ERR
 				"%s: User specified card type %d out of range (0 .. %d)\n",
 				ZR_DEVNAME(zr), card_num, NUM_CARDS - 1);
-			goto zr_free_mem;
+			goto zr_unreg;
 		}
 	}
 
@@ -1360,11 +1311,9 @@
 
 	zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0);
 	if (!zr->zr36057_mem) {
-		dprintk(1,
-			KERN_ERR
-			"%s: %s() - ioremap failed\n",
+		dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n",
 			ZR_DEVNAME(zr), __func__);
-		goto zr_free_mem;
+		goto zr_unreg;
 	}
 
 	result = request_irq(zr->pci_dev->irq, zoran_irq,
@@ -1373,18 +1322,18 @@
 		if (result == -EINVAL) {
 			dprintk(1,
 				KERN_ERR
-				"%s: find_zr36057() - bad irq number or handler\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - bad irq number or handler\n",
+				ZR_DEVNAME(zr), __func__);
 		} else if (result == -EBUSY) {
 			dprintk(1,
 				KERN_ERR
-				"%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
-				ZR_DEVNAME(zr), zr->pci_dev->irq);
+				"%s: %s - IRQ %d busy, change your PnP config in BIOS\n",
+				ZR_DEVNAME(zr), __func__, zr->pci_dev->irq);
 		} else {
 			dprintk(1,
 				KERN_ERR
-				"%s: find_zr36057() - can't assign irq, error code %d\n",
-				ZR_DEVNAME(zr), result);
+				"%s: %s - can't assign irq, error code %d\n",
+				ZR_DEVNAME(zr), __func__, result);
 		}
 		goto zr_unmap;
 	}
@@ -1394,9 +1343,7 @@
 			     &latency);
 	need_latency = zr->revision > 1 ? 32 : 48;
 	if (latency != need_latency) {
-		dprintk(2,
-			KERN_INFO
-			"%s: Changing PCI latency from %d to %d\n",
+		dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n",
 			ZR_DEVNAME(zr), latency, need_latency);
 		pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
 				      need_latency);
@@ -1407,54 +1354,20 @@
 	dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
 		ZR_DEVNAME(zr));
 
-	/* i2c decoder */
-	if (decoder[zr->id] != -1) {
-		i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
-		zr->card.i2c_decoder = decoder[zr->id];
-	} else if (zr->card.i2c_decoder != 0) {
-		i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder);
-	} else {
-		i2c_dec_name = NULL;
-	}
-
-	if (i2c_dec_name) {
-		result = request_module(i2c_dec_name);
-		if (result < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s: failed to load module %s: %d\n",
-				ZR_DEVNAME(zr), i2c_dec_name, result);
-		}
-	}
-
-	/* i2c encoder */
-	if (encoder[zr->id] != -1) {
-		i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
-		zr->card.i2c_encoder = encoder[zr->id];
-	} else if (zr->card.i2c_encoder != 0) {
-		i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder);
-	} else {
-		i2c_enc_name = NULL;
-	}
-
-	if (i2c_enc_name) {
-		result = request_module(i2c_enc_name);
-		if (result < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s: failed to load module %s: %d\n",
-				ZR_DEVNAME(zr), i2c_enc_name, result);
-		}
-	}
-
 	if (zoran_register_i2c(zr) < 0) {
-		dprintk(1,
-			KERN_ERR
-			"%s: find_zr36057() - can't initialize i2c bus\n",
-			ZR_DEVNAME(zr));
+		dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n",
+			ZR_DEVNAME(zr), __func__);
 		goto zr_free_irq;
 	}
 
+	zr->decoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter,
+		zr->card.mod_decoder, zr->card.i2c_decoder, zr->card.addrs_decoder);
+
+	if (zr->card.mod_encoder)
+		zr->encoder = v4l2_i2c_new_probed_subdev(&zr->i2c_adapter,
+			zr->card.mod_encoder, zr->card.i2c_encoder,
+			zr->card.addrs_encoder);
+
 	dprintk(2,
 		KERN_INFO "%s: Initializing videocodec bus...\n",
 		ZR_DEVNAME(zr));
@@ -1495,17 +1408,13 @@
 			goto zr_unreg_i2c;
 		zr->codec = videocodec_attach(master_codec);
 		if (!zr->codec) {
-			dprintk(1,
-				KERN_ERR
-				"%s: find_zr36057() - no codec found\n",
-				ZR_DEVNAME(zr));
+			dprintk(1, KERN_ERR "%s: %s - no codec found\n",
+				ZR_DEVNAME(zr), __func__);
 			goto zr_free_codec;
 		}
 		if (zr->codec->type != zr->card.video_codec) {
-			dprintk(1,
-				KERN_ERR
-				"%s: find_zr36057() - wrong codec\n",
-				ZR_DEVNAME(zr));
+			dprintk(1, KERN_ERR "%s: %s - wrong codec\n",
+				ZR_DEVNAME(zr), __func__);
 			goto zr_detach_codec;
 		}
 	}
@@ -1515,17 +1424,13 @@
 			goto zr_detach_codec;
 		zr->vfe = videocodec_attach(master_vfe);
 		if (!zr->vfe) {
-			dprintk(1,
-				KERN_ERR
-				"%s: find_zr36057() - no VFE found\n",
-				ZR_DEVNAME(zr));
+			dprintk(1, KERN_ERR "%s: %s - no VFE found\n",
+				ZR_DEVNAME(zr), __func__);
 			goto zr_free_vfe;
 		}
 		if (zr->vfe->type != zr->card.video_vfe) {
-			dprintk(1,
-				KERN_ERR
-				"%s: find_zr36057() = wrong VFE\n",
-				ZR_DEVNAME(zr));
+			dprintk(1, KERN_ERR "%s: %s = wrong VFE\n",
+				ZR_DEVNAME(zr), __func__);
 			goto zr_detach_vfe;
 		}
 	}
@@ -1533,8 +1438,7 @@
 	/* take care of Natoma chipset and a revision 1 zr36057 */
 	if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
 		zr->jpg_buffers.need_contiguous = 1;
-		dprintk(1,
-			KERN_INFO
+		dprintk(1, KERN_INFO
 			"%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
 			ZR_DEVNAME(zr));
 	}
@@ -1544,8 +1448,6 @@
 
 	zoran_proc_init(zr);
 
-	pci_set_drvdata(pdev, zr);
-
 	return 0;
 
 zr_detach_vfe:
@@ -1563,6 +1465,8 @@
 	free_irq(zr->pci_dev->irq, zr);
 zr_unmap:
 	iounmap(zr->zr36057_mem);
+zr_unreg:
+	v4l2_device_unregister(&zr->v4l2_dev);
 zr_free_mem:
 	kfree(zr);
 
@@ -1613,9 +1517,6 @@
 			ZORAN_NAME, vidmem);
 	}
 
-	/* random nonsense */
-	dprintk(6, KERN_DEBUG "Jotti is een held!\n");
-
 	/* some mainboards might not do PCI-PCI data transfer well */
 	if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
 		dprintk(1,
diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h
index 4507bdc..4936fea 100644
--- a/drivers/media/video/zoran/zoran_card.h
+++ b/drivers/media/video/zoran/zoran_card.h
@@ -44,7 +44,8 @@
 extern struct video_device zoran_template;
 
 extern int zoran_check_jpg_settings(struct zoran *zr,
-				    struct zoran_jpg_settings *settings);
+				    struct zoran_jpg_settings *settings,
+				    int try);
 extern void zoran_open_init_params(struct zoran *zr);
 extern void zoran_vdev_release(struct video_device *vdev);
 
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
index 5d948ff..e0223de 100644
--- a/drivers/media/video/zoran/zoran_device.c
+++ b/drivers/media/video/zoran/zoran_device.c
@@ -36,13 +36,12 @@
 #include <linux/proc_fs.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 
 #include <linux/pci.h>
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
 
@@ -312,9 +311,9 @@
 	case BUZ_MODE_MOTION_COMPRESS:
 	case BUZ_MODE_IDLE:
 	default:
-		if (zr->norm == VIDEO_MODE_NTSC ||
+		if ((zr->norm & V4L2_STD_NTSC) ||
 		    (zr->card.type == LML33R10 &&
-		     zr->norm == VIDEO_MODE_PAL))
+		     (zr->norm & V4L2_STD_PAL)))
 			btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
 		else
 			btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
@@ -355,14 +354,6 @@
 	dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
 		ZR_DEVNAME(zr), video_width, video_height);
 
-	if (zr->norm != VIDEO_MODE_PAL &&
-	    zr->norm != VIDEO_MODE_NTSC &&
-	    zr->norm != VIDEO_MODE_SECAM) {
-		dprintk(1,
-			KERN_ERR "%s: set_vfe() - norm = %d not valid\n",
-			ZR_DEVNAME(zr), zr->norm);
-		return;
-	}
 	if (video_width < BUZ_MIN_WIDTH ||
 	    video_height < BUZ_MIN_HEIGHT ||
 	    video_width > Wa || video_height > Ha) {
@@ -426,7 +417,7 @@
 	 * we get the correct colors when uncompressing to the screen  */
 	//reg |= ZR36057_VFESPFR_VCLKPol; /**/
 	/* RJ: Don't know if that is needed for NTSC also */
-	if (zr->norm != VIDEO_MODE_NTSC)
+	if (!(zr->norm & V4L2_STD_NTSC))
 		reg |= ZR36057_VFESPFR_ExtFl;	// NEEDED!!!!!!! Wolfgang
 	reg |= ZR36057_VFESPFR_TopField;
 	if (HorDcm >= 48) {
@@ -497,11 +488,11 @@
 		 * All error messages are internal driver checking only! */
 
 		/* video display top and bottom registers */
-		reg = (long) zr->buffer.base +
+		reg = (long) zr->vbuf_base +
 		    zr->overlay_settings.x *
 		    ((zr->overlay_settings.format->depth + 7) / 8) +
 		    zr->overlay_settings.y *
-		    zr->buffer.bytesperline;
+		    zr->vbuf_bytesperline;
 		btwrite(reg, ZR36057_VDTR);
 		if (reg & 3)
 			dprintk(1,
@@ -509,15 +500,15 @@
 				"%s: zr36057_overlay() - video_address not aligned\n",
 				ZR_DEVNAME(zr));
 		if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-			reg += zr->buffer.bytesperline;
+			reg += zr->vbuf_bytesperline;
 		btwrite(reg, ZR36057_VDBR);
 
 		/* video stride, status, and frame grab register */
-		reg = zr->buffer.bytesperline -
+		reg = zr->vbuf_bytesperline -
 		    zr->overlay_settings.width *
 		    ((zr->overlay_settings.format->depth + 7) / 8);
 		if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-			reg += zr->buffer.bytesperline;
+			reg += zr->vbuf_bytesperline;
 		if (reg & 3)
 			dprintk(1,
 				KERN_ERR
@@ -544,12 +535,8 @@
  *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
  */
 
-void
-write_overlay_mask (struct file       *file,
-		    struct video_clip *vp,
-		    int                count)
+void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
 	u32 *mask;
@@ -563,10 +550,10 @@
 
 	for (i = 0; i < count; ++i) {
 		/* pick up local copy of clip */
-		x = vp[i].x;
-		y = vp[i].y;
-		width = vp[i].width;
-		height = vp[i].height;
+		x = vp[i].c.left;
+		y = vp[i].c.top;
+		width = vp[i].c.width;
+		height = vp[i].c.height;
 
 		/* trim clips that extend beyond the window */
 		if (x < 0) {
@@ -981,11 +968,10 @@
 zr36057_enable_jpg (struct zoran          *zr,
 		    enum zoran_codec_mode  mode)
 {
-	static int zero;
-	static int one = 1;
 	struct vfe_settings cap;
 	int field_size =
 	    zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
+	struct v4l2_routing route = { 0, 0 };
 
 	zr->codec_mode = mode;
 
@@ -1007,8 +993,9 @@
 		 * the video bus direction set to input.
 		 */
 		set_videobus_dir(zr, 0);
-		decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
-		encoder_command(zr, ENCODER_SET_INPUT, &zero);
+		decoder_call(zr, video, s_stream, 1);
+		route.input = 0;
+		encoder_call(zr, video, s_routing, &route);
 
 		/* Take the JPEG codec and the VFE out of sleep */
 		jpeg_codec_sleep(zr, 0);
@@ -1054,9 +1041,10 @@
 		/* In motion decompression mode, the decoder output must be disabled, and
 		 * the video bus direction set to output.
 		 */
-		decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
+		decoder_call(zr, video, s_stream, 0);
 		set_videobus_dir(zr, 1);
-		encoder_command(zr, ENCODER_SET_INPUT, &one);
+		route.input = 1;
+		encoder_call(zr, video, s_routing, &route);
 
 		/* Take the JPEG codec and the VFE out of sleep */
 		jpeg_codec_sleep(zr, 0);
@@ -1100,8 +1088,9 @@
 		jpeg_codec_sleep(zr, 1);
 		zr36057_adjust_vfe(zr, mode);
 
-		decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
-		encoder_command(zr, ENCODER_SET_INPUT, &zero);
+		decoder_call(zr, video, s_stream, 1);
+		route.input = 0;
+		encoder_call(zr, video, s_routing, &route);
 
 		dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
 		break;
@@ -1132,7 +1121,7 @@
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 		} else {
 			/* fill 2 stat_com entries */
 			i = ((zr->jpg_dma_head -
@@ -1140,9 +1129,9 @@
 			if (!(zr->stat_com[i] & cpu_to_le32(1)))
 				break;
 			zr->stat_com[i] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 			zr->stat_com[i + 1] =
-			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+			    cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
 		}
 		zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
 		zr->jpg_dma_head++;
@@ -1162,7 +1151,7 @@
 	u32 stat_com;
 	unsigned int seq;
 	unsigned int dif;
-	struct zoran_jpg_buffer *buffer;
+	struct zoran_buffer *buffer;
 	int frame;
 
 	/* In motion decompress we don't have a hardware frame counter,
@@ -1208,22 +1197,52 @@
 	}
 }
 
+static void zoran_restart(struct zoran *zr)
+{
+	/* Now the stat_comm buffer is ready for restart */
+	int status = 0, mode;
+
+	if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+		decoder_call(zr, video, g_input_status, &status);
+		mode = CODEC_DO_COMPRESSION;
+	} else {
+		status = V4L2_IN_ST_NO_SIGNAL;
+		mode = CODEC_DO_EXPANSION;
+	}
+	if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+	    !(status & V4L2_IN_ST_NO_SIGNAL)) {
+		/********** RESTART code *************/
+		jpeg_codec_reset(zr);
+		zr->codec->set_mode(zr->codec, mode);
+		zr36057_set_jpg(zr, zr->codec_mode);
+		jpeg_start(zr);
+
+		if (zr->num_errors <= 8)
+			dprintk(2, KERN_INFO "%s: Restart\n",
+				ZR_DEVNAME(zr));
+
+		zr->JPEG_missed = 0;
+		zr->JPEG_error = 2;
+		/********** End RESTART code ***********/
+	}
+}
+
 static void
 error_handler (struct zoran *zr,
 	       u32           astat,
 	       u32           stat)
 {
+	int i, j;
+
 	/* This is JPEG error handling part */
-	if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) &&
-	    (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) {
-		//dprintk(1, KERN_ERR "%s: Internal error: error handling request in mode %d\n", ZR_DEVNAME(zr), zr->codec_mode);
+	if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS &&
+	    zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) {
 		return;
 	}
 
 	if ((stat & 1) == 0 &&
 	    zr->codec_mode == BUZ_MODE_MOTION_COMPRESS &&
-	    zr->jpg_dma_tail - zr->jpg_que_tail >=
-	     zr->jpg_buffers.num_buffers) {
+	    zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) {
 		/* No free buffers... */
 		zoran_reap_stat_com(zr);
 		zoran_feed_stat_com(zr);
@@ -1232,142 +1251,95 @@
 		return;
 	}
 
-	if (zr->JPEG_error != 1) {
-		/*
-		 * First entry: error just happened during normal operation
-		 *
-		 * In BUZ_MODE_MOTION_COMPRESS:
-		 *
-		 * Possible glitch in TV signal. In this case we should
-		 * stop the codec and wait for good quality signal before
-		 * restarting it to avoid further problems
-		 *
-		 * In BUZ_MODE_MOTION_DECOMPRESS:
-		 *
-		 * Bad JPEG frame: we have to mark it as processed (codec crashed
-		 * and was not able to do it itself), and to remove it from queue.
-		 */
-		btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
-		udelay(1);
-		stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
-		btwrite(0, ZR36057_JPC);
-		btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
-		jpeg_codec_reset(zr);
-		jpeg_codec_sleep(zr, 1);
-		zr->JPEG_error = 1;
-		zr->num_errors++;
-
-		/* Report error */
-		if (zr36067_debug > 1 && zr->num_errors <= 8) {
-			long frame;
-			frame =
-			    zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
-			printk(KERN_ERR
-			       "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
-			       ZR_DEVNAME(zr), stat, zr->last_isr,
-			       zr->jpg_que_tail, zr->jpg_dma_tail,
-			       zr->jpg_dma_head, zr->jpg_que_head,
-			       zr->jpg_seq_num, frame);
-			printk("stat_com frames:");
-			{
-				int i, j;
-				for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-					for (i = 0;
-					     i < zr->jpg_buffers.num_buffers;
-					     i++) {
-						if (le32_to_cpu(zr->stat_com[j]) ==
-						    zr->jpg_buffers.
-						    buffer[i].
-						    frag_tab_bus) {
-							printk("% d->%d",
-							       j, i);
-						}
-					}
-				}
-				printk("\n");
-			}
-		}
-		/* Find an entry in stat_com and rotate contents */
-		{
-			int i;
-
-			if (zr->jpg_settings.TmpDcm == 1)
-				i = (zr->jpg_dma_tail -
-				     zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-			else
-				i = ((zr->jpg_dma_tail -
-				      zr->jpg_err_shift) & 1) * 2;
-			if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
-				/* Mimic zr36067 operation */
-				zr->stat_com[i] |= cpu_to_le32(1);
-				if (zr->jpg_settings.TmpDcm != 1)
-					zr->stat_com[i + 1] |= cpu_to_le32(1);
-				/* Refill */
-				zoran_reap_stat_com(zr);
-				zoran_feed_stat_com(zr);
-				wake_up_interruptible(&zr->jpg_capq);
-				/* Find an entry in stat_com again after refill */
-				if (zr->jpg_settings.TmpDcm == 1)
-					i = (zr->jpg_dma_tail -
-					     zr->jpg_err_shift) &
-					    BUZ_MASK_STAT_COM;
-				else
-					i = ((zr->jpg_dma_tail -
-					      zr->jpg_err_shift) & 1) * 2;
-			}
-			if (i) {
-				/* Rotate stat_comm entries to make current entry first */
-				int j;
-				__le32 bus_addr[BUZ_NUM_STAT_COM];
-
-				/* Here we are copying the stat_com array, which
-				 * is already in little endian format, so
-				 * no endian conversions here
-				 */
-				memcpy(bus_addr, zr->stat_com,
-				       sizeof(bus_addr));
-				for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-					zr->stat_com[j] =
-					    bus_addr[(i + j) &
-						     BUZ_MASK_STAT_COM];
-
-				}
-				zr->jpg_err_shift += i;
-				zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
-			}
-			if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
-				zr->jpg_err_seq = zr->jpg_seq_num;	/* + 1; */
-		}
+	if (zr->JPEG_error == 1) {
+		zoran_restart(zr);
+		return;
 	}
 
-	/* Now the stat_comm buffer is ready for restart */
-	do {
-		int status, mode;
+	/*
+	 * First entry: error just happened during normal operation
+	 *
+	 * In BUZ_MODE_MOTION_COMPRESS:
+	 *
+	 * Possible glitch in TV signal. In this case we should
+	 * stop the codec and wait for good quality signal before
+	 * restarting it to avoid further problems
+	 *
+	 * In BUZ_MODE_MOTION_DECOMPRESS:
+	 *
+	 * Bad JPEG frame: we have to mark it as processed (codec crashed
+	 * and was not able to do it itself), and to remove it from queue.
+	 */
+	btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+	udelay(1);
+	stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
+	btwrite(0, ZR36057_JPC);
+	btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
+	jpeg_codec_reset(zr);
+	jpeg_codec_sleep(zr, 1);
+	zr->JPEG_error = 1;
+	zr->num_errors++;
 
-		if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-			decoder_command(zr, DECODER_GET_STATUS, &status);
-			mode = CODEC_DO_COMPRESSION;
-		} else {
-			status = 0;
-			mode = CODEC_DO_EXPANSION;
+	/* Report error */
+	if (zr36067_debug > 1 && zr->num_errors <= 8) {
+		long frame;
+
+		frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
+		printk(KERN_ERR
+		       "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
+		       ZR_DEVNAME(zr), stat, zr->last_isr,
+		       zr->jpg_que_tail, zr->jpg_dma_tail,
+		       zr->jpg_dma_head, zr->jpg_que_head,
+		       zr->jpg_seq_num, frame);
+		printk(KERN_INFO "stat_com frames:");
+		for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+			for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
+				if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus)
+					printk(KERN_CONT "% d->%d", j, i);
+			}
 		}
-		if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-		    (status & DECODER_STATUS_GOOD)) {
-			/********** RESTART code *************/
-			jpeg_codec_reset(zr);
-			zr->codec->set_mode(zr->codec, mode);
-			zr36057_set_jpg(zr, zr->codec_mode);
-			jpeg_start(zr);
+		printk(KERN_CONT "\n");
+	}
+	/* Find an entry in stat_com and rotate contents */
+	if (zr->jpg_settings.TmpDcm == 1)
+		i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+	else
+		i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+	if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+		/* Mimic zr36067 operation */
+		zr->stat_com[i] |= cpu_to_le32(1);
+		if (zr->jpg_settings.TmpDcm != 1)
+			zr->stat_com[i + 1] |= cpu_to_le32(1);
+		/* Refill */
+		zoran_reap_stat_com(zr);
+		zoran_feed_stat_com(zr);
+		wake_up_interruptible(&zr->jpg_capq);
+		/* Find an entry in stat_com again after refill */
+		if (zr->jpg_settings.TmpDcm == 1)
+			i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+		else
+			i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+	}
+	if (i) {
+		/* Rotate stat_comm entries to make current entry first */
+		int j;
+		__le32 bus_addr[BUZ_NUM_STAT_COM];
 
-			if (zr->num_errors <= 8)
-				dprintk(2, KERN_INFO "%s: Restart\n",
-					ZR_DEVNAME(zr));
+		/* Here we are copying the stat_com array, which
+		 * is already in little endian format, so
+		 * no endian conversions here
+		 */
+		memcpy(bus_addr, zr->stat_com, sizeof(bus_addr));
 
-			zr->JPEG_missed = 0;
-			zr->JPEG_error = 2;
-			/********** End RESTART code ***********/
-		}
-	} while (0);
+		for (j = 0; j < BUZ_NUM_STAT_COM; j++)
+			zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM];
+
+		zr->jpg_err_shift += i;
+		zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
+	}
+	if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
+		zr->jpg_err_seq = zr->jpg_seq_num;	/* + 1; */
+	zoran_restart(zr);
 }
 
 irqreturn_t
@@ -1425,10 +1397,8 @@
 			 * We simply ignore them */
 
 			if (zr->v4l_memgrab_active) {
-
 				/* A lot more checks should be here ... */
-				if ((btread(ZR36057_VSSFGR) &
-				     ZR36057_VSSFGR_SnapShot) == 0)
+				if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0)
 					dprintk(1,
 						KERN_WARNING
 						"%s: BuzIRQ with SnapShot off ???\n",
@@ -1436,10 +1406,7 @@
 
 				if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
 					/* There is a grab on a frame going on, check if it has finished */
-
-					if ((btread(ZR36057_VSSFGR) &
-					     ZR36057_VSSFGR_FrameGrab) ==
-					    0) {
+					if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) {
 						/* it is finished, notify the user */
 
 						zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
@@ -1457,9 +1424,7 @@
 
 				if (zr->v4l_grab_frame == NO_GRAB_ACTIVE &&
 				    zr->v4l_pend_tail != zr->v4l_pend_head) {
-
-					int frame = zr->v4l_pend[zr->v4l_pend_tail &
-							 V4L_MASK_FRAME];
+					int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
 					u32 reg;
 
 					zr->v4l_grab_frame = frame;
@@ -1468,27 +1433,17 @@
 
 					/* Buffer address */
 
-					reg =
-					    zr->v4l_buffers.buffer[frame].
-					    fbuffer_bus;
+					reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus;
 					btwrite(reg, ZR36057_VDTR);
-					if (zr->v4l_settings.height >
-					    BUZ_MAX_HEIGHT / 2)
-						reg +=
-						    zr->v4l_settings.
-						    bytesperline;
+					if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+						reg += zr->v4l_settings.bytesperline;
 					btwrite(reg, ZR36057_VDBR);
 
 					/* video stride, status, and frame grab register */
 					reg = 0;
-					if (zr->v4l_settings.height >
-					    BUZ_MAX_HEIGHT / 2)
-						reg +=
-						    zr->v4l_settings.
-						    bytesperline;
-					reg =
-					    (reg <<
-					     ZR36057_VSSFGR_DispStride);
+					if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+						reg += zr->v4l_settings.bytesperline;
+					reg = (reg << ZR36057_VSSFGR_DispStride);
 					reg |= ZR36057_VSSFGR_VidOvf;
 					reg |= ZR36057_VSSFGR_SnapShot;
 					reg |= ZR36057_VSSFGR_FrameGrab;
@@ -1506,77 +1461,66 @@
 #if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
 		if (astat & ZR36057_ISR_CodRepIRQ) {
 			zr->intr_counter_CodRepIRQ++;
-			IDEBUG(printk
-			       (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
+			IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
 				ZR_DEVNAME(zr)));
 			btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
 		}
 #endif				/* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
 
 #if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
-		if (astat & ZR36057_ISR_JPEGRepIRQ) {
+		if ((astat & ZR36057_ISR_JPEGRepIRQ) &&
+		    (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+		     zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) {
+			if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) {
+				char sc[] = "0000";
+				char sv[5];
+				int i;
 
-			if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-			    zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-				if (zr36067_debug > 1 &&
-				    (!zr->frame_num || zr->JPEG_error)) {
-					printk(KERN_INFO
-					       "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
-					       ZR_DEVNAME(zr), stat,
-					       zr->jpg_settings.odd_even,
-					       zr->jpg_settings.
-					       field_per_buff,
-					       zr->JPEG_missed);
-					{
-						char sc[] = "0000";
-						char sv[5];
-						int i;
-						strcpy(sv, sc);
-						for (i = 0; i < 4; i++) {
-							if (le32_to_cpu(zr->stat_com[i]) & 1)
-								sv[i] = '1';
-						}
-						sv[4] = 0;
-						printk(KERN_INFO
-						       "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
-						       ZR_DEVNAME(zr), sv,
-						       zr->jpg_que_tail,
-						       zr->jpg_dma_tail,
-						       zr->jpg_dma_head,
-						       zr->jpg_que_head);
-					}
-				} else {
-					if (zr->JPEG_missed > zr->JPEG_max_missed)	// Get statistics
-						zr->JPEG_max_missed =
-						    zr->JPEG_missed;
-					if (zr->JPEG_missed <
-					    zr->JPEG_min_missed)
-						zr->JPEG_min_missed =
-						    zr->JPEG_missed;
-				}
+				printk(KERN_INFO
+				       "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
+				       ZR_DEVNAME(zr), stat,
+				       zr->jpg_settings.odd_even,
+				       zr->jpg_settings.field_per_buff,
+				       zr->JPEG_missed);
 
-				if (zr36067_debug > 2 && zr->frame_num < 6) {
-					int i;
-					printk("%s: seq=%ld stat_com:",
-					       ZR_DEVNAME(zr), zr->jpg_seq_num);
-					for (i = 0; i < 4; i++) {
-						printk(" %08x",
-						       le32_to_cpu(zr->stat_com[i]));
-					}
-					printk("\n");
+				strcpy(sv, sc);
+				for (i = 0; i < 4; i++) {
+					if (le32_to_cpu(zr->stat_com[i]) & 1)
+						sv[i] = '1';
 				}
-				zr->frame_num++;
-				zr->JPEG_missed = 0;
-				zr->JPEG_error = 0;
-				zoran_reap_stat_com(zr);
-				zoran_feed_stat_com(zr);
-				wake_up_interruptible(&zr->jpg_capq);
-			} /*else {
-			      dprintk(1,
-					KERN_ERR
-					"%s: JPEG interrupt while not in motion (de)compress mode!\n",
-					ZR_DEVNAME(zr));
-			}*/
+				sv[4] = 0;
+				printk(KERN_INFO
+				       "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
+				       ZR_DEVNAME(zr), sv,
+				       zr->jpg_que_tail,
+				       zr->jpg_dma_tail,
+				       zr->jpg_dma_head,
+				       zr->jpg_que_head);
+			} else {
+				/* Get statistics */
+				if (zr->JPEG_missed > zr->JPEG_max_missed)
+					zr->JPEG_max_missed = zr->JPEG_missed;
+				if (zr->JPEG_missed < zr->JPEG_min_missed)
+					zr->JPEG_min_missed = zr->JPEG_missed;
+			}
+
+			if (zr36067_debug > 2 && zr->frame_num < 6) {
+				int i;
+
+				printk(KERN_INFO "%s: seq=%ld stat_com:",
+				       ZR_DEVNAME(zr), zr->jpg_seq_num);
+				for (i = 0; i < 4; i++) {
+					printk(KERN_CONT " %08x",
+					       le32_to_cpu(zr->stat_com[i]));
+				}
+				printk(KERN_CONT "\n");
+			}
+			zr->frame_num++;
+			zr->JPEG_missed = 0;
+			zr->JPEG_error = 0;
+			zoran_reap_stat_com(zr);
+			zoran_feed_stat_com(zr);
+			wake_up_interruptible(&zr->jpg_capq);
 		}
 #endif				/* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
 
@@ -1585,8 +1529,7 @@
 		    zr->JPEG_missed > 25 ||
 		    zr->JPEG_error == 1	||
 		    ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
-		     (zr->frame_num & (zr->JPEG_missed >
-				       zr->jpg_settings.field_per_buff)))) {
+		     (zr->frame_num & (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) {
 			error_handler(zr, astat, stat);
 		}
 
@@ -1628,7 +1571,7 @@
 void
 zoran_init_hardware (struct zoran *zr)
 {
-	int j, zero = 0;
+	struct v4l2_routing route = { 0, 0 };
 
 	/* Enable bus-mastering */
 	zoran_set_pci_master(zr, 1);
@@ -1638,15 +1581,16 @@
 		zr->card.init(zr);
 	}
 
-	j = zr->card.input[zr->input].muxsel;
+	route.input = zr->card.input[zr->input].muxsel;
 
-	decoder_command(zr, 0, NULL);
-	decoder_command(zr, DECODER_SET_NORM, &zr->norm);
-	decoder_command(zr, DECODER_SET_INPUT, &j);
+	decoder_call(zr, core, init, 0);
+	decoder_call(zr, tuner, s_std, zr->norm);
+	decoder_call(zr, video, s_routing, &route);
 
-	encoder_command(zr, 0, NULL);
-	encoder_command(zr, ENCODER_SET_NORM, &zr->norm);
-	encoder_command(zr, ENCODER_SET_INPUT, &zero);
+	encoder_call(zr, core, init, 0);
+	encoder_call(zr, video, s_std_output, zr->norm);
+	route.input = 0;
+	encoder_call(zr, video, s_routing, &route);
 
 	/* toggle JPEG codec sleep to sync PLL */
 	jpeg_codec_sleep(zr, 1);
@@ -1706,42 +1650,3 @@
 		reg |= ZR36057_VDCR_Triton;
 	btwrite(reg, ZR36057_VDCR);
 }
-
-/*
- * Interface to decoder and encoder chips using i2c bus
- */
-
-int
-decoder_command (struct zoran *zr,
-		 int           cmd,
-		 void         *data)
-{
-	if (zr->decoder == NULL)
-		return -EIO;
-
-	if (zr->card.type == LML33 &&
-	    (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
-		int res;
-
-		// Bt819 needs to reset its FIFO buffer using #FRST pin and
-		// LML33 card uses GPIO(7) for that.
-		GPIO(zr, 7, 0);
-		res = zr->decoder->driver->command(zr->decoder, cmd, data);
-		// Pull #FRST high.
-		GPIO(zr, 7, 1);
-		return res;
-	} else
-		return zr->decoder->driver->command(zr->decoder, cmd,
-						    data);
-}
-
-int
-encoder_command (struct zoran *zr,
-		 int           cmd,
-		 void         *data)
-{
-	if (zr->encoder == NULL)
-		return -1;
-
-	return zr->encoder->driver->command(zr->encoder, cmd, data);
-}
diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h
index 74c6c8e..07f2c23 100644
--- a/drivers/media/video/zoran/zoran_device.h
+++ b/drivers/media/video/zoran/zoran_device.h
@@ -54,8 +54,8 @@
 /* zr360x7 access to raw capture */
 extern void zr36057_overlay(struct zoran *zr,
 			    int on);
-extern void write_overlay_mask(struct file *file,
-			       struct video_clip *vp,
+extern void write_overlay_mask(struct zoran_fh *fh,
+			       struct v4l2_clip *vp,
 			       int count);
 extern void zr36057_set_memgrab(struct zoran *zr,
 				int mode);
@@ -87,11 +87,9 @@
 extern int pass_through;
 
 /* i2c */
-extern int decoder_command(struct zoran *zr,
-			   int cmd,
-			   void *data);
-extern int encoder_command(struct zoran *zr,
-			   int cmd,
-			   void *data);
+#define decoder_call(zr, o, f, args...) \
+	v4l2_subdev_call(zr->decoder, o, f, ##args)
+#define encoder_call(zr, o, f, args...) \
+	v4l2_subdev_call(zr->encoder, o, f, ##args)
 
 #endif				/* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 120ef23..f16e57c 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -58,16 +58,6 @@
 #include <linux/i2c-algo-bit.h>
 
 #include <linux/spinlock.h>
-#define     MAP_NR(x)       virt_to_page(x)
-#define     ZORAN_VID_TYPE  ( \
-				VID_TYPE_CAPTURE | \
-				VID_TYPE_OVERLAY | \
-				VID_TYPE_CLIPPING | \
-				VID_TYPE_FRAMERAM | \
-				VID_TYPE_SCALES | \
-				VID_TYPE_MJPEG_DECODER | \
-				VID_TYPE_MJPEG_ENCODER \
-			     )
 
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
@@ -79,36 +69,17 @@
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
 
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
 #include <linux/mutex.h>
 #include "zoran.h"
 #include "zoran_device.h"
 #include "zoran_card.h"
 
-	/* we declare some card type definitions here, they mean
-	 * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
-#define ZORAN_V4L2_VID_FLAGS ( \
-				V4L2_CAP_STREAMING |\
-				V4L2_CAP_VIDEO_CAPTURE |\
-				V4L2_CAP_VIDEO_OUTPUT |\
-				V4L2_CAP_VIDEO_OVERLAY \
-			      )
-
-
-#if defined(CONFIG_VIDEO_V4L1_COMPAT)
-#define ZFMT(pal, fcc, cs) \
-	.palette = (pal), .fourcc = (fcc), .colorspace = (cs)
-#else
-#define ZFMT(pal, fcc, cs) \
-	.fourcc = (fcc), .colorspace = (cs)
-#endif
 
 const struct zoran_format zoran_formats[] = {
 	{
 		.name = "15-bit RGB LE",
-		ZFMT(VIDEO_PALETTE_RGB555,
-		     V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_RGB555,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 15,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
@@ -116,16 +87,16 @@
 			   ZR36057_VFESPFR_LittleEndian,
 	}, {
 		.name = "15-bit RGB BE",
-		ZFMT(-1,
-		     V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_RGB555X,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 15,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
 	}, {
 		.name = "16-bit RGB LE",
-		ZFMT(VIDEO_PALETTE_RGB565,
-		     V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_RGB565,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 16,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
@@ -133,56 +104,56 @@
 			   ZR36057_VFESPFR_LittleEndian,
 	}, {
 		.name = "16-bit RGB BE",
-		ZFMT(-1,
-		     V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_RGB565X,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 16,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
 	}, {
 		.name = "24-bit RGB",
-		ZFMT(VIDEO_PALETTE_RGB24,
-		     V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_BGR24,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 24,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
 	}, {
 		.name = "32-bit RGB LE",
-		ZFMT(VIDEO_PALETTE_RGB32,
-		     V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_BGR32,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 32,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
 	}, {
 		.name = "32-bit RGB BE",
-		ZFMT(-1,
-		     V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB),
+		.fourcc = V4L2_PIX_FMT_RGB32,
+		.colorspace = V4L2_COLORSPACE_SRGB,
 		.depth = 32,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_RGB888,
 	}, {
 		.name = "4:2:2, packed, YUYV",
-		ZFMT(VIDEO_PALETTE_YUV422,
-		     V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M),
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 		.depth = 16,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_YUV422,
 	}, {
 		.name = "4:2:2, packed, UYVY",
-		ZFMT(VIDEO_PALETTE_UYVY,
-		     V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M),
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 		.depth = 16,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_OVERLAY,
 		.vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
 	}, {
 		.name = "Hardware-encoded Motion-JPEG",
-		ZFMT(-1,
-		     V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M),
+		.fourcc = V4L2_PIX_FMT_MJPEG,
+		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 		.depth = 0,
 		.flags = ZORAN_FORMAT_CAPTURE |
 			 ZORAN_FORMAT_PLAYBACK |
@@ -191,13 +162,6 @@
 };
 #define NUM_FORMATS ARRAY_SIZE(zoran_formats)
 
-// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
-
-
-static int lock_norm;	/* 0 = default 1 = Don't change TV standard (norm) */
-module_param(lock_norm, int, 0644);
-MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
-
 	/* small helper function for calculating buffersizes for v4l2
 	 * we calculate the nearest higher power-of-two, which
 	 * will be the recommended buffersize */
@@ -222,221 +186,106 @@
 }
 
 /* forward references */
-static void v4l_fbuffer_free(struct file *file);
-static void jpg_fbuffer_free(struct file *file);
+static void v4l_fbuffer_free(struct zoran_fh *fh);
+static void jpg_fbuffer_free(struct zoran_fh *fh);
+
+/* Set mapping mode */
+static void map_mode_raw(struct zoran_fh *fh)
+{
+	fh->map_mode = ZORAN_MAP_MODE_RAW;
+	fh->buffers.buffer_size = v4l_bufsize;
+	fh->buffers.num_buffers = v4l_nbufs;
+}
+static void map_mode_jpg(struct zoran_fh *fh, int play)
+{
+	fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC;
+	fh->buffers.buffer_size = jpg_bufsize;
+	fh->buffers.num_buffers = jpg_nbufs;
+}
+static inline const char *mode_name(enum zoran_map_mode mode)
+{
+	return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG";
+}
 
 /*
  *   Allocate the V4L grab buffers
  *
  *   These have to be pysically contiguous.
- *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc
- *   else we try to allocate them with bigphysarea_alloc_pages
- *   if the bigphysarea patch is present in the kernel,
- *   else we try to use high memory (if the user has bootet
- *   Linux with the necessary memory left over).
  */
 
-static unsigned long
-get_high_mem (unsigned long size)
+static int v4l_fbuffer_alloc(struct zoran_fh *fh)
 {
-/*
- * Check if there is usable memory at the end of Linux memory
- * of at least size. Return the physical address of this memory,
- * return 0 on failure.
- *
- * The idea is from Alexandro Rubini's book "Linux device drivers".
- * The driver from him which is downloadable from O'Reilly's
- * web site misses the "virt_to_phys(high_memory)" part
- * (and therefore doesn't work at all - at least with 2.2.x kernels).
- *
- * It should be unnecessary to mention that THIS IS DANGEROUS,
- * if more than one driver at a time has the idea to use this memory!!!!
- */
-
-	volatile unsigned char __iomem *mem;
-	unsigned char c;
-	unsigned long hi_mem_ph;
-	unsigned long i;
-
-	/* Map the high memory to user space */
-
-	hi_mem_ph = virt_to_phys(high_memory);
-
-	mem = ioremap(hi_mem_ph, size);
-	if (!mem) {
-		dprintk(1,
-			KERN_ERR "%s: get_high_mem() - ioremap failed\n",
-			ZORAN_NAME);
-		return 0;
-	}
-
-	for (i = 0; i < size; i++) {
-		/* Check if it is memory */
-		c = i & 0xff;
-		writeb(c, mem + i);
-		if (readb(mem + i) != c)
-			break;
-		c = 255 - c;
-		writeb(c, mem + i);
-		if (readb(mem + i) != c)
-			break;
-		writeb(0, mem + i);	/* zero out memory */
-
-		/* give the kernel air to breath */
-		if ((i & 0x3ffff) == 0x3ffff)
-			schedule();
-	}
-
-	iounmap(mem);
-
-	if (i != size) {
-		dprintk(1,
-			KERN_ERR
-			"%s: get_high_mem() - requested %lu, avail %lu\n",
-			ZORAN_NAME, size, i);
-		return 0;
-	}
-
-	return hi_mem_ph;
-}
-
-static int
-v4l_fbuffer_alloc (struct file *file)
-{
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int i, off;
 	unsigned char *mem;
-	unsigned long pmem = 0;
 
-	/* we might have old buffers lying around... */
-	if (fh->v4l_buffers.ready_to_be_freed) {
-		v4l_fbuffer_free(file);
-	}
-
-	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-		if (fh->v4l_buffers.buffer[i].fbuffer)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].v4l.fbuffer)
 			dprintk(2,
 				KERN_WARNING
-				"%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n",
-				ZR_DEVNAME(zr), i);
+				"%s: %s - buffer %d already allocated!?\n",
+				ZR_DEVNAME(zr), __func__, i);
 
 		//udelay(20);
-		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-			/* Use kmalloc */
-
-			mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
-			if (!mem) {
-				dprintk(1,
-					KERN_ERR
-					"%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",
-					ZR_DEVNAME(zr), i);
-				v4l_fbuffer_free(file);
-				return -ENOBUFS;
-			}
-			fh->v4l_buffers.buffer[i].fbuffer = mem;
-			fh->v4l_buffers.buffer[i].fbuffer_phys =
-			    virt_to_phys(mem);
-			fh->v4l_buffers.buffer[i].fbuffer_bus =
-			    virt_to_bus(mem);
-			for (off = 0; off < fh->v4l_buffers.buffer_size;
-			     off += PAGE_SIZE)
-				SetPageReserved(MAP_NR(mem + off));
-			dprintk(4,
-				KERN_INFO
-				"%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n",
-				ZR_DEVNAME(zr), i, (unsigned long) mem,
-				virt_to_bus(mem));
-		} else {
-
-			/* Use high memory which has been left at boot time */
-
-			/* Ok., Ok. this is an evil hack - we make
-			 * the assumption that physical addresses are
-			 * the same as bus addresses (true at least
-			 * for Intel processors). The whole method of
-			 * obtaining and using this memory is not very
-			 * nice - but I hope it saves some poor users
-			 * from kernel hacking, which might have even
-			 * more evil results */
-
-			if (i == 0) {
-				int size =
-				    fh->v4l_buffers.num_buffers *
-				    fh->v4l_buffers.buffer_size;
-
-				pmem = get_high_mem(size);
-				if (pmem == 0) {
-					dprintk(1,
-						KERN_ERR
-						"%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n",
-						ZR_DEVNAME(zr), size >> 10);
-					return -ENOBUFS;
-				}
-				fh->v4l_buffers.buffer[0].fbuffer = NULL;
-				fh->v4l_buffers.buffer[0].fbuffer_phys = pmem;
-				fh->v4l_buffers.buffer[0].fbuffer_bus = pmem;
-				dprintk(4,
-					KERN_INFO
-					"%s: v4l_fbuffer_alloc() - using %d KB high memory\n",
-					ZR_DEVNAME(zr), size >> 10);
-			} else {
-				fh->v4l_buffers.buffer[i].fbuffer = NULL;
-				fh->v4l_buffers.buffer[i].fbuffer_phys =
-				    pmem + i * fh->v4l_buffers.buffer_size;
-				fh->v4l_buffers.buffer[i].fbuffer_bus =
-				    pmem + i * fh->v4l_buffers.buffer_size;
-			}
+		mem = kmalloc(fh->buffers.buffer_size,
+			      GFP_KERNEL | __GFP_NOWARN);
+		if (!mem) {
+			dprintk(1,
+				KERN_ERR
+				"%s: %s - kmalloc for V4L buf %d failed\n",
+				ZR_DEVNAME(zr), __func__, i);
+			v4l_fbuffer_free(fh);
+			return -ENOBUFS;
 		}
+		fh->buffers.buffer[i].v4l.fbuffer = mem;
+		fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
+		fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
+		for (off = 0; off < fh->buffers.buffer_size;
+		     off += PAGE_SIZE)
+			SetPageReserved(virt_to_page(mem + off));
+		dprintk(4,
+			KERN_INFO
+			"%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n",
+			ZR_DEVNAME(zr), __func__, i, (unsigned long) mem,
+			(unsigned long long)virt_to_bus(mem));
 	}
 
-	fh->v4l_buffers.allocated = 1;
+	fh->buffers.allocated = 1;
 
 	return 0;
 }
 
 /* free the V4L grab buffers */
-static void
-v4l_fbuffer_free (struct file *file)
+static void v4l_fbuffer_free(struct zoran_fh *fh)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int i, off;
 	unsigned char *mem;
 
-	dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr));
+	dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__);
 
-	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-		if (!fh->v4l_buffers.buffer[i].fbuffer)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (!fh->buffers.buffer[i].v4l.fbuffer)
 			continue;
 
-		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-			mem = fh->v4l_buffers.buffer[i].fbuffer;
-			for (off = 0; off < fh->v4l_buffers.buffer_size;
-			     off += PAGE_SIZE)
-				ClearPageReserved(MAP_NR(mem + off));
-			kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
-		}
-		fh->v4l_buffers.buffer[i].fbuffer = NULL;
+		mem = fh->buffers.buffer[i].v4l.fbuffer;
+		for (off = 0; off < fh->buffers.buffer_size;
+		     off += PAGE_SIZE)
+			ClearPageReserved(virt_to_page(mem + off));
+		kfree(fh->buffers.buffer[i].v4l.fbuffer);
+		fh->buffers.buffer[i].v4l.fbuffer = NULL;
 	}
 
-	fh->v4l_buffers.allocated = 0;
-	fh->v4l_buffers.ready_to_be_freed = 0;
+	fh->buffers.allocated = 0;
 }
 
 /*
  *   Allocate the MJPEG grab buffers.
  *
- *   If the requested buffer size is smaller than MAX_KMALLOC_MEM,
- *   kmalloc is used to request a physically contiguous area,
- *   else we allocate the memory in framgents with get_zeroed_page.
- *
  *   If a Natoma chipset is present and this is a revision 1 zr36057,
  *   each MJPEG buffer needs to be physically contiguous.
  *   (RJ: This statement is from Dave Perks' original driver,
  *   I could never check it because I have a zr36067)
- *   The driver cares about this because it reduces the buffer
- *   size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation).
  *
  *   RJ: The contents grab buffers needs never be accessed in the driver.
  *       Therefore there is no need to allocate them with vmalloc in order
@@ -458,162 +307,128 @@
  *       and fragment buffers are not little-endian.
  */
 
-static int
-jpg_fbuffer_alloc (struct file *file)
+static int jpg_fbuffer_alloc(struct zoran_fh *fh)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int i, j, off;
-	unsigned long mem;
+	u8 *mem;
 
-	/* we might have old buffers lying around */
-	if (fh->jpg_buffers.ready_to_be_freed) {
-		jpg_fbuffer_free(file);
-	}
-
-	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (fh->jpg_buffers.buffer[i].frag_tab)
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].jpg.frag_tab)
 			dprintk(2,
 				KERN_WARNING
-				"%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n",
-				ZR_DEVNAME(zr), i);
+				"%s: %s - buffer %d already allocated!?\n",
+				ZR_DEVNAME(zr), __func__, i);
 
 		/* Allocate fragment table for this buffer */
 
-		mem = get_zeroed_page(GFP_KERNEL);
+		mem = (void *)get_zeroed_page(GFP_KERNEL);
 		if (mem == 0) {
 			dprintk(1,
 				KERN_ERR
-				"%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n",
-				ZR_DEVNAME(zr), i);
-			jpg_fbuffer_free(file);
+				"%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n",
+				ZR_DEVNAME(zr), __func__, i);
+			jpg_fbuffer_free(fh);
 			return -ENOBUFS;
 		}
-		fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
-		fh->jpg_buffers.buffer[i].frag_tab_bus =
-		    virt_to_bus((void *) mem);
+		fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
+		fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
 
-		//if (alloc_contig) {
-		if (fh->jpg_buffers.need_contiguous) {
-			mem =
-			    (unsigned long) kmalloc(fh->jpg_buffers.
-						    buffer_size,
-						    GFP_KERNEL);
-			if (mem == 0) {
+		if (fh->buffers.need_contiguous) {
+			mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
+			if (mem == NULL) {
 				dprintk(1,
 					KERN_ERR
-					"%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n",
-					ZR_DEVNAME(zr), i);
-				jpg_fbuffer_free(file);
+					"%s: %s - kmalloc failed for buffer %d\n",
+					ZR_DEVNAME(zr), __func__, i);
+				jpg_fbuffer_free(fh);
 				return -ENOBUFS;
 			}
-			fh->jpg_buffers.buffer[i].frag_tab[0] =
-			    cpu_to_le32(virt_to_bus((void *) mem));
-			fh->jpg_buffers.buffer[i].frag_tab[1] =
-			    cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);
-			for (off = 0; off < fh->jpg_buffers.buffer_size;
-			     off += PAGE_SIZE)
-				SetPageReserved(MAP_NR(mem + off));
+			fh->buffers.buffer[i].jpg.frag_tab[0] =
+				cpu_to_le32(virt_to_bus(mem));
+			fh->buffers.buffer[i].jpg.frag_tab[1] =
+				cpu_to_le32((fh->buffers.buffer_size >> 1) | 1);
+			for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
+				SetPageReserved(virt_to_page(mem + off));
 		} else {
-			/* jpg_bufsize is allreay page aligned */
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				mem = get_zeroed_page(GFP_KERNEL);
-				if (mem == 0) {
+			/* jpg_bufsize is already page aligned */
+			for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+				mem = (void *)get_zeroed_page(GFP_KERNEL);
+				if (mem == NULL) {
 					dprintk(1,
 						KERN_ERR
-						"%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n",
-						ZR_DEVNAME(zr), i);
-					jpg_fbuffer_free(file);
+						"%s: %s - get_zeroed_page failed for buffer %d\n",
+						ZR_DEVNAME(zr), __func__, i);
+					jpg_fbuffer_free(fh);
 					return -ENOBUFS;
 				}
 
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-				    cpu_to_le32(virt_to_bus((void *) mem));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-								   1] =
-				    cpu_to_le32((PAGE_SIZE / 4) << 1);
-				SetPageReserved(MAP_NR(mem));
+				fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
+					cpu_to_le32(virt_to_bus(mem));
+				fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
+					cpu_to_le32((PAGE_SIZE >> 2) << 1);
+				SetPageReserved(virt_to_page(mem));
 			}
 
-			fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);
+			fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
 		}
 	}
 
 	dprintk(4,
-		KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n",
-		ZR_DEVNAME(zr),
-		(fh->jpg_buffers.num_buffers *
-		 fh->jpg_buffers.buffer_size) >> 10);
+		KERN_DEBUG "%s: %s - %d KB allocated\n",
+		ZR_DEVNAME(zr), __func__,
+		(fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10);
 
-	fh->jpg_buffers.allocated = 1;
+	fh->buffers.allocated = 1;
 
 	return 0;
 }
 
 /* free the MJPEG grab buffers */
-static void
-jpg_fbuffer_free (struct file *file)
+static void jpg_fbuffer_free(struct zoran_fh *fh)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int i, j, off;
 	unsigned char *mem;
+	__le32 frag_tab;
+	struct zoran_buffer *buffer;
 
-	dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));
+	dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
 
-	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (!fh->jpg_buffers.buffer[i].frag_tab)
+	for (i = 0, buffer = &fh->buffers.buffer[0];
+	     i < fh->buffers.num_buffers; i++, buffer++) {
+		if (!buffer->jpg.frag_tab)
 			continue;
 
-		//if (alloc_contig) {
-		if (fh->jpg_buffers.need_contiguous) {
-			if (fh->jpg_buffers.buffer[i].frag_tab[0]) {
-				mem = (unsigned char *) bus_to_virt(le32_to_cpu(
-					fh->jpg_buffers.buffer[i].frag_tab[0]));
-				for (off = 0;
-				     off < fh->jpg_buffers.buffer_size;
-				     off += PAGE_SIZE)
-					ClearPageReserved(MAP_NR
-							  (mem + off));
+		if (fh->buffers.need_contiguous) {
+			frag_tab = buffer->jpg.frag_tab[0];
+
+			if (frag_tab) {
+				mem = bus_to_virt(le32_to_cpu(frag_tab));
+				for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
+					ClearPageReserved(virt_to_page(mem + off));
 				kfree(mem);
-				fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
-				fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
+				buffer->jpg.frag_tab[0] = 0;
+				buffer->jpg.frag_tab[1] = 0;
 			}
 		} else {
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				if (!fh->jpg_buffers.buffer[i].
-				    frag_tab[2 * j])
+			for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+				frag_tab = buffer->jpg.frag_tab[2 * j];
+
+				if (!frag_tab)
 					break;
-				ClearPageReserved(MAP_NR
-						  (bus_to_virt
-						   (le32_to_cpu
-						    (fh->jpg_buffers.
-						     buffer[i].frag_tab[2 *
-								       j]))));
-				free_page((unsigned long)
-					  bus_to_virt
-						  (le32_to_cpu
-						   (fh->jpg_buffers.
-						      buffer[i].
-						      frag_tab[2 * j])));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-				    0;
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-								   1] = 0;
+				ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
+				free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
+				buffer->jpg.frag_tab[2 * j] = 0;
+				buffer->jpg.frag_tab[2 * j + 1] = 0;
 			}
 		}
 
-		free_page((unsigned long) fh->jpg_buffers.buffer[i].
-			  frag_tab);
-		fh->jpg_buffers.buffer[i].frag_tab = NULL;
+		free_page((unsigned long)buffer->jpg.frag_tab);
+		buffer->jpg.frag_tab = NULL;
 	}
 
-	fh->jpg_buffers.allocated = 0;
-	fh->jpg_buffers.ready_to_be_freed = 0;
+	fh->buffers.allocated = 0;
 }
 
 /*
@@ -621,12 +436,11 @@
  */
 
 static int
-zoran_v4l_set_format (struct file               *file,
+zoran_v4l_set_format (struct zoran_fh           *fh,
 		      int                        width,
 		      int                        height,
 		      const struct zoran_format *format)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int bpp;
 
@@ -636,19 +450,19 @@
 	    height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_set_format() - wrong frame size (%dx%d)\n",
-			ZR_DEVNAME(zr), width, height);
+			"%s: %s - wrong frame size (%dx%d)\n",
+			ZR_DEVNAME(zr), __func__, width, height);
 		return -EINVAL;
 	}
 
 	bpp = (format->depth + 7) / 8;
 
 	/* Check against available buffer size */
-	if (height * width * bpp > fh->v4l_buffers.buffer_size) {
+	if (height * width * bpp > fh->buffers.buffer_size) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_set_format() - video buffer size (%d kB) is too small\n",
-			ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10);
+			"%s: %s - video buffer size (%d kB) is too small\n",
+			ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10);
 		return -EINVAL;
 	}
 
@@ -657,8 +471,8 @@
 	if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_set_format() - wrong frame alingment\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - wrong frame alignment\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
@@ -670,43 +484,40 @@
 	return 0;
 }
 
-static int
-zoran_v4l_queue_frame (struct file *file,
-		       int          num)
+static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	unsigned long flags;
 	int res = 0;
 
-	if (!fh->v4l_buffers.allocated) {
+	if (!fh->buffers.allocated) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_queue_frame() - buffers not yet allocated\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - buffers not yet allocated\n",
+			ZR_DEVNAME(zr), __func__);
 		res = -ENOMEM;
 	}
 
 	/* No grabbing outside the buffer range! */
-	if (num >= fh->v4l_buffers.num_buffers || num < 0) {
+	if (num >= fh->buffers.num_buffers || num < 0) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_queue_frame() - buffer %d is out of range\n",
-			ZR_DEVNAME(zr), num);
+			"%s: %s - buffer %d is out of range\n",
+			ZR_DEVNAME(zr), __func__, num);
 		res = -EINVAL;
 	}
 
 	spin_lock_irqsave(&zr->spinlock, flags);
 
-	if (fh->v4l_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		if (zr->v4l_buffers.active == ZORAN_FREE) {
-			zr->v4l_buffers = fh->v4l_buffers;
-			fh->v4l_buffers.active = ZORAN_ACTIVE;
+			zr->v4l_buffers = fh->buffers;
+			fh->buffers.active = ZORAN_ACTIVE;
 		} else {
 			dprintk(1,
 				KERN_ERR
-				"%s: v4l_queue_frame() - another session is already capturing\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - another session is already capturing\n",
+				ZR_DEVNAME(zr), __func__);
 			res = -EBUSY;
 		}
 	}
@@ -717,7 +528,7 @@
 		default:
 		case BUZ_STATE_PEND:
 			if (zr->v4l_buffers.active == ZORAN_FREE) {
-				fh->v4l_buffers.active = ZORAN_FREE;
+				fh->buffers.active = ZORAN_FREE;
 				zr->v4l_buffers.allocated = 0;
 			}
 			res = -EBUSY;	/* what are you doing? */
@@ -725,19 +536,17 @@
 		case BUZ_STATE_DONE:
 			dprintk(2,
 				KERN_WARNING
-				"%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n",
-				ZR_DEVNAME(zr), num);
+				"%s: %s - queueing buffer %d in state DONE!?\n",
+				ZR_DEVNAME(zr), __func__, num);
 		case BUZ_STATE_USER:
 			/* since there is at least one unused buffer there's room for at least
 			 * one more pend[] entry */
-			zr->v4l_pend[zr->v4l_pend_head++ &
-					V4L_MASK_FRAME] = num;
+			zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num;
 			zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
 			zr->v4l_buffers.buffer[num].bs.length =
 			    fh->v4l_settings.bytesperline *
 			    zr->v4l_settings.height;
-			fh->v4l_buffers.buffer[num] =
-			    zr->v4l_buffers.buffer[num];
+			fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num];
 			break;
 		}
 	}
@@ -745,65 +554,7 @@
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
 	if (!res && zr->v4l_buffers.active == ZORAN_FREE)
-		zr->v4l_buffers.active = fh->v4l_buffers.active;
-
-	return res;
-}
-
-static int
-v4l_grab (struct file       *file,
-	  struct video_mmap *mp)
-{
-	struct zoran_fh *fh = file->private_data;
-	struct zoran *zr = fh->zr;
-	int res = 0, i;
-
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (zoran_formats[i].palette == mp->format &&
-		    zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&
-		    !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))
-			break;
-	}
-	if (i == NUM_FORMATS || zoran_formats[i].depth == 0) {
-		dprintk(1,
-			KERN_ERR
-			"%s: v4l_grab() - wrong bytes-per-pixel format\n",
-			ZR_DEVNAME(zr));
-		return -EINVAL;
-	}
-
-	/*
-	 * To minimize the time spent in the IRQ routine, we avoid setting up
-	 * the video front end there.
-	 * If this grab has different parameters from a running streaming capture
-	 * we stop the streaming capture and start it over again.
-	 */
-	if (zr->v4l_memgrab_active &&
-	    (zr->v4l_settings.width != mp->width ||
-	     zr->v4l_settings.height != mp->height ||
-	     zr->v4l_settings.format->palette != mp->format)) {
-		res = wait_grab_pending(zr);
-		if (res)
-			return res;
-	}
-	if ((res = zoran_v4l_set_format(file,
-					mp->width,
-					mp->height,
-					&zoran_formats[i])))
-		return res;
-	zr->v4l_settings = fh->v4l_settings;
-
-	/* queue the frame in the pending queue */
-	if ((res = zoran_v4l_queue_frame(file, mp->frame))) {
-		fh->v4l_buffers.active = ZORAN_FREE;
-		return res;
-	}
-
-	/* put the 36057 into frame grabbing mode */
-	if (!res && !zr->v4l_memgrab_active)
-		zr36057_set_memgrab(zr, 1);
-
-	//dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr));
+		zr->v4l_buffers.active = fh->buffers.active;
 
 	return res;
 }
@@ -812,27 +563,24 @@
  * Sync on a V4L buffer
  */
 
-static int
-v4l_sync (struct file *file,
-	  int          frame)
+static int v4l_sync(struct zoran_fh *fh, int frame)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	unsigned long flags;
 
-	if (fh->v4l_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_sync() - no grab active for this session\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - no grab active for this session\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
 	/* check passed-in frame number */
-	if (frame >= fh->v4l_buffers.num_buffers || frame < 0) {
+	if (frame >= fh->buffers.num_buffers || frame < 0) {
 		dprintk(1,
-			KERN_ERR "%s: v4l_sync() - frame %d is invalid\n",
-			ZR_DEVNAME(zr), frame);
+			KERN_ERR "%s: %s - frame %d is invalid\n",
+			ZR_DEVNAME(zr), __func__, frame);
 		return -EINVAL;
 	}
 
@@ -840,15 +588,14 @@
 	if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
 		dprintk(1,
 			KERN_ERR
-			"%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - attempt to sync on a buffer which was not queued?\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EPROTO;
 	}
 
 	/* wait on this buffer to get ready */
 	if (!wait_event_interruptible_timeout(zr->v4l_capq,
-				(zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),
-				10*HZ))
+		(zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ))
 		return -ETIME;
 	if (signal_pending(current))
 		return -ERESTARTSYS;
@@ -856,11 +603,11 @@
 	/* buffer should now be in BUZ_STATE_DONE */
 	if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
 		dprintk(2,
-			KERN_ERR "%s: v4l_sync() - internal state error\n",
-			ZR_DEVNAME(zr));
+			KERN_ERR "%s: %s - internal state error\n",
+			ZR_DEVNAME(zr), __func__);
 
 	zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
-	fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
+	fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
 
 	spin_lock_irqsave(&zr->spinlock, flags);
 
@@ -868,8 +615,7 @@
 	if (zr->v4l_pend_tail == zr->v4l_pend_head) {
 		zr36057_set_memgrab(zr, 0);
 		if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
-			fh->v4l_buffers.active = zr->v4l_buffers.active =
-			    ZORAN_FREE;
+			fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE;
 			zr->v4l_buffers.allocated = 0;
 		}
 	}
@@ -883,31 +629,28 @@
  *   Queue a MJPEG buffer for capture/playback
  */
 
-static int
-zoran_jpg_queue_frame (struct file          *file,
-		       int                   num,
-		       enum zoran_codec_mode mode)
+static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num,
+				 enum zoran_codec_mode mode)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	unsigned long flags;
 	int res = 0;
 
 	/* Check if buffers are allocated */
-	if (!fh->jpg_buffers.allocated) {
+	if (!fh->buffers.allocated) {
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_queue_frame() - buffers not yet allocated\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - buffers not yet allocated\n",
+			ZR_DEVNAME(zr), __func__);
 		return -ENOMEM;
 	}
 
 	/* No grabbing outside the buffer range! */
-	if (num >= fh->jpg_buffers.num_buffers || num < 0) {
+	if (num >= fh->buffers.num_buffers || num < 0) {
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_queue_frame() - buffer %d out of range\n",
-			ZR_DEVNAME(zr), num);
+			"%s: %s - buffer %d out of range\n",
+			ZR_DEVNAME(zr), __func__, num);
 		return -EINVAL;
 	}
 
@@ -918,20 +661,20 @@
 		/* wrong codec mode active - invalid */
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_queue_frame() - codec in wrong mode\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - codec in wrong mode\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
-	if (fh->jpg_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		if (zr->jpg_buffers.active == ZORAN_FREE) {
-			zr->jpg_buffers = fh->jpg_buffers;
-			fh->jpg_buffers.active = ZORAN_ACTIVE;
+			zr->jpg_buffers = fh->buffers;
+			fh->buffers.active = ZORAN_ACTIVE;
 		} else {
 			dprintk(1,
 				KERN_ERR
-				"%s: jpg_queue_frame() - another session is already capturing\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - another session is already capturing\n",
+				ZR_DEVNAME(zr), __func__);
 			res = -EBUSY;
 		}
 	}
@@ -948,23 +691,21 @@
 		case BUZ_STATE_DONE:
 			dprintk(2,
 				KERN_WARNING
-				"%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - queing frame in BUZ_STATE_DONE state!?\n",
+				ZR_DEVNAME(zr), __func__);
 		case BUZ_STATE_USER:
 			/* since there is at least one unused buffer there's room for at
 			 *least one more pend[] entry */
-			zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] =
-			    num;
+			zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num;
 			zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
-			fh->jpg_buffers.buffer[num] =
-			    zr->jpg_buffers.buffer[num];
+			fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num];
 			zoran_feed_stat_com(zr);
 			break;
 		default:
 		case BUZ_STATE_DMA:
 		case BUZ_STATE_PEND:
 			if (zr->jpg_buffers.active == ZORAN_FREE) {
-				fh->jpg_buffers.active = ZORAN_FREE;
+				fh->buffers.active = ZORAN_FREE;
 				zr->jpg_buffers.allocated = 0;
 			}
 			res = -EBUSY;	/* what are you doing? */
@@ -974,47 +715,41 @@
 
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
-	if (!res && zr->jpg_buffers.active == ZORAN_FREE) {
-		zr->jpg_buffers.active = fh->jpg_buffers.active;
-	}
+	if (!res && zr->jpg_buffers.active == ZORAN_FREE)
+		zr->jpg_buffers.active = fh->buffers.active;
 
 	return res;
 }
 
-static int
-jpg_qbuf (struct file          *file,
-	  int                   frame,
-	  enum zoran_codec_mode mode)
+static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	int res = 0;
 
 	/* Does the user want to stop streaming? */
 	if (frame < 0) {
 		if (zr->codec_mode == mode) {
-			if (fh->jpg_buffers.active == ZORAN_FREE) {
+			if (fh->buffers.active == ZORAN_FREE) {
 				dprintk(1,
 					KERN_ERR
-					"%s: jpg_qbuf(-1) - session not active\n",
-					ZR_DEVNAME(zr));
+					"%s: %s(-1) - session not active\n",
+					ZR_DEVNAME(zr), __func__);
 				return -EINVAL;
 			}
-			fh->jpg_buffers.active = zr->jpg_buffers.active =
-			    ZORAN_FREE;
+			fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE;
 			zr->jpg_buffers.allocated = 0;
 			zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
 			return 0;
 		} else {
 			dprintk(1,
 				KERN_ERR
-				"%s: jpg_qbuf() - stop streaming but not in streaming mode\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - stop streaming but not in streaming mode\n",
+				ZR_DEVNAME(zr), __func__);
 			return -EINVAL;
 		}
 	}
 
-	if ((res = zoran_jpg_queue_frame(file, frame, mode)))
+	if ((res = zoran_jpg_queue_frame(fh, frame, mode)))
 		return res;
 
 	/* Start the jpeg codec when the first frame is queued  */
@@ -1028,28 +763,25 @@
  *   Sync on a MJPEG buffer
  */
 
-static int
-jpg_sync (struct file       *file,
-	  struct zoran_sync *bs)
+static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 	unsigned long flags;
 	int frame;
 
-	if (fh->jpg_buffers.active == ZORAN_FREE) {
+	if (fh->buffers.active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_sync() - capture is not currently active\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - capture is not currently active\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 	if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
 	    zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_sync() - codec not in streaming mode\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - codec not in streaming mode\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 	if (!wait_event_interruptible_timeout(zr->jpg_capq,
@@ -1064,8 +796,8 @@
 					   sizeof(isr), &isr);
 		dprintk(1,
 			KERN_ERR
-			"%s: jpg_sync() - timeout: codec isr=0x%02x\n",
-			ZR_DEVNAME(zr), isr);
+			"%s: %s - timeout: codec isr=0x%02x\n",
+			ZR_DEVNAME(zr), __func__, isr);
 
 		return -ETIME;
 
@@ -1083,28 +815,26 @@
 	/* buffer should now be in BUZ_STATE_DONE */
 	if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
 		dprintk(2,
-			KERN_ERR "%s: jpg_sync() - internal state error\n",
-			ZR_DEVNAME(zr));
+			KERN_ERR "%s: %s - internal state error\n",
+			ZR_DEVNAME(zr), __func__);
 
 	*bs = zr->jpg_buffers.buffer[frame].bs;
 	bs->frame = frame;
 	zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
-	fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
+	fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
 
 	spin_unlock_irqrestore(&zr->spinlock, flags);
 
 	return 0;
 }
 
-static void
-zoran_open_init_session (struct file *file)
+static void zoran_open_init_session(struct zoran_fh *fh)
 {
 	int i;
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 
 	/* Per default, map the V4L Buffers */
-	fh->map_mode = ZORAN_MAP_MODE_RAW;
+	map_mode_raw(fh);
 
 	/* take over the card's current settings */
 	fh->overlay_settings = zr->overlay_settings;
@@ -1114,40 +844,21 @@
 
 	/* v4l settings */
 	fh->v4l_settings = zr->v4l_settings;
-
-	/* v4l_buffers */
-	memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct));
-	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-		fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
-		fh->v4l_buffers.buffer[i].bs.frame = i;
-	}
-	fh->v4l_buffers.allocated = 0;
-	fh->v4l_buffers.ready_to_be_freed = 0;
-	fh->v4l_buffers.active = ZORAN_FREE;
-	fh->v4l_buffers.buffer_size = v4l_bufsize;
-	fh->v4l_buffers.num_buffers = v4l_nbufs;
-
 	/* jpg settings */
 	fh->jpg_settings = zr->jpg_settings;
 
-	/* jpg_buffers */
-	memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct));
-	for (i = 0; i < BUZ_MAX_FRAME; i++) {
-		fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
-		fh->jpg_buffers.buffer[i].bs.frame = i;
+	/* buffers */
+	memset(&fh->buffers, 0, sizeof(fh->buffers));
+	for (i = 0; i < MAX_FRAME; i++) {
+		fh->buffers.buffer[i].state = BUZ_STATE_USER;	/* nothing going on */
+		fh->buffers.buffer[i].bs.frame = i;
 	}
-	fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous;
-	fh->jpg_buffers.allocated = 0;
-	fh->jpg_buffers.ready_to_be_freed = 0;
-	fh->jpg_buffers.active = ZORAN_FREE;
-	fh->jpg_buffers.buffer_size = jpg_bufsize;
-	fh->jpg_buffers.num_buffers = jpg_nbufs;
+	fh->buffers.allocated = 0;
+	fh->buffers.active = ZORAN_FREE;
 }
 
-static void
-zoran_close_end_session (struct file *file)
+static void zoran_close_end_session(struct zoran_fh *fh)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 
 	/* overlay */
@@ -1159,36 +870,32 @@
 		zr->overlay_mask = NULL;
 	}
 
-	/* v4l capture */
-	if (fh->v4l_buffers.active != ZORAN_FREE) {
-		unsigned long flags;
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+		/* v4l capture */
+		if (fh->buffers.active != ZORAN_FREE) {
+			unsigned long flags;
 
-		spin_lock_irqsave(&zr->spinlock, flags);
-		zr36057_set_memgrab(zr, 0);
-		zr->v4l_buffers.allocated = 0;
-		zr->v4l_buffers.active = fh->v4l_buffers.active =
-		    ZORAN_FREE;
-		spin_unlock_irqrestore(&zr->spinlock, flags);
-	}
+			spin_lock_irqsave(&zr->spinlock, flags);
+			zr36057_set_memgrab(zr, 0);
+			zr->v4l_buffers.allocated = 0;
+			zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+			spin_unlock_irqrestore(&zr->spinlock, flags);
+		}
 
-	/* v4l buffers */
-	if (fh->v4l_buffers.allocated ||
-	    fh->v4l_buffers.ready_to_be_freed) {
-		v4l_fbuffer_free(file);
-	}
+		/* v4l buffers */
+		if (fh->buffers.allocated)
+			v4l_fbuffer_free(fh);
+	} else {
+		/* jpg capture */
+		if (fh->buffers.active != ZORAN_FREE) {
+			zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+			zr->jpg_buffers.allocated = 0;
+			zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+		}
 
-	/* jpg capture */
-	if (fh->jpg_buffers.active != ZORAN_FREE) {
-		zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-		zr->jpg_buffers.allocated = 0;
-		zr->jpg_buffers.active = fh->jpg_buffers.active =
-		    ZORAN_FREE;
-	}
-
-	/* jpg buffers */
-	if (fh->jpg_buffers.allocated ||
-	    fh->jpg_buffers.ready_to_be_freed) {
-		jpg_fbuffer_free(file);
+		/* jpg buffers */
+		if (fh->buffers.allocated)
+			jpg_fbuffer_free(fh);
 	}
 }
 
@@ -1202,15 +909,11 @@
 	struct zoran_fh *fh;
 	int res, first_open = 0;
 
-	dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
-		ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1);
+	dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n",
+		ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1);
 
 	lock_kernel();
 
-	/* see fs/device.c - the kernel already locks during open(),
-	 * so locking ourselves only causes deadlocks */
-	/*mutex_lock(&zr->resource_lock);*/
-
 	if (zr->user >= 2048) {
 		dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
 			ZR_DEVNAME(zr), zr->user);
@@ -1218,41 +921,15 @@
 		goto fail_unlock;
 	}
 
-	if (!zr->decoder) {
-		dprintk(1,
-			KERN_ERR "%s: no TV decoder loaded for device!\n",
-			ZR_DEVNAME(zr));
-		res = -EIO;
-		goto fail_unlock;
-	}
-
-	if (!try_module_get(zr->decoder->driver->driver.owner)) {
-		dprintk(1,
-			KERN_ERR
-			"%s: failed to grab ownership of video decoder\n",
-			ZR_DEVNAME(zr));
-		res = -EIO;
-		goto fail_unlock;
-	}
-	if (zr->encoder &&
-	    !try_module_get(zr->encoder->driver->driver.owner)) {
-		dprintk(1,
-			KERN_ERR
-			"%s: failed to grab ownership of video encoder\n",
-			ZR_DEVNAME(zr));
-		res = -EIO;
-		goto fail_decoder;
-	}
-
 	/* now, create the open()-specific file_ops struct */
 	fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
 	if (!fh) {
 		dprintk(1,
 			KERN_ERR
-			"%s: zoran_open() - allocation of zoran_fh failed\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - allocation of zoran_fh failed\n",
+			ZR_DEVNAME(zr), __func__);
 		res = -ENOMEM;
-		goto fail_encoder;
+		goto fail_unlock;
 	}
 	/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
 	 * on norm-change! */
@@ -1261,8 +938,8 @@
 	if (!fh->overlay_mask) {
 		dprintk(1,
 			KERN_ERR
-			"%s: zoran_open() - allocation of overlay_mask failed\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - allocation of overlay_mask failed\n",
+			ZR_DEVNAME(zr), __func__);
 		res = -ENOMEM;
 		goto fail_fh;
 	}
@@ -1284,18 +961,13 @@
 	/* set file_ops stuff */
 	file->private_data = fh;
 	fh->zr = zr;
-	zoran_open_init_session(file);
+	zoran_open_init_session(fh);
 	unlock_kernel();
 
 	return 0;
 
 fail_fh:
 	kfree(fh);
-fail_encoder:
-	if (zr->encoder)
-		module_put(zr->encoder->driver->driver.owner);
-fail_decoder:
-	module_put(zr->decoder->driver->driver.owner);
 fail_unlock:
 	unlock_kernel();
 
@@ -1311,14 +983,14 @@
 	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 
-	dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
-		ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1);
+	dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n",
+		ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1);
 
 	/* kernel locks (fs/device.c), so don't do that ourselves
 	 * (prevents deadlocks) */
 	/*mutex_lock(&zr->resource_lock);*/
 
-	zoran_close_end_session(file);
+	zoran_close_end_session(fh);
 
 	if (zr->user-- == 1) {	/* Last process */
 		/* Clean up JPEG process */
@@ -1346,9 +1018,10 @@
 		zoran_set_pci_master(zr, 0);
 
 		if (!pass_through) {	/* Switch to color bar */
-			int zero = 0, two = 2;
-			decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
-			encoder_command(zr, ENCODER_SET_INPUT, &two);
+			struct v4l2_routing route = { 2, 0 };
+
+			decoder_call(zr, video, s_stream, 0);
+			encoder_call(zr, video, s_routing, &route);
 		}
 	}
 
@@ -1356,14 +1029,7 @@
 	kfree(fh->overlay_mask);
 	kfree(fh);
 
-	/* release locks on the i2c modules */
-	module_put(zr->decoder->driver->driver.owner);
-	if (zr->encoder)
-		module_put(zr->encoder->driver->driver.owner);
-
-	/*mutex_unlock(&zr->resource_lock);*/
-
-	dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr));
+	dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__);
 
 	return 0;
 }
@@ -1391,15 +1057,13 @@
 	return -EINVAL;
 }
 
-static int
-setup_fbuffer (struct file               *file,
+static int setup_fbuffer(struct zoran_fh *fh,
 	       void                      *base,
 	       const struct zoran_format *fmt,
 	       int                        width,
 	       int                        height,
 	       int                        bytesperline)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 
 	/* (Ronald) v4l/v4l2 guidelines */
@@ -1427,8 +1091,8 @@
 		 * friendly and silently do as if nothing went wrong */
 		dprintk(3,
 			KERN_ERR
-			"%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - forced overlay turnoff because framebuffer changed\n",
+			ZR_DEVNAME(zr), __func__);
 		zr36057_overlay(zr, 0);
 	}
 #endif
@@ -1436,31 +1100,31 @@
 	if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_fbuffer() - no valid overlay format given\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - no valid overlay format given\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 	if (height <= 0 || width <= 0 || bytesperline <= 0) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n",
-			ZR_DEVNAME(zr), width, height, bytesperline);
+			"%s: %s - invalid height/width/bpl value (%d|%d|%d)\n",
+			ZR_DEVNAME(zr), __func__, width, height, bytesperline);
 		return -EINVAL;
 	}
 	if (bytesperline & 3) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n",
-			ZR_DEVNAME(zr), bytesperline);
+			"%s: %s - bytesperline (%d) must be 4-byte aligned\n",
+			ZR_DEVNAME(zr), __func__, bytesperline);
 		return -EINVAL;
 	}
 
-	zr->buffer.base = (void *) ((unsigned long) base & ~3);
-	zr->buffer.height = height;
-	zr->buffer.width = width;
-	zr->buffer.depth = fmt->depth;
+	zr->vbuf_base = (void *) ((unsigned long) base & ~3);
+	zr->vbuf_height = height;
+	zr->vbuf_width = width;
+	zr->vbuf_depth = fmt->depth;
 	zr->overlay_settings.format = fmt;
-	zr->buffer.bytesperline = bytesperline;
+	zr->vbuf_bytesperline = bytesperline;
 
 	/* The user should set new window parameters */
 	zr->overlay_settings.is_set = 0;
@@ -1469,35 +1133,27 @@
 }
 
 
-static int
-setup_window (struct file       *file,
-	      int                x,
-	      int                y,
-	      int                width,
-	      int                height,
-	      struct video_clip __user *clips,
-	      int                clipcount,
-	      void              __user *bitmap)
+static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height,
+	struct v4l2_clip __user *clips, int clipcount, void __user *bitmap)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
-	struct video_clip *vcp = NULL;
+	struct v4l2_clip *vcp = NULL;
 	int on, end;
 
 
-	if (!zr->buffer.base) {
+	if (!zr->vbuf_base) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_window() - frame buffer has to be set first\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - frame buffer has to be set first\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
 	if (!fh->overlay_settings.format) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_window() - no overlay format set\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - no overlay format set\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
@@ -1505,13 +1161,13 @@
 	 * The video front end needs 4-byte alinged line sizes, we correct that
 	 * silently here if necessary
 	 */
-	if (zr->buffer.depth == 15 || zr->buffer.depth == 16) {
+	if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) {
 		end = (x + width) & ~1;	/* round down */
 		x = (x + 1) & ~1;	/* round up */
 		width = end - x;
 	}
 
-	if (zr->buffer.depth == 24) {
+	if (zr->vbuf_depth == 24) {
 		end = (x + width) & ~3;	/* round down */
 		x = (x + 3) & ~3;	/* round up */
 		width = end - x;
@@ -1527,8 +1183,8 @@
 	    width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_window() - width = %d or height = %d invalid\n",
-			ZR_DEVNAME(zr), width, height);
+			"%s: %s - width = %d or height = %d invalid\n",
+			ZR_DEVNAME(zr), __func__, width, height);
 		return -EINVAL;
 	}
 
@@ -1566,20 +1222,20 @@
 		}
 	} else if (clipcount > 0) {
 		/* write our own bitmap from the clips */
-		vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4));
+		vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4));
 		if (vcp == NULL) {
 			dprintk(1,
 				KERN_ERR
-				"%s: setup_window() - Alloc of clip mask failed\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - Alloc of clip mask failed\n",
+				ZR_DEVNAME(zr), __func__);
 			return -ENOMEM;
 		}
 		if (copy_from_user
-		    (vcp, clips, sizeof(struct video_clip) * clipcount)) {
+		    (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) {
 			vfree(vcp);
 			return -EFAULT;
 		}
-		write_overlay_mask(file, vcp, clipcount);
+		write_overlay_mask(fh, vcp, clipcount);
 		vfree(vcp);
 	}
 
@@ -1595,11 +1251,8 @@
 	return wait_grab_pending(zr);
 }
 
-static int
-setup_overlay (struct file *file,
-	       int          on)
+static int setup_overlay(struct zoran_fh *fh, int on)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
 
 	/* If there is nothing to do, return immediatly */
@@ -1612,16 +1265,16 @@
 	    fh->overlay_active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_overlay() - overlay is already active for another session\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - overlay is already active for another session\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EBUSY;
 	}
 	if (!on && zr->overlay_active != ZORAN_FREE &&
 	    fh->overlay_active == ZORAN_FREE) {
 		dprintk(1,
 			KERN_ERR
-			"%s: setup_overlay() - you cannot cancel someone else's session\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - you cannot cancel someone else's session\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EPERM;
 	}
 
@@ -1634,18 +1287,18 @@
 			zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
 	} else {
-		if (!zr->buffer.base || !fh->overlay_settings.is_set) {
+		if (!zr->vbuf_base || !fh->overlay_settings.is_set) {
 			dprintk(1,
 				KERN_ERR
-				"%s: setup_overlay() - buffer or window not set\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - buffer or window not set\n",
+				ZR_DEVNAME(zr), __func__);
 			return -EINVAL;
 		}
 		if (!fh->overlay_settings.format) {
 			dprintk(1,
 				KERN_ERR
-				"%s: setup_overlay() - no overlay format set\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - no overlay format set\n",
+				ZR_DEVNAME(zr), __func__);
 			return -EINVAL;
 		}
 		zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
@@ -1662,41 +1315,47 @@
 	return wait_grab_pending(zr);
 }
 
-	/* get the status of a buffer in the clients buffer queue */
-static int
-zoran_v4l2_buffer_status (struct file        *file,
-			  struct v4l2_buffer *buf,
-			  int                 num)
+/* get the status of a buffer in the clients buffer queue */
+static int zoran_v4l2_buffer_status(struct zoran_fh *fh,
+				    struct v4l2_buffer *buf, int num)
 {
-	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
+	unsigned long flags;
 
 	buf->flags = V4L2_BUF_FLAG_MAPPED;
 
 	switch (fh->map_mode) {
 	case ZORAN_MAP_MODE_RAW:
-
 		/* check range */
-		if (num < 0 || num >= fh->v4l_buffers.num_buffers ||
-		    !fh->v4l_buffers.allocated) {
+		if (num < 0 || num >= fh->buffers.num_buffers ||
+		    !fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
-				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - wrong number or buffers not allocated\n",
+				ZR_DEVNAME(zr), __func__);
 			return -EINVAL;
 		}
 
+		spin_lock_irqsave(&zr->spinlock, flags);
+		dprintk(3,
+			KERN_DEBUG
+			"%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n",
+			ZR_DEVNAME(zr), __func__,
+			"FAL"[fh->buffers.active], num,
+			"UPMD"[zr->v4l_buffers.buffer[num].state],
+			fh->buffers.buffer[num].map ? 'Y' : 'N');
+		spin_unlock_irqrestore(&zr->spinlock, flags);
+
 		buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		buf->length = fh->v4l_buffers.buffer_size;
+		buf->length = fh->buffers.buffer_size;
 
 		/* get buffer */
-		buf->bytesused = fh->v4l_buffers.buffer[num].bs.length;
-		if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE ||
-		    fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) {
-			buf->sequence = fh->v4l_buffers.buffer[num].bs.seq;
+		buf->bytesused = fh->buffers.buffer[num].bs.length;
+		if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+		    fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+			buf->sequence = fh->buffers.buffer[num].bs.seq;
 			buf->flags |= V4L2_BUF_FLAG_DONE;
-			buf->timestamp =
-			    fh->v4l_buffers.buffer[num].bs.timestamp;
+			buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
 		} else {
 			buf->flags |= V4L2_BUF_FLAG_QUEUED;
 		}
@@ -1712,28 +1371,26 @@
 	case ZORAN_MAP_MODE_JPG_PLAY:
 
 		/* check range */
-		if (num < 0 || num >= fh->jpg_buffers.num_buffers ||
-		    !fh->jpg_buffers.allocated) {
+		if (num < 0 || num >= fh->buffers.num_buffers ||
+		    !fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
-				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - wrong number or buffers not allocated\n",
+				ZR_DEVNAME(zr), __func__);
 			return -EINVAL;
 		}
 
 		buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
 			      V4L2_BUF_TYPE_VIDEO_CAPTURE :
 			      V4L2_BUF_TYPE_VIDEO_OUTPUT;
-		buf->length = fh->jpg_buffers.buffer_size;
+		buf->length = fh->buffers.buffer_size;
 
 		/* these variables are only written after frame has been captured */
-		if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE ||
-		    fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) {
-			buf->sequence = fh->jpg_buffers.buffer[num].bs.seq;
-			buf->timestamp =
-			    fh->jpg_buffers.buffer[num].bs.timestamp;
-			buf->bytesused =
-			    fh->jpg_buffers.buffer[num].bs.length;
+		if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+		    fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+			buf->sequence = fh->buffers.buffer[num].bs.seq;
+			buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
+			buf->bytesused = fh->buffers.buffer[num].bs.length;
 			buf->flags |= V4L2_BUF_FLAG_DONE;
 		} else {
 			buf->flags |= V4L2_BUF_FLAG_QUEUED;
@@ -1741,14 +1398,11 @@
 
 		/* which fields are these? */
 		if (fh->jpg_settings.TmpDcm != 1)
-			buf->field =
-			    fh->jpg_settings.
-			    odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+			buf->field = fh->jpg_settings.odd_even ?
+				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
 		else
-			buf->field =
-			    fh->jpg_settings.
-			    odd_even ? V4L2_FIELD_SEQ_TB :
-			    V4L2_FIELD_SEQ_BT;
+			buf->field = fh->jpg_settings.odd_even ?
+				V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
 
 		break;
 
@@ -1756,8 +1410,8 @@
 
 		dprintk(5,
 			KERN_ERR
-			"%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n",
-			ZR_DEVNAME(zr), buf->type, fh->map_mode);
+			"%s: %s - invalid buffer type|map_mode (%d|%d)\n",
+			ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode);
 		return -EINVAL;
 	}
 
@@ -1770,81 +1424,55 @@
 
 static int
 zoran_set_norm (struct zoran *zr,
-		int           norm) /* VIDEO_MODE_* */
+		v4l2_std_id norm)
 {
-	int norm_encoder, on;
+	int on;
 
 	if (zr->v4l_buffers.active != ZORAN_FREE ||
 	    zr->jpg_buffers.active != ZORAN_FREE) {
 		dprintk(1,
 			KERN_WARNING
-			"%s: set_norm() called while in playback/capture mode\n",
-			ZR_DEVNAME(zr));
+			"%s: %s called while in playback/capture mode\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EBUSY;
 	}
 
-	if (lock_norm && norm != zr->norm) {
-		if (lock_norm > 1) {
-			dprintk(1,
-				KERN_WARNING
-				"%s: set_norm() - TV standard is locked, can not switch norm\n",
-				ZR_DEVNAME(zr));
-			return -EPERM;
-		} else {
-			dprintk(1,
-				KERN_WARNING
-				"%s: set_norm() - TV standard is locked, norm was not changed\n",
-				ZR_DEVNAME(zr));
-			norm = zr->norm;
-		}
-	}
-
-	if (norm != VIDEO_MODE_AUTO &&
-	    (norm < 0 || norm >= zr->card.norms ||
-	     !zr->card.tvn[norm])) {
+	if (!(norm & zr->card.norms)) {
 		dprintk(1,
-			KERN_ERR "%s: set_norm() - unsupported norm %d\n",
-			ZR_DEVNAME(zr), norm);
+			KERN_ERR "%s: %s - unsupported norm %llx\n",
+			ZR_DEVNAME(zr), __func__, norm);
 		return -EINVAL;
 	}
 
-	if (norm == VIDEO_MODE_AUTO) {
-		int status;
+	if (norm == V4L2_STD_ALL) {
+		int status = 0;
+		v4l2_std_id std = 0;
 
-		/* if we have autodetect, ... */
-		struct video_decoder_capability caps;
-		decoder_command(zr, DECODER_GET_CAPABILITIES, &caps);
-		if (!(caps.flags & VIDEO_DECODER_AUTO)) {
-			dprintk(1, KERN_ERR "%s: norm=auto unsupported\n",
-				ZR_DEVNAME(zr));
-			return -EINVAL;
-		}
-
-		decoder_command(zr, DECODER_SET_NORM, &norm);
+		decoder_call(zr, video, querystd, &std);
+		decoder_call(zr, tuner, s_std, std);
 
 		/* let changes come into effect */
 		ssleep(2);
 
-		decoder_command(zr, DECODER_GET_STATUS, &status);
-		if (!(status & DECODER_STATUS_GOOD)) {
+		decoder_call(zr, video, g_input_status, &status);
+		if (status & V4L2_IN_ST_NO_SIGNAL) {
 			dprintk(1,
 				KERN_ERR
-				"%s: set_norm() - no norm detected\n",
-				ZR_DEVNAME(zr));
+				"%s: %s - no norm detected\n",
+				ZR_DEVNAME(zr), __func__);
 			/* reset norm */
-			decoder_command(zr, DECODER_SET_NORM, &zr->norm);
+			decoder_call(zr, tuner, s_std, zr->norm);
 			return -EIO;
 		}
 
-		if (status & DECODER_STATUS_NTSC)
-			norm = VIDEO_MODE_NTSC;
-		else if (status & DECODER_STATUS_SECAM)
-			norm = VIDEO_MODE_SECAM;
-		else
-			norm = VIDEO_MODE_PAL;
+		norm = std;
 	}
-	zr->timing = zr->card.tvn[norm];
-	norm_encoder = norm;
+	if (norm & V4L2_STD_SECAM)
+		zr->timing = zr->card.tvn[2];
+	else if (norm & V4L2_STD_NTSC)
+		zr->timing = zr->card.tvn[1];
+	else
+		zr->timing = zr->card.tvn[0];
 
 	/* We switch overlay off and on since a change in the
 	 * norm needs different VFE settings */
@@ -1852,8 +1480,8 @@
 	if (on)
 		zr36057_overlay(zr, 0);
 
-	decoder_command(zr, DECODER_SET_NORM, &norm);
-	encoder_command(zr, ENCODER_SET_NORM, &norm_encoder);
+	decoder_call(zr, tuner, s_std, norm);
+	encoder_call(zr, video, s_std_output, norm);
 
 	if (on)
 		zr36057_overlay(zr, 1);
@@ -1868,7 +1496,7 @@
 zoran_set_input (struct zoran *zr,
 		 int           input)
 {
-	int realinput;
+	struct v4l2_routing route = { 0, 0 };
 
 	if (input == zr->input) {
 		return 0;
@@ -1878,23 +1506,23 @@
 	    zr->jpg_buffers.active != ZORAN_FREE) {
 		dprintk(1,
 			KERN_WARNING
-			"%s: set_input() called while in playback/capture mode\n",
-			ZR_DEVNAME(zr));
+			"%s: %s called while in playback/capture mode\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EBUSY;
 	}
 
 	if (input < 0 || input >= zr->card.inputs) {
 		dprintk(1,
 			KERN_ERR
-			"%s: set_input() - unnsupported input %d\n",
-			ZR_DEVNAME(zr), input);
+			"%s: %s - unnsupported input %d\n",
+			ZR_DEVNAME(zr), __func__, input);
 		return -EINVAL;
 	}
 
-	realinput = zr->card.input[input].muxsel;
+	route.input = zr->card.input[input].muxsel;
 	zr->input = input;
 
-	decoder_command(zr, DECODER_SET_INPUT, &realinput);
+	decoder_call(zr, video, s_routing, &route);
 
 	return 0;
 }
@@ -1903,410 +1531,14 @@
  *   ioctl routine
  */
 
-static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static long zoran_default(struct file *file, void *__fh, int cmd, void *arg)
 {
-	struct zoran_fh *fh = file->private_data;
+	struct zoran_fh *fh = __fh;
 	struct zoran *zr = fh->zr;
-	/* CAREFUL: used in multiple places here */
 	struct zoran_jpg_settings settings;
 
-	/* we might have older buffers lying around... We don't want
-	 * to wait, but we do want to try cleaning them up ASAP. So
-	 * we try to obtain the lock and free them. If that fails, we
-	 * don't do anything and wait for the next turn. In the end,
-	 * zoran_close() or a new allocation will still free them...
-	 * This is just a 'the sooner the better' extra 'feature'
-	 *
-	 * We don't free the buffers right on munmap() because that
-	 * causes oopses (kfree() inside munmap() oopses for no
-	 * apparent reason - it's also not reproduceable in any way,
-	 * but moving the free code outside the munmap() handler fixes
-	 * all this... If someone knows why, please explain me (Ronald)
-	 */
-	if (mutex_trylock(&zr->resource_lock)) {
-		/* we obtained it! Let's try to free some things */
-		if (fh->jpg_buffers.ready_to_be_freed)
-			jpg_fbuffer_free(file);
-		if (fh->v4l_buffers.ready_to_be_freed)
-			v4l_fbuffer_free(file);
-
-		mutex_unlock(&zr->resource_lock);
-	}
-
 	switch (cmd) {
-
-	case VIDIOCGCAP:
-	{
-		struct video_capability *vcap = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
-
-		memset(vcap, 0, sizeof(struct video_capability));
-		strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
-		vcap->type = ZORAN_VID_TYPE;
-
-		vcap->channels = zr->card.inputs;
-		vcap->audios = 0;
-		mutex_lock(&zr->resource_lock);
-		vcap->maxwidth = BUZ_MAX_WIDTH;
-		vcap->maxheight = BUZ_MAX_HEIGHT;
-		vcap->minwidth = BUZ_MIN_WIDTH;
-		vcap->minheight = BUZ_MIN_HEIGHT;
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *vchan = arg;
-		int channel = vchan->channel;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n",
-			ZR_DEVNAME(zr), vchan->channel);
-
-		memset(vchan, 0, sizeof(struct video_channel));
-		if (channel > zr->card.inputs || channel < 0) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOCGCHAN on not existing channel %d\n",
-				ZR_DEVNAME(zr), channel);
-			return -EINVAL;
-		}
-
-		strcpy(vchan->name, zr->card.input[channel].name);
-
-		vchan->tuners = 0;
-		vchan->flags = 0;
-		vchan->type = VIDEO_TYPE_CAMERA;
-		mutex_lock(&zr->resource_lock);
-		vchan->norm = zr->norm;
-		mutex_unlock(&zr->resource_lock);
-		vchan->channel = channel;
-
-		return 0;
-	}
-		break;
-
-		/* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
-		 *
-		 * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
-		 * *                                 ^^^^^^^
-		 * * The famos BTTV driver has it implemented with a struct video_channel argument
-		 * * and we follow it for compatibility reasons
-		 * *
-		 * * BTW: this is the only way the user can set the norm!
-		 */
-
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *vchan = arg;
-		int res;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOCSCHAN - channel=%d, norm=%d\n",
-			ZR_DEVNAME(zr), vchan->channel, vchan->norm);
-
-		mutex_lock(&zr->resource_lock);
-		if ((res = zoran_set_input(zr, vchan->channel)))
-			goto schan_unlock_and_return;
-		if ((res = zoran_set_norm(zr, vchan->norm)))
-			goto schan_unlock_and_return;
-
-		/* Make sure the changes come into effect */
-		res = wait_grab_pending(zr);
-	schan_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOCGPICT:
-	{
-		struct video_picture *vpict = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr));
-
-		memset(vpict, 0, sizeof(struct video_picture));
-		mutex_lock(&zr->resource_lock);
-		vpict->hue = zr->hue;
-		vpict->brightness = zr->brightness;
-		vpict->contrast = zr->contrast;
-		vpict->colour = zr->saturation;
-		if (fh->overlay_settings.format) {
-			vpict->depth = fh->overlay_settings.format->depth;
-			vpict->palette = fh->overlay_settings.format->palette;
-		} else {
-			vpict->depth = 0;
-		}
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOCSPICT:
-	{
-		struct video_picture *vpict = arg;
-		int i;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n",
-			ZR_DEVNAME(zr), vpict->brightness, vpict->hue,
-			vpict->colour, vpict->contrast, vpict->depth,
-			vpict->palette);
-
-		for (i = 0; i < NUM_FORMATS; i++) {
-			const struct zoran_format *fmt = &zoran_formats[i];
-
-			if (fmt->palette != -1 &&
-			    fmt->flags & ZORAN_FORMAT_OVERLAY &&
-			    fmt->palette == vpict->palette &&
-			    fmt->depth == vpict->depth)
-				break;
-		}
-		if (i == NUM_FORMATS) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOCSPICT - Invalid palette %d\n",
-				ZR_DEVNAME(zr), vpict->palette);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-
-		decoder_command(zr, DECODER_SET_PICTURE, vpict);
-
-		zr->hue = vpict->hue;
-		zr->contrast = vpict->contrast;
-		zr->saturation = vpict->colour;
-		zr->brightness = vpict->brightness;
-
-		fh->overlay_settings.format = &zoran_formats[i];
-
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOCCAPTURE:
-	{
-		int *on = arg, res;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n",
-			ZR_DEVNAME(zr), *on);
-
-		mutex_lock(&zr->resource_lock);
-		res = setup_overlay(file, *on);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOCGWIN:
-	{
-		struct video_window *vwin = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr));
-
-		memset(vwin, 0, sizeof(struct video_window));
-		mutex_lock(&zr->resource_lock);
-		vwin->x = fh->overlay_settings.x;
-		vwin->y = fh->overlay_settings.y;
-		vwin->width = fh->overlay_settings.width;
-		vwin->height = fh->overlay_settings.height;
-		mutex_unlock(&zr->resource_lock);
-		vwin->clipcount = 0;
-		return 0;
-	}
-		break;
-
-	case VIDIOCSWIN:
-	{
-		struct video_window *vwin = arg;
-		int res;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n",
-			ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width,
-			vwin->height, vwin->clipcount);
-
-		mutex_lock(&zr->resource_lock);
-		res =
-		    setup_window(file, vwin->x, vwin->y, vwin->width,
-				 vwin->height, vwin->clips,
-				 vwin->clipcount, NULL);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer *vbuf = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-		*vbuf = zr->buffer;
-		mutex_unlock(&zr->resource_lock);
-		return 0;
-	}
-		break;
-
-	case VIDIOCSFBUF:
-	{
-		struct video_buffer *vbuf = arg;
-		int i, res = 0;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n",
-			ZR_DEVNAME(zr), vbuf->base, vbuf->width,
-			vbuf->height, vbuf->depth, vbuf->bytesperline);
-
-		for (i = 0; i < NUM_FORMATS; i++)
-			if (zoran_formats[i].depth == vbuf->depth)
-				break;
-		if (i == NUM_FORMATS) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOCSFBUF - invalid fbuf depth %d\n",
-				ZR_DEVNAME(zr), vbuf->depth);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-		res =
-		    setup_fbuffer(file, vbuf->base, &zoran_formats[i],
-				  vbuf->width, vbuf->height,
-				  vbuf->bytesperline);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOCSYNC:
-	{
-		int *frame = arg, res;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n",
-			ZR_DEVNAME(zr), *frame);
-
-		mutex_lock(&zr->resource_lock);
-		res = v4l_sync(file, *frame);
-		mutex_unlock(&zr->resource_lock);
-		if (!res)
-			zr->v4l_sync_tail++;
-		return res;
-	}
-		break;
-
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vmap = arg;
-		int res;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n",
-			ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height,
-			vmap->format);
-
-		mutex_lock(&zr->resource_lock);
-		res = v4l_grab(file, vmap);
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vmbuf = arg;
-		int i, res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr));
-
-		vmbuf->size =
-		    fh->v4l_buffers.num_buffers *
-		    fh->v4l_buffers.buffer_size;
-		vmbuf->frames = fh->v4l_buffers.num_buffers;
-		for (i = 0; i < vmbuf->frames; i++) {
-			vmbuf->offsets[i] =
-			    i * fh->v4l_buffers.buffer_size;
-		}
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOCGMBUF - buffers already allocated\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto v4l1reqbuf_unlock_and_return;
-		}
-
-		if (v4l_fbuffer_alloc(file)) {
-			res = -ENOMEM;
-			goto v4l1reqbuf_unlock_and_return;
-		}
-
-		/* The next mmap will map the V4L buffers */
-		fh->map_mode = ZORAN_MAP_MODE_RAW;
-	v4l1reqbuf_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOCGUNIT:
-	{
-		struct video_unit *vunit = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr));
-
-		vunit->video = zr->video_dev->minor;
-		vunit->vbi = VIDEO_NO_UNIT;
-		vunit->radio = VIDEO_NO_UNIT;
-		vunit->audio = VIDEO_NO_UNIT;
-		vunit->teletext = VIDEO_NO_UNIT;
-
-		return 0;
-	}
-		break;
-
-		/*
-		 * RJ: In principal we could support subcaptures for V4L grabbing.
-		 *     Not even the famous BTTV driver has them, however.
-		 *     If there should be a strong demand, one could consider
-		 *     to implement them.
-		 */
-	case VIDIOCGCAPTURE:
-	{
-		dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n",
-			ZR_DEVNAME(zr));
-		return -EINVAL;
-	}
-		break;
-
-	case VIDIOCSCAPTURE:
-	{
-		dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n",
-			ZR_DEVNAME(zr));
-		return -EINVAL;
-	}
-		break;
-
 	case BUZIOC_G_PARAMS:
 	{
 		struct zoran_params *bparams = arg;
@@ -2319,7 +1551,13 @@
 
 		mutex_lock(&zr->resource_lock);
 
-		bparams->norm = zr->norm;
+		if (zr->norm & V4L2_STD_NTSC)
+			bparams->norm = VIDEO_MODE_NTSC;
+		else if (zr->norm & V4L2_STD_PAL)
+			bparams->norm = VIDEO_MODE_PAL;
+		else
+			bparams->norm = VIDEO_MODE_SECAM;
+
 		bparams->input = zr->input;
 
 		bparams->decimation = fh->jpg_settings.decimation;
@@ -2352,7 +1590,6 @@
 
 		return 0;
 	}
-		break;
 
 	case BUZIOC_S_PARAMS:
 	{
@@ -2395,18 +1632,17 @@
 
 		/* Check the params first before overwriting our
 		 * nternal values */
-		if (zoran_check_jpg_settings(zr, &settings)) {
+		if (zoran_check_jpg_settings(zr, &settings, 0)) {
 			res = -EINVAL;
 			goto sparams_unlock_and_return;
 		}
 
 		fh->jpg_settings = settings;
-	sparams_unlock_and_return:
+sparams_unlock_and_return:
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
 	}
-		break;
 
 	case BUZIOC_REQBUFS:
 	{
@@ -2430,38 +1666,34 @@
 		 * tables to a Maximum of 2 MB */
 		if (breq->size > jpg_bufsize)
 			breq->size = jpg_bufsize;
-		if (fh->jpg_buffers.need_contiguous &&
-		    breq->size > MAX_KMALLOC_MEM)
-			breq->size = MAX_KMALLOC_MEM;
 
 		mutex_lock(&zr->resource_lock);
 
-		if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+		if (fh->buffers.allocated) {
 			dprintk(1,
 				KERN_ERR
-				"%s: BUZIOC_REQBUFS - buffers allready allocated\n",
+				"%s: BUZIOC_REQBUFS - buffers already allocated\n",
 				ZR_DEVNAME(zr));
 			res = -EBUSY;
 			goto jpgreqbuf_unlock_and_return;
 		}
 
-		fh->jpg_buffers.num_buffers = breq->count;
-		fh->jpg_buffers.buffer_size = breq->size;
+		/* The next mmap will map the MJPEG buffers - could
+		 * also be *_PLAY, but it doesn't matter here */
+		map_mode_jpg(fh, 0);
+		fh->buffers.num_buffers = breq->count;
+		fh->buffers.buffer_size = breq->size;
 
-		if (jpg_fbuffer_alloc(file)) {
+		if (jpg_fbuffer_alloc(fh)) {
 			res = -ENOMEM;
 			goto jpgreqbuf_unlock_and_return;
 		}
 
-		/* The next mmap will map the MJPEG buffers - could
-		 * also be *_PLAY, but it doesn't matter here */
-		fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
-	jpgreqbuf_unlock_and_return:
+jpgreqbuf_unlock_and_return:
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
 	}
-		break;
 
 	case BUZIOC_QBUF_CAPT:
 	{
@@ -2471,12 +1703,11 @@
 			ZR_DEVNAME(zr), *frame);
 
 		mutex_lock(&zr->resource_lock);
-		res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS);
+		res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_COMPRESS);
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
 	}
-		break;
 
 	case BUZIOC_QBUF_PLAY:
 	{
@@ -2486,12 +1717,11 @@
 			ZR_DEVNAME(zr), *frame);
 
 		mutex_lock(&zr->resource_lock);
-		res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS);
+		res = jpg_qbuf(fh, *frame, BUZ_MODE_MOTION_DECOMPRESS);
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
 	}
-		break;
 
 	case BUZIOC_SYNC:
 	{
@@ -2501,17 +1731,26 @@
 		dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr));
 
 		mutex_lock(&zr->resource_lock);
-		res = jpg_sync(file, bsync);
+
+		if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+			dprintk(2, KERN_WARNING
+				"%s: %s - not in jpg capture mode\n",
+				ZR_DEVNAME(zr), __func__);
+			res = -EINVAL;
+		} else {
+			res = jpg_sync(fh, bsync);
+		}
 		mutex_unlock(&zr->resource_lock);
 
 		return res;
 	}
-		break;
 
 	case BUZIOC_G_STATUS:
 	{
 		struct zoran_status *bstat = arg;
-		int norm, input, status, res = 0;
+		struct v4l2_routing route = { 0, 0 };
+		int status = 0, res = 0;
+		v4l2_std_id norm;
 
 		dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr));
 
@@ -2523,8 +1762,7 @@
 			return -EINVAL;
 		}
 
-		input = zr->card.input[bstat->input].muxsel;
-		norm = VIDEO_MODE_AUTO;
+		route.input = zr->card.input[bstat->input].muxsel;
 
 		mutex_lock(&zr->resource_lock);
 
@@ -2537,1629 +1775,1262 @@
 			goto gstat_unlock_and_return;
 		}
 
-		decoder_command(zr, DECODER_SET_INPUT, &input);
-		decoder_command(zr, DECODER_SET_NORM, &norm);
+		decoder_call(zr, video, s_routing, &route);
 
 		/* sleep 1 second */
 		ssleep(1);
 
 		/* Get status of video decoder */
-		decoder_command(zr, DECODER_GET_STATUS, &status);
+		decoder_call(zr, video, querystd, &norm);
+		decoder_call(zr, video, g_input_status, &status);
 
 		/* restore previous input and norm */
-		input = zr->card.input[zr->input].muxsel;
-		decoder_command(zr, DECODER_SET_INPUT, &input);
-		decoder_command(zr, DECODER_SET_NORM, &zr->norm);
-	gstat_unlock_and_return:
+		route.input = zr->card.input[zr->input].muxsel;
+		decoder_call(zr, video, s_routing, &route);
+gstat_unlock_and_return:
 		mutex_unlock(&zr->resource_lock);
 
 		if (!res) {
 			bstat->signal =
-			    (status & DECODER_STATUS_GOOD) ? 1 : 0;
-			if (status & DECODER_STATUS_NTSC)
+			    (status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1;
+			if (norm & V4L2_STD_NTSC)
 				bstat->norm = VIDEO_MODE_NTSC;
-			else if (status & DECODER_STATUS_SECAM)
+			else if (norm & V4L2_STD_SECAM)
 				bstat->norm = VIDEO_MODE_SECAM;
 			else
 				bstat->norm = VIDEO_MODE_PAL;
 
 			bstat->color =
-			    (status & DECODER_STATUS_COLOR) ? 1 : 0;
+			    (status & V4L2_IN_ST_NO_COLOR) ? 0 : 1;
 		}
 
 		return res;
 	}
-		break;
-
-		/* The new video4linux2 capture interface - much nicer than video4linux1, since
-		 * it allows for integrating the JPEG capturing calls inside standard v4l2
-		 */
-
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
-
-		memset(cap, 0, sizeof(*cap));
-		strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
-		strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
-		snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-			 pci_name(zr->pci_dev));
-		cap->version =
-		    KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
-				   RELEASE_VERSION);
-		cap->capabilities = ZORAN_V4L2_VID_FLAGS;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *fmt = arg;
-		int index = fmt->index, num = -1, i, flag = 0, type =
-		    fmt->type;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUM_FMT - index=%d\n",
-			ZR_DEVNAME(zr), fmt->index);
-
-		switch (fmt->type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			flag = ZORAN_FORMAT_CAPTURE;
-			break;
-		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-			flag = ZORAN_FORMAT_PLAYBACK;
-			break;
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-			flag = ZORAN_FORMAT_OVERLAY;
-			break;
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_ENUM_FMT - unknown type %d\n",
-				ZR_DEVNAME(zr), fmt->type);
-			return -EINVAL;
-		}
-
-		for (i = 0; i < NUM_FORMATS; i++) {
-			if (zoran_formats[i].flags & flag)
-				num++;
-			if (num == fmt->index)
-				break;
-		}
-		if (fmt->index < 0 /* late, but not too late */  ||
-		    i == NUM_FORMATS)
-			return -EINVAL;
-
-		memset(fmt, 0, sizeof(*fmt));
-		fmt->index = index;
-		fmt->type = type;
-		strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
-		fmt->pixelformat = zoran_formats[i].fourcc;
-		if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
-			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *fmt = arg;
-		int type = fmt->type;
-
-		dprintk(5, KERN_DEBUG "%s: VIDIOC_G_FMT\n", ZR_DEVNAME(zr));
-
-		memset(fmt, 0, sizeof(*fmt));
-		fmt->type = type;
-
-		switch (fmt->type) {
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-
-			mutex_lock(&zr->resource_lock);
-
-			fmt->fmt.win.w.left = fh->overlay_settings.x;
-			fmt->fmt.win.w.top = fh->overlay_settings.y;
-			fmt->fmt.win.w.width = fh->overlay_settings.width;
-			fmt->fmt.win.w.height =
-			    fh->overlay_settings.height;
-			if (fh->overlay_settings.width * 2 >
-			    BUZ_MAX_HEIGHT)
-				fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
-			else
-				fmt->fmt.win.field = V4L2_FIELD_TOP;
-
-			mutex_unlock(&zr->resource_lock);
-
-			break;
-
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-
-			mutex_lock(&zr->resource_lock);
-
-			if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-			    fh->map_mode == ZORAN_MAP_MODE_RAW) {
-
-				fmt->fmt.pix.width =
-				    fh->v4l_settings.width;
-				fmt->fmt.pix.height =
-				    fh->v4l_settings.height;
-				fmt->fmt.pix.sizeimage =
-				    fh->v4l_settings.bytesperline *
-				    fh->v4l_settings.height;
-				fmt->fmt.pix.pixelformat =
-				    fh->v4l_settings.format->fourcc;
-				fmt->fmt.pix.colorspace =
-				    fh->v4l_settings.format->colorspace;
-				fmt->fmt.pix.bytesperline =
-				    fh->v4l_settings.bytesperline;
-				if (BUZ_MAX_HEIGHT <
-				    (fh->v4l_settings.height * 2))
-					fmt->fmt.pix.field =
-					    V4L2_FIELD_INTERLACED;
-				else
-					fmt->fmt.pix.field =
-					    V4L2_FIELD_TOP;
-
-			} else {
-
-				fmt->fmt.pix.width =
-				    fh->jpg_settings.img_width /
-				    fh->jpg_settings.HorDcm;
-				fmt->fmt.pix.height =
-				    fh->jpg_settings.img_height /
-				    (fh->jpg_settings.VerDcm *
-				     fh->jpg_settings.TmpDcm);
-				fmt->fmt.pix.sizeimage =
-				    zoran_v4l2_calc_bufsize(&fh->
-							    jpg_settings);
-				fmt->fmt.pix.pixelformat =
-				    V4L2_PIX_FMT_MJPEG;
-				if (fh->jpg_settings.TmpDcm == 1)
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_SEQ_BT :
-					     V4L2_FIELD_SEQ_BT);
-				else
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_TOP :
-					     V4L2_FIELD_BOTTOM);
-
-				fmt->fmt.pix.bytesperline = 0;
-				fmt->fmt.pix.colorspace =
-				    V4L2_COLORSPACE_SMPTE170M;
-			}
-
-			mutex_unlock(&zr->resource_lock);
-
-			break;
-
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_G_FMT - unsupported type %d\n",
-				ZR_DEVNAME(zr), fmt->type);
-			return -EINVAL;
-		}
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *fmt = arg;
-		int i, res = 0;
-		__le32 printformat;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ",
-			ZR_DEVNAME(zr), fmt->type);
-
-		switch (fmt->type) {
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-
-			dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
-				fmt->fmt.win.w.left, fmt->fmt.win.w.top,
-				fmt->fmt.win.w.width,
-				fmt->fmt.win.w.height,
-				fmt->fmt.win.clipcount,
-				fmt->fmt.win.bitmap);
-			mutex_lock(&zr->resource_lock);
-			res =
-			    setup_window(file, fmt->fmt.win.w.left,
-					 fmt->fmt.win.w.top,
-					 fmt->fmt.win.w.width,
-					 fmt->fmt.win.w.height,
-					 (struct video_clip __user *)
-					   fmt->fmt.win.clips,
-					 fmt->fmt.win.clipcount,
-					 fmt->fmt.win.bitmap);
-			mutex_unlock(&zr->resource_lock);
-			return res;
-			break;
-
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-
-			printformat =
-			    __cpu_to_le32(fmt->fmt.pix.pixelformat);
-			dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
-				fmt->fmt.pix.width, fmt->fmt.pix.height,
-				fmt->fmt.pix.pixelformat,
-				(char *) &printformat);
-
-			/* we can be requested to do JPEG/raw playback/capture */
-			if (!
-			    (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-			     (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-			      fmt->fmt.pix.pixelformat ==
-			      V4L2_PIX_FMT_MJPEG))) {
-				dprintk(1,
-					KERN_ERR
-					"%s: VIDIOC_S_FMT - unknown type %d/0x%x(%4.4s) combination\n",
-					ZR_DEVNAME(zr), fmt->type,
-					fmt->fmt.pix.pixelformat,
-					(char *) &printformat);
-				return -EINVAL;
-			}
-
-			if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
-				mutex_lock(&zr->resource_lock);
-
-				settings = fh->jpg_settings;
-
-				if (fh->v4l_buffers.allocated ||
-				    fh->jpg_buffers.allocated) {
-					dprintk(1,
-						KERN_ERR
-						"%s: VIDIOC_S_FMT - cannot change capture mode\n",
-						ZR_DEVNAME(zr));
-					res = -EBUSY;
-					goto sfmtjpg_unlock_and_return;
-				}
-
-				/* we actually need to set 'real' parameters now */
-				if ((fmt->fmt.pix.height * 2) >
-				    BUZ_MAX_HEIGHT)
-					settings.TmpDcm = 1;
-				else
-					settings.TmpDcm = 2;
-				settings.decimation = 0;
-				if (fmt->fmt.pix.height <=
-				    fh->jpg_settings.img_height / 2)
-					settings.VerDcm = 2;
-				else
-					settings.VerDcm = 1;
-				if (fmt->fmt.pix.width <=
-				    fh->jpg_settings.img_width / 4)
-					settings.HorDcm = 4;
-				else if (fmt->fmt.pix.width <=
-					 fh->jpg_settings.img_width / 2)
-					settings.HorDcm = 2;
-				else
-					settings.HorDcm = 1;
-				if (settings.TmpDcm == 1)
-					settings.field_per_buff = 2;
-				else
-					settings.field_per_buff = 1;
-
-				/* check */
-				if ((res =
-				     zoran_check_jpg_settings(zr,
-							      &settings)))
-					goto sfmtjpg_unlock_and_return;
-
-				/* it's ok, so set them */
-				fh->jpg_settings = settings;
-
-				/* tell the user what we actually did */
-				fmt->fmt.pix.width =
-				    settings.img_width / settings.HorDcm;
-				fmt->fmt.pix.height =
-				    settings.img_height * 2 /
-				    (settings.TmpDcm * settings.VerDcm);
-				if (settings.TmpDcm == 1)
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_SEQ_TB :
-					     V4L2_FIELD_SEQ_BT);
-				else
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_TOP :
-					     V4L2_FIELD_BOTTOM);
-				fh->jpg_buffers.buffer_size =
-				    zoran_v4l2_calc_bufsize(&fh->
-							    jpg_settings);
-				fmt->fmt.pix.bytesperline = 0;
-				fmt->fmt.pix.sizeimage =
-				    fh->jpg_buffers.buffer_size;
-				fmt->fmt.pix.colorspace =
-				    V4L2_COLORSPACE_SMPTE170M;
-
-				/* we hereby abuse this variable to show that
-				 * we're gonna do mjpeg capture */
-				fh->map_mode =
-				    (fmt->type ==
-				     V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
-				    ZORAN_MAP_MODE_JPG_REC :
-				    ZORAN_MAP_MODE_JPG_PLAY;
-			sfmtjpg_unlock_and_return:
-				mutex_unlock(&zr->resource_lock);
-			} else {
-				for (i = 0; i < NUM_FORMATS; i++)
-					if (fmt->fmt.pix.pixelformat ==
-					    zoran_formats[i].fourcc)
-						break;
-				if (i == NUM_FORMATS) {
-					dprintk(1,
-						KERN_ERR
-						"%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n",
-						ZR_DEVNAME(zr),
-						fmt->fmt.pix.pixelformat,
-						(char *) &printformat);
-					return -EINVAL;
-				}
-				mutex_lock(&zr->resource_lock);
-				if (fh->jpg_buffers.allocated ||
-				    (fh->v4l_buffers.allocated &&
-				     fh->v4l_buffers.active !=
-				     ZORAN_FREE)) {
-					dprintk(1,
-						KERN_ERR
-						"%s: VIDIOC_S_FMT - cannot change capture mode\n",
-						ZR_DEVNAME(zr));
-					res = -EBUSY;
-					goto sfmtv4l_unlock_and_return;
-				}
-				if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-					fmt->fmt.pix.height =
-					    BUZ_MAX_HEIGHT;
-				if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-					fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-
-				if ((res =
-				     zoran_v4l_set_format(file,
-							  fmt->fmt.pix.
-							  width,
-							  fmt->fmt.pix.
-							  height,
-							  &zoran_formats
-							  [i])))
-					goto sfmtv4l_unlock_and_return;
-
-				/* tell the user the
-				 * results/missing stuff */
-				fmt->fmt.pix.bytesperline =
-					fh->v4l_settings.bytesperline;
-				fmt->fmt.pix.sizeimage =
-					fh->v4l_settings.height *
-					fh->v4l_settings.bytesperline;
-				fmt->fmt.pix.colorspace =
-					fh->v4l_settings.format->colorspace;
-				if (BUZ_MAX_HEIGHT <
-				    (fh->v4l_settings.height * 2))
-					fmt->fmt.pix.field =
-					    V4L2_FIELD_INTERLACED;
-				else
-					fmt->fmt.pix.field =
-					    V4L2_FIELD_TOP;
-
-				fh->map_mode = ZORAN_MAP_MODE_RAW;
-			sfmtv4l_unlock_and_return:
-				mutex_unlock(&zr->resource_lock);
-			}
-
-			break;
-
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_S_FMT - unsupported type %d\n",
-				ZR_DEVNAME(zr), fmt->type);
-			return -EINVAL;
-		}
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_G_FBUF:
-	{
-		struct v4l2_framebuffer *fb = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr));
-
-		memset(fb, 0, sizeof(*fb));
-		mutex_lock(&zr->resource_lock);
-		fb->base = zr->buffer.base;
-		fb->fmt.width = zr->buffer.width;
-		fb->fmt.height = zr->buffer.height;
-		if (zr->overlay_settings.format) {
-			fb->fmt.pixelformat =
-				fh->overlay_settings.format->fourcc;
-		}
-		fb->fmt.bytesperline = zr->buffer.bytesperline;
-		mutex_unlock(&zr->resource_lock);
-		fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
-		fb->fmt.field = V4L2_FIELD_INTERLACED;
-		fb->flags = V4L2_FBUF_FLAG_OVERLAY;
-		fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_FBUF:
-	{
-		int i, res = 0;
-		struct v4l2_framebuffer *fb = arg;
-		__le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOC_S_FBUF - base=0x%p, size=%dx%d, bpl=%d, fmt=0x%x (%4.4s)\n",
-			ZR_DEVNAME(zr), fb->base, fb->fmt.width, fb->fmt.height,
-			fb->fmt.bytesperline, fb->fmt.pixelformat,
-			(char *) &printformat);
-
-		for (i = 0; i < NUM_FORMATS; i++)
-			if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
-				break;
-		if (i == NUM_FORMATS) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
-				ZR_DEVNAME(zr), fb->fmt.pixelformat,
-				(char *) &printformat);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-		res =
-		    setup_fbuffer(file, fb->base, &zoran_formats[i],
-				  fb->fmt.width, fb->fmt.height,
-				  fb->fmt.bytesperline);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_OVERLAY:
-	{
-		int *on = arg, res;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n",
-			ZR_DEVNAME(zr), *on);
-
-		mutex_lock(&zr->resource_lock);
-		res = setup_overlay(file, *on);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_REQBUFS:
-	{
-		struct v4l2_requestbuffers *req = arg;
-		int res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_REQBUFS - type=%d\n",
-			ZR_DEVNAME(zr), req->type);
-
-		if (req->memory != V4L2_MEMORY_MMAP) {
-			dprintk(1,
-				KERN_ERR
-				"%s: only MEMORY_MMAP capture is supported, not %d\n",
-				ZR_DEVNAME(zr), req->memory);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_REQBUFS - buffers allready allocated\n",
-				ZR_DEVNAME(zr));
-			res = -EBUSY;
-			goto v4l2reqbuf_unlock_and_return;
-		}
-
-		if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
-		    req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-
-			/* control user input */
-			if (req->count < 2)
-				req->count = 2;
-			if (req->count > v4l_nbufs)
-				req->count = v4l_nbufs;
-			fh->v4l_buffers.num_buffers = req->count;
-
-			if (v4l_fbuffer_alloc(file)) {
-				res = -ENOMEM;
-				goto v4l2reqbuf_unlock_and_return;
-			}
-
-			/* The next mmap will map the V4L buffers */
-			fh->map_mode = ZORAN_MAP_MODE_RAW;
-
-		} else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
-			   fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-
-			/* we need to calculate size ourselves now */
-			if (req->count < 4)
-				req->count = 4;
-			if (req->count > jpg_nbufs)
-				req->count = jpg_nbufs;
-			fh->jpg_buffers.num_buffers = req->count;
-			fh->jpg_buffers.buffer_size =
-			    zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-
-			if (jpg_fbuffer_alloc(file)) {
-				res = -ENOMEM;
-				goto v4l2reqbuf_unlock_and_return;
-			}
-
-			/* The next mmap will map the MJPEG buffers */
-			if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-				fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
-			else
-				fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
-
-		} else {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_REQBUFS - unknown type %d\n",
-				ZR_DEVNAME(zr), req->type);
-			res = -EINVAL;
-			goto v4l2reqbuf_unlock_and_return;
-		}
-	v4l2reqbuf_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_QUERYBUF:
-	{
-		struct v4l2_buffer *buf = arg;
-		__u32 type = buf->type;
-		int index = buf->index, res;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOC_QUERYBUF - index=%d, type=%d\n",
-			ZR_DEVNAME(zr), buf->index, buf->type);
-
-		memset(buf, 0, sizeof(*buf));
-		buf->type = type;
-		buf->index = index;
-
-		mutex_lock(&zr->resource_lock);
-		res = zoran_v4l2_buffer_status(file, buf, buf->index);
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_QBUF:
-	{
-		struct v4l2_buffer *buf = arg;
-		int res = 0, codec_mode, buf_type;
-
-		dprintk(3,
-			KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n",
-			ZR_DEVNAME(zr), buf->type, buf->index);
-
-		mutex_lock(&zr->resource_lock);
-
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_RAW:
-			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-				dprintk(1,
-					KERN_ERR
-					"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-					ZR_DEVNAME(zr), buf->type, fh->map_mode);
-				res = -EINVAL;
-				goto qbuf_unlock_and_return;
-			}
-
-			res = zoran_v4l_queue_frame(file, buf->index);
-			if (res)
-				goto qbuf_unlock_and_return;
-			if (!zr->v4l_memgrab_active &&
-			    fh->v4l_buffers.active == ZORAN_LOCKED)
-				zr36057_set_memgrab(zr, 1);
-			break;
-
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
-			if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-				buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-				codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
-			} else {
-				buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-				codec_mode = BUZ_MODE_MOTION_COMPRESS;
-			}
-
-			if (buf->type != buf_type) {
-				dprintk(1,
-					KERN_ERR
-					"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-					ZR_DEVNAME(zr), buf->type, fh->map_mode);
-				res = -EINVAL;
-				goto qbuf_unlock_and_return;
-			}
-
-			res =
-			    zoran_jpg_queue_frame(file, buf->index,
-						  codec_mode);
-			if (res != 0)
-				goto qbuf_unlock_and_return;
-			if (zr->codec_mode == BUZ_MODE_IDLE &&
-			    fh->jpg_buffers.active == ZORAN_LOCKED) {
-				zr36057_enable_jpg(zr, codec_mode);
-			}
-			break;
-
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_QBUF - unsupported type %d\n",
-				ZR_DEVNAME(zr), buf->type);
-			res = -EINVAL;
-			goto qbuf_unlock_and_return;
-		}
-	qbuf_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_DQBUF:
-	{
-		struct v4l2_buffer *buf = arg;
-		int res = 0, buf_type, num = -1;	/* compiler borks here (?) */
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n",
-			ZR_DEVNAME(zr), buf->type);
-
-		mutex_lock(&zr->resource_lock);
-
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_RAW:
-			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-				dprintk(1,
-					KERN_ERR
-					"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-					ZR_DEVNAME(zr), buf->type, fh->map_mode);
-				res = -EINVAL;
-				goto dqbuf_unlock_and_return;
-			}
-
-			num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
-			if (file->f_flags & O_NONBLOCK &&
-			    zr->v4l_buffers.buffer[num].state !=
-			    BUZ_STATE_DONE) {
-				res = -EAGAIN;
-				goto dqbuf_unlock_and_return;
-			}
-			res = v4l_sync(file, num);
-			if (res)
-				goto dqbuf_unlock_and_return;
-			else
-				zr->v4l_sync_tail++;
-			res = zoran_v4l2_buffer_status(file, buf, num);
-			break;
-
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
-		{
-			struct zoran_sync bs;
-
-			if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
-				buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-			else
-				buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-			if (buf->type != buf_type) {
-				dprintk(1,
-					KERN_ERR
-					"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-					ZR_DEVNAME(zr), buf->type, fh->map_mode);
-				res = -EINVAL;
-				goto dqbuf_unlock_and_return;
-			}
-
-			num =
-			    zr->jpg_pend[zr->
-					 jpg_que_tail & BUZ_MASK_FRAME];
-
-			if (file->f_flags & O_NONBLOCK &&
-			    zr->jpg_buffers.buffer[num].state !=
-			    BUZ_STATE_DONE) {
-				res = -EAGAIN;
-				goto dqbuf_unlock_and_return;
-			}
-			res = jpg_sync(file, &bs);
-			if (res)
-				goto dqbuf_unlock_and_return;
-			res =
-			    zoran_v4l2_buffer_status(file, buf, bs.frame);
-			break;
-		}
-
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_DQBUF - unsupported type %d\n",
-				ZR_DEVNAME(zr), buf->type);
-			res = -EINVAL;
-			goto dqbuf_unlock_and_return;
-		}
-	dqbuf_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_STREAMON:
-	{
-		int res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_RAW:	/* raw capture */
-			if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
-			    fh->v4l_buffers.active != ZORAN_ACTIVE) {
-				res = -EBUSY;
-				goto strmon_unlock_and_return;
-			}
-
-			zr->v4l_buffers.active = fh->v4l_buffers.active =
-			    ZORAN_LOCKED;
-			zr->v4l_settings = fh->v4l_settings;
-
-			zr->v4l_sync_tail = zr->v4l_pend_tail;
-			if (!zr->v4l_memgrab_active &&
-			    zr->v4l_pend_head != zr->v4l_pend_tail) {
-				zr36057_set_memgrab(zr, 1);
-			}
-			break;
-
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
-			/* what is the codec mode right now? */
-			if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
-			    fh->jpg_buffers.active != ZORAN_ACTIVE) {
-				res = -EBUSY;
-				goto strmon_unlock_and_return;
-			}
-
-			zr->jpg_buffers.active = fh->jpg_buffers.active =
-			    ZORAN_LOCKED;
-
-			if (zr->jpg_que_head != zr->jpg_que_tail) {
-				/* Start the jpeg codec when the first frame is queued  */
-				jpeg_start(zr);
-			}
-
-			break;
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_STREAMON - invalid map mode %d\n",
-				ZR_DEVNAME(zr), fh->map_mode);
-			res = -EINVAL;
-			goto strmon_unlock_and_return;
-		}
-	strmon_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_STREAMOFF:
-	{
-		int i, res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_RAW:	/* raw capture */
-			if (fh->v4l_buffers.active == ZORAN_FREE &&
-			    zr->v4l_buffers.active != ZORAN_FREE) {
-				res = -EPERM;	/* stay off other's settings! */
-				goto strmoff_unlock_and_return;
-			}
-			if (zr->v4l_buffers.active == ZORAN_FREE)
-				goto strmoff_unlock_and_return;
-
-			/* unload capture */
-			if (zr->v4l_memgrab_active) {
-				unsigned long flags;
-
-				spin_lock_irqsave(&zr->spinlock, flags);
-				zr36057_set_memgrab(zr, 0);
-				spin_unlock_irqrestore(&zr->spinlock, flags);
-			}
-
-			for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
-				zr->v4l_buffers.buffer[i].state =
-				    BUZ_STATE_USER;
-			fh->v4l_buffers = zr->v4l_buffers;
-
-			zr->v4l_buffers.active = fh->v4l_buffers.active =
-			    ZORAN_FREE;
-
-			zr->v4l_grab_seq = 0;
-			zr->v4l_pend_head = zr->v4l_pend_tail = 0;
-			zr->v4l_sync_tail = 0;
-
-			break;
-
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
-			if (fh->jpg_buffers.active == ZORAN_FREE &&
-			    zr->jpg_buffers.active != ZORAN_FREE) {
-				res = -EPERM;	/* stay off other's settings! */
-				goto strmoff_unlock_and_return;
-			}
-			if (zr->jpg_buffers.active == ZORAN_FREE)
-				goto strmoff_unlock_and_return;
-
-			res =
-			    jpg_qbuf(file, -1,
-				     (fh->map_mode ==
-				      ZORAN_MAP_MODE_JPG_REC) ?
-				     BUZ_MODE_MOTION_COMPRESS :
-				     BUZ_MODE_MOTION_DECOMPRESS);
-			if (res)
-				goto strmoff_unlock_and_return;
-			break;
-		default:
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
-				ZR_DEVNAME(zr), fh->map_mode);
-			res = -EINVAL;
-			goto strmoff_unlock_and_return;
-		}
-	strmoff_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *ctrl = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCTRL - id=%d\n",
-			ZR_DEVNAME(zr), ctrl->id);
-
-		/* we only support hue/saturation/contrast/brightness */
-		if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-		    ctrl->id > V4L2_CID_HUE)
-			return -EINVAL;
-		else {
-			int id = ctrl->id;
-			memset(ctrl, 0, sizeof(*ctrl));
-			ctrl->id = id;
-		}
-
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
-			break;
-		case V4L2_CID_CONTRAST:
-			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
-			break;
-		case V4L2_CID_SATURATION:
-			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
-			break;
-		case V4L2_CID_HUE:
-			strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
-			break;
-		}
-
-		ctrl->minimum = 0;
-		ctrl->maximum = 65535;
-		ctrl->step = 1;
-		ctrl->default_value = 32768;
-		ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_CTRL - id=%d\n",
-			ZR_DEVNAME(zr), ctrl->id);
-
-		/* we only support hue/saturation/contrast/brightness */
-		if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-		    ctrl->id > V4L2_CID_HUE)
-			return -EINVAL;
-
-		mutex_lock(&zr->resource_lock);
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			ctrl->value = zr->brightness;
-			break;
-		case V4L2_CID_CONTRAST:
-			ctrl->value = zr->contrast;
-			break;
-		case V4L2_CID_SATURATION:
-			ctrl->value = zr->saturation;
-			break;
-		case V4L2_CID_HUE:
-			ctrl->value = zr->hue;
-			break;
-		}
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		struct video_picture pict;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_S_CTRL - id=%d\n",
-			ZR_DEVNAME(zr), ctrl->id);
-
-		/* we only support hue/saturation/contrast/brightness */
-		if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-		    ctrl->id > V4L2_CID_HUE)
-			return -EINVAL;
-
-		if (ctrl->value < 0 || ctrl->value > 65535) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n",
-				ZR_DEVNAME(zr), ctrl->value, ctrl->id);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-		switch (ctrl->id) {
-		case V4L2_CID_BRIGHTNESS:
-			zr->brightness = ctrl->value;
-			break;
-		case V4L2_CID_CONTRAST:
-			zr->contrast = ctrl->value;
-			break;
-		case V4L2_CID_SATURATION:
-			zr->saturation = ctrl->value;
-			break;
-		case V4L2_CID_HUE:
-			zr->hue = ctrl->value;
-			break;
-		}
-		pict.brightness = zr->brightness;
-		pict.contrast = zr->contrast;
-		pict.colour = zr->saturation;
-		pict.hue = zr->hue;
-
-		decoder_command(zr, DECODER_SET_PICTURE, &pict);
-
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *std = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMSTD - index=%d\n",
-			ZR_DEVNAME(zr), std->index);
-
-		if (std->index < 0 || std->index >= (zr->card.norms + 1))
-			return -EINVAL;
-		else {
-			int id = std->index;
-			memset(std, 0, sizeof(*std));
-			std->index = id;
-		}
-
-		if (std->index == zr->card.norms) {
-			/* if we have autodetect, ... */
-			struct video_decoder_capability caps;
-			decoder_command(zr, DECODER_GET_CAPABILITIES,
-					&caps);
-			if (caps.flags & VIDEO_DECODER_AUTO) {
-				std->id = V4L2_STD_ALL;
-				strncpy(std->name, "Autodetect", sizeof(std->name)-1);
-				return 0;
-			} else
-				return -EINVAL;
-		}
-		switch (std->index) {
-		case 0:
-			std->id = V4L2_STD_PAL;
-			strncpy(std->name, "PAL", sizeof(std->name)-1);
-			std->frameperiod.numerator = 1;
-			std->frameperiod.denominator = 25;
-			std->framelines = zr->card.tvn[0]->Ht;
-			break;
-		case 1:
-			std->id = V4L2_STD_NTSC;
-			strncpy(std->name, "NTSC", sizeof(std->name)-1);
-			std->frameperiod.numerator = 1001;
-			std->frameperiod.denominator = 30000;
-			std->framelines = zr->card.tvn[1]->Ht;
-			break;
-		case 2:
-			std->id = V4L2_STD_SECAM;
-			strncpy(std->name, "SECAM", sizeof(std->name)-1);
-			std->frameperiod.numerator = 1;
-			std->frameperiod.denominator = 25;
-			std->framelines = zr->card.tvn[2]->Ht;
-			break;
-		}
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *std = arg;
-		int norm;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-		norm = zr->norm;
-		mutex_unlock(&zr->resource_lock);
-
-		switch (norm) {
-		case VIDEO_MODE_PAL:
-			*std = V4L2_STD_PAL;
-			break;
-		case VIDEO_MODE_NTSC:
-			*std = V4L2_STD_NTSC;
-			break;
-		case VIDEO_MODE_SECAM:
-			*std = V4L2_STD_SECAM;
-			break;
-		}
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_STD:
-	{
-		int norm = -1, res = 0;
-		v4l2_std_id *std = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
-			ZR_DEVNAME(zr), (unsigned long long)*std);
-
-		if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
-			norm = VIDEO_MODE_PAL;
-		else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
-			norm = VIDEO_MODE_NTSC;
-		else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
-			norm = VIDEO_MODE_SECAM;
-		else if (*std == V4L2_STD_ALL)
-			norm = VIDEO_MODE_AUTO;
-		else {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_S_STD - invalid norm 0x%llx\n",
-				ZR_DEVNAME(zr), (unsigned long long)*std);
-			return -EINVAL;
-		}
-
-		mutex_lock(&zr->resource_lock);
-		if ((res = zoran_set_norm(zr, norm)))
-			goto sstd_unlock_and_return;
-
-		res = wait_grab_pending(zr);
-	sstd_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *inp = arg;
-		int status;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMINPUT - index=%d\n",
-			ZR_DEVNAME(zr), inp->index);
-
-		if (inp->index < 0 || inp->index >= zr->card.inputs)
-			return -EINVAL;
-		else {
-			int id = inp->index;
-			memset(inp, 0, sizeof(*inp));
-			inp->index = id;
-		}
-
-		strncpy(inp->name, zr->card.input[inp->index].name,
-			sizeof(inp->name) - 1);
-		inp->type = V4L2_INPUT_TYPE_CAMERA;
-		inp->std = V4L2_STD_ALL;
-
-		/* Get status of video decoder */
-		mutex_lock(&zr->resource_lock);
-		decoder_command(zr, DECODER_GET_STATUS, &status);
-		mutex_unlock(&zr->resource_lock);
-
-		if (!(status & DECODER_STATUS_GOOD)) {
-			inp->status |= V4L2_IN_ST_NO_POWER;
-			inp->status |= V4L2_IN_ST_NO_SIGNAL;
-		}
-		if (!(status & DECODER_STATUS_COLOR))
-			inp->status |= V4L2_IN_ST_NO_COLOR;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_G_INPUT:
-	{
-		int *input = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr));
-
-		mutex_lock(&zr->resource_lock);
-		*input = zr->input;
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_INPUT:
-	{
-		int *input = arg, res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n",
-			ZR_DEVNAME(zr), *input);
-
-		mutex_lock(&zr->resource_lock);
-		if ((res = zoran_set_input(zr, *input)))
-			goto sinput_unlock_and_return;
-
-		/* Make sure the changes come into effect */
-		res = wait_grab_pending(zr);
-	sinput_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOC_ENUMOUTPUT:
-	{
-		struct v4l2_output *outp = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMOUTPUT - index=%d\n",
-			ZR_DEVNAME(zr), outp->index);
-
-		if (outp->index != 0)
-			return -EINVAL;
-
-		memset(outp, 0, sizeof(*outp));
-		outp->index = 0;
-		outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-		strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_G_OUTPUT:
-	{
-		int *output = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_OUTPUT\n", ZR_DEVNAME(zr));
-
-		*output = 0;
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_OUTPUT:
-	{
-		int *output = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_S_OUTPUT - output=%d\n",
-			ZR_DEVNAME(zr), *output);
-
-		if (*output != 0)
-			return -EINVAL;
-
-		return 0;
-	}
-		break;
-
-		/* cropping (sub-frame capture) */
-	case VIDIOC_CROPCAP:
-	{
-		struct v4l2_cropcap *cropcap = arg;
-		int type = cropcap->type, res = 0;
-
-		dprintk(3, KERN_ERR "%s: VIDIOC_CROPCAP - type=%d\n",
-			ZR_DEVNAME(zr), cropcap->type);
-
-		memset(cropcap, 0, sizeof(*cropcap));
-		cropcap->type = type;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-		    (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto cropcap_unlock_and_return;
-		}
-
-		cropcap->bounds.top = cropcap->bounds.left = 0;
-		cropcap->bounds.width = BUZ_MAX_WIDTH;
-		cropcap->bounds.height = BUZ_MAX_HEIGHT;
-		cropcap->defrect.top = cropcap->defrect.left = 0;
-		cropcap->defrect.width = BUZ_MIN_WIDTH;
-		cropcap->defrect.height = BUZ_MIN_HEIGHT;
-	cropcap_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOC_G_CROP:
-	{
-		struct v4l2_crop *crop = arg;
-		int type = crop->type, res = 0;
-
-		dprintk(3, KERN_ERR "%s: VIDIOC_G_CROP - type=%d\n",
-			ZR_DEVNAME(zr), crop->type);
-
-		memset(crop, 0, sizeof(*crop));
-		crop->type = type;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-		    (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto gcrop_unlock_and_return;
-		}
-
-		crop->c.top = fh->jpg_settings.img_y;
-		crop->c.left = fh->jpg_settings.img_x;
-		crop->c.width = fh->jpg_settings.img_width;
-		crop->c.height = fh->jpg_settings.img_height;
-
-	gcrop_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return res;
-	}
-		break;
-
-	case VIDIOC_S_CROP:
-	{
-		struct v4l2_crop *crop = arg;
-		int res = 0;
-
-		settings = fh->jpg_settings;
-
-		dprintk(3,
-			KERN_ERR
-			"%s: VIDIOC_S_CROP - type=%d, x=%d,y=%d,w=%d,h=%d\n",
-			ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top,
-			crop->c.width, crop->c.height);
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_S_CROP - cannot change settings while active\n",
-				ZR_DEVNAME(zr));
-			res = -EBUSY;
-			goto scrop_unlock_and_return;
-		}
-
-		if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-		    (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-			dprintk(1,
-				KERN_ERR
-				"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-				ZR_DEVNAME(zr));
-			res = -EINVAL;
-			goto scrop_unlock_and_return;
-		}
-
-		/* move into a form that we understand */
-		settings.img_x = crop->c.left;
-		settings.img_y = crop->c.top;
-		settings.img_width = crop->c.width;
-		settings.img_height = crop->c.height;
-
-		/* check validity */
-		if ((res = zoran_check_jpg_settings(zr, &settings)))
-			goto scrop_unlock_and_return;
-
-		/* accept */
-		fh->jpg_settings = settings;
-
-	scrop_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-		return res;
-	}
-		break;
-
-	case VIDIOC_G_JPEGCOMP:
-	{
-		struct v4l2_jpegcompression *params = arg;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_G_JPEGCOMP\n",
-			ZR_DEVNAME(zr));
-
-		memset(params, 0, sizeof(*params));
-
-		mutex_lock(&zr->resource_lock);
-
-		params->quality = fh->jpg_settings.jpg_comp.quality;
-		params->APPn = fh->jpg_settings.jpg_comp.APPn;
-		memcpy(params->APP_data,
-		       fh->jpg_settings.jpg_comp.APP_data,
-		       fh->jpg_settings.jpg_comp.APP_len);
-		params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
-		memcpy(params->COM_data,
-		       fh->jpg_settings.jpg_comp.COM_data,
-		       fh->jpg_settings.jpg_comp.COM_len);
-		params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
-		params->jpeg_markers =
-		    fh->jpg_settings.jpg_comp.jpeg_markers;
-
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_S_JPEGCOMP:
-	{
-		struct v4l2_jpegcompression *params = arg;
-		int res = 0;
-
-		settings = fh->jpg_settings;
-
-		dprintk(3,
-			KERN_DEBUG
-			"%s: VIDIOC_S_JPEGCOMP - quality=%d, APPN=%d, APP_len=%d, COM_len=%d\n",
-			ZR_DEVNAME(zr), params->quality, params->APPn,
-			params->APP_len, params->COM_len);
-
-		settings.jpg_comp = *params;
-
-		mutex_lock(&zr->resource_lock);
-
-		if (fh->v4l_buffers.active != ZORAN_FREE ||
-		    fh->jpg_buffers.active != ZORAN_FREE) {
-			dprintk(1,
-				KERN_WARNING
-				"%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
-				ZR_DEVNAME(zr));
-			res = -EBUSY;
-			goto sjpegc_unlock_and_return;
-		}
-
-		if ((res = zoran_check_jpg_settings(zr, &settings)))
-			goto sjpegc_unlock_and_return;
-		if (!fh->jpg_buffers.allocated)
-			fh->jpg_buffers.buffer_size =
-			    zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-		fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
-	sjpegc_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		return 0;
-	}
-		break;
-
-	case VIDIOC_QUERYSTD:	/* why is this useful? */
-	{
-		v4l2_std_id *std = arg;
-
-		dprintk(3,
-			KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n",
-			ZR_DEVNAME(zr), (unsigned long long)*std);
-
-		if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC ||
-		    *std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM &&
-					     zr->card.norms == 3)) {
-			return 0;
-		}
-
-		return -EINVAL;
-	}
-		break;
-
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *fmt = arg;
-		int res = 0;
-
-		dprintk(3, KERN_DEBUG "%s: VIDIOC_TRY_FMT - type=%d\n",
-			ZR_DEVNAME(zr), fmt->type);
-
-		switch (fmt->type) {
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-			mutex_lock(&zr->resource_lock);
-
-			if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
-				fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
-			if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
-				fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
-			if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
-				fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
-			if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
-				fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
-
-			mutex_unlock(&zr->resource_lock);
-			break;
-
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-			if (fmt->fmt.pix.bytesperline > 0)
-				return -EINVAL;
-
-			mutex_lock(&zr->resource_lock);
-
-			if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
-				settings = fh->jpg_settings;
-
-				/* we actually need to set 'real' parameters now */
-				if ((fmt->fmt.pix.height * 2) >
-				    BUZ_MAX_HEIGHT)
-					settings.TmpDcm = 1;
-				else
-					settings.TmpDcm = 2;
-				settings.decimation = 0;
-				if (fmt->fmt.pix.height <=
-				    fh->jpg_settings.img_height / 2)
-					settings.VerDcm = 2;
-				else
-					settings.VerDcm = 1;
-				if (fmt->fmt.pix.width <=
-				    fh->jpg_settings.img_width / 4)
-					settings.HorDcm = 4;
-				else if (fmt->fmt.pix.width <=
-					 fh->jpg_settings.img_width / 2)
-					settings.HorDcm = 2;
-				else
-					settings.HorDcm = 1;
-				if (settings.TmpDcm == 1)
-					settings.field_per_buff = 2;
-				else
-					settings.field_per_buff = 1;
-
-				/* check */
-				if ((res =
-				     zoran_check_jpg_settings(zr,
-							      &settings)))
-					goto tryfmt_unlock_and_return;
-
-				/* tell the user what we actually did */
-				fmt->fmt.pix.width =
-				    settings.img_width / settings.HorDcm;
-				fmt->fmt.pix.height =
-				    settings.img_height * 2 /
-				    (settings.TmpDcm * settings.VerDcm);
-				if (settings.TmpDcm == 1)
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_SEQ_TB :
-					     V4L2_FIELD_SEQ_BT);
-				else
-					fmt->fmt.pix.field =
-					    (fh->jpg_settings.
-					     odd_even ? V4L2_FIELD_TOP :
-					     V4L2_FIELD_BOTTOM);
-
-				fmt->fmt.pix.sizeimage =
-				    zoran_v4l2_calc_bufsize(&settings);
-			} else if (fmt->type ==
-				   V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-				int i;
-
-				for (i = 0; i < NUM_FORMATS; i++)
-					if (zoran_formats[i].fourcc ==
-					    fmt->fmt.pix.pixelformat)
-						break;
-				if (i == NUM_FORMATS) {
-					res = -EINVAL;
-					goto tryfmt_unlock_and_return;
-				}
-
-				if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-					fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-				if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
-					fmt->fmt.pix.width = BUZ_MIN_WIDTH;
-				if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-					fmt->fmt.pix.height =
-					    BUZ_MAX_HEIGHT;
-				if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
-					fmt->fmt.pix.height =
-					    BUZ_MIN_HEIGHT;
-			} else {
-				res = -EINVAL;
-				goto tryfmt_unlock_and_return;
-			}
-		tryfmt_unlock_and_return:
-			mutex_unlock(&zr->resource_lock);
-
-			return res;
-			break;
-
-		default:
-			return -EINVAL;
-		}
-
-		return 0;
-	}
-		break;
 
 	default:
-		dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
-			ZR_DEVNAME(zr), cmd);
-		return -ENOIOCTLCMD;
-		break;
-
+		return -EINVAL;
 	}
+}
+
+static int zoran_vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *vmbuf)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int i, res = 0;
+
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->buffers.allocated) {
+		dprintk(1,
+			KERN_ERR
+			"%s: VIDIOCGMBUF - buffers already allocated\n",
+			ZR_DEVNAME(zr));
+		res = -EINVAL;
+		goto v4l1reqbuf_unlock_and_return;
+	}
+
+	/* The next mmap will map the V4L buffers */
+	map_mode_raw(fh);
+
+	if (v4l_fbuffer_alloc(fh)) {
+		res = -ENOMEM;
+		goto v4l1reqbuf_unlock_and_return;
+	}
+
+	vmbuf->size = fh->buffers.num_buffers * fh->buffers.buffer_size;
+	vmbuf->frames = fh->buffers.num_buffers;
+	for (i = 0; i < vmbuf->frames; i++)
+		vmbuf->offsets[i] = i * fh->buffers.buffer_size;
+
+v4l1reqbuf_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+#endif
+
+static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	memset(cap, 0, sizeof(*cap));
+	strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+	strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+		 pci_name(zr->pci_dev));
+	cap->version = KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
+			   RELEASE_VERSION);
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+			    V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
 	return 0;
 }
 
-
-static long
-zoran_ioctl(struct file  *file,
-	    unsigned int  cmd,
-	    unsigned long arg)
+static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
 {
-	return video_usercopy(file, cmd, arg, zoran_do_ioctl);
+	int num = -1, i;
+
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (zoran_formats[i].flags & flag)
+			num++;
+		if (num == fmt->index)
+			break;
+	}
+	if (fmt->index < 0 /* late, but not too late */  || i == NUM_FORMATS)
+		return -EINVAL;
+
+	strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
+	fmt->pixelformat = zoran_formats[i].fourcc;
+	if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
+		fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+	return 0;
+}
+
+static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
+					    struct v4l2_fmtdesc *f)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE);
+}
+
+static int zoran_enum_fmt_vid_out(struct file *file, void *__fh,
+					    struct v4l2_fmtdesc *f)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK);
+}
+
+static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh,
+					    struct v4l2_fmtdesc *f)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY);
+}
+
+static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	mutex_lock(&zr->resource_lock);
+
+	fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm;
+	fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 /
+		(fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm);
+	fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+	fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+	if (fh->jpg_settings.TmpDcm == 1)
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+	else
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+	fmt->fmt.pix.bytesperline = 0;
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	if (fh->map_mode != ZORAN_MAP_MODE_RAW)
+		return zoran_g_fmt_vid_out(file, fh, fmt);
+
+	mutex_lock(&zr->resource_lock);
+	fmt->fmt.pix.width = fh->v4l_settings.width;
+	fmt->fmt.pix.height = fh->v4l_settings.height;
+	fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline *
+					fh->v4l_settings.height;
+	fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc;
+	fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
+	fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
+	if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
+		fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	else
+		fmt->fmt.pix.field = V4L2_FIELD_TOP;
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	mutex_lock(&zr->resource_lock);
+
+	fmt->fmt.win.w.left = fh->overlay_settings.x;
+	fmt->fmt.win.w.top = fh->overlay_settings.y;
+	fmt->fmt.win.w.width = fh->overlay_settings.width;
+	fmt->fmt.win.w.height = fh->overlay_settings.height;
+	if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT)
+		fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
+	else
+		fmt->fmt.win.field = V4L2_FIELD_TOP;
+
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
+		fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
+	if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
+		fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
+	if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
+		fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
+	if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
+		fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
+
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	struct zoran_jpg_settings settings;
+	int res = 0;
+
+	if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	mutex_lock(&zr->resource_lock);
+	settings = fh->jpg_settings;
+
+	/* we actually need to set 'real' parameters now */
+	if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
+		settings.TmpDcm = 1;
+	else
+		settings.TmpDcm = 2;
+	settings.decimation = 0;
+	if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
+		settings.VerDcm = 2;
+	else
+		settings.VerDcm = 1;
+	if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
+		settings.HorDcm = 4;
+	else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
+		settings.HorDcm = 2;
+	else
+		settings.HorDcm = 1;
+	if (settings.TmpDcm == 1)
+		settings.field_per_buff = 2;
+	else
+		settings.field_per_buff = 1;
+
+	if (settings.HorDcm > 1) {
+		settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+		settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+	} else {
+		settings.img_x = 0;
+		settings.img_width = BUZ_MAX_WIDTH;
+	}
+
+	/* check */
+	res = zoran_check_jpg_settings(zr, &settings, 1);
+	if (res)
+		goto tryfmt_unlock_and_return;
+
+	/* tell the user what we actually did */
+	fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
+	fmt->fmt.pix.height = settings.img_height * 2 /
+		(settings.TmpDcm * settings.VerDcm);
+	if (settings.TmpDcm == 1)
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+	else
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+
+	fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
+	fmt->fmt.pix.bytesperline = 0;
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+tryfmt_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int bpp;
+	int i;
+
+	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+		return zoran_try_fmt_vid_out(file, fh, fmt);
+
+	mutex_lock(&zr->resource_lock);
+
+	for (i = 0; i < NUM_FORMATS; i++)
+		if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
+			break;
+
+	if (i == NUM_FORMATS) {
+		mutex_unlock(&zr->resource_lock);
+		return -EINVAL;
+	}
+
+	bpp = (zoran_formats[i].depth + 7) / 8;
+	fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3);
+	if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+		fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+	if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
+		fmt->fmt.pix.width = BUZ_MIN_WIDTH;
+	if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+		fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
+	if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
+		fmt->fmt.pix.height = BUZ_MIN_HEIGHT;
+	mutex_unlock(&zr->resource_lock);
+
+	return 0;
+}
+
+static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res;
+
+	dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
+			fmt->fmt.win.w.left, fmt->fmt.win.w.top,
+			fmt->fmt.win.w.width,
+			fmt->fmt.win.w.height,
+			fmt->fmt.win.clipcount,
+			fmt->fmt.win.bitmap);
+	mutex_lock(&zr->resource_lock);
+	res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top,
+			   fmt->fmt.win.w.width, fmt->fmt.win.w.height,
+			   (struct v4l2_clip __user *)fmt->fmt.win.clips,
+			   fmt->fmt.win.clipcount, fmt->fmt.win.bitmap);
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	__le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
+	struct zoran_jpg_settings settings;
+	int res = 0;
+
+	dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
+			fmt->fmt.pix.width, fmt->fmt.pix.height,
+			fmt->fmt.pix.pixelformat,
+			(char *) &printformat);
+	if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->buffers.allocated) {
+		dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+			ZR_DEVNAME(zr));
+		res = -EBUSY;
+		goto sfmtjpg_unlock_and_return;
+	}
+
+	settings = fh->jpg_settings;
+
+	/* we actually need to set 'real' parameters now */
+	if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
+		settings.TmpDcm = 1;
+	else
+		settings.TmpDcm = 2;
+	settings.decimation = 0;
+	if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
+		settings.VerDcm = 2;
+	else
+		settings.VerDcm = 1;
+	if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
+		settings.HorDcm = 4;
+	else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
+		settings.HorDcm = 2;
+	else
+		settings.HorDcm = 1;
+	if (settings.TmpDcm == 1)
+		settings.field_per_buff = 2;
+	else
+		settings.field_per_buff = 1;
+
+	if (settings.HorDcm > 1) {
+		settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+		settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+	} else {
+		settings.img_x = 0;
+		settings.img_width = BUZ_MAX_WIDTH;
+	}
+
+	/* check */
+	res = zoran_check_jpg_settings(zr, &settings, 0);
+	if (res)
+		goto sfmtjpg_unlock_and_return;
+
+	/* it's ok, so set them */
+	fh->jpg_settings = settings;
+
+	map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+	/* tell the user what we actually did */
+	fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
+	fmt->fmt.pix.height = settings.img_height * 2 /
+		(settings.TmpDcm * settings.VerDcm);
+	if (settings.TmpDcm == 1)
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+	else
+		fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+				V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+	fmt->fmt.pix.bytesperline = 0;
+	fmt->fmt.pix.sizeimage = fh->buffers.buffer_size;
+	fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+sfmtjpg_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
+					struct v4l2_format *fmt)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int i;
+	int res = 0;
+
+	if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+		return zoran_s_fmt_vid_out(file, fh, fmt);
+
+	for (i = 0; i < NUM_FORMATS; i++)
+		if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
+			break;
+	if (i == NUM_FORMATS) {
+		dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
+			ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat);
+		return -EINVAL;
+	}
+
+	mutex_lock(&zr->resource_lock);
+
+	if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
+	    fh->buffers.active != ZORAN_FREE) {
+		dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+				ZR_DEVNAME(zr));
+		res = -EBUSY;
+		goto sfmtv4l_unlock_and_return;
+	}
+	if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+		fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
+	if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+		fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+
+	map_mode_raw(fh);
+
+	res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height,
+				   &zoran_formats[i]);
+	if (res)
+		goto sfmtv4l_unlock_and_return;
+
+	/* tell the user the results/missing stuff */
+	fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
+	fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline;
+	fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
+	if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
+		fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+	else
+		fmt->fmt.pix.field = V4L2_FIELD_TOP;
+
+sfmtv4l_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_g_fbuf(struct file *file, void *__fh,
+		struct v4l2_framebuffer *fb)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	memset(fb, 0, sizeof(*fb));
+	mutex_lock(&zr->resource_lock);
+	fb->base = zr->vbuf_base;
+	fb->fmt.width = zr->vbuf_width;
+	fb->fmt.height = zr->vbuf_height;
+	if (zr->overlay_settings.format)
+		fb->fmt.pixelformat = fh->overlay_settings.format->fourcc;
+	fb->fmt.bytesperline = zr->vbuf_bytesperline;
+	mutex_unlock(&zr->resource_lock);
+	fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
+	fb->fmt.field = V4L2_FIELD_INTERLACED;
+	fb->flags = V4L2_FBUF_FLAG_OVERLAY;
+	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+
+	return 0;
+}
+
+static int zoran_s_fbuf(struct file *file, void *__fh,
+		struct v4l2_framebuffer *fb)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int i, res = 0;
+	__le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
+
+	for (i = 0; i < NUM_FORMATS; i++)
+		if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
+			break;
+	if (i == NUM_FORMATS) {
+		dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
+			ZR_DEVNAME(zr), fb->fmt.pixelformat,
+			(char *)&printformat);
+		return -EINVAL;
+	}
+
+	mutex_lock(&zr->resource_lock);
+	res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width,
+			    fb->fmt.height, fb->fmt.bytesperline);
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_overlay(struct file *file, void *__fh, unsigned int on)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res;
+
+	mutex_lock(&zr->resource_lock);
+	res = setup_overlay(fh, on);
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type);
+
+static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0;
+
+	if (req->memory != V4L2_MEMORY_MMAP) {
+		dprintk(2,
+				KERN_ERR
+				"%s: only MEMORY_MMAP capture is supported, not %d\n",
+				ZR_DEVNAME(zr), req->memory);
+		return -EINVAL;
+	}
+
+	if (req->count == 0)
+		return zoran_streamoff(file, fh, req->type);
+
+	mutex_lock(&zr->resource_lock);
+	if (fh->buffers.allocated) {
+		dprintk(2,
+				KERN_ERR
+				"%s: VIDIOC_REQBUFS - buffers already allocated\n",
+				ZR_DEVNAME(zr));
+		res = -EBUSY;
+		goto v4l2reqbuf_unlock_and_return;
+	}
+
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
+	    req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		/* control user input */
+		if (req->count < 2)
+			req->count = 2;
+		if (req->count > v4l_nbufs)
+			req->count = v4l_nbufs;
+
+		/* The next mmap will map the V4L buffers */
+		map_mode_raw(fh);
+		fh->buffers.num_buffers = req->count;
+
+		if (v4l_fbuffer_alloc(fh)) {
+			res = -ENOMEM;
+			goto v4l2reqbuf_unlock_and_return;
+		}
+	} else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
+		   fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+		/* we need to calculate size ourselves now */
+		if (req->count < 4)
+			req->count = 4;
+		if (req->count > jpg_nbufs)
+			req->count = jpg_nbufs;
+
+		/* The next mmap will map the MJPEG buffers */
+		map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		fh->buffers.num_buffers = req->count;
+		fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+		if (jpg_fbuffer_alloc(fh)) {
+			res = -ENOMEM;
+			goto v4l2reqbuf_unlock_and_return;
+		}
+	} else {
+		dprintk(1,
+				KERN_ERR
+				"%s: VIDIOC_REQBUFS - unknown type %d\n",
+				ZR_DEVNAME(zr), req->type);
+		res = -EINVAL;
+		goto v4l2reqbuf_unlock_and_return;
+	}
+v4l2reqbuf_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res;
+
+	mutex_lock(&zr->resource_lock);
+	res = zoran_v4l2_buffer_status(fh, buf, buf->index);
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0, codec_mode, buf_type;
+
+	mutex_lock(&zr->resource_lock);
+
+	switch (fh->map_mode) {
+	case ZORAN_MAP_MODE_RAW:
+		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			dprintk(1, KERN_ERR
+				"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+				ZR_DEVNAME(zr), buf->type, fh->map_mode);
+			res = -EINVAL;
+			goto qbuf_unlock_and_return;
+		}
+
+		res = zoran_v4l_queue_frame(fh, buf->index);
+		if (res)
+			goto qbuf_unlock_and_return;
+		if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
+			zr36057_set_memgrab(zr, 1);
+		break;
+
+	case ZORAN_MAP_MODE_JPG_REC:
+	case ZORAN_MAP_MODE_JPG_PLAY:
+		if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+			buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+			codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
+		} else {
+			buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			codec_mode = BUZ_MODE_MOTION_COMPRESS;
+		}
+
+		if (buf->type != buf_type) {
+			dprintk(1, KERN_ERR
+				"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+				ZR_DEVNAME(zr), buf->type, fh->map_mode);
+			res = -EINVAL;
+			goto qbuf_unlock_and_return;
+		}
+
+		res = zoran_jpg_queue_frame(fh, buf->index, codec_mode);
+		if (res != 0)
+			goto qbuf_unlock_and_return;
+		if (zr->codec_mode == BUZ_MODE_IDLE &&
+		    fh->buffers.active == ZORAN_LOCKED)
+			zr36057_enable_jpg(zr, codec_mode);
+
+		break;
+
+	default:
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_QBUF - unsupported type %d\n",
+			ZR_DEVNAME(zr), buf->type);
+		res = -EINVAL;
+		break;
+	}
+qbuf_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0, buf_type, num = -1;	/* compiler borks here (?) */
+
+	mutex_lock(&zr->resource_lock);
+
+	switch (fh->map_mode) {
+	case ZORAN_MAP_MODE_RAW:
+		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			dprintk(1, KERN_ERR
+				"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+				ZR_DEVNAME(zr), buf->type, fh->map_mode);
+			res = -EINVAL;
+			goto dqbuf_unlock_and_return;
+		}
+
+		num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+		if (file->f_flags & O_NONBLOCK &&
+		    zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) {
+			res = -EAGAIN;
+			goto dqbuf_unlock_and_return;
+		}
+		res = v4l_sync(fh, num);
+		if (res)
+			goto dqbuf_unlock_and_return;
+		zr->v4l_sync_tail++;
+		res = zoran_v4l2_buffer_status(fh, buf, num);
+		break;
+
+	case ZORAN_MAP_MODE_JPG_REC:
+	case ZORAN_MAP_MODE_JPG_PLAY:
+	{
+		struct zoran_sync bs;
+
+		if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
+			buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		else
+			buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+		if (buf->type != buf_type) {
+			dprintk(1, KERN_ERR
+				"%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+				ZR_DEVNAME(zr), buf->type, fh->map_mode);
+			res = -EINVAL;
+			goto dqbuf_unlock_and_return;
+		}
+
+		num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+		if (file->f_flags & O_NONBLOCK &&
+		    zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) {
+			res = -EAGAIN;
+			goto dqbuf_unlock_and_return;
+		}
+		res = jpg_sync(fh, &bs);
+		if (res)
+			goto dqbuf_unlock_and_return;
+		res = zoran_v4l2_buffer_status(fh, buf, bs.frame);
+		break;
+	}
+
+	default:
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_DQBUF - unsupported type %d\n",
+			ZR_DEVNAME(zr), buf->type);
+		res = -EINVAL;
+		break;
+	}
+dqbuf_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0;
+
+	mutex_lock(&zr->resource_lock);
+
+	switch (fh->map_mode) {
+	case ZORAN_MAP_MODE_RAW:	/* raw capture */
+		if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
+		    fh->buffers.active != ZORAN_ACTIVE) {
+			res = -EBUSY;
+			goto strmon_unlock_and_return;
+		}
+
+		zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED;
+		zr->v4l_settings = fh->v4l_settings;
+
+		zr->v4l_sync_tail = zr->v4l_pend_tail;
+		if (!zr->v4l_memgrab_active &&
+		    zr->v4l_pend_head != zr->v4l_pend_tail) {
+			zr36057_set_memgrab(zr, 1);
+		}
+		break;
+
+	case ZORAN_MAP_MODE_JPG_REC:
+	case ZORAN_MAP_MODE_JPG_PLAY:
+		/* what is the codec mode right now? */
+		if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
+		    fh->buffers.active != ZORAN_ACTIVE) {
+			res = -EBUSY;
+			goto strmon_unlock_and_return;
+		}
+
+		zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED;
+
+		if (zr->jpg_que_head != zr->jpg_que_tail) {
+			/* Start the jpeg codec when the first frame is queued  */
+			jpeg_start(zr);
+		}
+		break;
+
+	default:
+		dprintk(1,
+			KERN_ERR
+			"%s: VIDIOC_STREAMON - invalid map mode %d\n",
+			ZR_DEVNAME(zr), fh->map_mode);
+		res = -EINVAL;
+		break;
+	}
+strmon_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int i, res = 0;
+	unsigned long flags;
+
+	mutex_lock(&zr->resource_lock);
+
+	switch (fh->map_mode) {
+	case ZORAN_MAP_MODE_RAW:	/* raw capture */
+		if (fh->buffers.active == ZORAN_FREE &&
+		    zr->v4l_buffers.active != ZORAN_FREE) {
+			res = -EPERM;	/* stay off other's settings! */
+			goto strmoff_unlock_and_return;
+		}
+		if (zr->v4l_buffers.active == ZORAN_FREE)
+			goto strmoff_unlock_and_return;
+
+		spin_lock_irqsave(&zr->spinlock, flags);
+		/* unload capture */
+		if (zr->v4l_memgrab_active) {
+
+			zr36057_set_memgrab(zr, 0);
+		}
+
+		for (i = 0; i < fh->buffers.num_buffers; i++)
+			zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;
+		fh->buffers = zr->v4l_buffers;
+
+		zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+
+		zr->v4l_grab_seq = 0;
+		zr->v4l_pend_head = zr->v4l_pend_tail = 0;
+		zr->v4l_sync_tail = 0;
+
+		spin_unlock_irqrestore(&zr->spinlock, flags);
+
+		break;
+
+	case ZORAN_MAP_MODE_JPG_REC:
+	case ZORAN_MAP_MODE_JPG_PLAY:
+		if (fh->buffers.active == ZORAN_FREE &&
+		    zr->jpg_buffers.active != ZORAN_FREE) {
+			res = -EPERM;	/* stay off other's settings! */
+			goto strmoff_unlock_and_return;
+		}
+		if (zr->jpg_buffers.active == ZORAN_FREE)
+			goto strmoff_unlock_and_return;
+
+		res = jpg_qbuf(fh, -1,
+			     (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
+			     BUZ_MODE_MOTION_COMPRESS :
+			     BUZ_MODE_MOTION_DECOMPRESS);
+		if (res)
+			goto strmoff_unlock_and_return;
+		break;
+	default:
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
+			ZR_DEVNAME(zr), fh->map_mode);
+		res = -EINVAL;
+		break;
+	}
+strmoff_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_queryctrl(struct file *file, void *__fh,
+					struct v4l2_queryctrl *ctrl)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	/* we only support hue/saturation/contrast/brightness */
+	if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+	    ctrl->id > V4L2_CID_HUE)
+		return -EINVAL;
+
+	decoder_call(zr, core, queryctrl, ctrl);
+
+	return 0;
+}
+
+static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	/* we only support hue/saturation/contrast/brightness */
+	if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+	    ctrl->id > V4L2_CID_HUE)
+		return -EINVAL;
+
+	mutex_lock(&zr->resource_lock);
+	decoder_call(zr, core, g_ctrl, ctrl);
+	mutex_unlock(&zr->resource_lock);
+
+	return 0;
+}
+
+static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	/* we only support hue/saturation/contrast/brightness */
+	if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+	    ctrl->id > V4L2_CID_HUE)
+		return -EINVAL;
+
+	mutex_lock(&zr->resource_lock);
+	decoder_call(zr, core, s_ctrl, ctrl);
+	mutex_unlock(&zr->resource_lock);
+
+	return 0;
+}
+
+static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	mutex_lock(&zr->resource_lock);
+	*std = zr->norm;
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0;
+
+	mutex_lock(&zr->resource_lock);
+	res = zoran_set_norm(zr, *std);
+	if (res)
+		goto sstd_unlock_and_return;
+
+	res = wait_grab_pending(zr);
+sstd_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_enum_input(struct file *file, void *__fh,
+				 struct v4l2_input *inp)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	if (inp->index < 0 || inp->index >= zr->card.inputs)
+		return -EINVAL;
+	else {
+		int id = inp->index;
+		memset(inp, 0, sizeof(*inp));
+		inp->index = id;
+	}
+
+	strncpy(inp->name, zr->card.input[inp->index].name,
+		sizeof(inp->name) - 1);
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	inp->std = V4L2_STD_ALL;
+
+	/* Get status of video decoder */
+	mutex_lock(&zr->resource_lock);
+	decoder_call(zr, video, g_input_status, &inp->status);
+	mutex_unlock(&zr->resource_lock);
+	return 0;
+}
+
+static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+
+	mutex_lock(&zr->resource_lock);
+	*input = zr->input;
+	mutex_unlock(&zr->resource_lock);
+
+	return 0;
+}
+
+static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res;
+
+	mutex_lock(&zr->resource_lock);
+	res = zoran_set_input(zr, input);
+	if (res)
+		goto sinput_unlock_and_return;
+
+	/* Make sure the changes come into effect */
+	res = wait_grab_pending(zr);
+sinput_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_enum_output(struct file *file, void *__fh,
+				  struct v4l2_output *outp)
+{
+	if (outp->index != 0)
+		return -EINVAL;
+
+	memset(outp, 0, sizeof(*outp));
+	outp->index = 0;
+	outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
+	strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
+
+	return 0;
+}
+
+static int zoran_g_output(struct file *file, void *__fh, unsigned int *output)
+{
+	*output = 0;
+
+	return 0;
+}
+
+static int zoran_s_output(struct file *file, void *__fh, unsigned int output)
+{
+	if (output != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* cropping (sub-frame capture) */
+static int zoran_cropcap(struct file *file, void *__fh,
+					struct v4l2_cropcap *cropcap)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int type = cropcap->type, res = 0;
+
+	memset(cropcap, 0, sizeof(*cropcap));
+	cropcap->type = type;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
+			ZR_DEVNAME(zr));
+		res = -EINVAL;
+		goto cropcap_unlock_and_return;
+	}
+
+	cropcap->bounds.top = cropcap->bounds.left = 0;
+	cropcap->bounds.width = BUZ_MAX_WIDTH;
+	cropcap->bounds.height = BUZ_MAX_HEIGHT;
+	cropcap->defrect.top = cropcap->defrect.left = 0;
+	cropcap->defrect.width = BUZ_MIN_WIDTH;
+	cropcap->defrect.height = BUZ_MIN_HEIGHT;
+cropcap_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int type = crop->type, res = 0;
+
+	memset(crop, 0, sizeof(*crop));
+	crop->type = type;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+		dprintk(1,
+			KERN_ERR
+			"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+			ZR_DEVNAME(zr));
+		res = -EINVAL;
+		goto gcrop_unlock_and_return;
+	}
+
+	crop->c.top = fh->jpg_settings.img_y;
+	crop->c.left = fh->jpg_settings.img_x;
+	crop->c.width = fh->jpg_settings.img_width;
+	crop->c.height = fh->jpg_settings.img_height;
+
+gcrop_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
+}
+
+static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0;
+	struct zoran_jpg_settings settings;
+
+	settings = fh->jpg_settings;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->buffers.allocated) {
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_S_CROP - cannot change settings while active\n",
+			ZR_DEVNAME(zr));
+		res = -EBUSY;
+		goto scrop_unlock_and_return;
+	}
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	     fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+		dprintk(1, KERN_ERR
+			"%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+			ZR_DEVNAME(zr));
+		res = -EINVAL;
+		goto scrop_unlock_and_return;
+	}
+
+	/* move into a form that we understand */
+	settings.img_x = crop->c.left;
+	settings.img_y = crop->c.top;
+	settings.img_width = crop->c.width;
+	settings.img_height = crop->c.height;
+
+	/* check validity */
+	res = zoran_check_jpg_settings(zr, &settings, 0);
+	if (res)
+		goto scrop_unlock_and_return;
+
+	/* accept */
+	fh->jpg_settings = settings;
+
+scrop_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+	return res;
+}
+
+static int zoran_g_jpegcomp(struct file *file, void *__fh,
+					struct v4l2_jpegcompression *params)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	memset(params, 0, sizeof(*params));
+
+	mutex_lock(&zr->resource_lock);
+
+	params->quality = fh->jpg_settings.jpg_comp.quality;
+	params->APPn = fh->jpg_settings.jpg_comp.APPn;
+	memcpy(params->APP_data,
+	       fh->jpg_settings.jpg_comp.APP_data,
+	       fh->jpg_settings.jpg_comp.APP_len);
+	params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
+	memcpy(params->COM_data,
+	       fh->jpg_settings.jpg_comp.COM_data,
+	       fh->jpg_settings.jpg_comp.COM_len);
+	params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
+	params->jpeg_markers =
+	    fh->jpg_settings.jpg_comp.jpeg_markers;
+
+	mutex_unlock(&zr->resource_lock);
+
+	return 0;
+}
+
+static int zoran_s_jpegcomp(struct file *file, void *__fh,
+					struct v4l2_jpegcompression *params)
+{
+	struct zoran_fh *fh = __fh;
+	struct zoran *zr = fh->zr;
+	int res = 0;
+	struct zoran_jpg_settings settings;
+
+	settings = fh->jpg_settings;
+
+	settings.jpg_comp = *params;
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->buffers.active != ZORAN_FREE) {
+		dprintk(1, KERN_WARNING
+			"%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
+			ZR_DEVNAME(zr));
+		res = -EBUSY;
+		goto sjpegc_unlock_and_return;
+	}
+
+	res = zoran_check_jpg_settings(zr, &settings, 0);
+	if (res)
+		goto sjpegc_unlock_and_return;
+	if (!fh->buffers.allocated)
+		fh->buffers.buffer_size =
+			zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+	fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
+sjpegc_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
+	return res;
 }
 
 static unsigned int
@@ -4191,11 +3062,11 @@
 			KERN_DEBUG
 			"%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
 			ZR_DEVNAME(zr), __func__,
-			"FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+			"FAL"[fh->buffers.active], zr->v4l_sync_tail,
 			"UPMD"[zr->v4l_buffers.buffer[frame].state],
 			zr->v4l_pend_tail, zr->v4l_pend_head);
 		/* Process is the one capturing? */
-		if (fh->v4l_buffers.active != ZORAN_FREE &&
+		if (fh->buffers.active != ZORAN_FREE &&
 		    /* Buffer ready to DQBUF? */
 		    zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
 			res = POLLIN | POLLRDNORM;
@@ -4213,10 +3084,10 @@
 			KERN_DEBUG
 			"%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
 			ZR_DEVNAME(zr), __func__,
-			"FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+			"FAL"[fh->buffers.active], zr->jpg_que_tail,
 			"UPMD"[zr->jpg_buffers.buffer[frame].state],
 			zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
-		if (fh->jpg_buffers.active != ZORAN_FREE &&
+		if (fh->buffers.active != ZORAN_FREE &&
 		    zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
 			if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
 				res = POLLIN | POLLRDNORM;
@@ -4230,8 +3101,8 @@
 	default:
 		dprintk(1,
 			KERN_ERR
-			"%s: zoran_poll() - internal error, unknown map_mode=%d\n",
-			ZR_DEVNAME(zr), fh->map_mode);
+			"%s: %s - internal error, unknown map_mode=%d\n",
+			ZR_DEVNAME(zr), __func__, fh->map_mode);
 		res = POLLNVAL;
 	}
 
@@ -4265,98 +3136,53 @@
 zoran_vm_close (struct vm_area_struct *vma)
 {
 	struct zoran_mapping *map = vma->vm_private_data;
-	struct file *file = map->file;
-	struct zoran_fh *fh = file->private_data;
+	struct zoran_fh *fh = map->file->private_data;
 	struct zoran *zr = fh->zr;
 	int i;
 
-	map->count--;
-	if (map->count == 0) {
-		switch (fh->map_mode) {
-		case ZORAN_MAP_MODE_JPG_REC:
-		case ZORAN_MAP_MODE_JPG_PLAY:
+	if (--map->count > 0)
+		return;
 
-			dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n",
-				ZR_DEVNAME(zr));
+	dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
+		__func__, mode_name(fh->map_mode));
 
-			for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-				if (fh->jpg_buffers.buffer[i].map == map) {
-					fh->jpg_buffers.buffer[i].map =
-					    NULL;
-				}
-			}
-			kfree(map);
-
-			for (i = 0; i < fh->jpg_buffers.num_buffers; i++)
-				if (fh->jpg_buffers.buffer[i].map)
-					break;
-			if (i == fh->jpg_buffers.num_buffers) {
-				mutex_lock(&zr->resource_lock);
-
-				if (fh->jpg_buffers.active != ZORAN_FREE) {
-					jpg_qbuf(file, -1, zr->codec_mode);
-					zr->jpg_buffers.allocated = 0;
-					zr->jpg_buffers.active =
-					    fh->jpg_buffers.active =
-					    ZORAN_FREE;
-				}
-				//jpg_fbuffer_free(file);
-				fh->jpg_buffers.allocated = 0;
-				fh->jpg_buffers.ready_to_be_freed = 1;
-
-				mutex_unlock(&zr->resource_lock);
-			}
-
-			break;
-
-		case ZORAN_MAP_MODE_RAW:
-
-			dprintk(3, KERN_INFO "%s: munmap(V4L)\n",
-				ZR_DEVNAME(zr));
-
-			for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-				if (fh->v4l_buffers.buffer[i].map == map) {
-					/* unqueue/unmap */
-					fh->v4l_buffers.buffer[i].map =
-					    NULL;
-				}
-			}
-			kfree(map);
-
-			for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
-				if (fh->v4l_buffers.buffer[i].map)
-					break;
-			if (i == fh->v4l_buffers.num_buffers) {
-				mutex_lock(&zr->resource_lock);
-
-				if (fh->v4l_buffers.active != ZORAN_FREE) {
-					unsigned long flags;
-
-					spin_lock_irqsave(&zr->spinlock, flags);
-					zr36057_set_memgrab(zr, 0);
-					zr->v4l_buffers.allocated = 0;
-					zr->v4l_buffers.active =
-					    fh->v4l_buffers.active =
-					    ZORAN_FREE;
-					spin_unlock_irqrestore(&zr->spinlock, flags);
-				}
-				//v4l_fbuffer_free(file);
-				fh->v4l_buffers.allocated = 0;
-				fh->v4l_buffers.ready_to_be_freed = 1;
-
-				mutex_unlock(&zr->resource_lock);
-			}
-
-			break;
-
-		default:
-			printk(KERN_ERR
-			       "%s: munmap() - internal error - unknown map mode %d\n",
-			       ZR_DEVNAME(zr), fh->map_mode);
-			break;
-
-		}
+	for (i = 0; i < fh->buffers.num_buffers; i++) {
+		if (fh->buffers.buffer[i].map == map)
+			fh->buffers.buffer[i].map = NULL;
 	}
+	kfree(map);
+
+	/* Any buffers still mapped? */
+	for (i = 0; i < fh->buffers.num_buffers; i++)
+		if (fh->buffers.buffer[i].map)
+			return;
+
+	dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
+		__func__, mode_name(fh->map_mode));
+
+	mutex_lock(&zr->resource_lock);
+
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+		if (fh->buffers.active != ZORAN_FREE) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&zr->spinlock, flags);
+			zr36057_set_memgrab(zr, 0);
+			zr->v4l_buffers.allocated = 0;
+			zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+			spin_unlock_irqrestore(&zr->spinlock, flags);
+		}
+		v4l_fbuffer_free(fh);
+	} else {
+		if (fh->buffers.active != ZORAN_FREE) {
+			jpg_qbuf(fh, -1, zr->codec_mode);
+			zr->jpg_buffers.allocated = 0;
+			zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+		}
+		jpg_fbuffer_free(fh);
+	}
+
+	mutex_unlock(&zr->resource_lock);
 }
 
 static struct vm_operations_struct zoran_vm_ops = {
@@ -4379,90 +3205,106 @@
 	int res = 0;
 
 	dprintk(3,
-		KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
-		ZR_DEVNAME(zr),
-		fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG",
-		vma->vm_start, vma->vm_end, size);
+		KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
+		ZR_DEVNAME(zr), __func__,
+		mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size);
 
 	if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
 	    !(vma->vm_flags & VM_WRITE)) {
 		dprintk(1,
 			KERN_ERR
-			"%s: mmap() - no MAP_SHARED/PROT_{READ,WRITE} given\n",
-			ZR_DEVNAME(zr));
+			"%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n",
+			ZR_DEVNAME(zr), __func__);
 		return -EINVAL;
 	}
 
-	switch (fh->map_mode) {
+	mutex_lock(&zr->resource_lock);
 
-	case ZORAN_MAP_MODE_JPG_REC:
-	case ZORAN_MAP_MODE_JPG_PLAY:
+	if (!fh->buffers.allocated) {
+		dprintk(1,
+			KERN_ERR
+			"%s: %s(%s) - buffers not yet allocated\n",
+			ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode));
+		res = -ENOMEM;
+		goto mmap_unlock_and_return;
+	}
 
-		/* lock */
-		mutex_lock(&zr->resource_lock);
+	first = offset / fh->buffers.buffer_size;
+	last = first - 1 + size / fh->buffers.buffer_size;
+	if (offset % fh->buffers.buffer_size != 0 ||
+	    size % fh->buffers.buffer_size != 0 || first < 0 ||
+	    last < 0 || first >= fh->buffers.num_buffers ||
+	    last >= fh->buffers.buffer_size) {
+		dprintk(1,
+			KERN_ERR
+			"%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
+			ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size,
+			fh->buffers.buffer_size,
+			fh->buffers.num_buffers);
+		res = -EINVAL;
+		goto mmap_unlock_and_return;
+	}
 
-		/* Map the MJPEG buffers */
-		if (!fh->jpg_buffers.allocated) {
+	/* Check if any buffers are already mapped */
+	for (i = first; i <= last; i++) {
+		if (fh->buffers.buffer[i].map) {
 			dprintk(1,
 				KERN_ERR
-				"%s: zoran_mmap(MJPEG) - buffers not yet allocated\n",
-				ZR_DEVNAME(zr));
-			res = -ENOMEM;
-			goto jpg_mmap_unlock_and_return;
+				"%s: %s(%s) - buffer %d already mapped\n",
+				ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i);
+			res = -EBUSY;
+			goto mmap_unlock_and_return;
 		}
+	}
 
-		first = offset / fh->jpg_buffers.buffer_size;
-		last = first - 1 + size / fh->jpg_buffers.buffer_size;
-		if (offset % fh->jpg_buffers.buffer_size != 0 ||
-		    size % fh->jpg_buffers.buffer_size != 0 || first < 0 ||
-		    last < 0 || first >= fh->jpg_buffers.num_buffers ||
-		    last >= fh->jpg_buffers.num_buffers) {
-			dprintk(1,
-				KERN_ERR
-				"%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-				ZR_DEVNAME(zr), offset, size,
-				fh->jpg_buffers.buffer_size,
-				fh->jpg_buffers.num_buffers);
-			res = -EINVAL;
-			goto jpg_mmap_unlock_and_return;
-		}
+	/* map these buffers */
+	map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
+	if (!map) {
+		res = -ENOMEM;
+		goto mmap_unlock_and_return;
+	}
+	map->file = file;
+	map->count = 1;
+
+	vma->vm_ops = &zoran_vm_ops;
+	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_private_data = map;
+
+	if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
 		for (i = first; i <= last; i++) {
-			if (fh->jpg_buffers.buffer[i].map) {
+			todo = size;
+			if (todo > fh->buffers.buffer_size)
+				todo = fh->buffers.buffer_size;
+			page = fh->buffers.buffer[i].v4l.fbuffer_phys;
+			if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
+							todo, PAGE_SHARED)) {
 				dprintk(1,
 					KERN_ERR
-					"%s: mmap(MJPEG) - buffer %d already mapped\n",
-					ZR_DEVNAME(zr), i);
-				res = -EBUSY;
-				goto jpg_mmap_unlock_and_return;
+					"%s: %s(V4L) - remap_pfn_range failed\n",
+					ZR_DEVNAME(zr), __func__);
+				res = -EAGAIN;
+				goto mmap_unlock_and_return;
 			}
+			size -= todo;
+			start += todo;
+			fh->buffers.buffer[i].map = map;
+			if (size == 0)
+				break;
 		}
-
-		/* map these buffers (v4l_buffers[i]) */
-		map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-		if (!map) {
-			res = -ENOMEM;
-			goto jpg_mmap_unlock_and_return;
-		}
-		map->file = file;
-		map->count = 1;
-
-		vma->vm_ops = &zoran_vm_ops;
-		vma->vm_flags |= VM_DONTEXPAND;
-		vma->vm_private_data = map;
-
+	} else {
 		for (i = first; i <= last; i++) {
 			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+			     j < fh->buffers.buffer_size / PAGE_SIZE;
 			     j++) {
 				fraglen =
-				    (le32_to_cpu(fh->jpg_buffers.buffer[i].
+				    (le32_to_cpu(fh->buffers.buffer[i].jpg.
 				     frag_tab[2 * j + 1]) & ~1) << 1;
 				todo = size;
 				if (todo > fraglen)
 					todo = fraglen;
 				pos =
-				    le32_to_cpu(fh->jpg_buffers.
-				    buffer[i].frag_tab[2 * j]);
+				    le32_to_cpu(fh->buffers.
+				    buffer[i].jpg.frag_tab[2 * j]);
 				/* should just be pos on i386 */
 				page = virt_to_phys(bus_to_virt(pos))
 								>> PAGE_SHIFT;
@@ -4470,123 +3312,82 @@
 							todo, PAGE_SHARED)) {
 					dprintk(1,
 						KERN_ERR
-						"%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
-						ZR_DEVNAME(zr));
+						"%s: %s(V4L) - remap_pfn_range failed\n",
+						ZR_DEVNAME(zr), __func__);
 					res = -EAGAIN;
-					goto jpg_mmap_unlock_and_return;
+					goto mmap_unlock_and_return;
 				}
 				size -= todo;
 				start += todo;
 				if (size == 0)
 					break;
-				if (le32_to_cpu(fh->jpg_buffers.buffer[i].
+				if (le32_to_cpu(fh->buffers.buffer[i].jpg.
 				    frag_tab[2 * j + 1]) & 1)
 					break;	/* was last fragment */
 			}
-			fh->jpg_buffers.buffer[i].map = map;
+			fh->buffers.buffer[i].map = map;
 			if (size == 0)
 				break;
 
 		}
-	jpg_mmap_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		break;
-
-	case ZORAN_MAP_MODE_RAW:
-
-		mutex_lock(&zr->resource_lock);
-
-		/* Map the V4L buffers */
-		if (!fh->v4l_buffers.allocated) {
-			dprintk(1,
-				KERN_ERR
-				"%s: zoran_mmap(V4L) - buffers not yet allocated\n",
-				ZR_DEVNAME(zr));
-			res = -ENOMEM;
-			goto v4l_mmap_unlock_and_return;
-		}
-
-		first = offset / fh->v4l_buffers.buffer_size;
-		last = first - 1 + size / fh->v4l_buffers.buffer_size;
-		if (offset % fh->v4l_buffers.buffer_size != 0 ||
-		    size % fh->v4l_buffers.buffer_size != 0 || first < 0 ||
-		    last < 0 || first >= fh->v4l_buffers.num_buffers ||
-		    last >= fh->v4l_buffers.buffer_size) {
-			dprintk(1,
-				KERN_ERR
-				"%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-				ZR_DEVNAME(zr), offset, size,
-				fh->v4l_buffers.buffer_size,
-				fh->v4l_buffers.num_buffers);
-			res = -EINVAL;
-			goto v4l_mmap_unlock_and_return;
-		}
-		for (i = first; i <= last; i++) {
-			if (fh->v4l_buffers.buffer[i].map) {
-				dprintk(1,
-					KERN_ERR
-					"%s: mmap(V4L) - buffer %d already mapped\n",
-					ZR_DEVNAME(zr), i);
-				res = -EBUSY;
-				goto v4l_mmap_unlock_and_return;
-			}
-		}
-
-		/* map these buffers (v4l_buffers[i]) */
-		map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-		if (!map) {
-			res = -ENOMEM;
-			goto v4l_mmap_unlock_and_return;
-		}
-		map->file = file;
-		map->count = 1;
-
-		vma->vm_ops = &zoran_vm_ops;
-		vma->vm_flags |= VM_DONTEXPAND;
-		vma->vm_private_data = map;
-
-		for (i = first; i <= last; i++) {
-			todo = size;
-			if (todo > fh->v4l_buffers.buffer_size)
-				todo = fh->v4l_buffers.buffer_size;
-			page = fh->v4l_buffers.buffer[i].fbuffer_phys;
-			if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
-							todo, PAGE_SHARED)) {
-				dprintk(1,
-					KERN_ERR
-					"%s: zoran_mmap(V4L)i - remap_pfn_range failed\n",
-					ZR_DEVNAME(zr));
-				res = -EAGAIN;
-				goto v4l_mmap_unlock_and_return;
-			}
-			size -= todo;
-			start += todo;
-			fh->v4l_buffers.buffer[i].map = map;
-			if (size == 0)
-				break;
-		}
-	v4l_mmap_unlock_and_return:
-		mutex_unlock(&zr->resource_lock);
-
-		break;
-
-	default:
-		dprintk(1,
-			KERN_ERR
-			"%s: zoran_mmap() - internal error - unknown map mode %d\n",
-			ZR_DEVNAME(zr), fh->map_mode);
-		break;
 	}
 
+mmap_unlock_and_return:
+	mutex_unlock(&zr->resource_lock);
+
 	return 0;
 }
 
+static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
+	.vidioc_querycap    		    = zoran_querycap,
+	.vidioc_cropcap       		    = zoran_cropcap,
+	.vidioc_s_crop       		    = zoran_s_crop,
+	.vidioc_g_crop       		    = zoran_g_crop,
+	.vidioc_enum_input     		    = zoran_enum_input,
+	.vidioc_g_input      		    = zoran_g_input,
+	.vidioc_s_input      		    = zoran_s_input,
+	.vidioc_enum_output    		    = zoran_enum_output,
+	.vidioc_g_output     		    = zoran_g_output,
+	.vidioc_s_output     		    = zoran_s_output,
+	.vidioc_g_fbuf			    = zoran_g_fbuf,
+	.vidioc_s_fbuf			    = zoran_s_fbuf,
+	.vidioc_g_std 			    = zoran_g_std,
+	.vidioc_s_std 			    = zoran_s_std,
+	.vidioc_g_jpegcomp 		    = zoran_g_jpegcomp,
+	.vidioc_s_jpegcomp 		    = zoran_s_jpegcomp,
+	.vidioc_overlay			    = zoran_overlay,
+	.vidioc_reqbufs			    = zoran_reqbufs,
+	.vidioc_querybuf		    = zoran_querybuf,
+	.vidioc_qbuf			    = zoran_qbuf,
+	.vidioc_dqbuf			    = zoran_dqbuf,
+	.vidioc_streamon		    = zoran_streamon,
+	.vidioc_streamoff		    = zoran_streamoff,
+	.vidioc_enum_fmt_vid_cap 	    = zoran_enum_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_out 	    = zoran_enum_fmt_vid_out,
+	.vidioc_enum_fmt_vid_overlay 	    = zoran_enum_fmt_vid_overlay,
+	.vidioc_g_fmt_vid_cap 		    = zoran_g_fmt_vid_cap,
+	.vidioc_g_fmt_vid_out               = zoran_g_fmt_vid_out,
+	.vidioc_g_fmt_vid_overlay           = zoran_g_fmt_vid_overlay,
+	.vidioc_s_fmt_vid_cap  		    = zoran_s_fmt_vid_cap,
+	.vidioc_s_fmt_vid_out               = zoran_s_fmt_vid_out,
+	.vidioc_s_fmt_vid_overlay           = zoran_s_fmt_vid_overlay,
+	.vidioc_try_fmt_vid_cap  	    = zoran_try_fmt_vid_cap,
+	.vidioc_try_fmt_vid_out 	    = zoran_try_fmt_vid_out,
+	.vidioc_try_fmt_vid_overlay 	    = zoran_try_fmt_vid_overlay,
+	.vidioc_queryctrl 		    = zoran_queryctrl,
+	.vidioc_s_ctrl       		    = zoran_s_ctrl,
+	.vidioc_g_ctrl       		    = zoran_g_ctrl,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidioc_default 		    = zoran_default,
+	.vidiocgmbuf 			    = zoran_vidiocgmbuf,
+#endif
+};
+
 static const struct v4l2_file_operations zoran_fops = {
 	.owner = THIS_MODULE,
 	.open = zoran_open,
 	.release = zoran_close,
-	.ioctl = zoran_ioctl,
+	.ioctl = video_ioctl2,
 	.read = zoran_read,
 	.write = zoran_write,
 	.mmap = zoran_mmap,
@@ -4596,7 +3397,9 @@
 struct video_device zoran_template __devinitdata = {
 	.name = ZORAN_NAME,
 	.fops = &zoran_fops,
+	.ioctl_ops = &zoran_ioctl_ops,
 	.release = &zoran_vdev_release,
+	.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
 	.minor = -1
 };
 
diff --git a/drivers/media/video/zoran/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c
index 870bc5a..f1423b7 100644
--- a/drivers/media/video/zoran/zoran_procfs.c
+++ b/drivers/media/video/zoran/zoran_procfs.c
@@ -36,7 +36,7 @@
 #include <linux/pci.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/seq_file.h>
diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/video/zoran/zr36016.c
index 00d132b..21c088e 100644
--- a/drivers/media/video/zoran/zr36016.c
+++ b/drivers/media/video/zoran/zr36016.c
@@ -34,15 +34,10 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
 /* I/O commands, error codes */
 #include <asm/io.h>
-//#include<errno.h>
 
 /* v4l  API */
-#include <linux/videodev.h>
 
 /* headerfile of this module */
 #include"zr36016.h"
diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/video/zoran/zr36050.c
index cf8b271..639dd87 100644
--- a/drivers/media/video/zoran/zr36050.c
+++ b/drivers/media/video/zoran/zr36050.c
@@ -34,12 +34,8 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
 /* I/O commands, error codes */
 #include <asm/io.h>
-//#include<errno.h>
 
 /* headerfile of this module */
 #include "zr36050.h"
diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c
index 8e74054..008746f 100644
--- a/drivers/media/video/zoran/zr36060.c
+++ b/drivers/media/video/zoran/zr36060.c
@@ -34,12 +34,8 @@
 #include <linux/types.h>
 #include <linux/wait.h>
 
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
 /* I/O commands, error codes */
 #include <asm/io.h>
-//#include<errno.h>
 
 /* headerfile of this module */
 #include "zr36060.h"
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index 9302356..221409f 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -96,6 +96,7 @@
 	{USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 },
 	{USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 },
 	{USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 },
+	{USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 },
 	{}			/* Terminating entry */
 };
 
@@ -425,7 +426,6 @@
 static int zr364xx_vidioc_querycap(struct file *file, void *priv,
 				   struct v4l2_capability *cap)
 {
-	memset(cap, 0, sizeof(*cap));
 	strcpy(cap->driver, DRIVER_DESC);
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
 	return 0;
@@ -436,8 +436,6 @@
 {
 	if (i->index != 0)
 		return -EINVAL;
-	memset(i, 0, sizeof(*i));
-	i->index = 0;
 	strcpy(i->name, DRIVER_DESC " Camera");
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 	return 0;
@@ -529,11 +527,6 @@
 {
 	if (f->index > 0)
 		return -EINVAL;
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	memset(f, 0, sizeof(*f));
-	f->index = 0;
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->flags = V4L2_FMT_FLAG_COMPRESSED;
 	strcpy(f->description, "JPEG");
 	f->pixelformat = V4L2_PIX_FMT_JPEG;
@@ -550,8 +543,6 @@
 		return -ENODEV;
 	cam = video_get_drvdata(vdev);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
 		return -EINVAL;
 	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
@@ -577,10 +568,6 @@
 		return -ENODEV;
 	cam = video_get_drvdata(vdev);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	f->fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
 	f->fmt.pix.field = V4L2_FIELD_NONE;
 	f->fmt.pix.width = cam->width;
@@ -602,8 +589,6 @@
 		return -ENODEV;
 	cam = video_get_drvdata(vdev);
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
 	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
 		return -EINVAL;
 	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index c76df8c..89fec05 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -2,7 +2,7 @@
 
 config EEPROM_AT24
 	tristate "I2C EEPROMs from most vendors"
-	depends on I2C && SYSFS && EXPERIMENTAL
+	depends on I2C && SYSFS
 	help
 	  Enable this driver to get read/write support to most I2C EEPROMs,
 	  after you configure the driver to know about each EEPROM on
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 2909bbc..a663429 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -490,7 +490,7 @@
 	mod_timer(&host->timer, jiffies + HZ);
 }
 
-static int mmci_probe(struct amba_device *dev, void *id)
+static int __devinit mmci_probe(struct amba_device *dev, void *id)
 {
 	struct mmc_platform_data *plat = dev->dev.platform_data;
 	struct mmci_host *host;
@@ -633,7 +633,7 @@
 	return ret;
 }
 
-static int mmci_remove(struct amba_device *dev)
+static int __devexit mmci_remove(struct amba_device *dev)
 {
 	struct mmc_host *mmc = amba_get_drvdata(dev);
 
@@ -730,7 +730,7 @@
 		.name	= DRIVER_NAME,
 	},
 	.probe		= mmci_probe,
-	.remove		= mmci_remove,
+	.remove		= __devexit_p(mmci_remove),
 	.suspend	= mmci_suspend,
 	.resume		= mmci_resume,
 	.id_table	= mmci_ids,
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index dda0be4..b4a615c 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -42,7 +42,7 @@
 #define HAS_DMA
 #endif
 
-#define DRIVER_NAME "imx-mmc"
+#define DRIVER_NAME "mxc-mmc"
 
 #define MMC_REG_STR_STP_CLK		0x00
 #define MMC_REG_STATUS			0x04
@@ -707,7 +707,7 @@
 	host->res = r;
 	host->irq = irq;
 
-	host->clk = clk_get(&pdev->dev, "sdhc_clk");
+	host->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
 		goto out_iounmap;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 67d7b7f..5570849 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1460,18 +1460,12 @@
 	if (!host->virt_base)
 		goto err_ioremap;
 
-	if (cpu_is_omap24xx()) {
-		host->iclk = clk_get(&pdev->dev, "mmc_ick");
-		if (IS_ERR(host->iclk))
-			goto err_free_mmc_host;
-		clk_enable(host->iclk);
-	}
+	host->iclk = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(host->iclk))
+		goto err_free_mmc_host;
+	clk_enable(host->iclk);
 
-	if (!cpu_is_omap24xx())
-		host->fclk = clk_get(&pdev->dev, "mmc_ck");
-	else
-		host->fclk = clk_get(&pdev->dev, "mmc_fck");
-
+	host->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(host->fclk)) {
 		ret = PTR_ERR(host->fclk);
 		goto err_free_iclk;
@@ -1536,10 +1530,10 @@
 	if (host->pdata->cleanup)
 		host->pdata->cleanup(&pdev->dev);
 
-	if (host->iclk && !IS_ERR(host->iclk))
-		clk_put(host->iclk);
-	if (host->fclk && !IS_ERR(host->fclk))
-		clk_put(host->fclk);
+	mmc_omap_fclk_enable(host, 0);
+	clk_put(host->fclk);
+	clk_disable(host->iclk);
+	clk_put(host->iclk);
 
 	iounmap(host->virt_base);
 	release_mem_region(pdev->resource[0].start,
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a631c81..3916a56 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -956,13 +956,13 @@
 
 	sema_init(&host->sem, 1);
 
-	host->iclk = clk_get(&pdev->dev, "mmchs_ick");
+	host->iclk = clk_get(&pdev->dev, "ick");
 	if (IS_ERR(host->iclk)) {
 		ret = PTR_ERR(host->iclk);
 		host->iclk = NULL;
 		goto err1;
 	}
-	host->fclk = clk_get(&pdev->dev, "mmchs_fck");
+	host->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(host->fclk)) {
 		ret = PTR_ERR(host->fclk);
 		host->fclk = NULL;
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 9702ad3..4300957 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -30,9 +30,8 @@
 
 #include <asm/sizes.h>
 
-#include <mach/dma.h>
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/dma.h>
 #include <mach/mmc.h>
 
 #include "pxamci.h"
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index d2ec262..c9681a3 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -31,6 +31,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
+#include <linux/io.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -38,7 +39,6 @@
 
 #include <asm/mach/flash.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #ifdef CONFIG_ARCH_P720T
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 6f6a0f6..8f57b6f 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
+#include <linux/io.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
@@ -19,7 +20,6 @@
 #include <linux/mtd/concat.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
 
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index fa129c0..10081e6 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -26,8 +26,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa2xx-regs.h>
 
 #define GPIO_NAND_CS	(11)
 #define GPIO_NAND_RB	(89)
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 21fd4f1..bad048a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -880,7 +880,7 @@
 	this->read_buf = mxc_nand_read_buf;
 	this->verify_buf = mxc_nand_verify_buf;
 
-	host->clk = clk_get(&pdev->dev, "nfc_clk");
+	host->clk = clk_get(&pdev->dev, "nfc");
 	if (IS_ERR(host->clk))
 		goto eclk;
 
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index cc55cbc..61b69cc4 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -22,7 +22,6 @@
 #include <linux/irq.h>
 
 #include <mach/dma.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa3xx_nand.h>
 
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index c2d012f..4bc6901 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -27,9 +27,9 @@
 #include <linux/crc32.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #define TX_BUFFERS 15
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index 5fe17d5..448487e 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -335,11 +335,20 @@
 	if (!(mdio_bus = mdiobus_alloc()))
 		return -ENOMEM;
 
-	/* All MII PHY accesses use NPE-B Ethernet registers */
-	spin_lock_init(&mdio_lock);
-	mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
-	__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
+	if (cpu_is_ixp43x()) {
+		/* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
+		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
+			return -ENOSYS;
+		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
+	} else {
+		/* All MII PHY accesses use NPE-B Ethernet registers */
+		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
+			return -ENOSYS;
+		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
+	}
 
+	__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
+	spin_lock_init(&mdio_lock);
 	mdio_bus->name = "IXP4xx MII Bus";
 	mdio_bus->read = &ixp4xx_mdio_read;
 	mdio_bus->write = &ixp4xx_mdio_write;
@@ -1250,9 +1259,6 @@
 static int __init eth_init_module(void)
 {
 	int err;
-	if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
-		return -ENOSYS;
-
 	if ((err = ixp4xx_mdio_register()))
 		return err;
 	return platform_driver_register(&ixp4xx_eth_driver);
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index cd8e98b..049b0a7 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -1123,9 +1123,9 @@
 #endif
 
 static struct of_device_id mpc52xx_fec_match[] = {
-	{ .type = "network", .compatible = "fsl,mpc5200b-fec", },
-	{ .type = "network", .compatible = "fsl,mpc5200-fec", },
-	{ .type = "network", .compatible = "mpc5200-fec", },
+	{ .compatible = "fsl,mpc5200b-fec", },
+	{ .compatible = "fsl,mpc5200-fec", },
+	{ .compatible = "mpc5200-fec", },
 	{ }
 };
 
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 31794c2..e775338 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -24,9 +24,8 @@
 
 #include <mach/dma.h>
 #include <mach/irda.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/regs-uart.h>
+#include <mach/regs-ost.h>
 
 #define FICP		__REG(0x40800000)  /* Start of FICP area */
 #define ICCR0		__REG(0x40800000)  /* ICP Control Register 0 */
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index c336a1f..aa08987 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -398,7 +398,7 @@
 			int len = (status & 0xffff) - 4; /* omit CRC */
 			/* length sanity check */
 			if (len < 60 || len > 1518) {
-				printk(KERN_DEBUG "%s: bogus packet size: %ld, status=%#2lx.\n",
+				printk(KERN_DEBUG "%s: bogus packet size: %ld, status=%#2Lx.\n",
 				       dev->name, priv->rx_write,
 				       priv->rx_ring[priv->rx_write]->status.raw);
 				dev->stats.rx_errors++;
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
index a45952e..8140f7c 100644
--- a/drivers/net/smc911x.h
+++ b/drivers/net/smc911x.h
@@ -236,8 +236,7 @@
  * Use a DMA for RX and TX packets.
  */
 #include <linux/dma-mapping.h>
-#include <asm/dma.h>
-#include <mach/pxa-regs.h>
+#include <mach/dma.h>
 
 static dma_addr_t rx_dmabuf, tx_dmabuf;
 static int rx_dmalen, tx_dmalen;
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index ed9ae43..912308e 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -44,6 +44,7 @@
     defined(CONFIG_MACH_MAINSTONE) ||\
     defined(CONFIG_MACH_ZYLONITE) ||\
     defined(CONFIG_MACH_LITTLETON) ||\
+    defined(CONFIG_MACH_ZYLONITE2) ||\
     defined(CONFIG_ARCH_VIPER)
 
 #include <asm/mach-types.h>
@@ -345,38 +346,6 @@
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
 
-#elif defined(CONFIG_SOC_AU1X00)
-
-#include <au1xxx.h>
-
-/* We can only do 16-bit reads and writes in the static memory space. */
-#define SMC_CAN_USE_8BIT	0
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	0
-#define SMC_IO_SHIFT		0
-#define SMC_NOWAIT		1
-
-#define SMC_inw(a, r)		au_readw((unsigned long)((a) + (r)))
-#define SMC_insw(a, r, p, l)	\
-	do {	\
-		unsigned long _a = (unsigned long)((a) + (r)); \
-		int _l = (l); \
-		u16 *_p = (u16 *)(p); \
-		while (_l-- > 0) \
-			*_p++ = au_readw(_a); \
-	} while(0)
-#define SMC_outw(v, a, r)	au_writew(v, (unsigned long)((a) + (r)))
-#define SMC_outsw(a, r, p, l)	\
-	do {	\
-		unsigned long _a = (unsigned long)((a) + (r)); \
-		int _l = (l); \
-		const u16 *_p = (const u16 *)(p); \
-		while (_l-- > 0) \
-			au_writew(*_p++ , _a); \
-	} while(0)
-
-#define SMC_IRQ_FLAGS		(0)
-
 #elif	defined(CONFIG_ARCH_VERSATILE)
 
 #define SMC_CAN_USE_8BIT	1
@@ -494,8 +463,6 @@
  */
 #include <linux/dma-mapping.h>
 #include <mach/dma.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 
 #ifdef SMC_insl
 #undef SMC_insl
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 5f33340..d313039 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -31,6 +31,8 @@
 #include <linux/iova.h>
 #include <linux/intel-iommu.h>
 #include <linux/timer.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #undef PREFIX
 #define PREFIX "DMAR:"
@@ -509,6 +511,7 @@
 		return -ENOMEM;
 
 	iommu->seq_id = iommu_allocated++;
+	sprintf (iommu->name, "dmar%d", iommu->seq_id);
 
 	iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
 	if (!iommu->reg) {
@@ -751,6 +754,42 @@
 }
 
 /*
+ * Disable Queued Invalidation interface.
+ */
+void dmar_disable_qi(struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	u32 sts;
+	cycles_t start_time = get_cycles();
+
+	if (!ecap_qis(iommu->ecap))
+		return;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	sts =  dmar_readq(iommu->reg + DMAR_GSTS_REG);
+	if (!(sts & DMA_GSTS_QIES))
+		goto end;
+
+	/*
+	 * Give a chance to HW to complete the pending invalidation requests.
+	 */
+	while ((readl(iommu->reg + DMAR_IQT_REG) !=
+		readl(iommu->reg + DMAR_IQH_REG)) &&
+		(DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
+		cpu_relax();
+
+	iommu->gcmd &= ~DMA_GCMD_QIE;
+
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
+		      !(sts & DMA_GSTS_QIES), sts);
+end:
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
+/*
  * Enable Queued Invalidation interface. This is a must to support
  * interrupt-remapping. Also used by DMA-remapping, which replaces
  * register based IOTLB invalidation.
@@ -770,20 +809,20 @@
 	if (iommu->qi)
 		return 0;
 
-	iommu->qi = kmalloc(sizeof(*qi), GFP_KERNEL);
+	iommu->qi = kmalloc(sizeof(*qi), GFP_ATOMIC);
 	if (!iommu->qi)
 		return -ENOMEM;
 
 	qi = iommu->qi;
 
-	qi->desc = (void *)(get_zeroed_page(GFP_KERNEL));
+	qi->desc = (void *)(get_zeroed_page(GFP_ATOMIC));
 	if (!qi->desc) {
 		kfree(qi);
 		iommu->qi = 0;
 		return -ENOMEM;
 	}
 
-	qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_KERNEL);
+	qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
 	if (!qi->desc_status) {
 		free_page((unsigned long) qi->desc);
 		kfree(qi);
@@ -812,3 +851,254 @@
 
 	return 0;
 }
+
+/* iommu interrupt handling. Most stuff are MSI-like. */
+
+enum faulttype {
+	DMA_REMAP,
+	INTR_REMAP,
+	UNKNOWN,
+};
+
+static const char *dma_remap_fault_reasons[] =
+{
+	"Software",
+	"Present bit in root entry is clear",
+	"Present bit in context entry is clear",
+	"Invalid context entry",
+	"Access beyond MGAW",
+	"PTE Write access is not set",
+	"PTE Read access is not set",
+	"Next page table ptr is invalid",
+	"Root table address invalid",
+	"Context table ptr is invalid",
+	"non-zero reserved fields in RTP",
+	"non-zero reserved fields in CTP",
+	"non-zero reserved fields in PTE",
+};
+
+static const char *intr_remap_fault_reasons[] =
+{
+	"Detected reserved fields in the decoded interrupt-remapped request",
+	"Interrupt index exceeded the interrupt-remapping table size",
+	"Present field in the IRTE entry is clear",
+	"Error accessing interrupt-remapping table pointed by IRTA_REG",
+	"Detected reserved fields in the IRTE entry",
+	"Blocked a compatibility format interrupt request",
+	"Blocked an interrupt request due to source-id verification failure",
+};
+
+#define MAX_FAULT_REASON_IDX 	(ARRAY_SIZE(fault_reason_strings) - 1)
+
+const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
+{
+	if (fault_reason >= 0x20 && (fault_reason <= 0x20 +
+				     ARRAY_SIZE(intr_remap_fault_reasons))) {
+		*fault_type = INTR_REMAP;
+		return intr_remap_fault_reasons[fault_reason - 0x20];
+	} else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
+		*fault_type = DMA_REMAP;
+		return dma_remap_fault_reasons[fault_reason];
+	} else {
+		*fault_type = UNKNOWN;
+		return "Unknown";
+	}
+}
+
+void dmar_msi_unmask(unsigned int irq)
+{
+	struct intel_iommu *iommu = get_irq_data(irq);
+	unsigned long flag;
+
+	/* unmask it */
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(0, iommu->reg + DMAR_FECTL_REG);
+	/* Read a reg to force flush the post write */
+	readl(iommu->reg + DMAR_FECTL_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_mask(unsigned int irq)
+{
+	unsigned long flag;
+	struct intel_iommu *iommu = get_irq_data(irq);
+
+	/* mask it */
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
+	/* Read a reg to force flush the post write */
+	readl(iommu->reg + DMAR_FECTL_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_write(int irq, struct msi_msg *msg)
+{
+	struct intel_iommu *iommu = get_irq_data(irq);
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
+	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
+	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+void dmar_msi_read(int irq, struct msi_msg *msg)
+{
+	struct intel_iommu *iommu = get_irq_data(irq);
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
+	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
+	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+}
+
+static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
+		u8 fault_reason, u16 source_id, unsigned long long addr)
+{
+	const char *reason;
+	int fault_type;
+
+	reason = dmar_get_fault_reason(fault_reason, &fault_type);
+
+	if (fault_type == INTR_REMAP)
+		printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
+		       "fault index %llx\n"
+			"INTR-REMAP:[fault reason %02d] %s\n",
+			(source_id >> 8), PCI_SLOT(source_id & 0xFF),
+			PCI_FUNC(source_id & 0xFF), addr >> 48,
+			fault_reason, reason);
+	else
+		printk(KERN_ERR
+		       "DMAR:[%s] Request device [%02x:%02x.%d] "
+		       "fault addr %llx \n"
+		       "DMAR:[fault reason %02d] %s\n",
+		       (type ? "DMA Read" : "DMA Write"),
+		       (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+		       PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
+	return 0;
+}
+
+#define PRIMARY_FAULT_REG_LEN (16)
+irqreturn_t dmar_fault(int irq, void *dev_id)
+{
+	struct intel_iommu *iommu = dev_id;
+	int reg, fault_index;
+	u32 fault_status;
+	unsigned long flag;
+
+	spin_lock_irqsave(&iommu->register_lock, flag);
+	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+	if (fault_status)
+		printk(KERN_ERR "DRHD: handling fault status reg %x\n",
+		       fault_status);
+
+	/* TBD: ignore advanced fault log currently */
+	if (!(fault_status & DMA_FSTS_PPF))
+		goto clear_rest;
+
+	fault_index = dma_fsts_fault_record_index(fault_status);
+	reg = cap_fault_reg_offset(iommu->cap);
+	while (1) {
+		u8 fault_reason;
+		u16 source_id;
+		u64 guest_addr;
+		int type;
+		u32 data;
+
+		/* highest 32 bits */
+		data = readl(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN + 12);
+		if (!(data & DMA_FRCD_F))
+			break;
+
+		fault_reason = dma_frcd_fault_reason(data);
+		type = dma_frcd_type(data);
+
+		data = readl(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN + 8);
+		source_id = dma_frcd_source_id(data);
+
+		guest_addr = dmar_readq(iommu->reg + reg +
+				fault_index * PRIMARY_FAULT_REG_LEN);
+		guest_addr = dma_frcd_page_addr(guest_addr);
+		/* clear the fault */
+		writel(DMA_FRCD_F, iommu->reg + reg +
+			fault_index * PRIMARY_FAULT_REG_LEN + 12);
+
+		spin_unlock_irqrestore(&iommu->register_lock, flag);
+
+		dmar_fault_do_one(iommu, type, fault_reason,
+				source_id, guest_addr);
+
+		fault_index++;
+		if (fault_index > cap_num_fault_regs(iommu->cap))
+			fault_index = 0;
+		spin_lock_irqsave(&iommu->register_lock, flag);
+	}
+clear_rest:
+	/* clear all the other faults */
+	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
+	writel(fault_status, iommu->reg + DMAR_FSTS_REG);
+
+	spin_unlock_irqrestore(&iommu->register_lock, flag);
+	return IRQ_HANDLED;
+}
+
+int dmar_set_interrupt(struct intel_iommu *iommu)
+{
+	int irq, ret;
+
+	/*
+	 * Check if the fault interrupt is already initialized.
+	 */
+	if (iommu->irq)
+		return 0;
+
+	irq = create_irq();
+	if (!irq) {
+		printk(KERN_ERR "IOMMU: no free vectors\n");
+		return -EINVAL;
+	}
+
+	set_irq_data(irq, iommu);
+	iommu->irq = irq;
+
+	ret = arch_setup_dmar_msi(irq);
+	if (ret) {
+		set_irq_data(irq, NULL);
+		iommu->irq = 0;
+		destroy_irq(irq);
+		return 0;
+	}
+
+	ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
+	if (ret)
+		printk(KERN_ERR "IOMMU: can't request irq\n");
+	return ret;
+}
+
+int __init enable_drhd_fault_handling(void)
+{
+	struct dmar_drhd_unit *drhd;
+
+	/*
+	 * Enable fault control interrupt.
+	 */
+	for_each_drhd_unit(drhd) {
+		int ret;
+		struct intel_iommu *iommu = drhd->iommu;
+		ret = dmar_set_interrupt(iommu);
+
+		if (ret) {
+			printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
+			       " interrupt, ret %d\n",
+			       (unsigned long long)drhd->reg_base_addr, ret);
+			return -1;
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index e7d058a..49402c3 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1004,194 +1004,6 @@
 	return 0;
 }
 
-/* iommu interrupt handling. Most stuff are MSI-like. */
-
-static const char *fault_reason_strings[] =
-{
-	"Software",
-	"Present bit in root entry is clear",
-	"Present bit in context entry is clear",
-	"Invalid context entry",
-	"Access beyond MGAW",
-	"PTE Write access is not set",
-	"PTE Read access is not set",
-	"Next page table ptr is invalid",
-	"Root table address invalid",
-	"Context table ptr is invalid",
-	"non-zero reserved fields in RTP",
-	"non-zero reserved fields in CTP",
-	"non-zero reserved fields in PTE",
-};
-#define MAX_FAULT_REASON_IDX 	(ARRAY_SIZE(fault_reason_strings) - 1)
-
-const char *dmar_get_fault_reason(u8 fault_reason)
-{
-	if (fault_reason > MAX_FAULT_REASON_IDX)
-		return "Unknown";
-	else
-		return fault_reason_strings[fault_reason];
-}
-
-void dmar_msi_unmask(unsigned int irq)
-{
-	struct intel_iommu *iommu = get_irq_data(irq);
-	unsigned long flag;
-
-	/* unmask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(0, iommu->reg + DMAR_FECTL_REG);
-	/* Read a reg to force flush the post write */
-	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_mask(unsigned int irq)
-{
-	unsigned long flag;
-	struct intel_iommu *iommu = get_irq_data(irq);
-
-	/* mask it */
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG);
-	/* Read a reg to force flush the post write */
-	readl(iommu->reg + DMAR_FECTL_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_write(int irq, struct msi_msg *msg)
-{
-	struct intel_iommu *iommu = get_irq_data(irq);
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	writel(msg->data, iommu->reg + DMAR_FEDATA_REG);
-	writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG);
-	writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-void dmar_msi_read(int irq, struct msi_msg *msg)
-{
-	struct intel_iommu *iommu = get_irq_data(irq);
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	msg->data = readl(iommu->reg + DMAR_FEDATA_REG);
-	msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG);
-	msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG);
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-}
-
-static int iommu_page_fault_do_one(struct intel_iommu *iommu, int type,
-		u8 fault_reason, u16 source_id, unsigned long long addr)
-{
-	const char *reason;
-
-	reason = dmar_get_fault_reason(fault_reason);
-
-	printk(KERN_ERR
-		"DMAR:[%s] Request device [%02x:%02x.%d] "
-		"fault addr %llx \n"
-		"DMAR:[fault reason %02d] %s\n",
-		(type ? "DMA Read" : "DMA Write"),
-		(source_id >> 8), PCI_SLOT(source_id & 0xFF),
-		PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason);
-	return 0;
-}
-
-#define PRIMARY_FAULT_REG_LEN (16)
-static irqreturn_t iommu_page_fault(int irq, void *dev_id)
-{
-	struct intel_iommu *iommu = dev_id;
-	int reg, fault_index;
-	u32 fault_status;
-	unsigned long flag;
-
-	spin_lock_irqsave(&iommu->register_lock, flag);
-	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
-
-	/* TBD: ignore advanced fault log currently */
-	if (!(fault_status & DMA_FSTS_PPF))
-		goto clear_overflow;
-
-	fault_index = dma_fsts_fault_record_index(fault_status);
-	reg = cap_fault_reg_offset(iommu->cap);
-	while (1) {
-		u8 fault_reason;
-		u16 source_id;
-		u64 guest_addr;
-		int type;
-		u32 data;
-
-		/* highest 32 bits */
-		data = readl(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN + 12);
-		if (!(data & DMA_FRCD_F))
-			break;
-
-		fault_reason = dma_frcd_fault_reason(data);
-		type = dma_frcd_type(data);
-
-		data = readl(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN + 8);
-		source_id = dma_frcd_source_id(data);
-
-		guest_addr = dmar_readq(iommu->reg + reg +
-				fault_index * PRIMARY_FAULT_REG_LEN);
-		guest_addr = dma_frcd_page_addr(guest_addr);
-		/* clear the fault */
-		writel(DMA_FRCD_F, iommu->reg + reg +
-			fault_index * PRIMARY_FAULT_REG_LEN + 12);
-
-		spin_unlock_irqrestore(&iommu->register_lock, flag);
-
-		iommu_page_fault_do_one(iommu, type, fault_reason,
-				source_id, guest_addr);
-
-		fault_index++;
-		if (fault_index > cap_num_fault_regs(iommu->cap))
-			fault_index = 0;
-		spin_lock_irqsave(&iommu->register_lock, flag);
-	}
-clear_overflow:
-	/* clear primary fault overflow */
-	fault_status = readl(iommu->reg + DMAR_FSTS_REG);
-	if (fault_status & DMA_FSTS_PFO)
-		writel(DMA_FSTS_PFO, iommu->reg + DMAR_FSTS_REG);
-
-	spin_unlock_irqrestore(&iommu->register_lock, flag);
-	return IRQ_HANDLED;
-}
-
-int dmar_set_interrupt(struct intel_iommu *iommu)
-{
-	int irq, ret;
-
-	irq = create_irq();
-	if (!irq) {
-		printk(KERN_ERR "IOMMU: no free vectors\n");
-		return -EINVAL;
-	}
-
-	set_irq_data(irq, iommu);
-	iommu->irq = irq;
-
-	ret = arch_setup_dmar_msi(irq);
-	if (ret) {
-		set_irq_data(irq, NULL);
-		iommu->irq = 0;
-		destroy_irq(irq);
-		return 0;
-	}
-
-	/* Force fault register is cleared */
-	iommu_page_fault(irq, iommu);
-
-	ret = request_irq(irq, iommu_page_fault, 0, iommu->name, iommu);
-	if (ret)
-		printk(KERN_ERR "IOMMU: can't request irq\n");
-	return ret;
-}
 
 static int iommu_init_domains(struct intel_iommu *iommu)
 {
@@ -1987,7 +1799,7 @@
 	struct dmar_rmrr_unit *rmrr;
 	struct pci_dev *pdev;
 	struct intel_iommu *iommu;
-	int i, ret, unit = 0;
+	int i, ret;
 
 	/*
 	 * for each drhd
@@ -2043,11 +1855,40 @@
 		}
 	}
 
+	/*
+	 * Start from the sane iommu hardware state.
+	 */
 	for_each_drhd_unit(drhd) {
 		if (drhd->ignored)
 			continue;
 
 		iommu = drhd->iommu;
+
+		/*
+		 * If the queued invalidation is already initialized by us
+		 * (for example, while enabling interrupt-remapping) then
+		 * we got the things already rolling from a sane state.
+		 */
+		if (iommu->qi)
+			continue;
+
+		/*
+		 * Clear any previous faults.
+		 */
+		dmar_fault(-1, iommu);
+		/*
+		 * Disable queued invalidation if supported and already enabled
+		 * before OS handover.
+		 */
+		dmar_disable_qi(iommu);
+	}
+
+	for_each_drhd_unit(drhd) {
+		if (drhd->ignored)
+			continue;
+
+		iommu = drhd->iommu;
+
 		if (dmar_enable_qi(iommu)) {
 			/*
 			 * Queued Invalidate not enabled, use Register Based
@@ -2109,7 +1950,6 @@
 		if (drhd->ignored)
 			continue;
 		iommu = drhd->iommu;
-		sprintf (iommu->name, "dmar%d", unit++);
 
 		iommu_flush_write_buffer(iommu);
 
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 9d07a05..b041a40 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -117,21 +117,22 @@
 {
 	int index;
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
 	if (!entry)
 		return -1;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	*entry = *(irq_iommu->iommu->ir_table->base + index);
 
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return 0;
 }
 
@@ -141,6 +142,7 @@
 	struct irq_2_iommu *irq_iommu;
 	u16 index, start_index;
 	unsigned int mask = 0;
+	unsigned long flags;
 	int i;
 
 	if (!count)
@@ -170,7 +172,7 @@
 		return -1;
 	}
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	do {
 		for (i = index; i < index + count; i++)
 			if  (table->base[i].present)
@@ -182,7 +184,7 @@
 		index = (index + count) % INTR_REMAP_TABLE_ENTRIES;
 
 		if (index == start_index) {
-			spin_unlock(&irq_2_ir_lock);
+			spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 			printk(KERN_ERR "can't allocate an IRTE\n");
 			return -1;
 		}
@@ -193,7 +195,7 @@
 
 	irq_iommu = irq_2_iommu_alloc(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		printk(KERN_ERR "can't allocate irq_2_iommu\n");
 		return -1;
 	}
@@ -203,7 +205,7 @@
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = mask;
 
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return index;
 }
@@ -223,30 +225,32 @@
 {
 	int index;
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
 	*sub_handle = irq_iommu->sub_handle;
 	index = irq_iommu->irte_index;
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 	return index;
 }
 
 int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
 {
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 
 	irq_iommu = irq_2_iommu_alloc(irq);
 
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		printk(KERN_ERR "can't allocate irq_2_iommu\n");
 		return -1;
 	}
@@ -256,7 +260,7 @@
 	irq_iommu->sub_handle = subhandle;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return 0;
 }
@@ -264,11 +268,12 @@
 int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
 {
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
@@ -277,7 +282,7 @@
 	irq_iommu->sub_handle = 0;
 	irq_2_iommu(irq)->irte_mask = 0;
 
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return 0;
 }
@@ -289,11 +294,12 @@
 	struct irte *irte;
 	struct intel_iommu *iommu;
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
@@ -302,11 +308,11 @@
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 	irte = &iommu->ir_table->base[index];
 
-	set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
+	set_64bit((unsigned long *)irte, irte_modified->low);
 	__iommu_flush_cache(iommu, irte, sizeof(*irte));
 
 	rc = qi_flush_iec(iommu, index, 0);
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -317,11 +323,12 @@
 	int index;
 	struct intel_iommu *iommu;
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
@@ -330,7 +337,7 @@
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 
 	rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -363,11 +370,12 @@
 	struct irte *irte;
 	struct intel_iommu *iommu;
 	struct irq_2_iommu *irq_iommu;
+	unsigned long flags;
 
-	spin_lock(&irq_2_ir_lock);
+	spin_lock_irqsave(&irq_2_ir_lock, flags);
 	irq_iommu = valid_irq_2_iommu(irq);
 	if (!irq_iommu) {
-		spin_unlock(&irq_2_ir_lock);
+		spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 		return -1;
 	}
 
@@ -378,7 +386,7 @@
 
 	if (!irq_iommu->sub_handle) {
 		for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
-			set_64bit((unsigned long *)irte, 0);
+			set_64bit((unsigned long *)(irte + i), 0);
 		rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
 	}
 
@@ -387,7 +395,7 @@
 	irq_iommu->sub_handle = 0;
 	irq_iommu->irte_mask = 0;
 
-	spin_unlock(&irq_2_ir_lock);
+	spin_unlock_irqrestore(&irq_2_ir_lock, flags);
 
 	return rc;
 }
@@ -439,12 +447,12 @@
 	struct page *pages;
 
 	ir_table = iommu->ir_table = kzalloc(sizeof(struct ir_table),
-					     GFP_KERNEL);
+					     GFP_ATOMIC);
 
 	if (!iommu->ir_table)
 		return -ENOMEM;
 
-	pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
+	pages = alloc_pages(GFP_ATOMIC | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
 
 	if (!pages) {
 		printk(KERN_ERR "failed to allocate pages of order %d\n",
@@ -459,11 +467,55 @@
 	return 0;
 }
 
+/*
+ * Disable Interrupt Remapping.
+ */
+static void disable_intr_remapping(struct intel_iommu *iommu)
+{
+	unsigned long flags;
+	u32 sts;
+
+	if (!ecap_ir_support(iommu->ecap))
+		return;
+
+	spin_lock_irqsave(&iommu->register_lock, flags);
+
+	sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
+	if (!(sts & DMA_GSTS_IRES))
+		goto end;
+
+	iommu->gcmd &= ~DMA_GCMD_IRE;
+	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+
+	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+		      readl, !(sts & DMA_GSTS_IRES), sts);
+
+end:
+	spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
 int __init enable_intr_remapping(int eim)
 {
 	struct dmar_drhd_unit *drhd;
 	int setup = 0;
 
+	for_each_drhd_unit(drhd) {
+		struct intel_iommu *iommu = drhd->iommu;
+
+		/*
+		 * Clear previous faults.
+		 */
+		dmar_fault(-1, iommu);
+
+		/*
+		 * Disable intr remapping and queued invalidation, if already
+		 * enabled prior to OS handover.
+		 */
+		disable_intr_remapping(iommu);
+
+		dmar_disable_qi(iommu);
+	}
+
 	/*
 	 * check for the Interrupt-remapping support
 	 */
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index bb9ddb9..c49a726 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <mach/pxa-regs.h>
 #include <mach/pxa2xx-regs.h>
 #include <asm/mach-types.h>
 
@@ -39,6 +38,44 @@
 #include "soc_common.h"
 #include "pxa2xx_base.h"
 
+/*
+ * Personal Computer Memory Card International Association (PCMCIA) sockets
+ */
+
+#define PCMCIAPrtSp	0x04000000	/* PCMCIA Partition Space [byte]   */
+#define PCMCIASp	(4*PCMCIAPrtSp)	/* PCMCIA Space [byte]             */
+#define PCMCIAIOSp	PCMCIAPrtSp	/* PCMCIA I/O Space [byte]         */
+#define PCMCIAAttrSp	PCMCIAPrtSp	/* PCMCIA Attribute Space [byte]   */
+#define PCMCIAMemSp	PCMCIAPrtSp	/* PCMCIA Memory Space [byte]      */
+
+#define PCMCIA0Sp	PCMCIASp	/* PCMCIA 0 Space [byte]           */
+#define PCMCIA0IOSp	PCMCIAIOSp	/* PCMCIA 0 I/O Space [byte]       */
+#define PCMCIA0AttrSp	PCMCIAAttrSp	/* PCMCIA 0 Attribute Space [byte] */
+#define PCMCIA0MemSp	PCMCIAMemSp	/* PCMCIA 0 Memory Space [byte]    */
+
+#define PCMCIA1Sp	PCMCIASp	/* PCMCIA 1 Space [byte]           */
+#define PCMCIA1IOSp	PCMCIAIOSp	/* PCMCIA 1 I/O Space [byte]       */
+#define PCMCIA1AttrSp	PCMCIAAttrSp	/* PCMCIA 1 Attribute Space [byte] */
+#define PCMCIA1MemSp	PCMCIAMemSp	/* PCMCIA 1 Memory Space [byte]    */
+
+#define _PCMCIA(Nb)			/* PCMCIA [0..1]                   */ \
+			(0x20000000 + (Nb) * PCMCIASp)
+#define _PCMCIAIO(Nb)	_PCMCIA(Nb)	/* PCMCIA I/O [0..1]               */
+#define _PCMCIAAttr(Nb)			/* PCMCIA Attribute [0..1]         */ \
+			(_PCMCIA(Nb) + 2 * PCMCIAPrtSp)
+#define _PCMCIAMem(Nb)			/* PCMCIA Memory [0..1]            */ \
+			(_PCMCIA(Nb) + 3 * PCMCIAPrtSp)
+
+#define _PCMCIA0	_PCMCIA(0)	/* PCMCIA 0                        */
+#define _PCMCIA0IO	_PCMCIAIO(0)	/* PCMCIA 0 I/O                    */
+#define _PCMCIA0Attr	_PCMCIAAttr(0)	/* PCMCIA 0 Attribute              */
+#define _PCMCIA0Mem	_PCMCIAMem(0)	/* PCMCIA 0 Memory                 */
+
+#define _PCMCIA1	_PCMCIA(1)	/* PCMCIA 1                        */
+#define _PCMCIA1IO	_PCMCIAIO(1)	/* PCMCIA 1 I/O                    */
+#define _PCMCIA1Attr	_PCMCIAAttr(1)	/* PCMCIA 1 Attribute              */
+#define _PCMCIA1Mem	_PCMCIAMem(1)	/* PCMCIA 1 Memory                 */
+
 
 #define MCXX_SETUP_MASK     (0x7f)
 #define MCXX_ASST_MASK      (0x1f)
@@ -177,29 +214,73 @@
 	MECR |= MECR_CIT;
 
 	/* Set MECR:NOS (Number Of Sockets) */
-	if (ops->nr > 1 || machine_is_viper())
+	if ((ops->first + ops->nr) > 1 || machine_is_viper())
 		MECR |= MECR_NOS;
 	else
 		MECR &= ~MECR_NOS;
 }
 
+static const char *skt_names[] = {
+	"PCMCIA socket 0",
+	"PCMCIA socket 1",
+};
+
+#define SKT_DEV_INFO_SIZE(n) \
+	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
+
 int __pxa2xx_drv_pcmcia_probe(struct device *dev)
 {
-	int ret;
+	int i, ret;
 	struct pcmcia_low_level *ops;
+	struct skt_dev_info *sinfo;
+	struct soc_pcmcia_socket *skt;
 
 	if (!dev || !dev->platform_data)
 		return -ENODEV;
 
 	ops = (struct pcmcia_low_level *)dev->platform_data;
 
+	sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
+	if (!sinfo)
+		return -ENOMEM;
+
+	sinfo->nskt = ops->nr;
+
+	/* Initialize processor specific parameters */
+	for (i = 0; i < ops->nr; i++) {
+		skt = &sinfo->skt[i];
+
+		skt->nr		= ops->first + i;
+		skt->irq	= NO_IRQ;
+
+		skt->res_skt.start	= _PCMCIA(skt->nr);
+		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1;
+		skt->res_skt.name	= skt_names[skt->nr];
+		skt->res_skt.flags	= IORESOURCE_MEM;
+
+		skt->res_io.start	= _PCMCIAIO(skt->nr);
+		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
+		skt->res_io.name	= "io";
+		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		skt->res_mem.start	= _PCMCIAMem(skt->nr);
+		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
+		skt->res_mem.name	= "memory";
+		skt->res_mem.flags	= IORESOURCE_MEM;
+
+		skt->res_attr.start	= _PCMCIAAttr(skt->nr);
+		skt->res_attr.end	= _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
+		skt->res_attr.name	= "attribute";
+		skt->res_attr.flags	= IORESOURCE_MEM;
+	}
+
 	/* Provide our PXA2xx specific timing routines. */
 	ops->set_timing  = pxa2xx_pcmcia_set_timing;
 #ifdef CONFIG_CPU_FREQ
 	ops->frequency_change = pxa2xx_pcmcia_frequency_change;
 #endif
 
-	ret = soc_common_drv_pcmcia_probe(dev, ops, ops->first, ops->nr);
+	ret = soc_common_drv_pcmcia_probe(dev, ops, sinfo);
 
 	if (!ret)
 		pxa2xx_configure_sockets(dev);
diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c
index 7c8bcb4..4ed64d8 100644
--- a/drivers/pcmcia/pxa2xx_cm_x255.c
+++ b/drivers/pcmcia/pxa2xx_cm_x255.c
@@ -16,7 +16,6 @@
 #include <linux/gpio.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
 
 #include "soc_common.h"
 
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index 6c3aac3..a7b943d 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -16,7 +16,6 @@
 #include <linux/gpio.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
 
 #include "soc_common.h"
 
diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c
index f663a01..d09c0dc 100644
--- a/drivers/pcmcia/pxa2xx_e740.c
+++ b/drivers/pcmcia/pxa2xx_e740.c
@@ -16,8 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/eseries-gpio.h>
 
 #include <asm/irq.h>
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index 37ec55d..6cbb1b1 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/pxa2xx_lubbock.c
@@ -24,7 +24,6 @@
 #include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
 #include <mach/lubbock.h>
 
 #include "sa1111_generic.h"
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 877001d..1138551 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -21,11 +21,10 @@
 
 #include <pcmcia/ss.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 
-#include <mach/pxa-regs.h>
+#include <mach/pxa2xx-regs.h>
 #include <mach/mainstone.h>
 
 #include "soc_common.h"
diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c
index 1736c67..5ba9b36 100644
--- a/drivers/pcmcia/pxa2xx_palmld.c
+++ b/drivers/pcmcia/pxa2xx_palmld.c
@@ -98,8 +98,8 @@
 static struct pcmcia_low_level palmld_pcmcia_ops = {
 	.owner			= THIS_MODULE,
 
-	.first			= 0,
-	.nr			= 2,
+	.first			= 1,
+	.nr			= 1,
 
 	.hw_init		= palmld_pcmcia_hw_init,
 	.hw_shutdown		= palmld_pcmcia_hw_shutdown,
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index 36c7a0b..e0e5cb3 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -22,8 +22,7 @@
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/pxa2xx-regs.h>
 #include <mach/trizeps4.h>
 
 #include "soc_common.h"
diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c
index dd10481..1787136 100644
--- a/drivers/pcmcia/pxa2xx_viper.c
+++ b/drivers/pcmcia/pxa2xx_viper.c
@@ -26,7 +26,6 @@
 
 #include <asm/irq.h>
 
-#include <mach/pxa-regs.h>
 #include <mach/viper.h>
 #include <asm/mach-types.h>
 
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index 6de4e1b..0cc3748 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -37,9 +37,9 @@
 	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
   
 	/* Disable CF bus: */
-	clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
-	clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
-	set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1);
 }
 
 static void
@@ -79,10 +79,7 @@
 		return -1;
 	}
 
-	if (state->flags & SS_RESET)
-		set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
-	else
-		clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
+	assign_h3600_egpio(IPAQ_EGPIO_CARD_RESET, !!(state->flags & SS_RESET));
 
 	/* Silently ignore Vpp, output enable, speaker enable. */
 
@@ -92,9 +89,9 @@
 static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
 	/* Enable CF bus: */
-	set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
-	set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
-	clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 1);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 1);
+	assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 0);
 
 	msleep(10);
 
@@ -112,10 +109,10 @@
 	 * socket 0 then socket 1.
 	 */
 	if (skt->nr == 1) {
-		clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
-		clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
+		assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0);
+		assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0);
 		/* hmm, does this suck power? */
-		set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
+		assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1);
 	}
 }
 
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 6924d0e..401052a 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -11,12 +11,12 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/io.h>
 
 #include <pcmcia/ss.h>
 
 #include <mach/hardware.h>
 #include <asm/hardware/sa1111.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 
 #include "sa1111_generic.h"
diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c
index 7cb1273..e15d59f 100644
--- a/drivers/pcmcia/sa11xx_base.c
+++ b/drivers/pcmcia/sa11xx_base.c
@@ -36,9 +36,9 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 
@@ -163,9 +163,55 @@
 	return p - buf;
 }
 
+static const char *skt_names[] = {
+	"PCMCIA socket 0",
+	"PCMCIA socket 1",
+};
+
+#define SKT_DEV_INFO_SIZE(n) \
+	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
+
 int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
 			    int first, int nr)
 {
+	struct skt_dev_info *sinfo;
+	struct soc_pcmcia_socket *skt;
+	int i;
+
+	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
+	if (!sinfo)
+		return -ENOMEM;
+
+	sinfo->nskt = nr;
+
+	/* Initiliaze processor specific parameters */
+	for (i = 0; i < nr; i++) {
+		skt = &sinfo->skt[i];
+
+		skt->nr		= first + i;
+		skt->irq	= NO_IRQ;
+
+		skt->res_skt.start	= _PCMCIA(skt->nr);
+		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1;
+		skt->res_skt.name	= skt_names[skt->nr];
+		skt->res_skt.flags	= IORESOURCE_MEM;
+
+		skt->res_io.start	= _PCMCIAIO(skt->nr);
+		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
+		skt->res_io.name	= "io";
+		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		skt->res_mem.start	= _PCMCIAMem(skt->nr);
+		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
+		skt->res_mem.name	= "memory";
+		skt->res_mem.flags	= IORESOURCE_MEM;
+
+		skt->res_attr.start	= _PCMCIAAttr(skt->nr);
+		skt->res_attr.end	= _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
+		skt->res_attr.name	= "attribute";
+		skt->res_attr.flags	= IORESOURCE_MEM;
+	}
+
 	/*
 	 * set default MECR calculation if the board specific
 	 * code did not specify one...
@@ -180,7 +226,7 @@
 	ops->frequency_change = sa1100_pcmcia_frequency_change;
 #endif
 
-	return soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+	return soc_common_drv_pcmcia_probe(dev, ops, sinfo);
 }
 EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
 
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index f49ac66..163cf98 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -49,11 +49,6 @@
 
 #include "soc_common.h"
 
-/* FIXME: platform dependent resource declaration has to move out of this file */
-#ifdef CONFIG_ARCH_PXA
-#include <mach/pxa-regs.h>
-#endif
-
 #ifdef CONFIG_PCMCIA_DEBUG
 
 static int pc_debug;
@@ -581,19 +576,6 @@
 LIST_HEAD(soc_pcmcia_sockets);
 static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
 
-static const char *skt_names[] = {
-	"PCMCIA socket 0",
-	"PCMCIA socket 1",
-};
-
-struct skt_dev_info {
-	int nskt;
-	struct soc_pcmcia_socket skt[0];
-};
-
-#define SKT_DEV_INFO_SIZE(n) \
-	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
-
 #ifdef CONFIG_CPU_FREQ
 static int
 soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
@@ -637,26 +619,18 @@
 static void soc_pcmcia_cpufreq_unregister(void) {}
 #endif
 
-int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
+int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
+				struct skt_dev_info *sinfo)
 {
-	struct skt_dev_info *sinfo;
 	struct soc_pcmcia_socket *skt;
 	int ret, i;
 
 	mutex_lock(&soc_pcmcia_sockets_lock);
 
-	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
-	if (!sinfo) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	sinfo->nskt = nr;
-
 	/*
 	 * Initialise the per-socket structure.
 	 */
-	for (i = 0; i < nr; i++) {
+	for (i = 0; i < sinfo->nskt; i++) {
 		skt = &sinfo->skt[i];
 
 		skt->socket.ops = &soc_common_pcmcia_operations;
@@ -668,43 +642,21 @@
 		skt->poll_timer.data = (unsigned long)skt;
 		skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
 
-		skt->nr		= first + i;
-		skt->irq	= NO_IRQ;
 		skt->dev	= dev;
 		skt->ops	= ops;
 
-		skt->res_skt.start	= _PCMCIA(skt->nr);
-		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1;
-		skt->res_skt.name	= skt_names[skt->nr];
-		skt->res_skt.flags	= IORESOURCE_MEM;
-
 		ret = request_resource(&iomem_resource, &skt->res_skt);
 		if (ret)
 			goto out_err_1;
 
-		skt->res_io.start	= _PCMCIAIO(skt->nr);
-		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
-		skt->res_io.name	= "io";
-		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY;
-
 		ret = request_resource(&skt->res_skt, &skt->res_io);
 		if (ret)
 			goto out_err_2;
 
-		skt->res_mem.start	= _PCMCIAMem(skt->nr);
-		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
-		skt->res_mem.name	= "memory";
-		skt->res_mem.flags	= IORESOURCE_MEM;
-
 		ret = request_resource(&skt->res_skt, &skt->res_mem);
 		if (ret)
 			goto out_err_3;
 
-		skt->res_attr.start	= _PCMCIAAttr(skt->nr);
-		skt->res_attr.end	= _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1;
-		skt->res_attr.name	= "attribute";
-		skt->res_attr.flags	= IORESOURCE_MEM;
-
 		ret = request_resource(&skt->res_skt, &skt->res_attr);
 		if (ret)
 			goto out_err_4;
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 38c6737..290e143 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -58,6 +58,11 @@
 	struct list_head	node;
 };
 
+struct skt_dev_info {
+	int nskt;
+	struct soc_pcmcia_socket skt[0];
+};
+
 struct pcmcia_state {
   unsigned detect: 1,
             ready: 1,
@@ -132,7 +137,7 @@
 
 extern struct list_head soc_pcmcia_sockets;
 
-extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
+extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, struct skt_dev_info *sinfo);
 extern int soc_common_drv_pcmcia_remove(struct device *dev);
 
 
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 5324978..235e87f 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -838,7 +838,7 @@
 }
 
 /* set mode using id */
-int ps3av_set_video_mode(u32 id)
+int ps3av_set_video_mode(int id)
 {
 	int size;
 	u32 option;
@@ -940,7 +940,7 @@
 static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
 	int res;
-	u32 id;
+	int id;
 
 	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 	dev_dbg(&dev->core, "  timeout=%d\n", timeout);
@@ -962,8 +962,10 @@
 	init_completion(&ps3av->done);
 	complete(&ps3av->done);
 	ps3av->wq = create_singlethread_workqueue("ps3avd");
-	if (!ps3av->wq)
+	if (!ps3av->wq) {
+		res = -ENOMEM;
 		goto fail;
+	}
 
 	switch (ps3_os_area_get_av_multi_out()) {
 	case PS3_PARAM_AV_MULTI_OUT_NTSC:
@@ -994,6 +996,12 @@
 		safe_mode = 1;
 #endif /* CONFIG_FB */
 	id = ps3av_auto_videomode(&ps3av->av_hw_conf);
+	if (id < 0) {
+		printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
+		res = -EINVAL;
+		goto fail;
+	}
+
 	safe_mode = 0;
 
 	mutex_lock(&ps3av->mutex);
@@ -1007,7 +1015,7 @@
 fail:
 	kfree(ps3av);
 	ps3av = NULL;
-	return -ENOMEM;
+	return res;
 }
 
 static int ps3av_remove(struct ps3_system_bus_device *dev)
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index 45f12dc..e0263d2 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -12,6 +12,7 @@
 #include <linux/bcd.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 
 #define RTC_TIME_REG_OFFS	0
@@ -119,6 +120,16 @@
 		return -EINVAL;
 	}
 
+	/* make sure it is actually functional */
+	if (rtc_time == 0x01000000) {
+		ssleep(1);
+		rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
+		if (rtc_time == 0x01000000) {
+			dev_err(&pdev->dev, "internal RTC not ticking\n");
+			return -ENODEV;
+		}
+	}
+
 	platform_set_drvdata(pdev, pdata);
 	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 					 &mv_rtc_ops, THIS_MODULE);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index d26a5f8..4f247e4 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -35,7 +35,8 @@
 #include <asm/irq.h>
 
 #ifdef CONFIG_ARCH_PXA
-#include <mach/pxa-regs.h>
+#include <mach/regs-rtc.h>
+#include <mach/regs-ost.h>
 #endif
 
 #define RTC_DEF_DIVIDER		32768 - 1
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 68a6412..c9902b5 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -318,7 +318,7 @@
 {
 	int ret = length;
 
-	if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) {
+	if (length >= 11 && strncmp(buffer, "CUMANASCSI2", 11) == 0) {
 		buffer += 11;
 		length -= 11;
 
@@ -390,7 +390,8 @@
 	.eh_abort_handler		= fas216_eh_abort,
 	.can_queue			= 1,
 	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
+	.sg_tablesize			= SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.dma_boundary			= IOMD_DMA_BOUNDARY,
 	.cmd_per_lun			= 1,
 	.use_clustering			= DISABLE_CLUSTERING,
 	.proc_name			= "cumanascsi2",
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index bb2477b..d843513 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -508,7 +508,8 @@
 	.eh_abort_handler		= fas216_eh_abort,
 	.can_queue			= 1,
 	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
+	.sg_tablesize			= SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.dma_boundary			= IOMD_DMA_BOUNDARY,
 	.cmd_per_lun			= 1,
 	.use_clustering			= DISABLE_CLUSTERING,
 	.proc_name			= "eesox",
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index d9a546d..e2297b4 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -302,7 +302,8 @@
 
 	.can_queue			= 8,
 	.this_id			= 7,
-	.sg_tablesize			= SG_ALL,
+	.sg_tablesize			= SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.dma_boundary			= IOMD_DMA_BOUNDARY,
 	.cmd_per_lun			= 2,
 	.use_clustering			= ENABLE_CLUSTERING,
 	.proc_name			= "powertec",
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index f31c669..cb6d85d 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -14,8 +14,8 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/dec21285.h>
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 7d7f576..9be11b0 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -628,7 +628,7 @@
 
 config SERIAL_PXA
 	bool "PXA serial port support"
-	depends on ARM && ARCH_PXA
+	depends on ARCH_PXA || ARCH_MMP
 	select SERIAL_CORE
 	help
 	  If you have a machine based on an Intel XScale PXA2xx CPU you
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 459f342..80e7642 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -38,9 +38,9 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/clps7111.h>
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index bde4b4b..5c6ef51 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -406,6 +406,18 @@
 
 	pr_debug("CPM uart[%d]:startup\n", port->line);
 
+	/* If the port is not the console, make sure rx is disabled. */
+	if (!(pinfo->flags & FLAG_CONSOLE)) {
+		/* Disable UART rx */
+		if (IS_SMC(pinfo)) {
+			clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN);
+			clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
+		} else {
+			clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR);
+			clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
+		}
+		cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
+	}
 	/* Install interrupt handler. */
 	retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
 	if (retval)
@@ -420,8 +432,6 @@
 		setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT));
 	}
 
-	if (!(pinfo->flags & FLAG_CONSOLE))
-		cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
 	return 0;
 }
 
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index a509546..9f460b1 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -1129,7 +1129,7 @@
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
 
-	sport->clk = clk_get(&pdev->dev, "uart_clk");
+	sport->clk = clk_get(&pdev->dev, "uart");
 	if (IS_ERR(sport->clk)) {
 		ret = PTR_ERR(sport->clk);
 		goto unmap;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 0c3a2ab..7f72f8c 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -50,8 +50,8 @@
 /* OF Platform device Usage :
  *
  * This driver is only used for PSCs configured in uart mode.  The device
- * tree will have a node for each PSC in uart mode w/ device_type = "serial"
- * and "mpc52xx-psc-uart" in the compatible string
+ * tree will have a node for each PSC with "mpc52xx-psc-uart" in the compatible
+ * list.
  *
  * By default, PSC devices are enumerated in the order they are found.  However
  * a particular PSC number can be forces by adding 'device_no = <port#>'
@@ -522,7 +522,7 @@
 
 	/* Request IRQ */
 	ret = request_irq(port->irq, mpc52xx_uart_int,
-		IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED,
+		IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 		"mpc52xx_psc_uart", port);
 	if (ret)
 		return ret;
@@ -1212,30 +1212,18 @@
 #endif
 
 static void
-mpc52xx_uart_of_assign(struct device_node *np, int idx)
+mpc52xx_uart_of_assign(struct device_node *np)
 {
-	int free_idx = -1;
 	int i;
 
-	/* Find the first free node */
+	/* Find the first free PSC number */
 	for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) {
 		if (mpc52xx_uart_nodes[i] == NULL) {
-			free_idx = i;
-			break;
+			of_node_get(np);
+			mpc52xx_uart_nodes[i] = np;
+			return;
 		}
 	}
-
-	if ((idx < 0) || (idx >= MPC52xx_PSC_MAXNUM))
-		idx = free_idx;
-
-	if (idx < 0)
-		return; /* No free slot; abort */
-
-	of_node_get(np);
-	/* If the slot is already occupied, then swap slots */
-	if (mpc52xx_uart_nodes[idx] && (free_idx != -1))
-		mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx];
-	mpc52xx_uart_nodes[idx] = np;
 }
 
 static void
@@ -1243,23 +1231,17 @@
 {
 	static int enum_done;
 	struct device_node *np;
-	const unsigned int *devno;
 	const struct  of_device_id *match;
 	int i;
 
 	if (enum_done)
 		return;
 
-	for_each_node_by_type(np, "serial") {
+	/* Assign index to each PSC in device tree */
+	for_each_matching_node(np, mpc52xx_uart_of_match) {
 		match = of_match_node(mpc52xx_uart_of_match, np);
-		if (!match)
-			continue;
-
 		psc_ops = match->data;
-
-		/* Is a particular device number requested? */
-		devno = of_get_property(np, "port-number", NULL);
-		mpc52xx_uart_of_assign(np, devno ? *devno : -1);
+		mpc52xx_uart_of_assign(np);
 	}
 
 	enum_done = 1;
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index f6e3b86..a48a8a1 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -43,13 +43,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/clk.h>
-
-#include <asm/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/pxa-regs.h>
-#include <mach/regs-uart.h>
-
+#include <linux/io.h>
 
 struct uart_pxa_port {
 	struct uart_port        port;
@@ -491,7 +485,7 @@
 	 * Ensure the port will be enabled.
 	 * This is required especially for serial console.
 	 */
-	up->ier |= IER_UUE;
+	up->ier |= UART_IER_UUE;
 
 	/*
 	 * Update the per-port timeout.
@@ -784,19 +778,15 @@
 	sport->port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 	sport->port.uartclk = clk_get_rate(sport->clk);
 
-	/*
-	 * Is it worth keeping this?
-	 */
-	if (mmres->start == __PREG(FFUART))
-		sport->name = "FFUART";
-	else if (mmres->start == __PREG(BTUART))
-		sport->name = "BTUART";
-	else if (mmres->start == __PREG(STUART))
-		sport->name = "STUART";
-	else if (mmres->start == __PREG(HWUART))
-		sport->name = "HWUART";
-	else
+	switch (dev->id) {
+	case 0: sport->name = "FFUART"; break;
+	case 1: sport->name = "BTUART"; break;
+	case 2: sport->name = "STUART"; break;
+	case 3: sport->name = "HWUART"; break;
+	default:
 		sport->name = "???";
+		break;
+	}
 
 	sport->port.membase = ioremap(mmres->start, mmres->end - mmres->start + 1);
 	if (!sport->port.membase) {
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index b24a25e..94530f0 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -36,8 +36,8 @@
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
 #include <asm/mach/serial_sa1100.h>
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index cab1ab7..93c20e1 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -776,7 +776,7 @@
 		.bus = &maple_bus_type,
 	},
 };
-/**
+/*
  * maple_bus_type - core maple bus structure
  */
 struct bus_type maple_bus_type = {
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 1c65e38..d6d0c5d 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -1021,13 +1021,13 @@
 	spin_lock_init(&mcspi->lock);
 	INIT_LIST_HEAD(&mcspi->msg_queue);
 
-	mcspi->ick = clk_get(&pdev->dev, "mcspi_ick");
+	mcspi->ick = clk_get(&pdev->dev, "ick");
 	if (IS_ERR(mcspi->ick)) {
 		dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
 		status = PTR_ERR(mcspi->ick);
 		goto err1a;
 	}
-	mcspi->fck = clk_get(&pdev->dev, "mcspi_fck");
+	mcspi->fck = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(mcspi->fck)) {
 		dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
 		status = PTR_ERR(mcspi->fck);
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
index 60b5381..fe8b9ac 100644
--- a/drivers/spi/omap_uwire.c
+++ b/drivers/spi/omap_uwire.c
@@ -506,11 +506,12 @@
 
 	dev_set_drvdata(&pdev->dev, uwire);
 
-	uwire->ck = clk_get(&pdev->dev, "armxor_ck");
-	if (!uwire->ck || IS_ERR(uwire->ck)) {
-		dev_dbg(&pdev->dev, "no mpu_xor_clk ?\n");
+	uwire->ck = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(uwire->ck)) {
+		status = PTR_ERR(uwire->ck);
+		dev_dbg(&pdev->dev, "no functional clock?\n");
 		spi_master_put(master);
-		return -ENODEV;
+		return status;
 	}
 	clk_enable(uwire->ck);
 
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index ec24f2d..33fcef3 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -34,8 +34,6 @@
 #include <asm/delay.h>
 
 #include <mach/dma.h>
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/regs-ssp.h>
 #include <mach/ssp.h>
 #include <mach/pxa2xx_spi.h>
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index fe7e5f3..494d3f7 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -354,7 +354,7 @@
 	if (xspi->regs == NULL) {
 		rc = -ENOMEM;
 		dev_warn(&ofdev->dev, "ioremap failure\n");
-		goto put_master;
+		goto release_mem;
 	}
 	xspi->irq = r_irq->start;
 
@@ -365,7 +365,7 @@
 	prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
 	if (!prop || len < sizeof(*prop)) {
 		dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
-		goto put_master;
+		goto unmap_io;
 	}
 	master->num_chipselect = *prop;
 
@@ -397,6 +397,8 @@
 	free_irq(xspi->irq, xspi);
 unmap_io:
 	iounmap(xspi->regs);
+release_mem:
+	release_mem_region(r_mem->start, resource_size(r_mem));
 put_master:
 	spi_master_put(master);
 	return rc;
@@ -406,6 +408,7 @@
 {
 	struct xilinx_spi *xspi;
 	struct spi_master *master;
+	struct resource r_mem;
 
 	master = platform_get_drvdata(ofdev);
 	xspi = spi_master_get_devdata(master);
@@ -413,6 +416,8 @@
 	spi_bitbang_stop(&xspi->bitbang);
 	free_irq(xspi->irq, xspi);
 	iounmap(xspi->regs);
+	if (!of_address_to_resource(ofdev->node, 0, &r_mem))
+		release_mem_region(r_mem.start, resource_size(&r_mem));
 	dev_set_drvdata(&ofdev->dev, 0);
 	spi_master_put(xspi->bitbang.master);
 
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index fb3055f..7cf74f8 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -28,8 +28,6 @@
 #include <linux/signal.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
-
 static struct clk *usb_host_clock;
 
 static void ep93xx_start_hc(struct device *dev)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index fb19803..41c27a4 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -397,7 +397,7 @@
 
 config FB_IMX
 	tristate "Motorola i.MX LCD support"
-	depends on FB && ARM && ARCH_IMX
+	depends on FB && (ARCH_IMX || ARCH_MX2)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -2120,16 +2120,30 @@
 	  the bootloader.
 
 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.
+	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.
 
 source "drivers/video/omap/Kconfig"
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 2a998ca..bb265ec 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -106,6 +106,7 @@
 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_S1D13XXX)	  += s1d13xxxfb.o
 obj-$(CONFIG_FB_SH7760)		  += sh7760fb.o
 obj-$(CONFIG_FB_IMX)              += imxfb.o
@@ -132,7 +133,7 @@
 obj-$(CONFIG_FB_OF)               += offb.o
 obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
 obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
-obj-$(CONFIG_FB_MX3)              += mx3fb.o
+obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 61c3d3f..6995fe1 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -28,9 +28,9 @@
 #include <linux/fb.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
new file mode 100644
index 0000000..509cb92
--- /dev/null
+++ b/drivers/video/broadsheetfb.c
@@ -0,0 +1,568 @@
+/*
+ * 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/uaccess.h>
+
+#include <video/broadsheetfb.h>
+
+/* Display specific information */
+#define DPY_W 800
+#define DPY_H 600
+
+static struct fb_fix_screeninfo broadsheetfb_fix __devinitdata = {
+	.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 __devinitdata = {
+	.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_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_issue_cmd(struct broadsheetfb_par *par, u16 data)
+{
+	par->board->set_ctl(par, BS_DC, 0);
+	broadsheet_issue_data(par, data);
+}
+
+static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
+{
+	par->board->wait_for_rdy(par);
+
+	par->board->set_ctl(par, BS_CS, 0);
+	broadsheet_issue_cmd(par, data);
+	par->board->set_ctl(par, BS_DC, 1);
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_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_issue_cmd(par, cmd);
+	par->board->set_ctl(par, BS_DC, 1);
+
+	for (i = 0; i < argc; i++)
+		broadsheet_issue_data(par, argv[i]);
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static void broadsheet_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 u16 broadsheet_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 void broadsheet_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_issue_cmd(par, BS_CMD_WR_REG);
+
+	par->board->set_ctl(par, BS_DC, 1);
+
+	broadsheet_issue_data(par, reg);
+	broadsheet_issue_data(par, data);
+
+	par->board->set_ctl(par, BS_CS, 1);
+}
+
+static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
+{
+	broadsheet_send_command(par, reg);
+	msleep(100);
+	return broadsheet_get_data(par);
+}
+
+static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
+{
+	u16 args[5];
+
+	args[0] = DPY_W;
+	args[1] = DPY_H;
+	args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */
+	args[3] = 2; /* gdrv cfg */
+	args[4] = (4 | (1 << 7)); /* lut index format */
+	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] = 4; /* fsync len */
+	args[1] = (10 << 8) | 4; /* fend/fbegin len */
+	args[2] = 10; /* line sync len */
+	args[3] = (100 << 8) | 4; /* line end/begin len */
+	args[4] = 6; /* pixel clock cfg */
+	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
+
+	/* 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, DPY_W*DPY_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 __devinit 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;
+
+	/* 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);
+
+}
+
+static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
+{
+	u16 args[5];
+
+	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, DPY_W*DPY_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);
+
+}
+
+/* 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 __devinit 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;
+
+	/* 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;
+
+	videomemorysize = (DPY_W*DPY_H);
+	videomemory = vmalloc(videomemorysize);
+	if (!videomemory)
+		goto err_fb_rel;
+
+	memset(videomemory, 0, videomemorysize);
+
+	info->screen_base = (char *)videomemory;
+	info->fbops = &broadsheetfb_ops;
+
+	info->var = broadsheetfb_var;
+	info->fix = broadsheetfb_fix;
+	info->fix.smem_len = videomemorysize;
+	par = info->par;
+	par->info = info;
+	par->board = board;
+	par->write_reg = broadsheet_write_reg;
+	par->read_reg = broadsheet_read_reg;
+	init_waitqueue_head(&par->waitq);
+
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	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_init(par);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_free_irq;
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
+	       info->node, videomemorysize >> 10);
+
+
+	return 0;
+
+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 __devexit broadsheetfb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		struct broadsheetfb_par *par = info->par;
+		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",
+	},
+};
+
+static int __init broadsheetfb_init(void)
+{
+	return platform_driver_register(&broadsheetfb_driver);
+}
+
+static void __exit broadsheetfb_exit(void)
+{
+	platform_driver_unregister(&broadsheetfb_driver);
+}
+
+module_init(broadsheetfb_init);
+module_exit(broadsheetfb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 7a9e42e..83c5cef 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -46,8 +46,8 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
@@ -1425,7 +1425,7 @@
 
 #ifdef CONFIG_ARCH_SHARK
 
-#include <mach/hardware.h>
+#include <mach/framebuffer.h>
 
 static int __devinit cyberpro_vl_probe(void)
 {
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index d58c68c..15a0ee6 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -14,7 +14,6 @@
  *	linux-arm-kernel@lists.arm.linux.org.uk
  */
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -27,9 +26,11 @@
 #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 <mach/imxfb.h>
 
@@ -44,7 +45,12 @@
 
 #define LCDC_SIZE	0x04
 #define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
+
+#ifdef CONFIG_ARCH_MX1
 #define SIZE_YMAX(y)	((y) & 0x1ff)
+#else
+#define SIZE_YMAX(y)	((y) & 0x3ff)
+#endif
 
 #define LCDC_VPW	0x08
 #define VPW_VPW(x)	((x) & 0x3ff)
@@ -54,7 +60,12 @@
 #define CPOS_CC0	(1<<30)
 #define CPOS_OP		(1<<28)
 #define CPOS_CXP(x)	(((x) & 3ff) << 16)
+
+#ifdef CONFIG_ARCH_MX1
 #define CPOS_CYP(y)	((y) & 0x1ff)
+#else
+#define CPOS_CYP(y)	((y) & 0x3ff)
+#endif
 
 #define LCDC_LCWHB	0x10
 #define LCWHB_BK_EN	(1<<31)
@@ -63,9 +74,16 @@
 #define LCWHB_BD(x)	((x) & 0xff)
 
 #define LCDC_LCHCC	0x14
+
+#ifdef CONFIG_ARCH_MX1
 #define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
 #define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
 #define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
+#else
+#define LCHCC_CUR_COL_R(r) (((r) & 0x3f) << 12)
+#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 6)
+#define LCHCC_CUR_COL_B(b) ((b) & 0x3f)
+#endif
 
 #define LCDC_PCR	0x18
 
@@ -92,7 +110,13 @@
 /* bit fields in imxfb.h */
 
 #define LCDC_RMCR	0x34
+
+#ifdef CONFIG_ARCH_MX1
 #define RMCR_LCDC_EN	(1<<1)
+#else
+#define RMCR_LCDC_EN	0
+#endif
+
 #define RMCR_SELF_REF	(1<<0)
 
 #define LCDC_LCDICR	0x38
@@ -119,6 +143,7 @@
 struct imxfb_info {
 	struct platform_device  *pdev;
 	void __iomem		*regs;
+	struct clk		*clk;
 
 	u_int			max_bpp;
 	u_int			max_xres;
@@ -159,6 +184,17 @@
 #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,},
@@ -286,9 +322,12 @@
 
 	pr_debug("var->bits_per_pixel=%d\n", var->bits_per_pixel);
 	switch (var->bits_per_pixel) {
+	case 32:
+		rgb = &def_rgb_18;
+		break;
 	case 16:
 	default:
-		if (readl(fbi->regs + LCDC_PCR) & PCR_TFT)
+		if (fbi->pcr & PCR_TFT)
 			rgb = &def_rgb_16_tft;
 		else
 			rgb = &def_rgb_16_stn;
@@ -327,9 +366,7 @@
 	struct imxfb_info *fbi = info->par;
 	struct fb_var_screeninfo *var = &info->var;
 
-	pr_debug("set_par\n");
-
-	if (var->bits_per_pixel == 16)
+	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;
@@ -354,10 +391,6 @@
 {
 	pr_debug("Enabling LCD controller\n");
 
-	/* initialize LCDC */
-	writel(readl(fbi->regs + LCDC_RMCR) & ~RMCR_LCDC_EN,
-		fbi->regs + LCDC_RMCR);	/* just to be safe... */
-
 	writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
 
 	/* physical screen start address	    */
@@ -373,6 +406,8 @@
 
 	writel(RMCR_LCDC_EN, fbi->regs + LCDC_RMCR);
 
+	clk_enable(fbi->clk);
+
 	if (fbi->backlight_power)
 		fbi->backlight_power(1);
 	if (fbi->lcd_power)
@@ -388,6 +423,8 @@
 	if (fbi->lcd_power)
 		fbi->lcd_power(0);
 
+	clk_disable(fbi->clk);
+
 	writel(0, fbi->regs + LCDC_RMCR);
 }
 
@@ -431,6 +468,9 @@
 static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct imxfb_info *fbi = info->par;
+	unsigned int pcr, lcd_clk;
+	unsigned long long tmp;
+
 	pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
 		var->xres, var->hsync_len,
 		var->left_margin, var->right_margin);
@@ -465,9 +505,9 @@
 			info->fix.id, var->lower_margin);
 #endif
 
-	writel(HCR_H_WIDTH(var->hsync_len) |
-		HCR_H_WAIT_1(var->right_margin) |
-		HCR_H_WAIT_2(var->left_margin),
+	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) |
@@ -477,7 +517,23 @@
 
 	writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
 			fbi->regs + LCDC_SIZE);
-	writel(fbi->pcr, fbi->regs + LCDC_PCR);
+
+	lcd_clk = clk_get_rate(fbi->clk);
+	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 %uHz\n",
+				lcd_clk / pcr);
+	}
+
+	/* add sync polarities */
+	pcr |= fbi->pcr & ~0x3F;
+
+	writel(pcr, fbi->regs + LCDC_PCR);
 	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
 	writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
 	writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
@@ -619,6 +675,13 @@
 		goto failed_req;
 	}
 
+	fbi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(fbi->clk)) {
+		ret = PTR_ERR(fbi->clk);;
+		dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
+		goto failed_getclock;
+	}
+
 	fbi->regs = ioremap(res->start, resource_size(res));
 	if (fbi->regs == NULL) {
 		printk(KERN_ERR"Cannot map frame buffer registers\n");
@@ -650,6 +713,12 @@
 		info->fix.smem_start = fbi->screen_dma;
 	}
 
+	if (pdata->init) {
+		ret = pdata->init(fbi->pdev);
+		if (ret)
+			goto failed_platform_init;
+	}
+
 	/*
 	 * This makes sure that our colour bitfield
 	 * descriptors are correctly initialised.
@@ -674,10 +743,15 @@
 failed_register:
 	fb_dealloc_cmap(&info->cmap);
 failed_cmap:
+	if (pdata->exit)
+		pdata->exit(fbi->pdev);
+failed_platform_init:
 	if (!pdata->fixed_screen_cpu)
 		dma_free_writecombine(&pdev->dev,fbi->map_size,fbi->map_cpu,
 			fbi->map_dma);
 failed_map:
+	clk_put(fbi->clk);
+failed_getclock:
 	iounmap(fbi->regs);
 failed_ioremap:
 	release_mem_region(res->start, res->end - res->start);
@@ -691,6 +765,7 @@
 
 static int __devexit 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;
@@ -701,12 +776,19 @@
 
 	unregister_framebuffer(info);
 
+	pdata = pdev->dev.platform_data;
+	if (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, res->end - res->start + 1);
+	clk_disable(fbi->clk);
+	clk_put(fbi->clk);
+
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 8a75d05..fa1a512 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -34,240 +34,240 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#define MX3FB_NAME             "mx3_sdc_fb"
+#define MX3FB_NAME		"mx3_sdc_fb"
 
-#define MX3FB_REG_OFFSET       0xB4
+#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)
+#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_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
+#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)
+#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
+#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
+#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,
+	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;
+	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,
-       },
+	{
+		/* 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;
+	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;
+	uint32_t		h_start_width;
+	uint32_t		v_start_width;
 };
 
 struct dma_chan_request {
-       struct mx3fb_data       *mx3fb;
-       enum ipu_channel        id;
+	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;
+	int				blank;
+	enum ipu_channel		ipu_ch;
+	uint32_t			cur_ipu_buf;
 
-       u32                             pseudo_palette[16];
+	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 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];
 
-       u32                             sync;   /* preserve var->sync flags */
+	u32				sync;	/* preserve var->sync flags */
 };
 
 static void mx3fb_dma_done(void *);
@@ -278,389 +278,389 @@
 
 static u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg)
 {
-       return __raw_readl(mx3fb->reg_base + 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);
+	__raw_writel(value, mx3fb->reg_base + reg);
 }
 
 static const uint32_t di_mappings[] = {
-       0x1600AAAA, 0x00E05555, 0x00070000, 3,  /* RGB888 */
-       0x0005000F, 0x000B000F, 0x0011000F, 1,  /* RGB666 */
-       0x0011000F, 0x000B000F, 0x0005000F, 1,  /* BGR666 */
-       0x0004003F, 0x000A000F, 0x000F003F, 1   /* RGB565 */
+	0x1600AAAA, 0x00E05555, 0x00070000, 3,	/* RGB888 */
+	0x0005000F, 0x000B000F, 0x0011000F, 1,	/* RGB666 */
+	0x0011000F, 0x000B000F, 0x0005000F, 1,	/* BGR666 */
+	0x0004003F, 0x000A000F, 0x000F003F, 1	/* RGB565 */
 };
 
 static void sdc_fb_init(struct mx3fb_info *fbi)
 {
-       struct mx3fb_data *mx3fb = fbi->mx3fb;
-       uint32_t reg;
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	uint32_t reg;
 
-       reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
 
-       mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, 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;
+	struct mx3fb_data *mx3fb = fbi->mx3fb;
+	uint32_t reg;
 
-       reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
+	reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF);
 
-       mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF);
+	mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF);
 
-       return reg & SDC_COM_BG_EN;
+	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;
+	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;
 
-       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);
+	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);
 
-       /* This enables the channel */
-       if (mx3_fbi->cookie < 0) {
-               mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
-                     &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
-               if (!mx3_fbi->txd) {
-                       dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n",
-                               dma_chan->chan_id);
-                       return;
-               }
+	/* This enables the channel */
+	if (mx3_fbi->cookie < 0) {
+		mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan,
+		      &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, 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;
+		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;
-               }
+		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) ? '-' : '+');
-       }
+		/* 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);
-       }
+	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);
+	/*
+	 * 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;
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	uint32_t enabled;
+	unsigned long flags;
 
-       spin_lock_irqsave(&mx3fb->lock, flags);
+	spin_lock_irqsave(&mx3fb->lock, flags);
 
-       enabled = sdc_fb_uninit(mx3_fbi);
+	enabled = sdc_fb_uninit(mx3_fbi);
 
-       spin_unlock_irqrestore(&mx3fb->lock, flags);
+	spin_unlock_irqrestore(&mx3fb->lock, flags);
 
-       mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan);
-       mx3_fbi->txd = NULL;
-       mx3_fbi->cookie = -EINVAL;
+	mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan);
+	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.
+ * @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)
+			      int16_t x_pos, int16_t y_pos)
 {
-       x_pos += mx3fb->h_start_width;
-       y_pos += mx3fb->v_start_width;
+	x_pos += mx3fb->h_start_width;
+	y_pos += mx3fb->v_start_width;
 
-       if (channel != IDMAC_SDC_0)
-               return -EINVAL;
+	if (channel != IDMAC_SDC_0)
+		return -EINVAL;
 
-       mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS);
-       return 0;
+	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.
- * @pixel_fmt:         pixel format of buffer as FOURCC ASCII code.
- * @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.
+ * @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.
+ * @pixel_fmt:		pixel format of buffer as FOURCC ASCII code.
+ * @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,
-                         enum pixel_fmt pixel_fmt,
-                         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)
+			  uint32_t pixel_clk,
+			  uint16_t width, uint16_t height,
+			  enum pixel_fmt pixel_fmt,
+			  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;
+	unsigned long lock_flags;
+	uint32_t reg;
+	uint32_t old_conf;
+	uint32_t div;
+	struct clk *ipu_clk;
 
-       dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
+	dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height);
 
-       if (v_sync_width == 0 || h_sync_width == 0)
-               return -EINVAL;
+	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);
+	/* 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);
+	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);
+	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);
+	printk(KERN_CONT " ver_conf %x\n", reg);
 #endif
 
-       mx3fb->h_start_width = h_start_width;
-       mx3fb->v_start_width = v_start_width;
+	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;
-       }
+	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 */
+	/* Init clocking */
 
-       /*
-        * Calculate divider: fractional part is 4 bits so simply multiple by
-        * 24 to get fractional part, as long as we stay under ~250MHz and on
-        * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz
-        */
-       dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk);
+	/*
+	 * 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
+	 */
+	dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk);
 
-       ipu_clk = clk_get(mx3fb->dev, "ipu_clk");
-       div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
-       clk_put(ipu_clk);
+	ipu_clk = clk_get(mx3fb->dev, NULL);
+	div = clk_get_rate(ipu_clk) * 16 / pixel_clk;
+	clk_put(ipu_clk);
 
-       if (div < 0x40) {       /* Divider less than 4 */
-               dev_dbg(mx3fb->dev,
-                       "InitPanel() - Pixel clock divider less than 4\n");
-               div = 0x40;
-       }
+	if (div < 0x40) {	/* Divider less than 4 */
+		dev_dbg(mx3fb->dev,
+			"InitPanel() - Pixel clock divider less than 4\n");
+		div = 0x40;
+	}
 
-       spin_lock_irqsave(&mx3fb->lock, lock_flags);
+	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);
+	/*
+	 * 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);
+	/* 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);
+	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);
 
-       switch (pixel_fmt) {
-       case IPU_PIX_FMT_RGB24:
-               mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       case IPU_PIX_FMT_RGB666:
-               mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       case IPU_PIX_FMT_BGR666:
-               mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       default:
-               mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
-               mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
-               mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
-                            ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
-               break;
-       }
+	switch (pixel_fmt) {
+	case IPU_PIX_FMT_RGB24:
+		mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP);
+		mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
+			     ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
+		break;
+	case IPU_PIX_FMT_RGB666:
+		mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP);
+		mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
+			     ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
+		break;
+	case IPU_PIX_FMT_BGR666:
+		mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP);
+		mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
+			     ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
+		break;
+	default:
+		mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP);
+		mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP);
+		mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) |
+			     ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
+		break;
+	}
 
-       spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
+	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));
+	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;
+	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.
+ * @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)
+			     bool enable, uint32_t color_key)
 {
-       uint32_t reg, sdc_conf;
-       unsigned long lock_flags;
+	uint32_t reg, sdc_conf;
+	unsigned long lock_flags;
 
-       spin_lock_irqsave(&mx3fb->lock, 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;
+	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);
+	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);
+		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);
+	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
 
-       return 0;
+	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.
+ * @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;
+	uint32_t reg;
+	unsigned long lock_flags;
 
-       spin_lock_irqsave(&mx3fb->lock, 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);
+	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);
-       }
+		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);
+	spin_unlock_irqrestore(&mx3fb->lock, lock_flags);
 
-       return 0;
+	return 0;
 }
 
 static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
 {
-       /* This might be board-specific */
-       mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
-       return;
+	/* 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;
+	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);
@@ -669,300 +669,300 @@
 
 /**
  * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings.
- * @info:      framebuffer information pointer
- * @return:    0 on success or negative error code on failure.
+ * @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;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
 
-       strncpy(fix->id, "DISP3 BG", 8);
+	strncpy(fix->id, "DISP3 BG", 8);
 
-       fix->line_length = var->xres_virtual * var->bits_per_pixel / 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;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->accel = FB_ACCEL_NONE;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
 
-       return 0;
+	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;
+	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);
+	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(ichannel->eof_irq);
+	/* We only need one interrupt, it will be re-enabled as needed */
+	disable_irq(ichannel->eof_irq);
 
-       complete(&mx3_fbi->flip_cmpl);
+	complete(&mx3_fbi->flip_cmpl);
 }
 
 /**
  * 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.
+ * @fbi:	framebuffer information pointer.
+ * @return:	0 on success or negative error code on failure.
  */
 static int mx3fb_set_par(struct fb_info *fbi)
 {
-       u32 mem_len;
-       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;
-       size_t screen_size;
+	u32 mem_len;
+	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;
+	size_t screen_size;
 
-       dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
+	dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
 
-       mutex_lock(&mx3_fbi->mutex);
+	mutex_lock(&mx3_fbi->mutex);
 
-       /* Total cleanup */
-       if (mx3_fbi->txd)
-               sdc_disable_channel(mx3_fbi);
+	/* Total cleanup */
+	if (mx3_fbi->txd)
+		sdc_disable_channel(mx3_fbi);
 
-       mx3fb_set_fix(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);
+	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);
 
-               fbi->fix.smem_len = mem_len;
-               if (mx3fb_map_video_memory(fbi) < 0) {
-                       mutex_unlock(&mx3_fbi->mutex);
-                       return -ENOMEM;
-               }
-       }
+		fbi->fix.smem_len = mem_len;
+		if (mx3fb_map_video_memory(fbi) < 0) {
+			mutex_unlock(&mx3_fbi->mutex);
+			return -ENOMEM;
+		}
+	}
 
-       screen_size = fbi->fix.line_length * fbi->var.yres;
+	screen_size = fbi->fix.line_length * fbi->var.yres;
 
-       sg_init_table(&sg[0], 1);
-       sg_init_table(&sg[1], 1);
+	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));
+	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;
+	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));
+		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.sync & FB_SYNC_SWAP_RGB) ?
-                                  IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
-                                  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) {
-                       mutex_unlock(&mx3_fbi->mutex);
-                       dev_err(fbi->device,
-                               "mx3fb: Error initializing panel.\n");
-                       return -EINVAL;
-               }
-       }
+		if (sdc_init_panel(mx3fb, mode,
+				   (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,
+				   fbi->var.xres, fbi->var.yres,
+				   (fbi->var.sync & FB_SYNC_SWAP_RGB) ?
+				   IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,
+				   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) {
+			mutex_unlock(&mx3_fbi->mutex);
+			dev_err(fbi->device,
+				"mx3fb: Error initializing panel.\n");
+			return -EINVAL;
+		}
+	}
 
-       sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);
+	sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);
 
-       mx3_fbi->cur_ipu_buf    = 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;
+	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);
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK)
+		sdc_enable_channel(mx3_fbi);
 
-       mutex_unlock(&mx3_fbi->mutex);
+	mutex_unlock(&mx3_fbi->mutex);
 
-       return 0;
+	return 0;
 }
 
 /**
  * mx3fb_check_var() - check and adjust framebuffer variable parameters.
- * @var:       framebuffer variable parameters
- * @fbi:       framebuffer information pointer
+ * @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;
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	u32 vtotal;
+	u32 htotal;
 
-       dev_dbg(fbi->device, "%s\n", __func__);
+	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->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;
+	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;
+	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->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->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->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->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->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->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->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->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->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);
-       }
+	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;
+	var->height = -1;
+	var->width = -1;
+	var->grayscale = 0;
 
-       /* Preserve sync flags */
-       var->sync |= mx3_fbi->sync;
-       mx3_fbi->sync |= var->sync;
+	/* Preserve sync flags */
+	var->sync |= mx3_fbi->sync;
+	mx3_fbi->sync |= var->sync;
 
-       return 0;
+	return 0;
 }
 
 static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf)
 {
-       chan &= 0xffff;
-       chan >>= 16 - bf->length;
-       return chan << bf->offset;
+	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)
+			   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;
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	u32 val;
+	int ret = 1;
 
-       dev_dbg(fbi->device, "%s\n", __func__);
+	dev_dbg(fbi->device, "%s\n", __func__);
 
-       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;
+	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);
+			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;
+			pal[regno] = val;
 
-                       ret = 0;
-               }
-               break;
+			ret = 0;
+		}
+		break;
 
-       case FB_VISUAL_STATIC_PSEUDOCOLOR:
-       case FB_VISUAL_PSEUDOCOLOR:
-               break;
-       }
-       mutex_unlock(&mx3_fbi->mutex);
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+	mutex_unlock(&mx3_fbi->mutex);
 
-       return ret;
+	return ret;
 }
 
 /**
@@ -970,152 +970,152 @@
  */
 static int mx3fb_blank(int blank, struct fb_info *fbi)
 {
-       struct mx3fb_info *mx3_fbi = fbi->par;
-       struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+	struct mx3fb_info *mx3_fbi = fbi->par;
+	struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
 
-       dev_dbg(fbi->device, "%s\n", __func__);
+	dev_dbg(fbi->device, "%s\n", __func__);
 
-       dev_dbg(fbi->device, "blank = %d\n", blank);
+	dev_dbg(fbi->device, "blank = %d\n", blank);
 
-       if (mx3_fbi->blank == blank)
-               return 0;
+	if (mx3_fbi->blank == blank)
+		return 0;
 
-       mutex_lock(&mx3_fbi->mutex);
-       mx3_fbi->blank = blank;
+	mutex_lock(&mx3_fbi->mutex);
+	mx3_fbi->blank = blank;
 
-       switch (blank) {
-       case FB_BLANK_POWERDOWN:
-       case FB_BLANK_VSYNC_SUSPEND:
-       case FB_BLANK_HSYNC_SUSPEND:
-       case FB_BLANK_NORMAL:
-               sdc_disable_channel(mx3_fbi);
-               sdc_set_brightness(mx3fb, 0);
-               break;
-       case FB_BLANK_UNBLANK:
-               sdc_enable_channel(mx3_fbi);
-               sdc_set_brightness(mx3fb, mx3fb->backlight_level);
-               break;
-       }
-       mutex_unlock(&mx3_fbi->mutex);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		sdc_disable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, 0);
+		break;
+	case FB_BLANK_UNBLANK:
+		sdc_enable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
+		break;
+	}
+	mutex_unlock(&mx3_fbi->mutex);
 
-       return 0;
+	return 0;
 }
 
 /**
  * mx3fb_pan_display() - pan or wrap the display
- * @var:       variable screen buffer information.
- * @info:      framebuffer information pointer.
+ * @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 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;
+	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) ? '-' : '+');
+	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 (var->xoffset > 0) {
+		dev_dbg(fbi->device, "x panning not supported\n");
+		return -EINVAL;
+	}
 
-       if (fbi->var.xoffset == var->xoffset &&
-           fbi->var.yoffset == var->yoffset)
-               return 0;       /* No change, do nothing */
+	if (fbi->var.xoffset == var->xoffset &&
+	    fbi->var.yoffset == var->yoffset)
+		return 0;	/* No change, do nothing */
 
-       y_bottom = var->yoffset;
+	y_bottom = var->yoffset;
 
-       if (!(var->vmode & FB_VMODE_YWRAP))
-               y_bottom += var->yres;
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += var->yres;
 
-       if (y_bottom > fbi->var.yres_virtual)
-               return -EINVAL;
+	if (y_bottom > fbi->var.yres_virtual)
+		return -EINVAL;
 
-       mutex_lock(&mx3_fbi->mutex);
+	mutex_lock(&mx3_fbi->mutex);
 
-       offset = (var->yoffset * var->xres_virtual + var->xoffset) *
-               (var->bits_per_pixel / 8);
-       base = fbi->fix.smem_start + offset;
+	offset = (var->yoffset * var->xres_virtual + var->xoffset) *
+		(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);
+	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);
+	/*
+	 * 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");
-               return ret ? : -ETIMEDOUT;
-       }
+	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");
+		return ret ? : -ETIMEDOUT;
+	}
 
-       mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf;
+	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));
+	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));
 
-       txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
-               mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
-       if (!txd) {
-               dev_err(fbi->device,
-                       "Error preparing a DMA transaction descriptor.\n");
-               mutex_unlock(&mx3_fbi->mutex);
-               return -EIO;
-       }
+	txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +
+		mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, 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;
+	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;
-       }
+	/*
+	 * 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;
+	}
 
-       if (mx3_fbi->txd)
-               async_tx_ack(mx3_fbi->txd);
-       mx3_fbi->txd = txd;
+	if (mx3_fbi->txd)
+		async_tx_ack(mx3_fbi->txd);
+	mx3_fbi->txd = txd;
 
-       fbi->var.xoffset = var->xoffset;
-       fbi->var.yoffset = var->yoffset;
+	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;
+	if (var->vmode & FB_VMODE_YWRAP)
+		fbi->var.vmode |= FB_VMODE_YWRAP;
+	else
+		fbi->var.vmode &= ~FB_VMODE_YWRAP;
 
-       mutex_unlock(&mx3_fbi->mutex);
+	mutex_unlock(&mx3_fbi->mutex);
 
-       dev_dbg(fbi->device, "Update complete\n");
+	dev_dbg(fbi->device, "Update complete\n");
 
-       return 0;
+	return 0;
 }
 
 /*
@@ -1124,15 +1124,15 @@
  * 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,
+	.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
@@ -1146,19 +1146,19 @@
  */
 static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
-       struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+	struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
+	struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
 
-       acquire_console_sem();
-       fb_set_suspend(drv_data->fbi, 1);
-       release_console_sem();
+	acquire_console_sem();
+	fb_set_suspend(drv_data->fbi, 1);
+	release_console_sem();
 
-       if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
-               sdc_disable_channel(mx3_fbi);
-               sdc_set_brightness(mx3fb, 0);
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
+		sdc_disable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, 0);
 
-       }
-       return 0;
+	}
+	return 0;
 }
 
 /*
@@ -1166,19 +1166,19 @@
  */
 static int mx3fb_resume(struct platform_device *pdev)
 {
-       struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
-       struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+	struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
+	struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
 
-       if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
-               sdc_enable_channel(mx3_fbi);
-               sdc_set_brightness(mx3fb, drv_data->backlight_level);
-       }
+	if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
+		sdc_enable_channel(mx3_fbi);
+		sdc_set_brightness(mx3fb, drv_data->backlight_level);
+	}
 
-       acquire_console_sem();
-       fb_set_suspend(drv_data->fbi, 0);
-       release_console_sem();
+	acquire_console_sem();
+	fb_set_suspend(drv_data->fbi, 0);
+	release_console_sem();
 
-       return 0;
+	return 0;
 }
 #else
 #define mx3fb_suspend   NULL
@@ -1191,8 +1191,8 @@
 
 /**
  * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
- * @fbi:       framebuffer information pointer
- * @return:    Error code indicating success or failure
+ * @fbi:	framebuffer information pointer
+ * @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
@@ -1201,349 +1201,349 @@
  */
 static int mx3fb_map_video_memory(struct fb_info *fbi)
 {
-       int retval = 0;
-       dma_addr_t addr;
+	int retval = 0;
+	dma_addr_t addr;
 
-       fbi->screen_base = dma_alloc_writecombine(fbi->device,
-                                                 fbi->fix.smem_len,
-                                                 &addr, GFP_DMA);
+	fbi->screen_base = dma_alloc_writecombine(fbi->device,
+						  fbi->fix.smem_len,
+						  &addr, GFP_DMA);
 
-       if (!fbi->screen_base) {
-               dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
-                       fbi->fix.smem_len);
-               retval = -EBUSY;
-               goto err0;
-       }
+	if (!fbi->screen_base) {
+		dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
+			fbi->fix.smem_len);
+		retval = -EBUSY;
+		goto err0;
+	}
 
-       fbi->fix.smem_start = addr;
+	fbi->fix.smem_start = addr;
 
-       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);
+	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;
+	fbi->screen_size = fbi->fix.smem_len;
 
-       /* Clear the screen */
-       memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
+	/* Clear the screen */
+	memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
 
-       return 0;
+	return 0;
 
 err0:
-       fbi->fix.smem_len = 0;
-       fbi->fix.smem_start = 0;
-       fbi->screen_base = NULL;
-       return retval;
+	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
+ * @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);
+	dma_free_writecombine(fbi->device, fbi->fix.smem_len,
+			      fbi->screen_base, fbi->fix.smem_start);
 
-       fbi->screen_base = 0;
-       fbi->fix.smem_start = 0;
-       fbi->fix.smem_len = 0;
-       return 0;
+	fbi->screen_base = 0;
+	fbi->fix.smem_start = 0;
+	fbi->fix.smem_len = 0;
+	return 0;
 }
 
 /**
  * mx3fb_init_fbinfo() - initialize framebuffer information object.
- * @return:    initialized framebuffer structure.
+ * @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;
+	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;
+	/* 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;
+	mx3fbi			= fbi->par;
+	mx3fbi->cookie		= -EINVAL;
+	mx3fbi->cur_ipu_buf	= 0;
 
-       fbi->var.activate       = FB_ACTIVATE_NOW;
+	fbi->var.activate	= FB_ACTIVATE_NOW;
 
-       fbi->fbops              = ops;
-       fbi->flags              = FBINFO_FLAG_DEFAULT;
-       fbi->pseudo_palette     = mx3fbi->pseudo_palette;
+	fbi->fbops		= ops;
+	fbi->flags		= FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette	= mx3fbi->pseudo_palette;
 
-       mutex_init(&mx3fbi->mutex);
+	mutex_init(&mx3fbi->mutex);
 
-       /* Allocate colormap */
-       ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
-       if (ret < 0) {
-               framebuffer_release(fbi);
-               return NULL;
-       }
+	/* Allocate colormap */
+	ret = fb_alloc_cmap(&fbi->cmap, 16, 0);
+	if (ret < 0) {
+		framebuffer_release(fbi);
+		return NULL;
+	}
 
-       return fbi;
+	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->platform_data;
-       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;
+	struct device *dev = mx3fb->dev;
+	struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data;
+	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;
 
-       ichan->client = mx3fb;
-       irq = ichan->eof_irq;
+	ichan->client = mx3fb;
+	irq = ichan->eof_irq;
 
-       if (ichan->dma_chan.chan_id != IDMAC_SDC_0)
-               return -EINVAL;
+	if (ichan->dma_chan.chan_id != IDMAC_SDC_0)
+		return -EINVAL;
 
-       fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops);
-       if (!fbi)
-               return -ENOMEM;
+	fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops);
+	if (!fbi)
+		return -ENOMEM;
 
-       if (!fb_mode)
-               fb_mode = name;
+	if (!fb_mode)
+		fb_mode = name;
 
-       if (!fb_mode) {
-               ret = -EINVAL;
-               goto emode;
-       }
+	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 (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;
-       }
+	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);
+	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;
+	/* Default Y virtual size is 2x panel size */
+	fbi->var.yres_virtual = fbi->var.yres * 2;
 
-       mx3fb->fbi = fbi;
+	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 */
+	/* 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);
+	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;
+	mx3fbi			= fbi->par;
+	mx3fbi->idmac_channel	= ichan;
+	mx3fbi->ipu_ch		= ichan->dma_chan.chan_id;
+	mx3fbi->mx3fb		= mx3fb;
+	mx3fbi->blank		= FB_BLANK_NORMAL;
 
-       init_completion(&mx3fbi->flip_cmpl);
-       disable_irq(ichan->eof_irq);
-       dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
-       ret = mx3fb_set_par(fbi);
-       if (ret < 0)
-               goto esetpar;
+	init_completion(&mx3fbi->flip_cmpl);
+	disable_irq(ichan->eof_irq);
+	dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
+	ret = mx3fb_set_par(fbi);
+	if (ret < 0)
+		goto esetpar;
 
-       mx3fb_blank(FB_BLANK_UNBLANK, fbi);
+	mx3fb_blank(FB_BLANK_UNBLANK, fbi);
 
-       dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode);
+	dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode);
 
-       ret = register_framebuffer(fbi);
-       if (ret < 0)
-               goto erfb;
+	ret = register_framebuffer(fbi);
+	if (ret < 0)
+		goto erfb;
 
-       return 0;
+	return 0;
 
 erfb:
 esetpar:
 emode:
-       fb_dealloc_cmap(&fbi->cmap);
-       framebuffer_release(fbi);
+	fb_dealloc_cmap(&fbi->cmap);
+	framebuffer_release(fbi);
 
-       return ret;
+	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;
+	struct dma_chan_request *rq = arg;
+	struct device *dev;
+	struct mx3fb_platform_data *mx3fb_pdata;
 
-       if (!rq)
-               return false;
+	if (!rq)
+		return false;
 
-       dev = rq->mx3fb->dev;
-       mx3fb_pdata = dev->platform_data;
+	dev = rq->mx3fb->dev;
+	mx3fb_pdata = dev->platform_data;
 
-       return rq->id == chan->chan_id &&
-               mx3fb_pdata->dma_dev == chan->device->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);
+	mx3fb_unmap_video_memory(fbi);
 
-       fb_dealloc_cmap(&fbi->cmap);
+	fb_dealloc_cmap(&fbi->cmap);
 
-       unregister_framebuffer(fbi);
-       framebuffer_release(fbi);
+	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;
+	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;
+	/*
+	 * 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;
+	mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL);
+	if (!mx3fb)
+		return -ENOMEM;
 
-       spin_lock_init(&mx3fb->lock);
+	spin_lock_init(&mx3fb->lock);
 
-       mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg));
-       if (!mx3fb->reg_base) {
-               ret = -ENOMEM;
-               goto eremap;
-       }
+	mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg));
+	if (!mx3fb->reg_base) {
+		ret = -ENOMEM;
+		goto eremap;
+	}
 
-       pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end,
-                mx3fb->reg_base);
+	pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end,
+		 mx3fb->reg_base);
 
-       /* IDMAC interface */
-       dmaengine_get();
+	/* IDMAC interface */
+	dmaengine_get();
 
-       mx3fb->dev = dev;
-       platform_set_drvdata(pdev, mx3fb);
+	mx3fb->dev = dev;
+	platform_set_drvdata(pdev, mx3fb);
 
-       rq.mx3fb = 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;
-       }
+	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;
+	}
 
-       ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
-       if (ret < 0)
-               goto eisdc0;
+	ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
+	if (ret < 0)
+		goto eisdc0;
 
-       mx3fb->backlight_level = 255;
+	mx3fb->backlight_level = 255;
 
-       return 0;
+	return 0;
 
 eisdc0:
-       dma_release_channel(chan);
+	dma_release_channel(chan);
 ersdc0:
-       dmaengine_put();
-       iounmap(mx3fb->reg_base);
+	dmaengine_put();
+	iounmap(mx3fb->reg_base);
 eremap:
-       kfree(mx3fb);
-       dev_err(dev, "mx3fb: failed to register fb\n");
-       return ret;
+	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;
+	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);
+	chan = &mx3_fbi->idmac_channel->dma_chan;
+	release_fbi(fbi);
 
-       dma_release_channel(chan);
-       dmaengine_put();
+	dma_release_channel(chan);
+	dmaengine_put();
 
-       iounmap(mx3fb->reg_base);
-       kfree(mx3fb);
-       return 0;
+	iounmap(mx3fb->reg_base);
+	kfree(mx3fb);
+	return 0;
 }
 
 static struct platform_driver mx3fb_driver = {
-       .driver = {
-                  .name = MX3FB_NAME,
-       },
-       .probe = mx3fb_probe,
-       .remove = mx3fb_remove,
-       .suspend = mx3fb_suspend,
-       .resume = mx3fb_resume,
+	.driver = {
+		   .name = MX3FB_NAME,
+	},
+	.probe = mx3fb_probe,
+	.remove = mx3fb_remove,
+	.suspend = mx3fb_suspend,
+	.resume = mx3fb_resume,
 };
 
 /*
  * Parse user specified options (`video=mx3fb:')
  * example:
- *     video=mx3fb:bpp=16
+ * 	video=mx3fb:bpp=16
  */
 static int mx3fb_setup(void)
 {
 #ifndef MODULE
-       char *opt, *options = NULL;
+	char *opt, *options = NULL;
 
-       if (fb_get_options("mx3fb", &options))
-               return -ENODEV;
+	if (fb_get_options("mx3fb", &options))
+		return -ENODEV;
 
-       if (!options || !*options)
-               return 0;
+	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;
-       }
+	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;
+	return 0;
 }
 
 static int __init mx3fb_init(void)
 {
-       int ret = mx3fb_setup();
+	int ret = mx3fb_setup();
 
-       if (ret < 0)
-               return ret;
+	if (ret < 0)
+		return ret;
 
-       ret = platform_driver_register(&mx3fb_driver);
-       return ret;
+	ret = platform_driver_register(&mx3fb_driver);
+	return ret;
 }
 
 static void __exit mx3fb_exit(void)
 {
-       platform_driver_unregister(&mx3fb_driver);
+	platform_driver_unregister(&mx3fb_driver);
 }
 
 module_init(mx3fb_init);
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 2552b9f..84f63205 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -59,7 +59,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
-#include <mach/pxa-regs.h>
 #include <mach/bitfield.h>
 #include <mach/pxafb.h>
 
@@ -883,10 +882,21 @@
 	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 __devinit pxafb_overlay_init(struct pxafb_info *fbi)
 {
 	int i, ret;
 
+	if (!pxafb_overlay_supported())
+		return 0;
+
 	for (i = 0; i < 2; i++) {
 		init_pxafb_overlay(fbi, &fbi->overlay[i], i);
 		ret = register_framebuffer(&fbi->overlay[i].fb);
@@ -909,6 +919,9 @@
 {
 	int i;
 
+	if (!pxafb_overlay_supported())
+		return;
+
 	for (i = 0; i < 2; i++)
 		unregister_framebuffer(&fbi->overlay[i].fb);
 }
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 79cf0b1..b0b4513 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -1017,6 +1017,10 @@
 
 	s3c2410fb_init_registers(fbinfo);
 
+	/* re-activate our display after resume */
+	s3c2410fb_activate_var(fbinfo);
+	s3c2410fb_blank(FB_BLANK_UNBLANK, fbinfo);
+
 	return 0;
 }
 
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 076f946..fad58cf 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -176,9 +176,9 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/mutex.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/mach-types.h>
 #include <mach/assabet.h>
 #include <mach/shannon.h>
@@ -251,22 +251,6 @@
 #endif
 #endif
 
-#ifdef CONFIG_SA1100_H3800
-static struct sa1100fb_mach_info h3800_info __initdata = {
-	.pixclock	= 174757, 	.bpp		= 16,
-	.xres		= 320,		.yres		= 240,
-
-	.hsync_len	= 3,		.vsync_len	= 3,
-	.left_margin	= 12,		.upper_margin	= 10,
-	.right_margin	= 17,		.lower_margin	= 1,
-
-	.cmap_static	= 1,
-
-	.lccr0		= LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-	.lccr3		= LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-#endif
-
 #ifdef CONFIG_SA1100_H3600
 static struct sa1100fb_mach_info h3600_info __initdata = {
 	.pixclock	= 174757, 	.bpp		= 16,
@@ -432,11 +416,6 @@
 		fbi->rgb[RGB_16] = &h3600_rgb_16;
 	}
 #endif
-#ifdef CONFIG_SA1100_H3800
-	if (machine_is_h3800()) {
-		inf = &h3800_info;
-	}
-#endif
 #ifdef CONFIG_SA1100_COLLIE
 	if (machine_is_collie()) {
 		inf = &collie_info;
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index b9d74d0..65244c0 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -116,7 +116,7 @@
 	if (!mdev)
 		return -ENOMEM;
 
-	mdev->clk = clk_get(&pdev->dev, "owire_clk");
+	mdev->clk = clk_get(&pdev->dev, "owire");
 	if (!mdev->clk) {
 		err = -ENODEV;
 		goto failed_clk;
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index c973889..a7e3b70 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -590,8 +590,8 @@
 	}
 
 	/* get interface & functional clock objects */
-	hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick");
-	hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck");
+	hdq_data->hdq_ick = clk_get(&pdev->dev, "ick");
+	hdq_data->hdq_fck = clk_get(&pdev->dev, "fck");
 
 	if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) {
 		dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n");
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 55f64af..6302414 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -772,7 +772,7 @@
 
 config GEF_WDT
 	tristate "GE Fanuc Watchdog Timer"
-	depends on GEF_SBC610
+	depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
 	---help---
 	  Watchdog timer found in a number of GE Fanuc single board computers.
 
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 2f2ce74..aa5ad6e 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -60,9 +60,8 @@
 	void __iomem    *base;          /* physical */
 	struct device   *dev;
 	int             omap_wdt_users;
-	struct clk      *armwdt_ck;
-	struct clk      *mpu_wdt_ick;
-	struct clk      *mpu_wdt_fck;
+	struct clk      *ick;
+	struct clk      *fck;
 	struct resource *mem;
 	struct miscdevice omap_wdt_miscdev;
 };
@@ -146,13 +145,8 @@
 	if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
 		return -EBUSY;
 
-	if (cpu_is_omap16xx())
-		clk_enable(wdev->armwdt_ck);	/* Enable the clock */
-
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-		clk_enable(wdev->mpu_wdt_ick);    /* Enable the interface clock */
-		clk_enable(wdev->mpu_wdt_fck);    /* Enable the functional clock */
-	}
+	clk_enable(wdev->ick);    /* Enable the interface clock */
+	clk_enable(wdev->fck);    /* Enable the functional clock */
 
 	/* initialize prescaler */
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -181,13 +175,8 @@
 
 	omap_wdt_disable(wdev);
 
-	if (cpu_is_omap16xx())
-		clk_disable(wdev->armwdt_ck);	/* Disable the clock */
-
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-		clk_disable(wdev->mpu_wdt_ick);	/* Disable the clock */
-		clk_disable(wdev->mpu_wdt_fck);	/* Disable the clock */
-	}
+	clk_disable(wdev->ick);
+	clk_disable(wdev->fck);
 #else
 	printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
 #endif
@@ -303,44 +292,19 @@
 	wdev->omap_wdt_users = 0;
 	wdev->mem = mem;
 
-	if (cpu_is_omap16xx()) {
-		wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
-		if (IS_ERR(wdev->armwdt_ck)) {
-			ret = PTR_ERR(wdev->armwdt_ck);
-			wdev->armwdt_ck = NULL;
-			goto err_clk;
-		}
+	wdev->ick = clk_get(&pdev->dev, "ick");
+	if (IS_ERR(wdev->ick)) {
+		ret = PTR_ERR(wdev->ick);
+		wdev->ick = NULL;
+		goto err_clk;
+	}
+	wdev->fck = clk_get(&pdev->dev, "fck");
+	if (IS_ERR(wdev->fck)) {
+		ret = PTR_ERR(wdev->fck);
+		wdev->fck = NULL;
+		goto err_clk;
 	}
 
-	if (cpu_is_omap24xx()) {
-		wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
-		if (IS_ERR(wdev->mpu_wdt_ick)) {
-			ret = PTR_ERR(wdev->mpu_wdt_ick);
-			wdev->mpu_wdt_ick = NULL;
-			goto err_clk;
-		}
-		wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
-		if (IS_ERR(wdev->mpu_wdt_fck)) {
-			ret = PTR_ERR(wdev->mpu_wdt_fck);
-			wdev->mpu_wdt_fck = NULL;
-			goto err_clk;
-		}
-	}
-
-	if (cpu_is_omap34xx()) {
-		wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick");
-		if (IS_ERR(wdev->mpu_wdt_ick)) {
-			ret = PTR_ERR(wdev->mpu_wdt_ick);
-			wdev->mpu_wdt_ick = NULL;
-			goto err_clk;
-		}
-		wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck");
-		if (IS_ERR(wdev->mpu_wdt_fck)) {
-			ret = PTR_ERR(wdev->mpu_wdt_fck);
-			wdev->mpu_wdt_fck = NULL;
-			goto err_clk;
-		}
-	}
 	wdev->base = ioremap(res->start, res->end - res->start + 1);
 	if (!wdev->base) {
 		ret = -ENOMEM;
@@ -380,12 +344,10 @@
 	wdev->base = NULL;
 
 err_clk:
-	if (wdev->armwdt_ck)
-		clk_put(wdev->armwdt_ck);
-	if (wdev->mpu_wdt_ick)
-		clk_put(wdev->mpu_wdt_ick);
-	if (wdev->mpu_wdt_fck)
-		clk_put(wdev->mpu_wdt_fck);
+	if (wdev->ick)
+		clk_put(wdev->ick);
+	if (wdev->fck)
+		clk_put(wdev->fck);
 	kfree(wdev);
 
 err_kzalloc:
@@ -417,20 +379,8 @@
 	release_mem_region(res->start, res->end - res->start + 1);
 	platform_set_drvdata(pdev, NULL);
 
-	if (wdev->armwdt_ck) {
-		clk_put(wdev->armwdt_ck);
-		wdev->armwdt_ck = NULL;
-	}
-
-	if (wdev->mpu_wdt_ick) {
-		clk_put(wdev->mpu_wdt_ick);
-		wdev->mpu_wdt_ick = NULL;
-	}
-
-	if (wdev->mpu_wdt_fck) {
-		clk_put(wdev->mpu_wdt_fck);
-		wdev->mpu_wdt_fck = NULL;
-	}
+	clk_put(wdev->ick);
+	clk_put(wdev->fck);
 	iounmap(wdev->base);
 
 	kfree(wdev);
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
index 5bd782f..ee1caae 100644
--- a/drivers/watchdog/sa1100_wdt.c
+++ b/drivers/watchdog/sa1100_wdt.c
@@ -30,7 +30,7 @@
 #include <linux/timex.h>
 
 #ifdef CONFIG_ARCH_PXA
-#include <mach/pxa-regs.h>
+#include <mach/regs-ost.h>
 #endif
 
 #include <mach/reset.h>
diff --git a/fs/compat.c b/fs/compat.c
index 5e374aa..55efdfe 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1420,12 +1420,17 @@
 {
 	struct linux_binprm *bprm;
 	struct file *file;
+	struct files_struct *displaced;
 	int retval;
 
+	retval = unshare_files(&displaced);
+	if (retval)
+		goto out_ret;
+
 	retval = -ENOMEM;
 	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
 	if (!bprm)
-		goto out_ret;
+		goto out_files;
 
 	retval = mutex_lock_interruptible(&current->cred_exec_mutex);
 	if (retval < 0)
@@ -1436,7 +1441,7 @@
 	bprm->cred = prepare_exec_creds();
 	if (!bprm->cred)
 		goto out_unlock;
-	check_unsafe_exec(bprm, current->files);
+	check_unsafe_exec(bprm);
 
 	file = open_exec(filename);
 	retval = PTR_ERR(file);
@@ -1487,6 +1492,8 @@
 	mutex_unlock(&current->cred_exec_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
+	if (displaced)
+		put_files_struct(displaced);
 	return retval;
 
 out:
@@ -1506,6 +1513,9 @@
 out_free:
 	free_bprm(bprm);
 
+out_files:
+	if (displaced)
+		reset_files_struct(displaced);
 out_ret:
 	return retval;
 }
diff --git a/fs/exec.c b/fs/exec.c
index b9f1c14..c5128fb 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1056,28 +1056,24 @@
  * - the caller must hold current->cred_exec_mutex to protect against
  *   PTRACE_ATTACH
  */
-void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files)
+void check_unsafe_exec(struct linux_binprm *bprm)
 {
 	struct task_struct *p = current, *t;
 	unsigned long flags;
-	unsigned n_fs, n_files, n_sighand;
+	unsigned n_fs, n_sighand;
 
 	bprm->unsafe = tracehook_unsafe_exec(p);
 
 	n_fs = 1;
-	n_files = 1;
 	n_sighand = 1;
 	lock_task_sighand(p, &flags);
 	for (t = next_thread(p); t != p; t = next_thread(t)) {
 		if (t->fs == p->fs)
 			n_fs++;
-		if (t->files == files)
-			n_files++;
 		n_sighand++;
 	}
 
 	if (atomic_read(&p->fs->count) > n_fs ||
-	    atomic_read(&p->files->count) > n_files ||
 	    atomic_read(&p->sighand->count) > n_sighand)
 		bprm->unsafe |= LSM_UNSAFE_SHARE;
 
@@ -1300,7 +1296,7 @@
 	bprm->cred = prepare_exec_creds();
 	if (!bprm->cred)
 		goto out_unlock;
-	check_unsafe_exec(bprm, displaced);
+	check_unsafe_exec(bprm);
 
 	file = open_exec(filename);
 	retval = PTR_ERR(file);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index d865ca66..cc8e4de 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -531,6 +531,12 @@
 		if (!new)
 			return -ENOMEM;
 	}
+
+	/*
+	 * We need to take f_lock first since it's not an IRQ-safe
+	 * lock.
+	 */
+	spin_lock(&filp->f_lock);
 	write_lock_irq(&fasync_lock);
 	for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
 		if (fa->fa_file == filp) {
@@ -555,14 +561,12 @@
 		result = 1;
 	}
 out:
-	/* Fix up FASYNC bit while still holding fasync_lock */
-	spin_lock(&filp->f_lock);
 	if (on)
 		filp->f_flags |= FASYNC;
 	else
 		filp->f_flags &= ~FASYNC;
-	spin_unlock(&filp->f_lock);
 	write_unlock_irq(&fasync_lock);
+	spin_unlock(&filp->f_lock);
 	return result;
 }
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index d9fdb7c..821d10f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1465,7 +1465,7 @@
 	case SEEK_END:
 		retval = fuse_update_attributes(inode, NULL, file, NULL);
 		if (retval)
-			return retval;
+			goto exit;
 		offset += i_size_read(inode);
 		break;
 	case SEEK_CUR:
@@ -1479,6 +1479,7 @@
 		}
 		retval = offset;
 	}
+exit:
 	mutex_unlock(&inode->i_mutex);
 	return retval;
 }
diff --git a/fs/internal.h b/fs/internal.h
index 0d8ac49..53af885 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -43,7 +43,7 @@
 /*
  * exec.c
  */
-extern void check_unsafe_exec(struct linux_binprm *, struct files_struct *);
+extern void check_unsafe_exec(struct linux_binprm *);
 
 /*
  * namespace.c
diff --git a/fs/jfs/Kconfig b/fs/jfs/Kconfig
index 9ff619a..57cef19 100644
--- a/fs/jfs/Kconfig
+++ b/fs/jfs/Kconfig
@@ -1,6 +1,7 @@
 config JFS_FS
 	tristate "JFS filesystem support"
 	select NLS
+	select CRC32
 	help
 	  This is a port of IBM's Journaled Filesystem .  More information is
 	  available in the file <file:Documentation/filesystems/jfs.txt>.
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 169802e..bbbd5f2 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -362,11 +362,12 @@
 int extHint(struct inode *ip, s64 offset, xad_t * xp)
 {
 	struct super_block *sb = ip->i_sb;
-	struct xadlist xadl;
-	struct lxdlist lxdl;
-	lxd_t lxd;
+	int nbperpage = JFS_SBI(sb)->nbperpage;
 	s64 prev;
-	int rc, nbperpage = JFS_SBI(sb)->nbperpage;
+	int rc = 0;
+	s64 xaddr;
+	int xlen;
+	int xflag;
 
 	/* init the hint as "no hint provided" */
 	XADaddress(xp, 0);
@@ -376,46 +377,30 @@
 	 */
 	prev = ((offset & ~POFFSET) >> JFS_SBI(sb)->l2bsize) - nbperpage;
 
-	/* if the offsets in the first page of the file,
-	 * no hint provided.
+	/* if the offset is in the first page of the file, no hint provided.
 	 */
 	if (prev < 0)
-		return (0);
+		goto out;
 
-	/* prepare to lookup the previous page's extent info */
-	lxdl.maxnlxd = 1;
-	lxdl.nlxd = 1;
-	lxdl.lxd = &lxd;
-	LXDoffset(&lxd, prev)
-	LXDlength(&lxd, nbperpage);
+	rc = xtLookup(ip, prev, nbperpage, &xflag, &xaddr, &xlen, 0);
 
-	xadl.maxnxad = 1;
-	xadl.nxad = 0;
-	xadl.xad = xp;
+	if ((rc == 0) && xlen) {
+		if (xlen != nbperpage) {
+			jfs_error(ip->i_sb, "extHint: corrupt xtree");
+			rc = -EIO;
+		}
+		XADaddress(xp, xaddr);
+		XADlength(xp, xlen);
+		/*
+		 * only preserve the abnr flag within the xad flags
+		 * of the returned hint.
+		 */
+		xp->flag  = xflag & XAD_NOTRECORDED;
+	} else
+		rc = 0;
 
-	/* perform the lookup */
-	if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
-		return (rc);
-
-	/* check if no extent exists for the previous page.
-	 * this is possible for sparse files.
-	 */
-	if (xadl.nxad == 0) {
-//		assert(ISSPARSE(ip));
-		return (0);
-	}
-
-	/* only preserve the abnr flag within the xad flags
-	 * of the returned hint.
-	 */
-	xp->flag &= XAD_NOTRECORDED;
-
-	if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
-		jfs_error(ip->i_sb, "extHint: corrupt xtree");
-		return -EIO;
-	}
-
-	return (0);
+out:
+	return (rc);
 }
 
 
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 0f94381..3460572 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -57,12 +57,6 @@
 #include "jfs_debug.h"
 
 /*
- * __mark_inode_dirty expects inodes to be hashed.  Since we don't want
- * special inodes in the fileset inode space, we make them appear hashed,
- * but do not put on any lists.
- */
-
-/*
  * imap locks
  */
 /* iag free list lock */
@@ -497,7 +491,9 @@
 	release_metapage(mp);
 
 	/*
-	 * that will look hashed, but won't be on any list; hlist_del()
+	 * __mark_inode_dirty expects inodes to be hashed.  Since we don't
+	 * want special inodes in the fileset inode space, we make them
+	 * appear hashed, but do not put on any lists.  hlist_del()
 	 * will work fine and require no locking.
 	 */
 	ip->i_hash.pprev = &ip->i_hash.next;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index c350057..07b6c5d 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -369,6 +369,7 @@
 	unsigned long bio_bytes = 0;
 	unsigned long bio_offset = 0;
 	int offset;
+	int bad_blocks = 0;
 
 	page_start = (sector_t)page->index <<
 		     (PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -394,6 +395,7 @@
 		}
 
 		clear_bit(META_dirty, &mp->flag);
+		set_bit(META_io, &mp->flag);
 		block_offset = offset >> inode->i_blkbits;
 		lblock = page_start + block_offset;
 		if (bio) {
@@ -402,7 +404,6 @@
 				len = min(xlen, blocks_per_mp);
 				xlen -= len;
 				bio_bytes += len << inode->i_blkbits;
-				set_bit(META_io, &mp->flag);
 				continue;
 			}
 			/* Not contiguous */
@@ -424,12 +425,14 @@
 		xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
 		pblock = metapage_get_blocks(inode, lblock, &xlen);
 		if (!pblock) {
-			/* Need better error handling */
 			printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
-			dec_io(page, last_write_complete);
+			/*
+			 * We already called inc_io(), but can't cancel it
+			 * with dec_io() until we're done with the page
+			 */
+			bad_blocks++;
 			continue;
 		}
-		set_bit(META_io, &mp->flag);
 		len = min(xlen, (int)JFS_SBI(inode->i_sb)->nbperpage);
 
 		bio = bio_alloc(GFP_NOFS, 1);
@@ -459,6 +462,9 @@
 
 	unlock_page(page);
 
+	if (bad_blocks)
+		goto err_out;
+
 	if (nr_underway == 0)
 		end_page_writeback(page);
 
@@ -474,7 +480,9 @@
 	bio_put(bio);
 	unlock_page(page);
 	dec_io(page, last_write_complete);
-
+err_out:
+	while (bad_blocks--)
+		dec_io(page, last_write_complete);
 	return -EIO;
 }
 
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 649f981..43ea371 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -58,35 +58,6 @@
 #define	ONES		0xffffffffu	/* all bit on		*/
 
 /*
- *	logical xd (lxd)
- */
-typedef struct {
-	unsigned len:24;
-	unsigned off1:8;
-	u32 off2;
-} lxd_t;
-
-/* lxd_t field construction */
-#define	LXDlength(lxd, length32)	( (lxd)->len = length32 )
-#define	LXDoffset(lxd, offset64)\
-{\
-	(lxd)->off1 = ((s64)offset64) >> 32;\
-	(lxd)->off2 = (offset64) & 0xffffffff;\
-}
-
-/* lxd_t field extraction */
-#define	lengthLXD(lxd)	( (lxd)->len )
-#define	offsetLXD(lxd)\
-	( ((s64)((lxd)->off1)) << 32 | (lxd)->off2 )
-
-/* lxd list */
-struct lxdlist {
-	s16 maxnlxd;
-	s16 nlxd;
-	lxd_t *lxd;
-};
-
-/*
  *	physical xd (pxd)
  */
 typedef struct {
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index a27e26c..d654a64 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -164,11 +164,8 @@
 		/* is lookup offset beyond eof ? */
 		size = ((u64) ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
 		    JFS_SBI(ip->i_sb)->l2bsize;
-		if (lstart >= size) {
-			jfs_err("xtLookup: lstart (0x%lx) >= size (0x%lx)",
-				(ulong) lstart, (ulong) size);
+		if (lstart >= size)
 			return 0;
-		}
 	}
 
 	/*
@@ -220,264 +217,6 @@
 	return rc;
 }
 
-
-/*
- *	xtLookupList()
- *
- * function: map a single logical extent into a list of physical extent;
- *
- * parameter:
- *	struct inode	*ip,
- *	struct lxdlist	*lxdlist,	lxd list (in)
- *	struct xadlist	*xadlist,	xad list (in/out)
- *	int		flag)
- *
- * coverage of lxd by xad under assumption of
- * . lxd's are ordered and disjoint.
- * . xad's are ordered and disjoint.
- *
- * return:
- *	0:	success
- *
- * note: a page being written (even a single byte) is backed fully,
- *	except the last page which is only backed with blocks
- *	required to cover the last byte;
- *	the extent backing a page is fully contained within an xad;
- */
-int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
-		 struct xadlist * xadlist, int flag)
-{
-	int rc = 0;
-	struct btstack btstack;
-	int cmp;
-	s64 bn;
-	struct metapage *mp;
-	xtpage_t *p;
-	int index;
-	lxd_t *lxd;
-	xad_t *xad, *pxd;
-	s64 size, lstart, lend, xstart, xend, pstart;
-	s64 llen, xlen, plen;
-	s64 xaddr, paddr;
-	int nlxd, npxd, maxnpxd;
-
-	npxd = xadlist->nxad = 0;
-	maxnpxd = xadlist->maxnxad;
-	pxd = xadlist->xad;
-
-	nlxd = lxdlist->nlxd;
-	lxd = lxdlist->lxd;
-
-	lstart = offsetLXD(lxd);
-	llen = lengthLXD(lxd);
-	lend = lstart + llen;
-
-	size = (ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
-	    JFS_SBI(ip->i_sb)->l2bsize;
-
-	/*
-	 * search for the xad entry covering the logical extent
-	 */
-      search:
-	if (lstart >= size)
-		return 0;
-
-	if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0)))
-		return rc;
-
-	/*
-	 *	compute the physical extent covering logical extent
-	 *
-	 * N.B. search may have failed (e.g., hole in sparse file),
-	 * and returned the index of the next entry.
-	 */
-//map:
-	/* retrieve search result */
-	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
-
-	/* is xad on the next sibling page ? */
-	if (index == le16_to_cpu(p->header.nextindex)) {
-		if (p->header.flag & BT_ROOT)
-			goto mapend;
-
-		if ((bn = le64_to_cpu(p->header.next)) == 0)
-			goto mapend;
-
-		XT_PUTPAGE(mp);
-
-		/* get next sibling page */
-		XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-		if (rc)
-			return rc;
-
-		index = XTENTRYSTART;
-	}
-
-	xad = &p->xad[index];
-
-	/*
-	 * is lxd covered by xad ?
-	 */
-      compare:
-	xstart = offsetXAD(xad);
-	xlen = lengthXAD(xad);
-	xend = xstart + xlen;
-	xaddr = addressXAD(xad);
-
-      compare1:
-	if (xstart < lstart)
-		goto compare2;
-
-	/* (lstart <= xstart) */
-
-	/* lxd is NOT covered by xad */
-	if (lend <= xstart) {
-		/*
-		 * get next lxd
-		 */
-		if (--nlxd == 0)
-			goto mapend;
-		lxd++;
-
-		lstart = offsetLXD(lxd);
-		llen = lengthLXD(lxd);
-		lend = lstart + llen;
-		if (lstart >= size)
-			goto mapend;
-
-		/* compare with the current xad */
-		goto compare1;
-	}
-	/* lxd is covered by xad */
-	else {			/* (xstart < lend) */
-
-		/* initialize new pxd */
-		pstart = xstart;
-		plen = min(lend - xstart, xlen);
-		paddr = xaddr;
-
-		goto cover;
-	}
-
-	/* (xstart < lstart) */
-      compare2:
-	/* lxd is covered by xad */
-	if (lstart < xend) {
-		/* initialize new pxd */
-		pstart = lstart;
-		plen = min(xend - lstart, llen);
-		paddr = xaddr + (lstart - xstart);
-
-		goto cover;
-	}
-	/* lxd is NOT covered by xad */
-	else {			/* (xend <= lstart) */
-
-		/*
-		 * get next xad
-		 *
-		 * linear search next xad covering lxd on
-		 * the current xad page, and then tree search
-		 */
-		if (index == le16_to_cpu(p->header.nextindex) - 1) {
-			if (p->header.flag & BT_ROOT)
-				goto mapend;
-
-			XT_PUTPAGE(mp);
-			goto search;
-		} else {
-			index++;
-			xad++;
-
-			/* compare with new xad */
-			goto compare;
-		}
-	}
-
-	/*
-	 * lxd is covered by xad and a new pxd has been initialized
-	 * (lstart <= xstart < lend) or (xstart < lstart < xend)
-	 */
-      cover:
-	/* finalize pxd corresponding to current xad */
-	XT_PUTENTRY(pxd, xad->flag, pstart, plen, paddr);
-
-	if (++npxd >= maxnpxd)
-		goto mapend;
-	pxd++;
-
-	/*
-	 * lxd is fully covered by xad
-	 */
-	if (lend <= xend) {
-		/*
-		 * get next lxd
-		 */
-		if (--nlxd == 0)
-			goto mapend;
-		lxd++;
-
-		lstart = offsetLXD(lxd);
-		llen = lengthLXD(lxd);
-		lend = lstart + llen;
-		if (lstart >= size)
-			goto mapend;
-
-		/*
-		 * test for old xad covering new lxd
-		 * (old xstart < new lstart)
-		 */
-		goto compare2;
-	}
-	/*
-	 * lxd is partially covered by xad
-	 */
-	else {			/* (xend < lend) */
-
-		/*
-		 * get next xad
-		 *
-		 * linear search next xad covering lxd on
-		 * the current xad page, and then next xad page search
-		 */
-		if (index == le16_to_cpu(p->header.nextindex) - 1) {
-			if (p->header.flag & BT_ROOT)
-				goto mapend;
-
-			if ((bn = le64_to_cpu(p->header.next)) == 0)
-				goto mapend;
-
-			XT_PUTPAGE(mp);
-
-			/* get next sibling page */
-			XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
-			if (rc)
-				return rc;
-
-			index = XTENTRYSTART;
-			xad = &p->xad[index];
-		} else {
-			index++;
-			xad++;
-		}
-
-		/*
-		 * test for new xad covering old lxd
-		 * (old lstart < new xstart)
-		 */
-		goto compare;
-	}
-
-      mapend:
-	xadlist->nxad = npxd;
-
-//out:
-	XT_PUTPAGE(mp);
-
-	return rc;
-}
-
-
 /*
  *	xtSearch()
  *
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 70815c8a3..08c0c74 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -110,8 +110,6 @@
  */
 extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
 		    int *pflag, s64 * paddr, int *plen, int flag);
-extern int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
-			struct xadlist * xadlist, int flag);
 extern void xtInitRoot(tid_t tid, struct inode *ip);
 extern int xtInsert(tid_t tid, struct inode *ip,
 		    int xflag, s64 xoff, int xlen, s64 * xaddrp, int flag);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index b37d1f7..6f21adf 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -29,6 +29,7 @@
 #include <linux/posix_acl.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
+#include <linux/crc32.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 
@@ -168,6 +169,9 @@
 	buf->f_files = maxinodes;
 	buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
 				    atomic_read(&imap->im_numfree));
+	buf->f_fsid.val[0] = (u32)crc32_le(0, sbi->uuid, sizeof(sbi->uuid)/2);
+	buf->f_fsid.val[1] = (u32)crc32_le(0, sbi->uuid + sizeof(sbi->uuid)/2,
+					sizeof(sbi->uuid)/2);
 
 	buf->f_namelen = JFS_NAME_MAX;
 	return 0;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index aef6d55..e0afd32 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -146,15 +146,22 @@
 	return count;
 }
 
-static struct fs_struct *get_fs_struct(struct task_struct *task)
+static int get_fs_path(struct task_struct *task, struct path *path, bool root)
 {
 	struct fs_struct *fs;
+	int result = -ENOENT;
+
 	task_lock(task);
 	fs = task->fs;
-	if(fs)
-		atomic_inc(&fs->count);
+	if (fs) {
+		read_lock(&fs->lock);
+		*path = root ? fs->root : fs->pwd;
+		path_get(path);
+		read_unlock(&fs->lock);
+		result = 0;
+	}
 	task_unlock(task);
-	return fs;
+	return result;
 }
 
 static int get_nr_threads(struct task_struct *tsk)
@@ -172,42 +179,24 @@
 static int proc_cwd_link(struct inode *inode, struct path *path)
 {
 	struct task_struct *task = get_proc_task(inode);
-	struct fs_struct *fs = NULL;
 	int result = -ENOENT;
 
 	if (task) {
-		fs = get_fs_struct(task);
+		result = get_fs_path(task, path, 0);
 		put_task_struct(task);
 	}
-	if (fs) {
-		read_lock(&fs->lock);
-		*path = fs->pwd;
-		path_get(&fs->pwd);
-		read_unlock(&fs->lock);
-		result = 0;
-		put_fs_struct(fs);
-	}
 	return result;
 }
 
 static int proc_root_link(struct inode *inode, struct path *path)
 {
 	struct task_struct *task = get_proc_task(inode);
-	struct fs_struct *fs = NULL;
 	int result = -ENOENT;
 
 	if (task) {
-		fs = get_fs_struct(task);
+		result = get_fs_path(task, path, 1);
 		put_task_struct(task);
 	}
-	if (fs) {
-		read_lock(&fs->lock);
-		*path = fs->root;
-		path_get(&fs->root);
-		read_unlock(&fs->lock);
-		result = 0;
-		put_fs_struct(fs);
-	}
 	return result;
 }
 
@@ -596,7 +585,6 @@
 	struct task_struct *task = get_proc_task(inode);
 	struct nsproxy *nsp;
 	struct mnt_namespace *ns = NULL;
-	struct fs_struct *fs = NULL;
 	struct path root;
 	struct proc_mounts *p;
 	int ret = -EINVAL;
@@ -610,22 +598,16 @@
 				get_mnt_ns(ns);
 		}
 		rcu_read_unlock();
-		if (ns)
-			fs = get_fs_struct(task);
+		if (ns && get_fs_path(task, &root, 1) == 0)
+			ret = 0;
 		put_task_struct(task);
 	}
 
 	if (!ns)
 		goto err;
-	if (!fs)
+	if (ret)
 		goto err_put_ns;
 
-	read_lock(&fs->lock);
-	root = fs->root;
-	path_get(&root);
-	read_unlock(&fs->lock);
-	put_fs_struct(fs);
-
 	ret = -ENOMEM;
 	p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
 	if (!p)
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
index 0eb7ac0..7c5ab63 100644
--- a/fs/reiserfs/Makefile
+++ b/fs/reiserfs/Makefile
@@ -7,10 +7,10 @@
 reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \
 		 super.o prints.o objectid.o lbalance.o ibalance.o stree.o \
 		 hashes.o tail_conversion.o journal.o resize.o \
-		 item_ops.o ioctl.o procfs.o
+		 item_ops.o ioctl.o procfs.o xattr.o
 
 ifeq ($(CONFIG_REISERFS_FS_XATTR),y)
-reiserfs-objs += xattr.o xattr_user.o xattr_trusted.o
+reiserfs-objs += xattr_user.o xattr_trusted.o
 endif
 
 ifeq ($(CONFIG_REISERFS_FS_SECURITY),y)
diff --git a/fs/reiserfs/README b/fs/reiserfs/README
index 90e1670..14e8c9d 100644
--- a/fs/reiserfs/README
+++ b/fs/reiserfs/README
@@ -1,4 +1,4 @@
-[LICENSING] 
+[LICENSING]
 
 ReiserFS is hereby licensed under the GNU General
 Public License version 2.
@@ -31,7 +31,7 @@
 it wrongly, and Richard Stallman agrees with me, when carefully read
 you can see that those restrictions on additional terms do not apply
 to the owner of the copyright, and my interpretation of this shall
-govern for this license.  
+govern for this license.
 
 Finally, nothing in this license shall be interpreted to allow you to
 fail to fairly credit me, or to remove my credits, without my
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index f32d142..e716161 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -40,8 +40,8 @@
 
 #define SET_OPTION(optname) \
    do { \
-        reiserfs_warning(s, "reiserfs: option \"%s\" is set", #optname); \
-        set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
+	reiserfs_info(s, "block allocator option \"%s\" is set", #optname); \
+	set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
     } while(0)
 #define TEST_OPTION(optname, s) \
     test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
@@ -64,9 +64,9 @@
 	unsigned int bmap_count = reiserfs_bmap_count(s);
 
 	if (block == 0 || block >= SB_BLOCK_COUNT(s)) {
-		reiserfs_warning(s,
-				 "vs-4010: is_reusable: block number is out of range %lu (%u)",
-				 block, SB_BLOCK_COUNT(s));
+		reiserfs_error(s, "vs-4010",
+			       "block number is out of range %lu (%u)",
+			       block, SB_BLOCK_COUNT(s));
 		return 0;
 	}
 
@@ -79,31 +79,30 @@
 		b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1;
 		if (block >= bmap1 &&
 		    block <= bmap1 + bmap_count) {
-			reiserfs_warning(s, "vs: 4019: is_reusable: "
-					 "bitmap block %lu(%u) can't be freed or reused",
-					 block, bmap_count);
+			reiserfs_error(s, "vs-4019", "bitmap block %lu(%u) "
+				       "can't be freed or reused",
+				       block, bmap_count);
 			return 0;
 		}
 	} else {
 		if (offset == 0) {
-			reiserfs_warning(s, "vs: 4020: is_reusable: "
-					 "bitmap block %lu(%u) can't be freed or reused",
-					 block, bmap_count);
+			reiserfs_error(s, "vs-4020", "bitmap block %lu(%u) "
+				       "can't be freed or reused",
+				       block, bmap_count);
 			return 0;
 		}
 	}
 
 	if (bmap >= bmap_count) {
-		reiserfs_warning(s,
-				 "vs-4030: is_reusable: there is no so many bitmap blocks: "
-				 "block=%lu, bitmap_nr=%u", block, bmap);
+		reiserfs_error(s, "vs-4030", "bitmap for requested block "
+			       "is out of range: block=%lu, bitmap_nr=%u",
+			       block, bmap);
 		return 0;
 	}
 
 	if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) {
-		reiserfs_warning(s,
-				 "vs-4050: is_reusable: this is root block (%u), "
-				 "it must be busy", SB_ROOT_BLOCK(s));
+		reiserfs_error(s, "vs-4050", "this is root block (%u), "
+			       "it must be busy", SB_ROOT_BLOCK(s));
 		return 0;
 	}
 
@@ -154,8 +153,8 @@
 /* - I mean `a window of zero bits' as in description of this function - Zam. */
 
 	if (!bi) {
-		reiserfs_warning(s, "NULL bitmap info pointer for bitmap %d",
-				 bmap_n);
+		reiserfs_error(s, "jdm-4055", "NULL bitmap info pointer "
+			       "for bitmap %d", bmap_n);
 		return 0;
 	}
 
@@ -400,11 +399,8 @@
 	get_bit_address(s, block, &nr, &offset);
 
 	if (nr >= reiserfs_bmap_count(s)) {
-		reiserfs_warning(s, "vs-4075: reiserfs_free_block: "
-				 "block %lu is out of range on %s "
-				 "(nr=%u,max=%u)", block,
-				 reiserfs_bdevname(s), nr,
-				 reiserfs_bmap_count(s));
+		reiserfs_error(s, "vs-4075", "block %lu is out of range",
+			       block);
 		return;
 	}
 
@@ -416,9 +412,8 @@
 
 	/* clear bit for the given block in bit map */
 	if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) {
-		reiserfs_warning(s, "vs-4080: reiserfs_free_block: "
-				 "free_block (%s:%lu)[dev:blocknr]: bit already cleared",
-				 reiserfs_bdevname(s), block);
+		reiserfs_error(s, "vs-4080",
+			       "block %lu: bit already cleared", block);
 	}
 	apbi[nr].free_count++;
 	journal_mark_dirty(th, s, bmbh);
@@ -445,7 +440,7 @@
 		return;
 
 	if (block > sb_block_count(REISERFS_SB(s)->s_rs)) {
-		reiserfs_panic(th->t_super, "bitmap-4072",
+		reiserfs_error(th->t_super, "bitmap-4072",
 			       "Trying to free block outside file system "
 			       "boundaries (%lu > %lu)",
 			       block, sb_block_count(REISERFS_SB(s)->s_rs));
@@ -477,9 +472,8 @@
 	BUG_ON(!th->t_trans_id);
 #ifdef CONFIG_REISERFS_CHECK
 	if (ei->i_prealloc_count < 0)
-		reiserfs_warning(th->t_super,
-				 "zam-4001:%s: inode has negative prealloc blocks count.",
-				 __func__);
+		reiserfs_error(th->t_super, "zam-4001",
+			       "inode has negative prealloc blocks count.");
 #endif
 	while (ei->i_prealloc_count > 0) {
 		reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block);
@@ -515,9 +509,9 @@
 				i_prealloc_list);
 #ifdef CONFIG_REISERFS_CHECK
 		if (!ei->i_prealloc_count) {
-			reiserfs_warning(th->t_super,
-					 "zam-4001:%s: inode is in prealloc list but has no preallocated blocks.",
-					 __func__);
+			reiserfs_error(th->t_super, "zam-4001",
+				       "inode is in prealloc list but has "
+				       "no preallocated blocks.");
 		}
 #endif
 		__discard_prealloc(th, ei);
@@ -631,12 +625,12 @@
 			continue;
 		}
 
-		reiserfs_warning(s, "zam-4001: %s : unknown option - %s",
-				 __func__, this_char);
+		reiserfs_warning(s, "zam-4001", "unknown option - %s",
+				 this_char);
 		return 1;
 	}
 
-	reiserfs_warning(s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
+	reiserfs_info(s, "allocator options = [%08x]\n", SB_ALLOC_OPTS(s));
 	return 0;
 }
 
@@ -1221,7 +1215,9 @@
 	unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size);
 
 	/* The first bit must ALWAYS be 1 */
-	BUG_ON(!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data));
+	if (!reiserfs_test_le_bit(0, (unsigned long *)bh->b_data))
+		reiserfs_error(sb, "reiserfs-2025", "bitmap block %lu is "
+			       "corrupted: first bit must be 1", bh->b_blocknr);
 
 	info->free_count = 0;
 
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
index e6b03d2..67a80d7 100644
--- a/fs/reiserfs/dir.c
+++ b/fs/reiserfs/dir.c
@@ -41,10 +41,10 @@
 
 #define store_ih(where,what) copy_item_head (where, what)
 
-//
-static int reiserfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
+			   filldir_t filldir, loff_t *pos)
 {
-	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct inode *inode = dentry->d_inode;
 	struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
 	INITIALIZE_PATH(path_to_entry);
 	struct buffer_head *bh;
@@ -64,13 +64,9 @@
 
 	/* form key for search the next directory entry using f_pos field of
 	   file structure */
-	make_cpu_key(&pos_key, inode,
-		     (filp->f_pos) ? (filp->f_pos) : DOT_OFFSET, TYPE_DIRENTRY,
-		     3);
+	make_cpu_key(&pos_key, inode, *pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
 	next_pos = cpu_key_k_offset(&pos_key);
 
-	/*  reiserfs_warning (inode->i_sb, "reiserfs_readdir 1: f_pos = %Ld", filp->f_pos); */
-
 	path_to_entry.reada = PATH_READA;
 	while (1) {
 	      research:
@@ -144,7 +140,7 @@
 				/* Ignore the .reiserfs_priv entry */
 				if (reiserfs_xattrs(inode->i_sb) &&
 				    !old_format_only(inode->i_sb) &&
-				    filp->f_path.dentry == inode->i_sb->s_root &&
+				    dentry == inode->i_sb->s_root &&
 				    REISERFS_SB(inode->i_sb)->priv_root &&
 				    REISERFS_SB(inode->i_sb)->priv_root->d_inode
 				    && deh_objectid(deh) ==
@@ -156,7 +152,7 @@
 				}
 
 				d_off = deh_offset(deh);
-				filp->f_pos = d_off;
+				*pos = d_off;
 				d_ino = deh_objectid(deh);
 				if (d_reclen <= 32) {
 					local_buf = small_buf;
@@ -223,15 +219,21 @@
 
 	}			/* while */
 
-      end:
-	filp->f_pos = next_pos;
+end:
+	*pos = next_pos;
 	pathrelse(&path_to_entry);
 	reiserfs_check_path(&path_to_entry);
-      out:
+out:
 	reiserfs_write_unlock(inode->i_sb);
 	return ret;
 }
 
+static int reiserfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	struct dentry *dentry = file->f_path.dentry;
+	return reiserfs_readdir_dentry(dentry, dirent, filldir, &file->f_pos);
+}
+
 /* compose directory item containing "." and ".." entries (entries are
    not aligned to 4 byte boundary) */
 /* the last four params are LE */
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index 2f87f5b..4beb964 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -29,6 +29,43 @@
 					   is interrupting do_balance */
 #endif
 
+static inline void buffer_info_init_left(struct tree_balance *tb,
+                                         struct buffer_info *bi)
+{
+	bi->tb          = tb;
+	bi->bi_bh       = tb->L[0];
+	bi->bi_parent   = tb->FL[0];
+	bi->bi_position = get_left_neighbor_position(tb, 0);
+}
+
+static inline void buffer_info_init_right(struct tree_balance *tb,
+                                          struct buffer_info *bi)
+{
+	bi->tb          = tb;
+	bi->bi_bh       = tb->R[0];
+	bi->bi_parent   = tb->FR[0];
+	bi->bi_position = get_right_neighbor_position(tb, 0);
+}
+
+static inline void buffer_info_init_tbS0(struct tree_balance *tb,
+                                         struct buffer_info *bi)
+{
+	bi->tb          = tb;
+	bi->bi_bh        = PATH_PLAST_BUFFER(tb->tb_path);
+	bi->bi_parent   = PATH_H_PPARENT(tb->tb_path, 0);
+	bi->bi_position = PATH_H_POSITION(tb->tb_path, 1);
+}
+
+static inline void buffer_info_init_bh(struct tree_balance *tb,
+                                       struct buffer_info *bi,
+                                       struct buffer_head *bh)
+{
+	bi->tb          = tb;
+	bi->bi_bh       = bh;
+	bi->bi_parent   = NULL;
+	bi->bi_position = 0;
+}
+
 inline void do_balance_mark_leaf_dirty(struct tree_balance *tb,
 				       struct buffer_head *bh, int flag)
 {
@@ -39,21 +76,21 @@
 #define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty
 #define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty
 
-/* summary: 
+/* summary:
  if deleting something ( tb->insert_size[0] < 0 )
    return(balance_leaf_when_delete()); (flag d handled here)
  else
    if lnum is larger than 0 we put items into the left node
    if rnum is larger than 0 we put items into the right node
    if snum1 is larger than 0 we put items into the new node s1
-   if snum2 is larger than 0 we put items into the new node s2 
+   if snum2 is larger than 0 we put items into the new node s2
 Note that all *num* count new items being created.
 
 It would be easier to read balance_leaf() if each of these summary
 lines was a separate procedure rather than being inlined.  I think
 that there are many passages here and in balance_leaf_when_delete() in
 which two calls to one procedure can replace two passages, and it
-might save cache space and improve software maintenance costs to do so.  
+might save cache space and improve software maintenance costs to do so.
 
 Vladimir made the perceptive comment that we should offload most of
 the decision making in this function into fix_nodes/check_balance, and
@@ -86,6 +123,7 @@
 	       "PAP-12010: tree can not be empty");
 
 	ih = B_N_PITEM_HEAD(tbS0, item_pos);
+	buffer_info_init_tbS0(tb, &bi);
 
 	/* Delete or truncate the item */
 
@@ -96,10 +134,6 @@
 		       "vs-12013: mode Delete, insert size %d, ih to be deleted %h",
 		       -tb->insert_size[0], ih);
 
-		bi.tb = tb;
-		bi.bi_bh = tbS0;
-		bi.bi_parent = PATH_H_PPARENT(tb->tb_path, 0);
-		bi.bi_position = PATH_H_POSITION(tb->tb_path, 1);
 		leaf_delete_items(&bi, 0, item_pos, 1, -1);
 
 		if (!item_pos && tb->CFL[0]) {
@@ -121,10 +155,6 @@
 		break;
 
 	case M_CUT:{		/* cut item in S[0] */
-			bi.tb = tb;
-			bi.bi_bh = tbS0;
-			bi.bi_parent = PATH_H_PPARENT(tb->tb_path, 0);
-			bi.bi_position = PATH_H_POSITION(tb->tb_path, 1);
 			if (is_direntry_le_ih(ih)) {
 
 				/* UFS unlink semantics are such that you can only delete one directory entry at a time. */
@@ -153,8 +183,8 @@
 
 	default:
 		print_cur_tb("12040");
-		reiserfs_panic(tb->tb_sb,
-			       "PAP-12040: balance_leaf_when_delete: unexpectable mode: %s(%d)",
+		reiserfs_panic(tb->tb_sb, "PAP-12040",
+			       "unexpected mode: %s(%d)",
 			       (flag ==
 				M_PASTE) ? "PASTE" : ((flag ==
 						       M_INSERT) ? "INSERT" :
@@ -258,15 +288,15 @@
     )
 {
 	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
-	int item_pos = PATH_LAST_POSITION(tb->tb_path);	/*  index into the array of item headers in S[0] 
+	int item_pos = PATH_LAST_POSITION(tb->tb_path);	/*  index into the array of item headers in S[0]
 							   of the affected item */
 	struct buffer_info bi;
 	struct buffer_head *S_new[2];	/* new nodes allocated to hold what could not fit into S */
 	int snum[2];		/* number of items that will be placed
 				   into S_new (includes partially shifted
 				   items) */
-	int sbytes[2];		/* if an item is partially shifted into S_new then 
-				   if it is a directory item 
+	int sbytes[2];		/* if an item is partially shifted into S_new then
+				   if it is a directory item
 				   it is the number of entries from the item that are shifted into S_new
 				   else
 				   it is the number of bytes from the item that are shifted into S_new
@@ -325,11 +355,7 @@
 					       ih_item_len(ih));
 
 					/* Insert new item into L[0] */
-					bi.tb = tb;
-					bi.bi_bh = tb->L[0];
-					bi.bi_parent = tb->FL[0];
-					bi.bi_position =
-					    get_left_neighbor_position(tb, 0);
+					buffer_info_init_left(tb, &bi);
 					leaf_insert_into_buf(&bi,
 							     n + item_pos -
 							     ret_val, ih, body,
@@ -369,11 +395,7 @@
 					    leaf_shift_left(tb, tb->lnum[0] - 1,
 							    tb->lbytes);
 					/* Insert new item into L[0] */
-					bi.tb = tb;
-					bi.bi_bh = tb->L[0];
-					bi.bi_parent = tb->FL[0];
-					bi.bi_position =
-					    get_left_neighbor_position(tb, 0);
+					buffer_info_init_left(tb, &bi);
 					leaf_insert_into_buf(&bi,
 							     n + item_pos -
 							     ret_val, ih, body,
@@ -429,13 +451,7 @@
 							}
 
 							/* Append given directory entry to directory item */
-							bi.tb = tb;
-							bi.bi_bh = tb->L[0];
-							bi.bi_parent =
-							    tb->FL[0];
-							bi.bi_position =
-							    get_left_neighbor_position
-							    (tb, 0);
+							buffer_info_init_left(tb, &bi);
 							leaf_paste_in_buffer
 							    (&bi,
 							     n + item_pos -
@@ -449,8 +465,7 @@
 							/* when we have merge directory item, pos_in_item has been changed too */
 
 							/* paste new directory entry. 1 is entry number */
-							leaf_paste_entries(bi.
-									   bi_bh,
+							leaf_paste_entries(&bi,
 									   n +
 									   item_pos
 									   -
@@ -524,13 +539,7 @@
 									     (tbS0,
 									      item_pos)));
 							/* Append to body of item in L[0] */
-							bi.tb = tb;
-							bi.bi_bh = tb->L[0];
-							bi.bi_parent =
-							    tb->FL[0];
-							bi.bi_position =
-							    get_left_neighbor_position
-							    (tb, 0);
+							buffer_info_init_left(tb, &bi);
 							leaf_paste_in_buffer
 							    (&bi,
 							     n + item_pos -
@@ -681,11 +690,7 @@
 					    leaf_shift_left(tb, tb->lnum[0],
 							    tb->lbytes);
 					/* Append to body of item in L[0] */
-					bi.tb = tb;
-					bi.bi_bh = tb->L[0];
-					bi.bi_parent = tb->FL[0];
-					bi.bi_position =
-					    get_left_neighbor_position(tb, 0);
+					buffer_info_init_left(tb, &bi);
 					leaf_paste_in_buffer(&bi,
 							     n + item_pos -
 							     ret_val,
@@ -699,7 +704,7 @@
 							   n + item_pos -
 							   ret_val);
 					if (is_direntry_le_ih(pasted))
-						leaf_paste_entries(bi.bi_bh,
+						leaf_paste_entries(&bi,
 								   n +
 								   item_pos -
 								   ret_val,
@@ -722,8 +727,9 @@
 				}
 				break;
 			default:	/* cases d and t */
-				reiserfs_panic(tb->tb_sb,
-					       "PAP-12130: balance_leaf: lnum > 0: unexpectable mode: %s(%d)",
+				reiserfs_panic(tb->tb_sb, "PAP-12130",
+					       "lnum > 0: unexpected mode: "
+					       " %s(%d)",
 					       (flag ==
 						M_DELETE) ? "DELETE" : ((flag ==
 									 M_CUT)
@@ -776,11 +782,7 @@
 					set_le_ih_k_offset(ih, offset);
 					put_ih_item_len(ih, tb->rbytes);
 					/* Insert part of the item into R[0] */
-					bi.tb = tb;
-					bi.bi_bh = tb->R[0];
-					bi.bi_parent = tb->FR[0];
-					bi.bi_position =
-					    get_right_neighbor_position(tb, 0);
+					buffer_info_init_right(tb, &bi);
 					if ((old_len - tb->rbytes) > zeros_num) {
 						r_zeros_number = 0;
 						r_body =
@@ -817,11 +819,7 @@
 							     tb->rnum[0] - 1,
 							     tb->rbytes);
 					/* Insert new item into R[0] */
-					bi.tb = tb;
-					bi.bi_bh = tb->R[0];
-					bi.bi_parent = tb->FR[0];
-					bi.bi_position =
-					    get_right_neighbor_position(tb, 0);
+					buffer_info_init_right(tb, &bi);
 					leaf_insert_into_buf(&bi,
 							     item_pos - n +
 							     tb->rnum[0] - 1,
@@ -881,21 +879,14 @@
 							    pos_in_item -
 							    entry_count +
 							    tb->rbytes - 1;
-							bi.tb = tb;
-							bi.bi_bh = tb->R[0];
-							bi.bi_parent =
-							    tb->FR[0];
-							bi.bi_position =
-							    get_right_neighbor_position
-							    (tb, 0);
+							buffer_info_init_right(tb, &bi);
 							leaf_paste_in_buffer
 							    (&bi, 0,
 							     paste_entry_position,
 							     tb->insert_size[0],
 							     body, zeros_num);
 							/* paste entry */
-							leaf_paste_entries(bi.
-									   bi_bh,
+							leaf_paste_entries(&bi,
 									   0,
 									   paste_entry_position,
 									   1,
@@ -1019,12 +1010,7 @@
 						    (tb, tb->CFR[0], 0);
 
 						/* Append part of body into R[0] */
-						bi.tb = tb;
-						bi.bi_bh = tb->R[0];
-						bi.bi_parent = tb->FR[0];
-						bi.bi_position =
-						    get_right_neighbor_position
-						    (tb, 0);
+						buffer_info_init_right(tb, &bi);
 						if (n_rem > zeros_num) {
 							r_zeros_number = 0;
 							r_body =
@@ -1071,12 +1057,7 @@
 							     tb->rbytes);
 					/* append item in R[0] */
 					if (pos_in_item >= 0) {
-						bi.tb = tb;
-						bi.bi_bh = tb->R[0];
-						bi.bi_parent = tb->FR[0];
-						bi.bi_position =
-						    get_right_neighbor_position
-						    (tb, 0);
+						buffer_info_init_right(tb, &bi);
 						leaf_paste_in_buffer(&bi,
 								     item_pos -
 								     n +
@@ -1096,7 +1077,7 @@
 							   tb->rnum[0]);
 					if (is_direntry_le_ih(pasted)
 					    && pos_in_item >= 0) {
-						leaf_paste_entries(bi.bi_bh,
+						leaf_paste_entries(&bi,
 								   item_pos -
 								   n +
 								   tb->rnum[0],
@@ -1136,8 +1117,8 @@
 			}
 			break;
 		default:	/* cases d and t */
-			reiserfs_panic(tb->tb_sb,
-				       "PAP-12175: balance_leaf: rnum > 0: unexpectable mode: %s(%d)",
+			reiserfs_panic(tb->tb_sb, "PAP-12175",
+				       "rnum > 0: unexpected mode: %s(%d)",
 				       (flag ==
 					M_DELETE) ? "DELETE" : ((flag ==
 								 M_CUT) ? "CUT"
@@ -1167,8 +1148,8 @@
 		   not set correctly */
 		if (tb->CFL[0]) {
 			if (!tb->CFR[0])
-				reiserfs_panic(tb->tb_sb,
-					       "vs-12195: balance_leaf: CFR not initialized");
+				reiserfs_panic(tb->tb_sb, "vs-12195",
+					       "CFR not initialized");
 			copy_key(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]),
 				 B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]));
 			do_balance_mark_internal_dirty(tb, tb->CFL[0], 0);
@@ -1232,10 +1213,7 @@
 					put_ih_item_len(ih, sbytes[i]);
 
 					/* Insert part of the item into S_new[i] before 0-th item */
-					bi.tb = tb;
-					bi.bi_bh = S_new[i];
-					bi.bi_parent = NULL;
-					bi.bi_position = 0;
+					buffer_info_init_bh(tb, &bi, S_new[i]);
 
 					if ((old_len - sbytes[i]) > zeros_num) {
 						r_zeros_number = 0;
@@ -1267,10 +1245,7 @@
 							S_new[i]);
 
 					/* Insert new item into S_new[i] */
-					bi.tb = tb;
-					bi.bi_bh = S_new[i];
-					bi.bi_parent = NULL;
-					bi.bi_position = 0;
+					buffer_info_init_bh(tb, &bi, S_new[i]);
 					leaf_insert_into_buf(&bi,
 							     item_pos - n +
 							     snum[i] - 1, ih,
@@ -1327,10 +1302,7 @@
 							     sbytes[i] - 1,
 							     S_new[i]);
 							/* Paste given directory entry to directory item */
-							bi.tb = tb;
-							bi.bi_bh = S_new[i];
-							bi.bi_parent = NULL;
-							bi.bi_position = 0;
+							buffer_info_init_bh(tb, &bi, S_new[i]);
 							leaf_paste_in_buffer
 							    (&bi, 0,
 							     pos_in_item -
@@ -1339,8 +1311,7 @@
 							     tb->insert_size[0],
 							     body, zeros_num);
 							/* paste new directory entry */
-							leaf_paste_entries(bi.
-									   bi_bh,
+							leaf_paste_entries(&bi,
 									   0,
 									   pos_in_item
 									   -
@@ -1401,11 +1372,7 @@
 						if (n_rem < 0)
 							n_rem = 0;
 						/* Append part of body into S_new[0] */
-						bi.tb = tb;
-						bi.bi_bh = S_new[i];
-						bi.bi_parent = NULL;
-						bi.bi_position = 0;
-
+						buffer_info_init_bh(tb, &bi, S_new[i]);
 						if (n_rem > zeros_num) {
 							r_zeros_number = 0;
 							r_body =
@@ -1475,7 +1442,10 @@
 					    && (pos_in_item != ih_item_len(ih_check)
 						|| tb->insert_size[0] <= 0))
 						reiserfs_panic(tb->tb_sb,
-							       "PAP-12235: balance_leaf: pos_in_item must be equal to ih_item_len");
+							     "PAP-12235",
+							     "pos_in_item "
+							     "must be equal "
+							     "to ih_item_len");
 #endif				/* CONFIG_REISERFS_CHECK */
 
 					leaf_mi =
@@ -1489,10 +1459,7 @@
 					       leaf_mi);
 
 					/* paste into item */
-					bi.tb = tb;
-					bi.bi_bh = S_new[i];
-					bi.bi_parent = NULL;
-					bi.bi_position = 0;
+					buffer_info_init_bh(tb, &bi, S_new[i]);
 					leaf_paste_in_buffer(&bi,
 							     item_pos - n +
 							     snum[i],
@@ -1505,7 +1472,7 @@
 							   item_pos - n +
 							   snum[i]);
 					if (is_direntry_le_ih(pasted)) {
-						leaf_paste_entries(bi.bi_bh,
+						leaf_paste_entries(&bi,
 								   item_pos -
 								   n + snum[i],
 								   pos_in_item,
@@ -1535,8 +1502,8 @@
 			}
 			break;
 		default:	/* cases d and t */
-			reiserfs_panic(tb->tb_sb,
-				       "PAP-12245: balance_leaf: blknum > 2: unexpectable mode: %s(%d)",
+			reiserfs_panic(tb->tb_sb, "PAP-12245",
+				       "blknum > 2: unexpected mode: %s(%d)",
 				       (flag ==
 					M_DELETE) ? "DELETE" : ((flag ==
 								 M_CUT) ? "CUT"
@@ -1559,10 +1526,7 @@
 
 		switch (flag) {
 		case M_INSERT:	/* insert item into S[0] */
-			bi.tb = tb;
-			bi.bi_bh = tbS0;
-			bi.bi_parent = PATH_H_PPARENT(tb->tb_path, 0);
-			bi.bi_position = PATH_H_POSITION(tb->tb_path, 1);
+			buffer_info_init_tbS0(tb, &bi);
 			leaf_insert_into_buf(&bi, item_pos, ih, body,
 					     zeros_num);
 
@@ -1589,14 +1553,7 @@
 						       "PAP-12260: insert_size is 0 already");
 
 						/* prepare space */
-						bi.tb = tb;
-						bi.bi_bh = tbS0;
-						bi.bi_parent =
-						    PATH_H_PPARENT(tb->tb_path,
-								   0);
-						bi.bi_position =
-						    PATH_H_POSITION(tb->tb_path,
-								    1);
+						buffer_info_init_tbS0(tb, &bi);
 						leaf_paste_in_buffer(&bi,
 								     item_pos,
 								     pos_in_item,
@@ -1606,7 +1563,7 @@
 								     zeros_num);
 
 						/* paste entry */
-						leaf_paste_entries(bi.bi_bh,
+						leaf_paste_entries(&bi,
 								   item_pos,
 								   pos_in_item,
 								   1,
@@ -1644,14 +1601,7 @@
 						RFALSE(tb->insert_size[0] <= 0,
 						       "PAP-12275: insert size must not be %d",
 						       tb->insert_size[0]);
-						bi.tb = tb;
-						bi.bi_bh = tbS0;
-						bi.bi_parent =
-						    PATH_H_PPARENT(tb->tb_path,
-								   0);
-						bi.bi_position =
-						    PATH_H_POSITION(tb->tb_path,
-								    1);
+						buffer_info_init_tbS0(tb, &bi);
 						leaf_paste_in_buffer(&bi,
 								     item_pos,
 								     pos_in_item,
@@ -1681,10 +1631,11 @@
 							print_cur_tb("12285");
 							reiserfs_panic(tb->
 								       tb_sb,
-								       "PAP-12285: balance_leaf: insert_size must be 0 (%d)",
-								       tb->
-								       insert_size
-								       [0]);
+							    "PAP-12285",
+							    "insert_size "
+							    "must be 0 "
+							    "(%d)",
+							    tb->insert_size[0]);
 						}
 					}
 #endif				/* CONFIG_REISERFS_CHECK */
@@ -1697,11 +1648,10 @@
 	if (flag == M_PASTE && tb->insert_size[0]) {
 		print_cur_tb("12290");
 		reiserfs_panic(tb->tb_sb,
-			       "PAP-12290: balance_leaf: insert_size is still not 0 (%d)",
+			       "PAP-12290", "insert_size is still not 0 (%d)",
 			       tb->insert_size[0]);
 	}
 #endif				/* CONFIG_REISERFS_CHECK */
-
 	return 0;
 }				/* Leaf level of the tree is balanced (end of balance_leaf) */
 
@@ -1724,7 +1674,6 @@
 struct buffer_head *get_FEB(struct tree_balance *tb)
 {
 	int i;
-	struct buffer_head *first_b;
 	struct buffer_info bi;
 
 	for (i = 0; i < MAX_FEB_SIZE; i++)
@@ -1732,19 +1681,15 @@
 			break;
 
 	if (i == MAX_FEB_SIZE)
-		reiserfs_panic(tb->tb_sb,
-			       "vs-12300: get_FEB: FEB list is empty");
+		reiserfs_panic(tb->tb_sb, "vs-12300", "FEB list is empty");
 
-	bi.tb = tb;
-	bi.bi_bh = first_b = tb->FEB[i];
-	bi.bi_parent = NULL;
-	bi.bi_position = 0;
+	buffer_info_init_bh(tb, &bi, tb->FEB[i]);
 	make_empty_node(&bi);
-	set_buffer_uptodate(first_b);
+	set_buffer_uptodate(tb->FEB[i]);
+	tb->used[i] = tb->FEB[i];
 	tb->FEB[i] = NULL;
-	tb->used[i] = first_b;
 
-	return (first_b);
+	return tb->used[i];
 }
 
 /* This is now used because reiserfs_free_block has to be able to
@@ -1755,15 +1700,16 @@
 	int i;
 
 	if (buffer_dirty(bh))
-		reiserfs_warning(tb->tb_sb,
-				 "store_thrown deals with dirty buffer");
+		reiserfs_warning(tb->tb_sb, "reiserfs-12320",
+				 "called with dirty buffer");
 	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
 		if (!tb->thrown[i]) {
 			tb->thrown[i] = bh;
 			get_bh(bh);	/* free_thrown puts this */
 			return;
 		}
-	reiserfs_warning(tb->tb_sb, "store_thrown: too many thrown buffers");
+	reiserfs_warning(tb->tb_sb, "reiserfs-12321",
+			 "too many thrown buffers");
 }
 
 static void free_thrown(struct tree_balance *tb)
@@ -1774,8 +1720,8 @@
 		if (tb->thrown[i]) {
 			blocknr = tb->thrown[i]->b_blocknr;
 			if (buffer_dirty(tb->thrown[i]))
-				reiserfs_warning(tb->tb_sb,
-						 "free_thrown deals with dirty buffer %d",
+				reiserfs_warning(tb->tb_sb, "reiserfs-12322",
+						 "called with dirty buffer %d",
 						 blocknr);
 			brelse(tb->thrown[i]);	/* incremented in store_thrown */
 			reiserfs_free_block(tb->transaction_handle, NULL,
@@ -1873,20 +1819,19 @@
 	for (i = 0; i <= B_NR_ITEMS(bh); i++, dc++) {
 		if (!is_reusable(s, dc_block_number(dc), 1)) {
 			print_cur_tb(mes);
-			reiserfs_panic(s,
-				       "PAP-12338: check_internal_node: invalid child pointer %y in %b",
+			reiserfs_panic(s, "PAP-12338",
+				       "invalid child pointer %y in %b",
 				       dc, bh);
 		}
 	}
 }
 
-static int locked_or_not_in_tree(struct buffer_head *bh, char *which)
+static int locked_or_not_in_tree(struct tree_balance *tb,
+				  struct buffer_head *bh, char *which)
 {
 	if ((!buffer_journal_prepared(bh) && buffer_locked(bh)) ||
 	    !B_IS_IN_TREE(bh)) {
-		reiserfs_warning(NULL,
-				 "vs-12339: locked_or_not_in_tree: %s (%b)",
-				 which, bh);
+		reiserfs_warning(tb->tb_sb, "vs-12339", "%s (%b)", which, bh);
 		return 1;
 	}
 	return 0;
@@ -1897,26 +1842,28 @@
 	int retval = 0;
 
 	if (cur_tb) {
-		reiserfs_panic(tb->tb_sb, "vs-12335: check_before_balancing: "
-			       "suspect that schedule occurred based on cur_tb not being null at this point in code. "
-			       "do_balance cannot properly handle schedule occurring while it runs.");
+		reiserfs_panic(tb->tb_sb, "vs-12335", "suspect that schedule "
+			       "occurred based on cur_tb not being null at "
+			       "this point in code. do_balance cannot properly "
+			       "handle schedule occurring while it runs.");
 	}
 
 	/* double check that buffers that we will modify are unlocked. (fix_nodes should already have
 	   prepped all of these for us). */
 	if (tb->lnum[0]) {
-		retval |= locked_or_not_in_tree(tb->L[0], "L[0]");
-		retval |= locked_or_not_in_tree(tb->FL[0], "FL[0]");
-		retval |= locked_or_not_in_tree(tb->CFL[0], "CFL[0]");
+		retval |= locked_or_not_in_tree(tb, tb->L[0], "L[0]");
+		retval |= locked_or_not_in_tree(tb, tb->FL[0], "FL[0]");
+		retval |= locked_or_not_in_tree(tb, tb->CFL[0], "CFL[0]");
 		check_leaf(tb->L[0]);
 	}
 	if (tb->rnum[0]) {
-		retval |= locked_or_not_in_tree(tb->R[0], "R[0]");
-		retval |= locked_or_not_in_tree(tb->FR[0], "FR[0]");
-		retval |= locked_or_not_in_tree(tb->CFR[0], "CFR[0]");
+		retval |= locked_or_not_in_tree(tb, tb->R[0], "R[0]");
+		retval |= locked_or_not_in_tree(tb, tb->FR[0], "FR[0]");
+		retval |= locked_or_not_in_tree(tb, tb->CFR[0], "CFR[0]");
 		check_leaf(tb->R[0]);
 	}
-	retval |= locked_or_not_in_tree(PATH_PLAST_BUFFER(tb->tb_path), "S[0]");
+	retval |= locked_or_not_in_tree(tb, PATH_PLAST_BUFFER(tb->tb_path),
+					"S[0]");
 	check_leaf(PATH_PLAST_BUFFER(tb->tb_path));
 
 	return retval;
@@ -1930,8 +1877,8 @@
 		    dc_size(B_N_CHILD
 			    (tb->FL[0], get_left_neighbor_position(tb, 0)))) {
 			print_cur_tb("12221");
-			reiserfs_panic(tb->tb_sb,
-				       "PAP-12355: check_after_balance_leaf: shift to left was incorrect");
+			reiserfs_panic(tb->tb_sb, "PAP-12355",
+				       "shift to left was incorrect");
 		}
 	}
 	if (tb->rnum[0]) {
@@ -1940,8 +1887,8 @@
 		    dc_size(B_N_CHILD
 			    (tb->FR[0], get_right_neighbor_position(tb, 0)))) {
 			print_cur_tb("12222");
-			reiserfs_panic(tb->tb_sb,
-				       "PAP-12360: check_after_balance_leaf: shift to right was incorrect");
+			reiserfs_panic(tb->tb_sb, "PAP-12360",
+				       "shift to right was incorrect");
 		}
 	}
 	if (PATH_H_PBUFFER(tb->tb_path, 1) &&
@@ -1955,7 +1902,7 @@
 					       PATH_H_POSITION(tb->tb_path,
 							       1))));
 		print_cur_tb("12223");
-		reiserfs_warning(tb->tb_sb,
+		reiserfs_warning(tb->tb_sb, "reiserfs-12363",
 				 "B_FREE_SPACE (PATH_H_PBUFFER(tb->tb_path,0)) = %d; "
 				 "MAX_CHILD_SIZE (%d) - dc_size( %y, %d ) [%d] = %d",
 				 left,
@@ -1966,8 +1913,7 @@
 					 (PATH_H_PBUFFER(tb->tb_path, 1),
 					  PATH_H_POSITION(tb->tb_path, 1))),
 				 right);
-		reiserfs_panic(tb->tb_sb,
-			       "PAP-12365: check_after_balance_leaf: S is incorrect");
+		reiserfs_panic(tb->tb_sb, "PAP-12365", "S is incorrect");
 	}
 }
 
@@ -2037,7 +1983,7 @@
 	/* store_print_tb (tb); */
 
 	/* do not delete, just comment it out */
-/*    print_tb(flag, PATH_LAST_POSITION(tb->tb_path), tb->tb_path->pos_in_item, tb, 
+/*    print_tb(flag, PATH_LAST_POSITION(tb->tb_path), tb->tb_path->pos_in_item, tb,
 	     "check");*/
 	RFALSE(check_before_balancing(tb), "PAP-12340: locked buffers in TB");
 #ifdef CONFIG_REISERFS_CHECK
@@ -2102,14 +2048,13 @@
 	tb->need_balance_dirty = 0;
 
 	if (FILESYSTEM_CHANGED_TB(tb)) {
-		reiserfs_panic(tb->tb_sb,
-			       "clm-6000: do_balance, fs generation has changed\n");
+		reiserfs_panic(tb->tb_sb, "clm-6000", "fs generation has "
+			       "changed");
 	}
 	/* if we have no real work to do  */
 	if (!tb->insert_size[0]) {
-		reiserfs_warning(tb->tb_sb,
-				 "PAP-12350: do_balance: insert_size == 0, mode == %c",
-				 flag);
+		reiserfs_warning(tb->tb_sb, "PAP-12350",
+				 "insert_size == 0, mode == %c", flag);
 		unfix_nodes(tb);
 		return;
 	}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 3340841..9f43666 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -20,14 +20,14 @@
 ** insertion/balancing, for files that are written in one write.
 ** It avoids unnecessary tail packings (balances) for files that are written in
 ** multiple writes and are small enough to have tails.
-** 
+**
 ** file_release is called by the VFS layer when the file is closed.  If
 ** this is the last open file descriptor, and the file
 ** small enough to have a tail, and the tail is currently in an
 ** unformatted node, the tail is converted back into a direct item.
-** 
+**
 ** We use reiserfs_truncate_file to pack the tail, since it already has
-** all the conditions coded.  
+** all the conditions coded.
 */
 static int reiserfs_file_release(struct inode *inode, struct file *filp)
 {
@@ -76,7 +76,7 @@
 			 * and let the admin know what is going on.
 			 */
 			igrab(inode);
-			reiserfs_warning(inode->i_sb,
+			reiserfs_warning(inode->i_sb, "clm-9001",
 					 "pinning inode %lu because the "
 					 "preallocation can't be freed",
 					 inode->i_ino);
@@ -134,23 +134,23 @@
  * be removed...
  */
 
-static int reiserfs_sync_file(struct file *p_s_filp,
-			      struct dentry *p_s_dentry, int datasync)
+static int reiserfs_sync_file(struct file *filp,
+			      struct dentry *dentry, int datasync)
 {
-	struct inode *p_s_inode = p_s_dentry->d_inode;
-	int n_err;
+	struct inode *inode = dentry->d_inode;
+	int err;
 	int barrier_done;
 
-	BUG_ON(!S_ISREG(p_s_inode->i_mode));
-	n_err = sync_mapping_buffers(p_s_inode->i_mapping);
-	reiserfs_write_lock(p_s_inode->i_sb);
-	barrier_done = reiserfs_commit_for_inode(p_s_inode);
-	reiserfs_write_unlock(p_s_inode->i_sb);
-	if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb))
-		blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
+	BUG_ON(!S_ISREG(inode->i_mode));
+	err = sync_mapping_buffers(inode->i_mapping);
+	reiserfs_write_lock(inode->i_sb);
+	barrier_done = reiserfs_commit_for_inode(inode);
+	reiserfs_write_unlock(inode->i_sb);
+	if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
+		blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
 	if (barrier_done < 0)
 		return barrier_done;
-	return (n_err < 0) ? -EIO : 0;
+	return (err < 0) ? -EIO : 0;
 }
 
 /* taken fs/buffer.c:__block_commit_write */
@@ -223,7 +223,7 @@
 }
 
 /* Write @count bytes at position @ppos in a file indicated by @file
-   from the buffer @buf.  
+   from the buffer @buf.
 
    generic_file_write() is only appropriate for filesystems that are not seeking to optimize performance and want
    something simple that works.  It is not for serious use by general purpose filesystems, excepting the one that it was
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
index 07d05e0..5e5a4e6 100644
--- a/fs/reiserfs/fix_node.c
+++ b/fs/reiserfs/fix_node.c
@@ -30,8 +30,8 @@
  ** get_direct_parent
  ** get_neighbors
  ** fix_nodes
- ** 
- ** 
+ **
+ **
  **/
 
 #include <linux/time.h>
@@ -135,8 +135,7 @@
 		vn->vn_free_ptr +=
 		    op_create_vi(vn, vi, is_affected, tb->insert_size[0]);
 		if (tb->vn_buf + tb->vn_buf_size < vn->vn_free_ptr)
-			reiserfs_panic(tb->tb_sb,
-				       "vs-8030: create_virtual_node: "
+			reiserfs_panic(tb->tb_sb, "vs-8030",
 				       "virtual node space consumed");
 
 		if (!is_affected)
@@ -186,8 +185,9 @@
 			     && I_ENTRY_COUNT(B_N_PITEM_HEAD(Sh, 0)) == 1)) {
 				/* node contains more than 1 item, or item is not directory item, or this item contains more than 1 entry */
 				print_block(Sh, 0, -1, -1);
-				reiserfs_panic(tb->tb_sb,
-					       "vs-8045: create_virtual_node: rdkey %k, affected item==%d (mode==%c) Must be %c",
+				reiserfs_panic(tb->tb_sb, "vs-8045",
+					       "rdkey %k, affected item==%d "
+					       "(mode==%c) Must be %c",
 					       key, vn->vn_affected_item_num,
 					       vn->vn_mode, M_DELETE);
 			}
@@ -377,9 +377,9 @@
 	int needed_nodes;
 	int start_item,		/* position of item we start filling node from */
 	 end_item,		/* position of item we finish filling node by */
-	 start_bytes,		/* number of first bytes (entries for directory) of start_item-th item 
+	 start_bytes,		/* number of first bytes (entries for directory) of start_item-th item
 				   we do not include into node that is being filled */
-	 end_bytes;		/* number of last bytes (entries for directory) of end_item-th item 
+	 end_bytes;		/* number of last bytes (entries for directory) of end_item-th item
 				   we do node include into node that is being filled */
 	int split_item_positions[2];	/* these are positions in virtual item of
 					   items, that are split between S[0] and
@@ -496,8 +496,8 @@
 		snum012[needed_nodes - 1 + 3] = units;
 
 		if (needed_nodes > 2)
-			reiserfs_warning(tb->tb_sb, "vs-8111: get_num_ver: "
-					 "split_item_position is out of boundary");
+			reiserfs_warning(tb->tb_sb, "vs-8111",
+					 "split_item_position is out of range");
 		snum012[needed_nodes - 1]++;
 		split_item_positions[needed_nodes - 1] = i;
 		needed_nodes++;
@@ -533,8 +533,8 @@
 
 		if (vn->vn_vi[split_item_num].vi_index != TYPE_DIRENTRY &&
 		    vn->vn_vi[split_item_num].vi_index != TYPE_INDIRECT)
-			reiserfs_warning(tb->tb_sb, "vs-8115: get_num_ver: not "
-					 "directory or indirect item");
+			reiserfs_warning(tb->tb_sb, "vs-8115",
+					 "not directory or indirect item");
 	}
 
 	/* now we know S2bytes, calculate S1bytes */
@@ -569,7 +569,7 @@
 
 /* Set parameters for balancing.
  * Performs write of results of analysis of balancing into structure tb,
- * where it will later be used by the functions that actually do the balancing. 
+ * where it will later be used by the functions that actually do the balancing.
  * Parameters:
  *	tb	tree_balance structure;
  *	h	current level of the node;
@@ -749,25 +749,26 @@
 		  -1, -1);\
 }
 
-static void free_buffers_in_tb(struct tree_balance *p_s_tb)
+static void free_buffers_in_tb(struct tree_balance *tb)
 {
-	int n_counter;
+	int i;
 
-	decrement_counters_in_path(p_s_tb->tb_path);
+	pathrelse(tb->tb_path);
 
-	for (n_counter = 0; n_counter < MAX_HEIGHT; n_counter++) {
-		decrement_bcount(p_s_tb->L[n_counter]);
-		p_s_tb->L[n_counter] = NULL;
-		decrement_bcount(p_s_tb->R[n_counter]);
-		p_s_tb->R[n_counter] = NULL;
-		decrement_bcount(p_s_tb->FL[n_counter]);
-		p_s_tb->FL[n_counter] = NULL;
-		decrement_bcount(p_s_tb->FR[n_counter]);
-		p_s_tb->FR[n_counter] = NULL;
-		decrement_bcount(p_s_tb->CFL[n_counter]);
-		p_s_tb->CFL[n_counter] = NULL;
-		decrement_bcount(p_s_tb->CFR[n_counter]);
-		p_s_tb->CFR[n_counter] = NULL;
+	for (i = 0; i < MAX_HEIGHT; i++) {
+		brelse(tb->L[i]);
+		brelse(tb->R[i]);
+		brelse(tb->FL[i]);
+		brelse(tb->FR[i]);
+		brelse(tb->CFL[i]);
+		brelse(tb->CFR[i]);
+
+		tb->L[i] = NULL;
+		tb->R[i] = NULL;
+		tb->FL[i] = NULL;
+		tb->FR[i] = NULL;
+		tb->CFL[i] = NULL;
+		tb->CFR[i] = NULL;
 	}
 }
 
@@ -777,14 +778,14 @@
  *	        NO_DISK_SPACE - no disk space.
  */
 /* The function is NOT SCHEDULE-SAFE! */
-static int get_empty_nodes(struct tree_balance *p_s_tb, int n_h)
+static int get_empty_nodes(struct tree_balance *tb, int h)
 {
-	struct buffer_head *p_s_new_bh,
-	    *p_s_Sh = PATH_H_PBUFFER(p_s_tb->tb_path, n_h);
-	b_blocknr_t *p_n_blocknr, a_n_blocknrs[MAX_AMOUNT_NEEDED] = { 0, };
-	int n_counter, n_number_of_freeblk, n_amount_needed,	/* number of needed empty blocks */
-	 n_retval = CARRY_ON;
-	struct super_block *p_s_sb = p_s_tb->tb_sb;
+	struct buffer_head *new_bh,
+	    *Sh = PATH_H_PBUFFER(tb->tb_path, h);
+	b_blocknr_t *blocknr, blocknrs[MAX_AMOUNT_NEEDED] = { 0, };
+	int counter, number_of_freeblk, amount_needed,	/* number of needed empty blocks */
+	 retval = CARRY_ON;
+	struct super_block *sb = tb->tb_sb;
 
 	/* number_of_freeblk is the number of empty blocks which have been
 	   acquired for use by the balancing algorithm minus the number of
@@ -792,7 +793,7 @@
 	   number_of_freeblk = tb->cur_blknum can be non-zero if a schedule occurs
 	   after empty blocks are acquired, and the balancing analysis is
 	   then restarted, amount_needed is the number needed by this level
-	   (n_h) of the balancing analysis.
+	   (h) of the balancing analysis.
 
 	   Note that for systems with many processes writing, it would be
 	   more layout optimal to calculate the total number needed by all
@@ -800,54 +801,54 @@
 
 	/* Initiate number_of_freeblk to the amount acquired prior to the restart of
 	   the analysis or 0 if not restarted, then subtract the amount needed
-	   by all of the levels of the tree below n_h. */
-	/* blknum includes S[n_h], so we subtract 1 in this calculation */
-	for (n_counter = 0, n_number_of_freeblk = p_s_tb->cur_blknum;
-	     n_counter < n_h; n_counter++)
-		n_number_of_freeblk -=
-		    (p_s_tb->blknum[n_counter]) ? (p_s_tb->blknum[n_counter] -
+	   by all of the levels of the tree below h. */
+	/* blknum includes S[h], so we subtract 1 in this calculation */
+	for (counter = 0, number_of_freeblk = tb->cur_blknum;
+	     counter < h; counter++)
+		number_of_freeblk -=
+		    (tb->blknum[counter]) ? (tb->blknum[counter] -
 						   1) : 0;
 
 	/* Allocate missing empty blocks. */
-	/* if p_s_Sh == 0  then we are getting a new root */
-	n_amount_needed = (p_s_Sh) ? (p_s_tb->blknum[n_h] - 1) : 1;
+	/* if Sh == 0  then we are getting a new root */
+	amount_needed = (Sh) ? (tb->blknum[h] - 1) : 1;
 	/*  Amount_needed = the amount that we need more than the amount that we have. */
-	if (n_amount_needed > n_number_of_freeblk)
-		n_amount_needed -= n_number_of_freeblk;
+	if (amount_needed > number_of_freeblk)
+		amount_needed -= number_of_freeblk;
 	else			/* If we have enough already then there is nothing to do. */
 		return CARRY_ON;
 
 	/* No need to check quota - is not allocated for blocks used for formatted nodes */
-	if (reiserfs_new_form_blocknrs(p_s_tb, a_n_blocknrs,
-				       n_amount_needed) == NO_DISK_SPACE)
+	if (reiserfs_new_form_blocknrs(tb, blocknrs,
+				       amount_needed) == NO_DISK_SPACE)
 		return NO_DISK_SPACE;
 
 	/* for each blocknumber we just got, get a buffer and stick it on FEB */
-	for (p_n_blocknr = a_n_blocknrs, n_counter = 0;
-	     n_counter < n_amount_needed; p_n_blocknr++, n_counter++) {
+	for (blocknr = blocknrs, counter = 0;
+	     counter < amount_needed; blocknr++, counter++) {
 
-		RFALSE(!*p_n_blocknr,
+		RFALSE(!*blocknr,
 		       "PAP-8135: reiserfs_new_blocknrs failed when got new blocks");
 
-		p_s_new_bh = sb_getblk(p_s_sb, *p_n_blocknr);
-		RFALSE(buffer_dirty(p_s_new_bh) ||
-		       buffer_journaled(p_s_new_bh) ||
-		       buffer_journal_dirty(p_s_new_bh),
+		new_bh = sb_getblk(sb, *blocknr);
+		RFALSE(buffer_dirty(new_bh) ||
+		       buffer_journaled(new_bh) ||
+		       buffer_journal_dirty(new_bh),
 		       "PAP-8140: journlaled or dirty buffer %b for the new block",
-		       p_s_new_bh);
+		       new_bh);
 
 		/* Put empty buffers into the array. */
-		RFALSE(p_s_tb->FEB[p_s_tb->cur_blknum],
+		RFALSE(tb->FEB[tb->cur_blknum],
 		       "PAP-8141: busy slot for new buffer");
 
-		set_buffer_journal_new(p_s_new_bh);
-		p_s_tb->FEB[p_s_tb->cur_blknum++] = p_s_new_bh;
+		set_buffer_journal_new(new_bh);
+		tb->FEB[tb->cur_blknum++] = new_bh;
 	}
 
-	if (n_retval == CARRY_ON && FILESYSTEM_CHANGED_TB(p_s_tb))
-		n_retval = REPEAT_SEARCH;
+	if (retval == CARRY_ON && FILESYSTEM_CHANGED_TB(tb))
+		retval = REPEAT_SEARCH;
 
-	return n_retval;
+	return retval;
 }
 
 /* Get free space of the left neighbor, which is stored in the parent
@@ -895,35 +896,36 @@
 }
 
 /* Check whether left neighbor is in memory. */
-static int is_left_neighbor_in_cache(struct tree_balance *p_s_tb, int n_h)
+static int is_left_neighbor_in_cache(struct tree_balance *tb, int h)
 {
-	struct buffer_head *p_s_father, *left;
-	struct super_block *p_s_sb = p_s_tb->tb_sb;
-	b_blocknr_t n_left_neighbor_blocknr;
-	int n_left_neighbor_position;
+	struct buffer_head *father, *left;
+	struct super_block *sb = tb->tb_sb;
+	b_blocknr_t left_neighbor_blocknr;
+	int left_neighbor_position;
 
-	if (!p_s_tb->FL[n_h])	/* Father of the left neighbor does not exist. */
+	/* Father of the left neighbor does not exist. */
+	if (!tb->FL[h])
 		return 0;
 
 	/* Calculate father of the node to be balanced. */
-	p_s_father = PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1);
+	father = PATH_H_PBUFFER(tb->tb_path, h + 1);
 
-	RFALSE(!p_s_father ||
-	       !B_IS_IN_TREE(p_s_father) ||
-	       !B_IS_IN_TREE(p_s_tb->FL[n_h]) ||
-	       !buffer_uptodate(p_s_father) ||
-	       !buffer_uptodate(p_s_tb->FL[n_h]),
+	RFALSE(!father ||
+	       !B_IS_IN_TREE(father) ||
+	       !B_IS_IN_TREE(tb->FL[h]) ||
+	       !buffer_uptodate(father) ||
+	       !buffer_uptodate(tb->FL[h]),
 	       "vs-8165: F[h] (%b) or FL[h] (%b) is invalid",
-	       p_s_father, p_s_tb->FL[n_h]);
+	       father, tb->FL[h]);
 
 	/* Get position of the pointer to the left neighbor into the left father. */
-	n_left_neighbor_position = (p_s_father == p_s_tb->FL[n_h]) ?
-	    p_s_tb->lkey[n_h] : B_NR_ITEMS(p_s_tb->FL[n_h]);
+	left_neighbor_position = (father == tb->FL[h]) ?
+	    tb->lkey[h] : B_NR_ITEMS(tb->FL[h]);
 	/* Get left neighbor block number. */
-	n_left_neighbor_blocknr =
-	    B_N_CHILD_NUM(p_s_tb->FL[n_h], n_left_neighbor_position);
+	left_neighbor_blocknr =
+	    B_N_CHILD_NUM(tb->FL[h], left_neighbor_position);
 	/* Look for the left neighbor in the cache. */
-	if ((left = sb_find_get_block(p_s_sb, n_left_neighbor_blocknr))) {
+	if ((left = sb_find_get_block(sb, left_neighbor_blocknr))) {
 
 		RFALSE(buffer_uptodate(left) && !B_IS_IN_TREE(left),
 		       "vs-8170: left neighbor (%b %z) is not in the tree",
@@ -938,10 +940,10 @@
 #define LEFT_PARENTS  'l'
 #define RIGHT_PARENTS 'r'
 
-static void decrement_key(struct cpu_key *p_s_key)
+static void decrement_key(struct cpu_key *key)
 {
 	// call item specific function for this key
-	item_ops[cpu_key_k_type(p_s_key)]->decrement_key(p_s_key);
+	item_ops[cpu_key_k_type(key)]->decrement_key(key);
 }
 
 /* Calculate far left/right parent of the left/right neighbor of the current node, that
@@ -952,77 +954,77 @@
  		SCHEDULE_OCCURRED - schedule occurred while the function worked;
  *	        CARRY_ON         - schedule didn't occur while the function worked;
  */
-static int get_far_parent(struct tree_balance *p_s_tb,
-			  int n_h,
-			  struct buffer_head **pp_s_father,
-			  struct buffer_head **pp_s_com_father, char c_lr_par)
+static int get_far_parent(struct tree_balance *tb,
+			  int h,
+			  struct buffer_head **pfather,
+			  struct buffer_head **pcom_father, char c_lr_par)
 {
-	struct buffer_head *p_s_parent;
+	struct buffer_head *parent;
 	INITIALIZE_PATH(s_path_to_neighbor_father);
-	struct treepath *p_s_path = p_s_tb->tb_path;
+	struct treepath *path = tb->tb_path;
 	struct cpu_key s_lr_father_key;
-	int n_counter,
-	    n_position = INT_MAX,
-	    n_first_last_position = 0,
-	    n_path_offset = PATH_H_PATH_OFFSET(p_s_path, n_h);
+	int counter,
+	    position = INT_MAX,
+	    first_last_position = 0,
+	    path_offset = PATH_H_PATH_OFFSET(path, h);
 
-	/* Starting from F[n_h] go upwards in the tree, and look for the common
-	   ancestor of F[n_h], and its neighbor l/r, that should be obtained. */
+	/* Starting from F[h] go upwards in the tree, and look for the common
+	   ancestor of F[h], and its neighbor l/r, that should be obtained. */
 
-	n_counter = n_path_offset;
+	counter = path_offset;
 
-	RFALSE(n_counter < FIRST_PATH_ELEMENT_OFFSET,
+	RFALSE(counter < FIRST_PATH_ELEMENT_OFFSET,
 	       "PAP-8180: invalid path length");
 
-	for (; n_counter > FIRST_PATH_ELEMENT_OFFSET; n_counter--) {
+	for (; counter > FIRST_PATH_ELEMENT_OFFSET; counter--) {
 		/* Check whether parent of the current buffer in the path is really parent in the tree. */
 		if (!B_IS_IN_TREE
-		    (p_s_parent = PATH_OFFSET_PBUFFER(p_s_path, n_counter - 1)))
+		    (parent = PATH_OFFSET_PBUFFER(path, counter - 1)))
 			return REPEAT_SEARCH;
 		/* Check whether position in the parent is correct. */
-		if ((n_position =
-		     PATH_OFFSET_POSITION(p_s_path,
-					  n_counter - 1)) >
-		    B_NR_ITEMS(p_s_parent))
+		if ((position =
+		     PATH_OFFSET_POSITION(path,
+					  counter - 1)) >
+		    B_NR_ITEMS(parent))
 			return REPEAT_SEARCH;
 		/* Check whether parent at the path really points to the child. */
-		if (B_N_CHILD_NUM(p_s_parent, n_position) !=
-		    PATH_OFFSET_PBUFFER(p_s_path, n_counter)->b_blocknr)
+		if (B_N_CHILD_NUM(parent, position) !=
+		    PATH_OFFSET_PBUFFER(path, counter)->b_blocknr)
 			return REPEAT_SEARCH;
 		/* Return delimiting key if position in the parent is not equal to first/last one. */
 		if (c_lr_par == RIGHT_PARENTS)
-			n_first_last_position = B_NR_ITEMS(p_s_parent);
-		if (n_position != n_first_last_position) {
-			*pp_s_com_father = p_s_parent;
-			get_bh(*pp_s_com_father);
-			/*(*pp_s_com_father = p_s_parent)->b_count++; */
+			first_last_position = B_NR_ITEMS(parent);
+		if (position != first_last_position) {
+			*pcom_father = parent;
+			get_bh(*pcom_father);
+			/*(*pcom_father = parent)->b_count++; */
 			break;
 		}
 	}
 
 	/* if we are in the root of the tree, then there is no common father */
-	if (n_counter == FIRST_PATH_ELEMENT_OFFSET) {
+	if (counter == FIRST_PATH_ELEMENT_OFFSET) {
 		/* Check whether first buffer in the path is the root of the tree. */
 		if (PATH_OFFSET_PBUFFER
-		    (p_s_tb->tb_path,
+		    (tb->tb_path,
 		     FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
-		    SB_ROOT_BLOCK(p_s_tb->tb_sb)) {
-			*pp_s_father = *pp_s_com_father = NULL;
+		    SB_ROOT_BLOCK(tb->tb_sb)) {
+			*pfather = *pcom_father = NULL;
 			return CARRY_ON;
 		}
 		return REPEAT_SEARCH;
 	}
 
-	RFALSE(B_LEVEL(*pp_s_com_father) <= DISK_LEAF_NODE_LEVEL,
+	RFALSE(B_LEVEL(*pcom_father) <= DISK_LEAF_NODE_LEVEL,
 	       "PAP-8185: (%b %z) level too small",
-	       *pp_s_com_father, *pp_s_com_father);
+	       *pcom_father, *pcom_father);
 
 	/* Check whether the common parent is locked. */
 
-	if (buffer_locked(*pp_s_com_father)) {
-		__wait_on_buffer(*pp_s_com_father);
-		if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
-			decrement_bcount(*pp_s_com_father);
+	if (buffer_locked(*pcom_father)) {
+		__wait_on_buffer(*pcom_father);
+		if (FILESYSTEM_CHANGED_TB(tb)) {
+			brelse(*pcom_father);
 			return REPEAT_SEARCH;
 		}
 	}
@@ -1032,128 +1034,131 @@
 
 	/* Form key to get parent of the left/right neighbor. */
 	le_key2cpu_key(&s_lr_father_key,
-		       B_N_PDELIM_KEY(*pp_s_com_father,
+		       B_N_PDELIM_KEY(*pcom_father,
 				      (c_lr_par ==
-				       LEFT_PARENTS) ? (p_s_tb->lkey[n_h - 1] =
-							n_position -
-							1) : (p_s_tb->rkey[n_h -
+				       LEFT_PARENTS) ? (tb->lkey[h - 1] =
+							position -
+							1) : (tb->rkey[h -
 									   1] =
-							      n_position)));
+							      position)));
 
 	if (c_lr_par == LEFT_PARENTS)
 		decrement_key(&s_lr_father_key);
 
 	if (search_by_key
-	    (p_s_tb->tb_sb, &s_lr_father_key, &s_path_to_neighbor_father,
-	     n_h + 1) == IO_ERROR)
+	    (tb->tb_sb, &s_lr_father_key, &s_path_to_neighbor_father,
+	     h + 1) == IO_ERROR)
 		// path is released
 		return IO_ERROR;
 
-	if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
-		decrement_counters_in_path(&s_path_to_neighbor_father);
-		decrement_bcount(*pp_s_com_father);
+	if (FILESYSTEM_CHANGED_TB(tb)) {
+		pathrelse(&s_path_to_neighbor_father);
+		brelse(*pcom_father);
 		return REPEAT_SEARCH;
 	}
 
-	*pp_s_father = PATH_PLAST_BUFFER(&s_path_to_neighbor_father);
+	*pfather = PATH_PLAST_BUFFER(&s_path_to_neighbor_father);
 
-	RFALSE(B_LEVEL(*pp_s_father) != n_h + 1,
-	       "PAP-8190: (%b %z) level too small", *pp_s_father, *pp_s_father);
+	RFALSE(B_LEVEL(*pfather) != h + 1,
+	       "PAP-8190: (%b %z) level too small", *pfather, *pfather);
 	RFALSE(s_path_to_neighbor_father.path_length <
 	       FIRST_PATH_ELEMENT_OFFSET, "PAP-8192: path length is too small");
 
 	s_path_to_neighbor_father.path_length--;
-	decrement_counters_in_path(&s_path_to_neighbor_father);
+	pathrelse(&s_path_to_neighbor_father);
 	return CARRY_ON;
 }
 
-/* Get parents of neighbors of node in the path(S[n_path_offset]) and common parents of
- * S[n_path_offset] and L[n_path_offset]/R[n_path_offset]: F[n_path_offset], FL[n_path_offset],
- * FR[n_path_offset], CFL[n_path_offset], CFR[n_path_offset].
- * Calculate numbers of left and right delimiting keys position: lkey[n_path_offset], rkey[n_path_offset].
+/* Get parents of neighbors of node in the path(S[path_offset]) and common parents of
+ * S[path_offset] and L[path_offset]/R[path_offset]: F[path_offset], FL[path_offset],
+ * FR[path_offset], CFL[path_offset], CFR[path_offset].
+ * Calculate numbers of left and right delimiting keys position: lkey[path_offset], rkey[path_offset].
  * Returns:	SCHEDULE_OCCURRED - schedule occurred while the function worked;
  *	        CARRY_ON - schedule didn't occur while the function worked;
  */
-static int get_parents(struct tree_balance *p_s_tb, int n_h)
+static int get_parents(struct tree_balance *tb, int h)
 {
-	struct treepath *p_s_path = p_s_tb->tb_path;
-	int n_position,
-	    n_ret_value,
-	    n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
-	struct buffer_head *p_s_curf, *p_s_curcf;
+	struct treepath *path = tb->tb_path;
+	int position,
+	    ret,
+	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h);
+	struct buffer_head *curf, *curcf;
 
 	/* Current node is the root of the tree or will be root of the tree */
-	if (n_path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
+	if (path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
 		/* The root can not have parents.
 		   Release nodes which previously were obtained as parents of the current node neighbors. */
-		decrement_bcount(p_s_tb->FL[n_h]);
-		decrement_bcount(p_s_tb->CFL[n_h]);
-		decrement_bcount(p_s_tb->FR[n_h]);
-		decrement_bcount(p_s_tb->CFR[n_h]);
-		p_s_tb->FL[n_h] = p_s_tb->CFL[n_h] = p_s_tb->FR[n_h] =
-		    p_s_tb->CFR[n_h] = NULL;
+		brelse(tb->FL[h]);
+		brelse(tb->CFL[h]);
+		brelse(tb->FR[h]);
+		brelse(tb->CFR[h]);
+		tb->FL[h]  = NULL;
+		tb->CFL[h] = NULL;
+		tb->FR[h]  = NULL;
+		tb->CFR[h] = NULL;
 		return CARRY_ON;
 	}
 
-	/* Get parent FL[n_path_offset] of L[n_path_offset]. */
-	if ((n_position = PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1))) {
+	/* Get parent FL[path_offset] of L[path_offset]. */
+	position = PATH_OFFSET_POSITION(path, path_offset - 1);
+	if (position) {
 		/* Current node is not the first child of its parent. */
-		/*(p_s_curf = p_s_curcf = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1))->b_count += 2; */
-		p_s_curf = p_s_curcf =
-		    PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1);
-		get_bh(p_s_curf);
-		get_bh(p_s_curf);
-		p_s_tb->lkey[n_h] = n_position - 1;
+		curf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
+		curcf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
+		get_bh(curf);
+		get_bh(curf);
+		tb->lkey[h] = position - 1;
 	} else {
-		/* Calculate current parent of L[n_path_offset], which is the left neighbor of the current node.
-		   Calculate current common parent of L[n_path_offset] and the current node. Note that
-		   CFL[n_path_offset] not equal FL[n_path_offset] and CFL[n_path_offset] not equal F[n_path_offset].
-		   Calculate lkey[n_path_offset]. */
-		if ((n_ret_value = get_far_parent(p_s_tb, n_h + 1, &p_s_curf,
-						  &p_s_curcf,
+		/* Calculate current parent of L[path_offset], which is the left neighbor of the current node.
+		   Calculate current common parent of L[path_offset] and the current node. Note that
+		   CFL[path_offset] not equal FL[path_offset] and CFL[path_offset] not equal F[path_offset].
+		   Calculate lkey[path_offset]. */
+		if ((ret = get_far_parent(tb, h + 1, &curf,
+						  &curcf,
 						  LEFT_PARENTS)) != CARRY_ON)
-			return n_ret_value;
+			return ret;
 	}
 
-	decrement_bcount(p_s_tb->FL[n_h]);
-	p_s_tb->FL[n_h] = p_s_curf;	/* New initialization of FL[n_h]. */
-	decrement_bcount(p_s_tb->CFL[n_h]);
-	p_s_tb->CFL[n_h] = p_s_curcf;	/* New initialization of CFL[n_h]. */
+	brelse(tb->FL[h]);
+	tb->FL[h] = curf;	/* New initialization of FL[h]. */
+	brelse(tb->CFL[h]);
+	tb->CFL[h] = curcf;	/* New initialization of CFL[h]. */
 
-	RFALSE((p_s_curf && !B_IS_IN_TREE(p_s_curf)) ||
-	       (p_s_curcf && !B_IS_IN_TREE(p_s_curcf)),
-	       "PAP-8195: FL (%b) or CFL (%b) is invalid", p_s_curf, p_s_curcf);
+	RFALSE((curf && !B_IS_IN_TREE(curf)) ||
+	       (curcf && !B_IS_IN_TREE(curcf)),
+	       "PAP-8195: FL (%b) or CFL (%b) is invalid", curf, curcf);
 
-/* Get parent FR[n_h] of R[n_h]. */
+/* Get parent FR[h] of R[h]. */
 
-/* Current node is the last child of F[n_h]. FR[n_h] != F[n_h]. */
-	if (n_position == B_NR_ITEMS(PATH_H_PBUFFER(p_s_path, n_h + 1))) {
-/* Calculate current parent of R[n_h], which is the right neighbor of F[n_h].
-   Calculate current common parent of R[n_h] and current node. Note that CFR[n_h]
-   not equal FR[n_path_offset] and CFR[n_h] not equal F[n_h]. */
-		if ((n_ret_value =
-		     get_far_parent(p_s_tb, n_h + 1, &p_s_curf, &p_s_curcf,
+/* Current node is the last child of F[h]. FR[h] != F[h]. */
+	if (position == B_NR_ITEMS(PATH_H_PBUFFER(path, h + 1))) {
+/* Calculate current parent of R[h], which is the right neighbor of F[h].
+   Calculate current common parent of R[h] and current node. Note that CFR[h]
+   not equal FR[path_offset] and CFR[h] not equal F[h]. */
+		if ((ret =
+		     get_far_parent(tb, h + 1, &curf, &curcf,
 				    RIGHT_PARENTS)) != CARRY_ON)
-			return n_ret_value;
+			return ret;
 	} else {
-/* Current node is not the last child of its parent F[n_h]. */
-		/*(p_s_curf = p_s_curcf = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1))->b_count += 2; */
-		p_s_curf = p_s_curcf =
-		    PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1);
-		get_bh(p_s_curf);
-		get_bh(p_s_curf);
-		p_s_tb->rkey[n_h] = n_position;
+/* Current node is not the last child of its parent F[h]. */
+		curf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
+		curcf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
+		get_bh(curf);
+		get_bh(curf);
+		tb->rkey[h] = position;
 	}
 
-	decrement_bcount(p_s_tb->FR[n_h]);
-	p_s_tb->FR[n_h] = p_s_curf;	/* New initialization of FR[n_path_offset]. */
+	brelse(tb->FR[h]);
+	/* New initialization of FR[path_offset]. */
+	tb->FR[h] = curf;
 
-	decrement_bcount(p_s_tb->CFR[n_h]);
-	p_s_tb->CFR[n_h] = p_s_curcf;	/* New initialization of CFR[n_path_offset]. */
+	brelse(tb->CFR[h]);
+	/* New initialization of CFR[path_offset]. */
+	tb->CFR[h] = curcf;
 
-	RFALSE((p_s_curf && !B_IS_IN_TREE(p_s_curf)) ||
-	       (p_s_curcf && !B_IS_IN_TREE(p_s_curcf)),
-	       "PAP-8205: FR (%b) or CFR (%b) is invalid", p_s_curf, p_s_curcf);
+	RFALSE((curf && !B_IS_IN_TREE(curf)) ||
+	       (curcf && !B_IS_IN_TREE(curcf)),
+	       "PAP-8205: FR (%b) or CFR (%b) is invalid", curf, curcf);
 
 	return CARRY_ON;
 }
@@ -1203,7 +1208,7 @@
  *	h	current level of the node;
  *	inum	item number in S[h];
  *	mode	i - insert, p - paste;
- * Returns:	1 - schedule occurred; 
+ * Returns:	1 - schedule occurred;
  *	        0 - balancing for higher levels needed;
  *	       -1 - no balancing for higher levels needed;
  *	       -2 - no disk space.
@@ -1217,7 +1222,7 @@
 				   contains node being balanced.  The mnemonic is
 				   that the attempted change in node space used level
 				   is levbytes bytes. */
-	 n_ret_value;
+	 ret;
 
 	int lfree, sfree, rfree /* free space in L, S and R */ ;
 
@@ -1238,7 +1243,7 @@
 	/* we perform 8 calls to get_num_ver().  For each call we calculate five parameters.
 	   where 4th parameter is s1bytes and 5th - s2bytes
 	 */
-	short snum012[40] = { 0, };	/* s0num, s1num, s2num for 8 cases 
+	short snum012[40] = { 0, };	/* s0num, s1num, s2num for 8 cases
 					   0,1 - do not shift and do not shift but bottle
 					   2 - shift only whole item to left
 					   3 - shift to left and bottle as much as possible
@@ -1255,24 +1260,24 @@
 	/* Calculate balance parameters for creating new root. */
 	if (!Sh) {
 		if (!h)
-			reiserfs_panic(tb->tb_sb,
-				       "vs-8210: ip_check_balance: S[0] can not be 0");
-		switch (n_ret_value = get_empty_nodes(tb, h)) {
+			reiserfs_panic(tb->tb_sb, "vs-8210",
+				       "S[0] can not be 0");
+		switch (ret = get_empty_nodes(tb, h)) {
 		case CARRY_ON:
 			set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
 			return NO_BALANCING_NEEDED;	/* no balancing for higher levels needed */
 
 		case NO_DISK_SPACE:
 		case REPEAT_SEARCH:
-			return n_ret_value;
+			return ret;
 		default:
-			reiserfs_panic(tb->tb_sb,
-				       "vs-8215: ip_check_balance: incorrect return value of get_empty_nodes");
+			reiserfs_panic(tb->tb_sb, "vs-8215", "incorrect "
+				       "return value of get_empty_nodes");
 		}
 	}
 
-	if ((n_ret_value = get_parents(tb, h)) != CARRY_ON)	/* get parents of S[h] neighbors. */
-		return n_ret_value;
+	if ((ret = get_parents(tb, h)) != CARRY_ON)	/* get parents of S[h] neighbors. */
+		return ret;
 
 	sfree = B_FREE_SPACE(Sh);
 
@@ -1287,7 +1292,7 @@
 
 	create_virtual_node(tb, h);
 
-	/*  
+	/*
 	   determine maximal number of items we can shift to the left neighbor (in tb structure)
 	   and the maximal number of bytes that can flow to the left neighbor
 	   from the left most liquid item that cannot be shifted from S[0] entirely (returned value)
@@ -1348,13 +1353,13 @@
 
 	{
 		int lpar, rpar, nset, lset, rset, lrset;
-		/* 
+		/*
 		 * regular overflowing of the node
 		 */
 
-		/* get_num_ver works in 2 modes (FLOW & NO_FLOW) 
+		/* get_num_ver works in 2 modes (FLOW & NO_FLOW)
 		   lpar, rpar - number of items we can shift to left/right neighbor (including splitting item)
-		   nset, lset, rset, lrset - shows, whether flowing items give better packing 
+		   nset, lset, rset, lrset - shows, whether flowing items give better packing
 		 */
 #define FLOW 1
 #define NO_FLOW 0		/* do not any splitting */
@@ -1544,7 +1549,7 @@
  *	h	current level of the node;
  *	inum	item number in S[h];
  *	mode	i - insert, p - paste;
- * Returns:	1 - schedule occurred; 
+ * Returns:	1 - schedule occurred;
  *	        0 - balancing for higher levels needed;
  *	       -1 - no balancing for higher levels needed;
  *	       -2 - no disk space.
@@ -1559,7 +1564,7 @@
 	/* Sh is the node whose balance is currently being checked,
 	   and Fh is its father.  */
 	struct buffer_head *Sh, *Fh;
-	int maxsize, n_ret_value;
+	int maxsize, ret;
 	int lfree, rfree /* free space in L and R */ ;
 
 	Sh = PATH_H_PBUFFER(tb->tb_path, h);
@@ -1584,8 +1589,8 @@
 		return CARRY_ON;
 	}
 
-	if ((n_ret_value = get_parents(tb, h)) != CARRY_ON)
-		return n_ret_value;
+	if ((ret = get_parents(tb, h)) != CARRY_ON)
+		return ret;
 
 	/* get free space of neighbors */
 	rfree = get_rfree(tb, h);
@@ -1727,7 +1732,7 @@
  *	h	current level of the node;
  *	inum	item number in S[h];
  *	mode	i - insert, p - paste;
- * Returns:	1 - schedule occurred; 
+ * Returns:	1 - schedule occurred;
  *	        0 - balancing for higher levels needed;
  *	       -1 - no balancing for higher levels needed;
  *	       -2 - no disk space.
@@ -1742,7 +1747,7 @@
 	   attempted change in node space used level is levbytes bytes. */
 	int levbytes;
 	/* the maximal item size */
-	int maxsize, n_ret_value;
+	int maxsize, ret;
 	/* S0 is the node whose balance is currently being checked,
 	   and F0 is its father.  */
 	struct buffer_head *S0, *F0;
@@ -1764,8 +1769,8 @@
 		return NO_BALANCING_NEEDED;
 	}
 
-	if ((n_ret_value = get_parents(tb, h)) != CARRY_ON)
-		return n_ret_value;
+	if ((ret = get_parents(tb, h)) != CARRY_ON)
+		return ret;
 
 	/* get free space of neighbors */
 	rfree = get_rfree(tb, h);
@@ -1821,7 +1826,7 @@
  *	h	current level of the node;
  *	inum	item number in S[h];
  *	mode	d - delete, c - cut.
- * Returns:	1 - schedule occurred; 
+ * Returns:	1 - schedule occurred;
  *	        0 - balancing for higher levels needed;
  *	       -1 - no balancing for higher levels needed;
  *	       -2 - no disk space.
@@ -1850,7 +1855,7 @@
  *	h	current level of the node;
  *	inum	item number in S[h];
  *	mode	i - insert, p - paste, d - delete, c - cut.
- * Returns:	1 - schedule occurred; 
+ * Returns:	1 - schedule occurred;
  *	        0 - balancing for higher levels needed;
  *	       -1 - no balancing for higher levels needed;
  *	       -2 - no disk space.
@@ -1884,137 +1889,138 @@
 }
 
 /* Check whether parent at the path is the really parent of the current node.*/
-static int get_direct_parent(struct tree_balance *p_s_tb, int n_h)
+static int get_direct_parent(struct tree_balance *tb, int h)
 {
-	struct buffer_head *p_s_bh;
-	struct treepath *p_s_path = p_s_tb->tb_path;
-	int n_position,
-	    n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
+	struct buffer_head *bh;
+	struct treepath *path = tb->tb_path;
+	int position,
+	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h);
 
 	/* We are in the root or in the new root. */
-	if (n_path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
+	if (path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
 
-		RFALSE(n_path_offset < FIRST_PATH_ELEMENT_OFFSET - 1,
+		RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET - 1,
 		       "PAP-8260: invalid offset in the path");
 
-		if (PATH_OFFSET_PBUFFER(p_s_path, FIRST_PATH_ELEMENT_OFFSET)->
-		    b_blocknr == SB_ROOT_BLOCK(p_s_tb->tb_sb)) {
+		if (PATH_OFFSET_PBUFFER(path, FIRST_PATH_ELEMENT_OFFSET)->
+		    b_blocknr == SB_ROOT_BLOCK(tb->tb_sb)) {
 			/* Root is not changed. */
-			PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1) = NULL;
-			PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1) = 0;
+			PATH_OFFSET_PBUFFER(path, path_offset - 1) = NULL;
+			PATH_OFFSET_POSITION(path, path_offset - 1) = 0;
 			return CARRY_ON;
 		}
 		return REPEAT_SEARCH;	/* Root is changed and we must recalculate the path. */
 	}
 
 	if (!B_IS_IN_TREE
-	    (p_s_bh = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1)))
+	    (bh = PATH_OFFSET_PBUFFER(path, path_offset - 1)))
 		return REPEAT_SEARCH;	/* Parent in the path is not in the tree. */
 
-	if ((n_position =
-	     PATH_OFFSET_POSITION(p_s_path,
-				  n_path_offset - 1)) > B_NR_ITEMS(p_s_bh))
+	if ((position =
+	     PATH_OFFSET_POSITION(path,
+				  path_offset - 1)) > B_NR_ITEMS(bh))
 		return REPEAT_SEARCH;
 
-	if (B_N_CHILD_NUM(p_s_bh, n_position) !=
-	    PATH_OFFSET_PBUFFER(p_s_path, n_path_offset)->b_blocknr)
+	if (B_N_CHILD_NUM(bh, position) !=
+	    PATH_OFFSET_PBUFFER(path, path_offset)->b_blocknr)
 		/* Parent in the path is not parent of the current node in the tree. */
 		return REPEAT_SEARCH;
 
-	if (buffer_locked(p_s_bh)) {
-		__wait_on_buffer(p_s_bh);
-		if (FILESYSTEM_CHANGED_TB(p_s_tb))
+	if (buffer_locked(bh)) {
+		__wait_on_buffer(bh);
+		if (FILESYSTEM_CHANGED_TB(tb))
 			return REPEAT_SEARCH;
 	}
 
 	return CARRY_ON;	/* Parent in the path is unlocked and really parent of the current node.  */
 }
 
-/* Using lnum[n_h] and rnum[n_h] we should determine what neighbors
- * of S[n_h] we
- * need in order to balance S[n_h], and get them if necessary.
+/* Using lnum[h] and rnum[h] we should determine what neighbors
+ * of S[h] we
+ * need in order to balance S[h], and get them if necessary.
  * Returns:	SCHEDULE_OCCURRED - schedule occurred while the function worked;
  *	        CARRY_ON - schedule didn't occur while the function worked;
  */
-static int get_neighbors(struct tree_balance *p_s_tb, int n_h)
+static int get_neighbors(struct tree_balance *tb, int h)
 {
-	int n_child_position,
-	    n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h + 1);
-	unsigned long n_son_number;
-	struct super_block *p_s_sb = p_s_tb->tb_sb;
-	struct buffer_head *p_s_bh;
+	int child_position,
+	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h + 1);
+	unsigned long son_number;
+	struct super_block *sb = tb->tb_sb;
+	struct buffer_head *bh;
 
-	PROC_INFO_INC(p_s_sb, get_neighbors[n_h]);
+	PROC_INFO_INC(sb, get_neighbors[h]);
 
-	if (p_s_tb->lnum[n_h]) {
-		/* We need left neighbor to balance S[n_h]. */
-		PROC_INFO_INC(p_s_sb, need_l_neighbor[n_h]);
-		p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset);
+	if (tb->lnum[h]) {
+		/* We need left neighbor to balance S[h]. */
+		PROC_INFO_INC(sb, need_l_neighbor[h]);
+		bh = PATH_OFFSET_PBUFFER(tb->tb_path, path_offset);
 
-		RFALSE(p_s_bh == p_s_tb->FL[n_h] &&
-		       !PATH_OFFSET_POSITION(p_s_tb->tb_path, n_path_offset),
+		RFALSE(bh == tb->FL[h] &&
+		       !PATH_OFFSET_POSITION(tb->tb_path, path_offset),
 		       "PAP-8270: invalid position in the parent");
 
-		n_child_position =
-		    (p_s_bh ==
-		     p_s_tb->FL[n_h]) ? p_s_tb->lkey[n_h] : B_NR_ITEMS(p_s_tb->
-								       FL[n_h]);
-		n_son_number = B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position);
-		p_s_bh = sb_bread(p_s_sb, n_son_number);
-		if (!p_s_bh)
+		child_position =
+		    (bh ==
+		     tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb->
+								       FL[h]);
+		son_number = B_N_CHILD_NUM(tb->FL[h], child_position);
+		bh = sb_bread(sb, son_number);
+		if (!bh)
 			return IO_ERROR;
-		if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
-			decrement_bcount(p_s_bh);
-			PROC_INFO_INC(p_s_sb, get_neighbors_restart[n_h]);
+		if (FILESYSTEM_CHANGED_TB(tb)) {
+			brelse(bh);
+			PROC_INFO_INC(sb, get_neighbors_restart[h]);
 			return REPEAT_SEARCH;
 		}
 
-		RFALSE(!B_IS_IN_TREE(p_s_tb->FL[n_h]) ||
-		       n_child_position > B_NR_ITEMS(p_s_tb->FL[n_h]) ||
-		       B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position) !=
-		       p_s_bh->b_blocknr, "PAP-8275: invalid parent");
-		RFALSE(!B_IS_IN_TREE(p_s_bh), "PAP-8280: invalid child");
-		RFALSE(!n_h &&
-		       B_FREE_SPACE(p_s_bh) !=
-		       MAX_CHILD_SIZE(p_s_bh) -
-		       dc_size(B_N_CHILD(p_s_tb->FL[0], n_child_position)),
+		RFALSE(!B_IS_IN_TREE(tb->FL[h]) ||
+		       child_position > B_NR_ITEMS(tb->FL[h]) ||
+		       B_N_CHILD_NUM(tb->FL[h], child_position) !=
+		       bh->b_blocknr, "PAP-8275: invalid parent");
+		RFALSE(!B_IS_IN_TREE(bh), "PAP-8280: invalid child");
+		RFALSE(!h &&
+		       B_FREE_SPACE(bh) !=
+		       MAX_CHILD_SIZE(bh) -
+		       dc_size(B_N_CHILD(tb->FL[0], child_position)),
 		       "PAP-8290: invalid child size of left neighbor");
 
-		decrement_bcount(p_s_tb->L[n_h]);
-		p_s_tb->L[n_h] = p_s_bh;
+		brelse(tb->L[h]);
+		tb->L[h] = bh;
 	}
 
-	if (p_s_tb->rnum[n_h]) {	/* We need right neighbor to balance S[n_path_offset]. */
-		PROC_INFO_INC(p_s_sb, need_r_neighbor[n_h]);
-		p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset);
+	/* We need right neighbor to balance S[path_offset]. */
+	if (tb->rnum[h]) {	/* We need right neighbor to balance S[path_offset]. */
+		PROC_INFO_INC(sb, need_r_neighbor[h]);
+		bh = PATH_OFFSET_PBUFFER(tb->tb_path, path_offset);
 
-		RFALSE(p_s_bh == p_s_tb->FR[n_h] &&
-		       PATH_OFFSET_POSITION(p_s_tb->tb_path,
-					    n_path_offset) >=
-		       B_NR_ITEMS(p_s_bh),
+		RFALSE(bh == tb->FR[h] &&
+		       PATH_OFFSET_POSITION(tb->tb_path,
+					    path_offset) >=
+		       B_NR_ITEMS(bh),
 		       "PAP-8295: invalid position in the parent");
 
-		n_child_position =
-		    (p_s_bh == p_s_tb->FR[n_h]) ? p_s_tb->rkey[n_h] + 1 : 0;
-		n_son_number = B_N_CHILD_NUM(p_s_tb->FR[n_h], n_child_position);
-		p_s_bh = sb_bread(p_s_sb, n_son_number);
-		if (!p_s_bh)
+		child_position =
+		    (bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0;
+		son_number = B_N_CHILD_NUM(tb->FR[h], child_position);
+		bh = sb_bread(sb, son_number);
+		if (!bh)
 			return IO_ERROR;
-		if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
-			decrement_bcount(p_s_bh);
-			PROC_INFO_INC(p_s_sb, get_neighbors_restart[n_h]);
+		if (FILESYSTEM_CHANGED_TB(tb)) {
+			brelse(bh);
+			PROC_INFO_INC(sb, get_neighbors_restart[h]);
 			return REPEAT_SEARCH;
 		}
-		decrement_bcount(p_s_tb->R[n_h]);
-		p_s_tb->R[n_h] = p_s_bh;
+		brelse(tb->R[h]);
+		tb->R[h] = bh;
 
-		RFALSE(!n_h
-		       && B_FREE_SPACE(p_s_bh) !=
-		       MAX_CHILD_SIZE(p_s_bh) -
-		       dc_size(B_N_CHILD(p_s_tb->FR[0], n_child_position)),
+		RFALSE(!h
+		       && B_FREE_SPACE(bh) !=
+		       MAX_CHILD_SIZE(bh) -
+		       dc_size(B_N_CHILD(tb->FR[0], child_position)),
 		       "PAP-8300: invalid child size of right neighbor (%d != %d - %d)",
-		       B_FREE_SPACE(p_s_bh), MAX_CHILD_SIZE(p_s_bh),
-		       dc_size(B_N_CHILD(p_s_tb->FR[0], n_child_position)));
+		       B_FREE_SPACE(bh), MAX_CHILD_SIZE(bh),
+		       dc_size(B_N_CHILD(tb->FR[0], child_position)));
 
 	}
 	return CARRY_ON;
@@ -2088,52 +2094,46 @@
 }
 
 #ifdef CONFIG_REISERFS_CHECK
-static void tb_buffer_sanity_check(struct super_block *p_s_sb,
-				   struct buffer_head *p_s_bh,
+static void tb_buffer_sanity_check(struct super_block *sb,
+				   struct buffer_head *bh,
 				   const char *descr, int level)
 {
-	if (p_s_bh) {
-		if (atomic_read(&(p_s_bh->b_count)) <= 0) {
+	if (bh) {
+		if (atomic_read(&(bh->b_count)) <= 0)
 
-			reiserfs_panic(p_s_sb,
-				       "jmacd-1: tb_buffer_sanity_check(): negative or zero reference counter for buffer %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+			reiserfs_panic(sb, "jmacd-1", "negative or zero "
+				       "reference counter for buffer %s[%d] "
+				       "(%b)", descr, level, bh);
 
-		if (!buffer_uptodate(p_s_bh)) {
-			reiserfs_panic(p_s_sb,
-				       "jmacd-2: tb_buffer_sanity_check(): buffer is not up to date %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+		if (!buffer_uptodate(bh))
+			reiserfs_panic(sb, "jmacd-2", "buffer is not up "
+				       "to date %s[%d] (%b)",
+				       descr, level, bh);
 
-		if (!B_IS_IN_TREE(p_s_bh)) {
-			reiserfs_panic(p_s_sb,
-				       "jmacd-3: tb_buffer_sanity_check(): buffer is not in tree %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+		if (!B_IS_IN_TREE(bh))
+			reiserfs_panic(sb, "jmacd-3", "buffer is not "
+				       "in tree %s[%d] (%b)",
+				       descr, level, bh);
 
-		if (p_s_bh->b_bdev != p_s_sb->s_bdev) {
-			reiserfs_panic(p_s_sb,
-				       "jmacd-4: tb_buffer_sanity_check(): buffer has wrong device %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+		if (bh->b_bdev != sb->s_bdev)
+			reiserfs_panic(sb, "jmacd-4", "buffer has wrong "
+				       "device %s[%d] (%b)",
+				       descr, level, bh);
 
-		if (p_s_bh->b_size != p_s_sb->s_blocksize) {
-			reiserfs_panic(p_s_sb,
-				       "jmacd-5: tb_buffer_sanity_check(): buffer has wrong blocksize %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+		if (bh->b_size != sb->s_blocksize)
+			reiserfs_panic(sb, "jmacd-5", "buffer has wrong "
+				       "blocksize %s[%d] (%b)",
+				       descr, level, bh);
 
-		if (p_s_bh->b_blocknr > SB_BLOCK_COUNT(p_s_sb)) {
-			reiserfs_panic(p_s_sb,
-				       "jmacd-6: tb_buffer_sanity_check(): buffer block number too high %s[%d] (%b)\n",
-				       descr, level, p_s_bh);
-		}
+		if (bh->b_blocknr > SB_BLOCK_COUNT(sb))
+			reiserfs_panic(sb, "jmacd-6", "buffer block "
+				       "number too high %s[%d] (%b)",
+				       descr, level, bh);
 	}
 }
 #else
-static void tb_buffer_sanity_check(struct super_block *p_s_sb,
-				   struct buffer_head *p_s_bh,
+static void tb_buffer_sanity_check(struct super_block *sb,
+				   struct buffer_head *bh,
 				   const char *descr, int level)
 {;
 }
@@ -2144,7 +2144,7 @@
 	return reiserfs_prepare_for_journal(s, bh, 0);
 }
 
-static int wait_tb_buffers_until_unlocked(struct tree_balance *p_s_tb)
+static int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
 {
 	struct buffer_head *locked;
 #ifdef CONFIG_REISERFS_CHECK
@@ -2156,95 +2156,94 @@
 
 		locked = NULL;
 
-		for (i = p_s_tb->tb_path->path_length;
+		for (i = tb->tb_path->path_length;
 		     !locked && i > ILLEGAL_PATH_ELEMENT_OFFSET; i--) {
-			if (PATH_OFFSET_PBUFFER(p_s_tb->tb_path, i)) {
+			if (PATH_OFFSET_PBUFFER(tb->tb_path, i)) {
 				/* if I understand correctly, we can only be sure the last buffer
 				 ** in the path is in the tree --clm
 				 */
 #ifdef CONFIG_REISERFS_CHECK
-				if (PATH_PLAST_BUFFER(p_s_tb->tb_path) ==
-				    PATH_OFFSET_PBUFFER(p_s_tb->tb_path, i)) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
+				if (PATH_PLAST_BUFFER(tb->tb_path) ==
+				    PATH_OFFSET_PBUFFER(tb->tb_path, i))
+					tb_buffer_sanity_check(tb->tb_sb,
 							       PATH_OFFSET_PBUFFER
-							       (p_s_tb->tb_path,
+							       (tb->tb_path,
 								i), "S",
-							       p_s_tb->tb_path->
+							       tb->tb_path->
 							       path_length - i);
-				}
 #endif
-				if (!clear_all_dirty_bits(p_s_tb->tb_sb,
+				if (!clear_all_dirty_bits(tb->tb_sb,
 							  PATH_OFFSET_PBUFFER
-							  (p_s_tb->tb_path,
+							  (tb->tb_path,
 							   i))) {
 					locked =
-					    PATH_OFFSET_PBUFFER(p_s_tb->tb_path,
+					    PATH_OFFSET_PBUFFER(tb->tb_path,
 								i);
 				}
 			}
 		}
 
-		for (i = 0; !locked && i < MAX_HEIGHT && p_s_tb->insert_size[i];
+		for (i = 0; !locked && i < MAX_HEIGHT && tb->insert_size[i];
 		     i++) {
 
-			if (p_s_tb->lnum[i]) {
+			if (tb->lnum[i]) {
 
-				if (p_s_tb->L[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->L[i],
+				if (tb->L[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->L[i],
 							       "L", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->L[i]))
-						locked = p_s_tb->L[i];
+					    (tb->tb_sb, tb->L[i]))
+						locked = tb->L[i];
 				}
 
-				if (!locked && p_s_tb->FL[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->FL[i],
+				if (!locked && tb->FL[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->FL[i],
 							       "FL", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->FL[i]))
-						locked = p_s_tb->FL[i];
+					    (tb->tb_sb, tb->FL[i]))
+						locked = tb->FL[i];
 				}
 
-				if (!locked && p_s_tb->CFL[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->CFL[i],
+				if (!locked && tb->CFL[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->CFL[i],
 							       "CFL", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->CFL[i]))
-						locked = p_s_tb->CFL[i];
+					    (tb->tb_sb, tb->CFL[i]))
+						locked = tb->CFL[i];
 				}
 
 			}
 
-			if (!locked && (p_s_tb->rnum[i])) {
+			if (!locked && (tb->rnum[i])) {
 
-				if (p_s_tb->R[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->R[i],
+				if (tb->R[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->R[i],
 							       "R", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->R[i]))
-						locked = p_s_tb->R[i];
+					    (tb->tb_sb, tb->R[i]))
+						locked = tb->R[i];
 				}
 
-				if (!locked && p_s_tb->FR[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->FR[i],
+				if (!locked && tb->FR[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->FR[i],
 							       "FR", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->FR[i]))
-						locked = p_s_tb->FR[i];
+					    (tb->tb_sb, tb->FR[i]))
+						locked = tb->FR[i];
 				}
 
-				if (!locked && p_s_tb->CFR[i]) {
-					tb_buffer_sanity_check(p_s_tb->tb_sb,
-							       p_s_tb->CFR[i],
+				if (!locked && tb->CFR[i]) {
+					tb_buffer_sanity_check(tb->tb_sb,
+							       tb->CFR[i],
 							       "CFR", i);
 					if (!clear_all_dirty_bits
-					    (p_s_tb->tb_sb, p_s_tb->CFR[i]))
-						locked = p_s_tb->CFR[i];
+					    (tb->tb_sb, tb->CFR[i]))
+						locked = tb->CFR[i];
 				}
 			}
 		}
@@ -2257,10 +2256,10 @@
 		 ** --clm
 		 */
 		for (i = 0; !locked && i < MAX_FEB_SIZE; i++) {
-			if (p_s_tb->FEB[i]) {
+			if (tb->FEB[i]) {
 				if (!clear_all_dirty_bits
-				    (p_s_tb->tb_sb, p_s_tb->FEB[i]))
-					locked = p_s_tb->FEB[i];
+				    (tb->tb_sb, tb->FEB[i]))
+					locked = tb->FEB[i];
 			}
 		}
 
@@ -2268,21 +2267,20 @@
 #ifdef CONFIG_REISERFS_CHECK
 			repeat_counter++;
 			if ((repeat_counter % 10000) == 0) {
-				reiserfs_warning(p_s_tb->tb_sb,
-						 "wait_tb_buffers_until_released(): too many "
-						 "iterations waiting for buffer to unlock "
+				reiserfs_warning(tb->tb_sb, "reiserfs-8200",
+						 "too many iterations waiting "
+						 "for buffer to unlock "
 						 "(%b)", locked);
 
 				/* Don't loop forever.  Try to recover from possible error. */
 
-				return (FILESYSTEM_CHANGED_TB(p_s_tb)) ?
+				return (FILESYSTEM_CHANGED_TB(tb)) ?
 				    REPEAT_SEARCH : CARRY_ON;
 			}
 #endif
 			__wait_on_buffer(locked);
-			if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
+			if (FILESYSTEM_CHANGED_TB(tb))
 				return REPEAT_SEARCH;
-			}
 		}
 
 	} while (locked);
@@ -2295,15 +2293,15 @@
  *	analyze what and where should be moved;
  *	get sufficient number of new nodes;
  * Balancing will start only after all resources will be collected at a time.
- * 
+ *
  * When ported to SMP kernels, only at the last moment after all needed nodes
  * are collected in cache, will the resources be locked using the usual
  * textbook ordered lock acquisition algorithms.  Note that ensuring that
  * this code neither write locks what it does not need to write lock nor locks out of order
  * will be a pain in the butt that could have been avoided.  Grumble grumble. -Hans
- * 
+ *
  * fix is meant in the sense of render unchanging
- * 
+ *
  * Latency might be improved by first gathering a list of what buffers are needed
  * and then getting as many of them in parallel as possible? -Hans
  *
@@ -2312,159 +2310,160 @@
  *	tb	tree_balance structure;
  *	inum	item number in S[h];
  *      pos_in_item - comment this if you can
- *      ins_ih & ins_sd are used when inserting
+ *      ins_ih	item head of item being inserted
+ *	data	inserted item or data to be pasted
  * Returns:	1 - schedule occurred while the function worked;
  *	        0 - schedule didn't occur while the function worked;
- *             -1 - if no_disk_space 
+ *             -1 - if no_disk_space
  */
 
-int fix_nodes(int n_op_mode, struct tree_balance *p_s_tb, struct item_head *p_s_ins_ih,	// item head of item being inserted
-	      const void *data	// inserted item or data to be pasted
-    )
+int fix_nodes(int op_mode, struct tree_balance *tb,
+	      struct item_head *ins_ih, const void *data)
 {
-	int n_ret_value, n_h, n_item_num = PATH_LAST_POSITION(p_s_tb->tb_path);
-	int n_pos_in_item;
+	int ret, h, item_num = PATH_LAST_POSITION(tb->tb_path);
+	int pos_in_item;
 
 	/* we set wait_tb_buffers_run when we have to restore any dirty bits cleared
 	 ** during wait_tb_buffers_run
 	 */
 	int wait_tb_buffers_run = 0;
-	struct buffer_head *p_s_tbS0 = PATH_PLAST_BUFFER(p_s_tb->tb_path);
+	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
 
-	++REISERFS_SB(p_s_tb->tb_sb)->s_fix_nodes;
+	++REISERFS_SB(tb->tb_sb)->s_fix_nodes;
 
-	n_pos_in_item = p_s_tb->tb_path->pos_in_item;
+	pos_in_item = tb->tb_path->pos_in_item;
 
-	p_s_tb->fs_gen = get_generation(p_s_tb->tb_sb);
+	tb->fs_gen = get_generation(tb->tb_sb);
 
 	/* we prepare and log the super here so it will already be in the
 	 ** transaction when do_balance needs to change it.
 	 ** This way do_balance won't have to schedule when trying to prepare
 	 ** the super for logging
 	 */
-	reiserfs_prepare_for_journal(p_s_tb->tb_sb,
-				     SB_BUFFER_WITH_SB(p_s_tb->tb_sb), 1);
-	journal_mark_dirty(p_s_tb->transaction_handle, p_s_tb->tb_sb,
-			   SB_BUFFER_WITH_SB(p_s_tb->tb_sb));
-	if (FILESYSTEM_CHANGED_TB(p_s_tb))
+	reiserfs_prepare_for_journal(tb->tb_sb,
+				     SB_BUFFER_WITH_SB(tb->tb_sb), 1);
+	journal_mark_dirty(tb->transaction_handle, tb->tb_sb,
+			   SB_BUFFER_WITH_SB(tb->tb_sb));
+	if (FILESYSTEM_CHANGED_TB(tb))
 		return REPEAT_SEARCH;
 
 	/* if it possible in indirect_to_direct conversion */
-	if (buffer_locked(p_s_tbS0)) {
-		__wait_on_buffer(p_s_tbS0);
-		if (FILESYSTEM_CHANGED_TB(p_s_tb))
+	if (buffer_locked(tbS0)) {
+		__wait_on_buffer(tbS0);
+		if (FILESYSTEM_CHANGED_TB(tb))
 			return REPEAT_SEARCH;
 	}
 #ifdef CONFIG_REISERFS_CHECK
 	if (cur_tb) {
 		print_cur_tb("fix_nodes");
-		reiserfs_panic(p_s_tb->tb_sb,
-			       "PAP-8305: fix_nodes:  there is pending do_balance");
+		reiserfs_panic(tb->tb_sb, "PAP-8305",
+			       "there is pending do_balance");
 	}
 
-	if (!buffer_uptodate(p_s_tbS0) || !B_IS_IN_TREE(p_s_tbS0)) {
-		reiserfs_panic(p_s_tb->tb_sb,
-			       "PAP-8320: fix_nodes: S[0] (%b %z) is not uptodate "
-			       "at the beginning of fix_nodes or not in tree (mode %c)",
-			       p_s_tbS0, p_s_tbS0, n_op_mode);
-	}
+	if (!buffer_uptodate(tbS0) || !B_IS_IN_TREE(tbS0))
+		reiserfs_panic(tb->tb_sb, "PAP-8320", "S[0] (%b %z) is "
+			       "not uptodate at the beginning of fix_nodes "
+			       "or not in tree (mode %c)",
+			       tbS0, tbS0, op_mode);
 
 	/* Check parameters. */
-	switch (n_op_mode) {
+	switch (op_mode) {
 	case M_INSERT:
-		if (n_item_num <= 0 || n_item_num > B_NR_ITEMS(p_s_tbS0))
-			reiserfs_panic(p_s_tb->tb_sb,
-				       "PAP-8330: fix_nodes: Incorrect item number %d (in S0 - %d) in case of insert",
-				       n_item_num, B_NR_ITEMS(p_s_tbS0));
+		if (item_num <= 0 || item_num > B_NR_ITEMS(tbS0))
+			reiserfs_panic(tb->tb_sb, "PAP-8330", "Incorrect "
+				       "item number %d (in S0 - %d) in case "
+				       "of insert", item_num,
+				       B_NR_ITEMS(tbS0));
 		break;
 	case M_PASTE:
 	case M_DELETE:
 	case M_CUT:
-		if (n_item_num < 0 || n_item_num >= B_NR_ITEMS(p_s_tbS0)) {
-			print_block(p_s_tbS0, 0, -1, -1);
-			reiserfs_panic(p_s_tb->tb_sb,
-				       "PAP-8335: fix_nodes: Incorrect item number(%d); mode = %c insert_size = %d\n",
-				       n_item_num, n_op_mode,
-				       p_s_tb->insert_size[0]);
+		if (item_num < 0 || item_num >= B_NR_ITEMS(tbS0)) {
+			print_block(tbS0, 0, -1, -1);
+			reiserfs_panic(tb->tb_sb, "PAP-8335", "Incorrect "
+				       "item number(%d); mode = %c "
+				       "insert_size = %d",
+				       item_num, op_mode,
+				       tb->insert_size[0]);
 		}
 		break;
 	default:
-		reiserfs_panic(p_s_tb->tb_sb,
-			       "PAP-8340: fix_nodes: Incorrect mode of operation");
+		reiserfs_panic(tb->tb_sb, "PAP-8340", "Incorrect mode "
+			       "of operation");
 	}
 #endif
 
-	if (get_mem_for_virtual_node(p_s_tb) == REPEAT_SEARCH)
+	if (get_mem_for_virtual_node(tb) == REPEAT_SEARCH)
 		// FIXME: maybe -ENOMEM when tb->vn_buf == 0? Now just repeat
 		return REPEAT_SEARCH;
 
-	/* Starting from the leaf level; for all levels n_h of the tree. */
-	for (n_h = 0; n_h < MAX_HEIGHT && p_s_tb->insert_size[n_h]; n_h++) {
-		if ((n_ret_value = get_direct_parent(p_s_tb, n_h)) != CARRY_ON) {
+	/* Starting from the leaf level; for all levels h of the tree. */
+	for (h = 0; h < MAX_HEIGHT && tb->insert_size[h]; h++) {
+		ret = get_direct_parent(tb, h);
+		if (ret != CARRY_ON)
 			goto repeat;
-		}
 
-		if ((n_ret_value =
-		     check_balance(n_op_mode, p_s_tb, n_h, n_item_num,
-				   n_pos_in_item, p_s_ins_ih,
-				   data)) != CARRY_ON) {
-			if (n_ret_value == NO_BALANCING_NEEDED) {
+		ret = check_balance(op_mode, tb, h, item_num,
+				    pos_in_item, ins_ih, data);
+		if (ret != CARRY_ON) {
+			if (ret == NO_BALANCING_NEEDED) {
 				/* No balancing for higher levels needed. */
-				if ((n_ret_value =
-				     get_neighbors(p_s_tb, n_h)) != CARRY_ON) {
+				ret = get_neighbors(tb, h);
+				if (ret != CARRY_ON)
 					goto repeat;
-				}
-				if (n_h != MAX_HEIGHT - 1)
-					p_s_tb->insert_size[n_h + 1] = 0;
+				if (h != MAX_HEIGHT - 1)
+					tb->insert_size[h + 1] = 0;
 				/* ok, analysis and resource gathering are complete */
 				break;
 			}
 			goto repeat;
 		}
 
-		if ((n_ret_value = get_neighbors(p_s_tb, n_h)) != CARRY_ON) {
+		ret = get_neighbors(tb, h);
+		if (ret != CARRY_ON)
 			goto repeat;
-		}
 
-		if ((n_ret_value = get_empty_nodes(p_s_tb, n_h)) != CARRY_ON) {
-			goto repeat;	/* No disk space, or schedule occurred and
-					   analysis may be invalid and needs to be redone. */
-		}
+		/* No disk space, or schedule occurred and analysis may be
+		 * invalid and needs to be redone. */
+		ret = get_empty_nodes(tb, h);
+		if (ret != CARRY_ON)
+			goto repeat;
 
-		if (!PATH_H_PBUFFER(p_s_tb->tb_path, n_h)) {
+		if (!PATH_H_PBUFFER(tb->tb_path, h)) {
 			/* We have a positive insert size but no nodes exist on this
 			   level, this means that we are creating a new root. */
 
-			RFALSE(p_s_tb->blknum[n_h] != 1,
+			RFALSE(tb->blknum[h] != 1,
 			       "PAP-8350: creating new empty root");
 
-			if (n_h < MAX_HEIGHT - 1)
-				p_s_tb->insert_size[n_h + 1] = 0;
-		} else if (!PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1)) {
-			if (p_s_tb->blknum[n_h] > 1) {
-				/* The tree needs to be grown, so this node S[n_h]
+			if (h < MAX_HEIGHT - 1)
+				tb->insert_size[h + 1] = 0;
+		} else if (!PATH_H_PBUFFER(tb->tb_path, h + 1)) {
+			if (tb->blknum[h] > 1) {
+				/* The tree needs to be grown, so this node S[h]
 				   which is the root node is split into two nodes,
-				   and a new node (S[n_h+1]) will be created to
+				   and a new node (S[h+1]) will be created to
 				   become the root node.  */
 
-				RFALSE(n_h == MAX_HEIGHT - 1,
+				RFALSE(h == MAX_HEIGHT - 1,
 				       "PAP-8355: attempt to create too high of a tree");
 
-				p_s_tb->insert_size[n_h + 1] =
+				tb->insert_size[h + 1] =
 				    (DC_SIZE +
-				     KEY_SIZE) * (p_s_tb->blknum[n_h] - 1) +
+				     KEY_SIZE) * (tb->blknum[h] - 1) +
 				    DC_SIZE;
-			} else if (n_h < MAX_HEIGHT - 1)
-				p_s_tb->insert_size[n_h + 1] = 0;
+			} else if (h < MAX_HEIGHT - 1)
+				tb->insert_size[h + 1] = 0;
 		} else
-			p_s_tb->insert_size[n_h + 1] =
-			    (DC_SIZE + KEY_SIZE) * (p_s_tb->blknum[n_h] - 1);
+			tb->insert_size[h + 1] =
+			    (DC_SIZE + KEY_SIZE) * (tb->blknum[h] - 1);
 	}
 
-	if ((n_ret_value = wait_tb_buffers_until_unlocked(p_s_tb)) == CARRY_ON) {
-		if (FILESYSTEM_CHANGED_TB(p_s_tb)) {
+	ret = wait_tb_buffers_until_unlocked(tb);
+	if (ret == CARRY_ON) {
+		if (FILESYSTEM_CHANGED_TB(tb)) {
 			wait_tb_buffers_run = 1;
-			n_ret_value = REPEAT_SEARCH;
+			ret = REPEAT_SEARCH;
 			goto repeat;
 		} else {
 			return CARRY_ON;
@@ -2485,57 +2484,57 @@
 
 		/* Release path buffers. */
 		if (wait_tb_buffers_run) {
-			pathrelse_and_restore(p_s_tb->tb_sb, p_s_tb->tb_path);
+			pathrelse_and_restore(tb->tb_sb, tb->tb_path);
 		} else {
-			pathrelse(p_s_tb->tb_path);
+			pathrelse(tb->tb_path);
 		}
 		/* brelse all resources collected for balancing */
 		for (i = 0; i < MAX_HEIGHT; i++) {
 			if (wait_tb_buffers_run) {
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->L[i]);
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->R[i]);
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->FL[i]);
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->FR[i]);
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->L[i]);
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->R[i]);
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->FL[i]);
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->FR[i]);
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->
 								 CFL[i]);
-				reiserfs_restore_prepared_buffer(p_s_tb->tb_sb,
-								 p_s_tb->
+				reiserfs_restore_prepared_buffer(tb->tb_sb,
+								 tb->
 								 CFR[i]);
 			}
 
-			brelse(p_s_tb->L[i]);
-			p_s_tb->L[i] = NULL;
-			brelse(p_s_tb->R[i]);
-			p_s_tb->R[i] = NULL;
-			brelse(p_s_tb->FL[i]);
-			p_s_tb->FL[i] = NULL;
-			brelse(p_s_tb->FR[i]);
-			p_s_tb->FR[i] = NULL;
-			brelse(p_s_tb->CFL[i]);
-			p_s_tb->CFL[i] = NULL;
-			brelse(p_s_tb->CFR[i]);
-			p_s_tb->CFR[i] = NULL;
+			brelse(tb->L[i]);
+			brelse(tb->R[i]);
+			brelse(tb->FL[i]);
+			brelse(tb->FR[i]);
+			brelse(tb->CFL[i]);
+			brelse(tb->CFR[i]);
+
+			tb->L[i] = NULL;
+			tb->R[i] = NULL;
+			tb->FL[i] = NULL;
+			tb->FR[i] = NULL;
+			tb->CFL[i] = NULL;
+			tb->CFR[i] = NULL;
 		}
 
 		if (wait_tb_buffers_run) {
 			for (i = 0; i < MAX_FEB_SIZE; i++) {
-				if (p_s_tb->FEB[i]) {
+				if (tb->FEB[i])
 					reiserfs_restore_prepared_buffer
-					    (p_s_tb->tb_sb, p_s_tb->FEB[i]);
-				}
+					    (tb->tb_sb, tb->FEB[i]);
 			}
 		}
-		return n_ret_value;
+		return ret;
 	}
 
 }
 
-/* Anatoly will probably forgive me renaming p_s_tb to tb. I just
+/* Anatoly will probably forgive me renaming tb to tb. I just
    wanted to make lines shorter */
 void unfix_nodes(struct tree_balance *tb)
 {
diff --git a/fs/reiserfs/hashes.c b/fs/reiserfs/hashes.c
index e664ac1..6471c67 100644
--- a/fs/reiserfs/hashes.c
+++ b/fs/reiserfs/hashes.c
@@ -7,7 +7,7 @@
  * (see Applied Cryptography, 2nd edition, p448).
  *
  * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
- * 
+ *
  * Jeremy has agreed to the contents of reiserfs/README. -Hans
  * Yura's function is added (04/07/2000)
  */
diff --git a/fs/reiserfs/ibalance.c b/fs/reiserfs/ibalance.c
index de391a8..2074fd9 100644
--- a/fs/reiserfs/ibalance.c
+++ b/fs/reiserfs/ibalance.c
@@ -105,8 +105,8 @@
 		break;
 
 	default:
-		reiserfs_panic(tb->tb_sb,
-			       "internal_define_dest_src_infos: shift type is unknown (%d)",
+		reiserfs_panic(tb->tb_sb, "ibalance-1",
+			       "shift type is unknown (%d)",
 			       shift_mode);
 	}
 }
@@ -278,7 +278,7 @@
 
 /* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest
 * last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest
- * last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest 
+ * last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest
  */
 static void internal_copy_pointers_items(struct buffer_info *dest_bi,
 					 struct buffer_head *src,
@@ -385,7 +385,7 @@
 	if (last_first == FIRST_TO_LAST) {	/* shift_left occurs */
 		first_pointer = 0;
 		first_item = 0;
-		/* delete cpy_num - del_par pointers and keys starting for pointers with first_pointer, 
+		/* delete cpy_num - del_par pointers and keys starting for pointers with first_pointer,
 		   for key - with first_item */
 		internal_delete_pointers_items(src_bi, first_pointer,
 					       first_item, cpy_num - del_par);
@@ -453,7 +453,7 @@
 	}
 }
 
-/* Insert d_key'th (delimiting) key from buffer cfl to tail of dest. 
+/* Insert d_key'th (delimiting) key from buffer cfl to tail of dest.
  * Copy pointer_amount node pointers and pointer_amount - 1 items from buffer src to buffer dest.
  * Replace  d_key'th key in buffer cfl.
  * Delete pointer_amount items and node pointers from buffer src.
@@ -518,7 +518,7 @@
 	/*    internal_move_pointers_items (tb->L[h], tb->S[h], FIRST_TO_LAST, pointer_amount, 1); */
 }
 
-/* Insert d_key'th (delimiting) key from buffer cfr to head of dest. 
+/* Insert d_key'th (delimiting) key from buffer cfr to head of dest.
  * Copy n node pointers and n - 1 items from buffer src to buffer dest.
  * Replace  d_key'th key in buffer cfr.
  * Delete n items and node pointers from buffer src.
@@ -702,8 +702,8 @@
 
 		return;
 	}
-	reiserfs_panic(tb->tb_sb,
-		       "balance_internal_when_delete: unexpected tb->lnum[%d]==%d or tb->rnum[%d]==%d",
+	reiserfs_panic(tb->tb_sb, "ibalance-2",
+		       "unexpected tb->lnum[%d]==%d or tb->rnum[%d]==%d",
 		       h, tb->lnum[h], h, tb->rnum[h]);
 }
 
@@ -749,7 +749,7 @@
        this means that new pointers and items must be inserted AFTER *
        child_pos
        }
-       else 
+       else
        {
        it is the position of the leftmost pointer that must be deleted (together with
        its corresponding key to the left of the pointer)
@@ -940,8 +940,8 @@
 		struct block_head *blkh;
 
 		if (tb->blknum[h] != 1)
-			reiserfs_panic(NULL,
-				       "balance_internal: One new node required for creating the new root");
+			reiserfs_panic(NULL, "ibalance-3", "One new node "
+				       "required for creating the new root");
 		/* S[h] = empty buffer from the list FEB. */
 		tbSh = get_FEB(tb);
 		blkh = B_BLK_HEAD(tbSh);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 823227a..6fd0f47 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -363,7 +363,7 @@
 		}
 		/* make sure we don't read more bytes than actually exist in
 		 ** the file.  This can happen in odd cases where i_size isn't
-		 ** correct, and when direct item padding results in a few 
+		 ** correct, and when direct item padding results in a few
 		 ** extra bytes at the end of the direct item
 		 */
 		if ((le_ih_k_offset(ih) + path.pos_in_item) > inode->i_size)
@@ -438,15 +438,15 @@
 ** -ENOENT instead of a valid buffer.  block_prepare_write expects to
 ** be able to do i/o on the buffers returned, unless an error value
 ** is also returned.
-** 
+**
 ** So, this allows block_prepare_write to be used for reading a single block
 ** in a page.  Where it does not produce a valid page for holes, or past the
 ** end of the file.  This turns out to be exactly what we need for reading
 ** tails for conversion.
 **
 ** The point of the wrapper is forcing a certain value for create, even
-** though the VFS layer is calling this function with create==1.  If you 
-** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, 
+** though the VFS layer is calling this function with create==1.  If you
+** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block,
 ** don't use this function.
 */
 static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,
@@ -602,7 +602,7 @@
 	int done;
 	int fs_gen;
 	struct reiserfs_transaction_handle *th = NULL;
-	/* space reserved in transaction batch: 
+	/* space reserved in transaction batch:
 	   . 3 balancings in direct->indirect conversion
 	   . 1 block involved into reiserfs_update_sd()
 	   XXX in practically impossible worst case direct2indirect()
@@ -754,7 +754,7 @@
 		reiserfs_write_unlock(inode->i_sb);
 
 		/* the item was found, so new blocks were not added to the file
-		 ** there is no need to make sure the inode is updated with this 
+		 ** there is no need to make sure the inode is updated with this
 		 ** transaction
 		 */
 		return retval;
@@ -841,10 +841,12 @@
 							  tail_offset);
 				if (retval) {
 					if (retval != -ENOSPC)
-						reiserfs_warning(inode->i_sb,
-								 "clm-6004: convert tail failed inode %lu, error %d",
-								 inode->i_ino,
-								 retval);
+						reiserfs_error(inode->i_sb,
+							"clm-6004",
+							"convert tail failed "
+							"inode %lu, error %d",
+							inode->i_ino,
+							retval);
 					if (allocated_block_nr) {
 						/* the bitmap, the super, and the stat data == 3 */
 						if (!th)
@@ -984,7 +986,7 @@
 
 		/* this loop could log more blocks than we had originally asked
 		 ** for.  So, we have to allow the transaction to end if it is
-		 ** too big or too full.  Update the inode so things are 
+		 ** too big or too full.  Update the inode so things are
 		 ** consistent if we crash before the function returns
 		 **
 		 ** release the path so that anybody waiting on the path before
@@ -995,7 +997,7 @@
 			if (retval)
 				goto failure;
 		}
-		/* inserting indirect pointers for a hole can take a 
+		/* inserting indirect pointers for a hole can take a
 		 ** long time.  reschedule if needed
 		 */
 		cond_resched();
@@ -1006,8 +1008,7 @@
 			goto failure;
 		}
 		if (retval == POSITION_FOUND) {
-			reiserfs_warning(inode->i_sb,
-					 "vs-825: reiserfs_get_block: "
+			reiserfs_warning(inode->i_sb, "vs-825",
 					 "%K should not be found", &key);
 			retval = -EEXIST;
 			if (allocated_block_nr)
@@ -1299,8 +1300,7 @@
 	ih = PATH_PITEM_HEAD(path);
 
 	if (!is_statdata_le_ih(ih))
-		reiserfs_panic(inode->i_sb,
-			       "vs-13065: update_stat_data: key %k, found item %h",
+		reiserfs_panic(inode->i_sb, "vs-13065", "key %k, found item %h",
 			       INODE_PKEY(inode), ih);
 
 	if (stat_data_v1(ih)) {
@@ -1332,10 +1332,9 @@
 		/* look for the object's stat data */
 		retval = search_item(inode->i_sb, &key, &path);
 		if (retval == IO_ERROR) {
-			reiserfs_warning(inode->i_sb,
-					 "vs-13050: reiserfs_update_sd: "
-					 "i/o failure occurred trying to update %K stat data",
-					 &key);
+			reiserfs_error(inode->i_sb, "vs-13050",
+				       "i/o failure occurred trying to "
+				       "update %K stat data", &key);
 			return;
 		}
 		if (retval == ITEM_NOT_FOUND) {
@@ -1345,9 +1344,9 @@
 				/*reiserfs_warning (inode->i_sb, "vs-13050: reiserfs_update_sd: i_nlink == 0, stat data not found"); */
 				return;
 			}
-			reiserfs_warning(inode->i_sb,
-					 "vs-13060: reiserfs_update_sd: "
-					 "stat data of object %k (nlink == %d) not found (pos %d)",
+			reiserfs_warning(inode->i_sb, "vs-13060",
+					 "stat data of object %k (nlink == %d) "
+					 "not found (pos %d)",
 					 INODE_PKEY(inode), inode->i_nlink,
 					 pos);
 			reiserfs_check_path(&path);
@@ -1424,10 +1423,9 @@
 	/* look for the object's stat data */
 	retval = search_item(inode->i_sb, &key, &path_to_sd);
 	if (retval == IO_ERROR) {
-		reiserfs_warning(inode->i_sb,
-				 "vs-13070: reiserfs_read_locked_inode: "
-				 "i/o failure occurred trying to find stat data of %K",
-				 &key);
+		reiserfs_error(inode->i_sb, "vs-13070",
+			       "i/o failure occurred trying to find "
+			       "stat data of %K", &key);
 		reiserfs_make_bad_inode(inode);
 		return;
 	}
@@ -1446,7 +1444,7 @@
 	   update sd on unlink all that is required is to check for nlink
 	   here. This bug was first found by Sizif when debugging
 	   SquidNG/Butterfly, forgotten, and found again after Philippe
-	   Gramoulle <philippe.gramoulle@mmania.com> reproduced it. 
+	   Gramoulle <philippe.gramoulle@mmania.com> reproduced it.
 
 	   More logical fix would require changes in fs/inode.c:iput() to
 	   remove inode from hash-table _after_ fs cleaned disk stuff up and
@@ -1457,8 +1455,7 @@
 	   during mount (fs/reiserfs/super.c:finish_unfinished()). */
 	if ((inode->i_nlink == 0) &&
 	    !REISERFS_SB(inode->i_sb)->s_is_unlinked_ok) {
-		reiserfs_warning(inode->i_sb,
-				 "vs-13075: reiserfs_read_locked_inode: "
+		reiserfs_warning(inode->i_sb, "vs-13075",
 				 "dead inode read from disk %K. "
 				 "This is likely to be race with knfsd. Ignore",
 				 &key);
@@ -1555,7 +1552,7 @@
 	 */
 	if (fh_type > fh_len) {
 		if (fh_type != 6 || fh_len != 5)
-			reiserfs_warning(sb,
+			reiserfs_warning(sb, "reiserfs-13077",
 				"nfsd/reiserfs, fhtype=%d, len=%d - odd",
 				fh_type, fh_len);
 		fh_type = 5;
@@ -1622,7 +1619,7 @@
 	if (inode->i_sb->s_flags & MS_RDONLY)
 		return -EROFS;
 	/* memory pressure can sometimes initiate write_inode calls with sync == 1,
-	 ** these cases are just when the system needs ram, not when the 
+	 ** these cases are just when the system needs ram, not when the
 	 ** inode needs to reach disk for safety, and they can safely be
 	 ** ignored because the altered inode has already been logged.
 	 */
@@ -1680,13 +1677,13 @@
 	/* look for place in the tree for new item */
 	retval = search_item(sb, &key, path);
 	if (retval == IO_ERROR) {
-		reiserfs_warning(sb, "vs-13080: reiserfs_new_directory: "
-				 "i/o failure occurred creating new directory");
+		reiserfs_error(sb, "vs-13080",
+			       "i/o failure occurred creating new directory");
 		return -EIO;
 	}
 	if (retval == ITEM_FOUND) {
 		pathrelse(path);
-		reiserfs_warning(sb, "vs-13070: reiserfs_new_directory: "
+		reiserfs_warning(sb, "vs-13070",
 				 "object with this key exists (%k)",
 				 &(ih->ih_key));
 		return -EEXIST;
@@ -1720,13 +1717,13 @@
 	/* look for place in the tree for new item */
 	retval = search_item(sb, &key, path);
 	if (retval == IO_ERROR) {
-		reiserfs_warning(sb, "vs-13080: reiserfs_new_symlinik: "
-				 "i/o failure occurred creating new symlink");
+		reiserfs_error(sb, "vs-13080",
+			       "i/o failure occurred creating new symlink");
 		return -EIO;
 	}
 	if (retval == ITEM_FOUND) {
 		pathrelse(path);
-		reiserfs_warning(sb, "vs-13080: reiserfs_new_symlink: "
+		reiserfs_warning(sb, "vs-13080",
 				 "object with this key exists (%k)",
 				 &(ih->ih_key));
 		return -EEXIST;
@@ -1739,7 +1736,7 @@
 /* inserts the stat data into the tree, and then calls
    reiserfs_new_directory (to insert ".", ".." item if new object is
    directory) or reiserfs_new_symlink (to insert symlink body if new
-   object is symlink) or nothing (if new object is regular file) 
+   object is symlink) or nothing (if new object is regular file)
 
    NOTE! uid and gid must already be set in the inode.  If we return
    non-zero due to an error, we have to drop the quota previously allocated
@@ -1747,10 +1744,11 @@
    if we return non-zero, we also end the transaction.  */
 int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 		       struct inode *dir, int mode, const char *symname,
-		       /* 0 for regular, EMTRY_DIR_SIZE for dirs, 
+		       /* 0 for regular, EMTRY_DIR_SIZE for dirs,
 		          strlen (symname) for symlinks) */
 		       loff_t i_size, struct dentry *dentry,
-		       struct inode *inode)
+		       struct inode *inode,
+		       struct reiserfs_security_handle *security)
 {
 	struct super_block *sb;
 	struct reiserfs_iget_args args;
@@ -1796,7 +1794,7 @@
 		goto out_bad_inode;
 	}
 	if (old_format_only(sb))
-		/* not a perfect generation count, as object ids can be reused, but 
+		/* not a perfect generation count, as object ids can be reused, but
 		 ** this is as good as reiserfs can do right now.
 		 ** note that the private part of inode isn't filled in yet, we have
 		 ** to use the directory.
@@ -1917,9 +1915,8 @@
 		goto out_inserted_sd;
 	}
 
-	/* XXX CHECK THIS */
 	if (reiserfs_posixacl(inode->i_sb)) {
-		retval = reiserfs_inherit_default_acl(dir, dentry, inode);
+		retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
 		if (retval) {
 			err = retval;
 			reiserfs_check_path(&path_to_key);
@@ -1927,10 +1924,23 @@
 			goto out_inserted_sd;
 		}
 	} else if (inode->i_sb->s_flags & MS_POSIXACL) {
-		reiserfs_warning(inode->i_sb, "ACLs aren't enabled in the fs, "
+		reiserfs_warning(inode->i_sb, "jdm-13090",
+				 "ACLs aren't enabled in the fs, "
 				 "but vfs thinks they are!");
-	} else if (is_reiserfs_priv_object(dir)) {
-		reiserfs_mark_inode_private(inode);
+	} else if (IS_PRIVATE(dir))
+		inode->i_flags |= S_PRIVATE;
+
+	if (security->name) {
+		retval = reiserfs_security_write(th, inode, security);
+		if (retval) {
+			err = retval;
+			reiserfs_check_path(&path_to_key);
+			retval = journal_end(th, th->t_super,
+					     th->t_blocks_allocated);
+			if (retval)
+				err = retval;
+			goto out_inserted_sd;
+		}
 	}
 
 	reiserfs_update_sd(th, inode);
@@ -1960,19 +1970,7 @@
 	inode->i_nlink = 0;
 	th->t_trans_id = 0;	/* so the caller can't use this handle later */
 	unlock_new_inode(inode); /* OK to do even if we hadn't locked it */
-
-	/* If we were inheriting an ACL, we need to release the lock so that
-	 * iput doesn't deadlock in reiserfs_delete_xattrs. The locking
-	 * code really needs to be reworked, but this will take care of it
-	 * for now. -jeffm */
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-	if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) {
-		reiserfs_write_unlock_xattrs(dir->i_sb);
-		iput(inode);
-		reiserfs_write_lock_xattrs(dir->i_sb);
-	} else
-#endif
-		iput(inode);
+	iput(inode);
 	return err;
 }
 
@@ -1989,7 +1987,7 @@
 **
 ** on failure, nonzero is returned, page_result and bh_result are untouched.
 */
-static int grab_tail_page(struct inode *p_s_inode,
+static int grab_tail_page(struct inode *inode,
 			  struct page **page_result,
 			  struct buffer_head **bh_result)
 {
@@ -1997,11 +1995,11 @@
 	/* we want the page with the last byte in the file,
 	 ** not the page that will hold the next byte for appending
 	 */
-	unsigned long index = (p_s_inode->i_size - 1) >> PAGE_CACHE_SHIFT;
+	unsigned long index = (inode->i_size - 1) >> PAGE_CACHE_SHIFT;
 	unsigned long pos = 0;
 	unsigned long start = 0;
-	unsigned long blocksize = p_s_inode->i_sb->s_blocksize;
-	unsigned long offset = (p_s_inode->i_size) & (PAGE_CACHE_SIZE - 1);
+	unsigned long blocksize = inode->i_sb->s_blocksize;
+	unsigned long offset = (inode->i_size) & (PAGE_CACHE_SIZE - 1);
 	struct buffer_head *bh;
 	struct buffer_head *head;
 	struct page *page;
@@ -2015,7 +2013,7 @@
 	if ((offset & (blocksize - 1)) == 0) {
 		return -ENOENT;
 	}
-	page = grab_cache_page(p_s_inode->i_mapping, index);
+	page = grab_cache_page(inode->i_mapping, index);
 	error = -ENOMEM;
 	if (!page) {
 		goto out;
@@ -2044,10 +2042,8 @@
 		 ** I've screwed up the code to find the buffer, or the code to
 		 ** call prepare_write
 		 */
-		reiserfs_warning(p_s_inode->i_sb,
-				 "clm-6000: error reading block %lu on dev %s",
-				 bh->b_blocknr,
-				 reiserfs_bdevname(p_s_inode->i_sb));
+		reiserfs_error(inode->i_sb, "clm-6000",
+			       "error reading block %lu", bh->b_blocknr);
 		error = -EIO;
 		goto unlock;
 	}
@@ -2069,57 +2065,58 @@
 **
 ** some code taken from block_truncate_page
 */
-int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
+int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
 {
 	struct reiserfs_transaction_handle th;
 	/* we want the offset for the first byte after the end of the file */
-	unsigned long offset = p_s_inode->i_size & (PAGE_CACHE_SIZE - 1);
-	unsigned blocksize = p_s_inode->i_sb->s_blocksize;
+	unsigned long offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+	unsigned blocksize = inode->i_sb->s_blocksize;
 	unsigned length;
 	struct page *page = NULL;
 	int error;
 	struct buffer_head *bh = NULL;
 	int err2;
 
-	reiserfs_write_lock(p_s_inode->i_sb);
+	reiserfs_write_lock(inode->i_sb);
 
-	if (p_s_inode->i_size > 0) {
-		if ((error = grab_tail_page(p_s_inode, &page, &bh))) {
-			// -ENOENT means we truncated past the end of the file, 
+	if (inode->i_size > 0) {
+		error = grab_tail_page(inode, &page, &bh);
+		if (error) {
+			// -ENOENT means we truncated past the end of the file,
 			// and get_block_create_0 could not find a block to read in,
 			// which is ok.
 			if (error != -ENOENT)
-				reiserfs_warning(p_s_inode->i_sb,
-						 "clm-6001: grab_tail_page failed %d",
-						 error);
+				reiserfs_error(inode->i_sb, "clm-6001",
+					       "grab_tail_page failed %d",
+					       error);
 			page = NULL;
 			bh = NULL;
 		}
 	}
 
-	/* so, if page != NULL, we have a buffer head for the offset at 
-	 ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0, 
-	 ** then we have an unformatted node.  Otherwise, we have a direct item, 
-	 ** and no zeroing is required on disk.  We zero after the truncate, 
-	 ** because the truncate might pack the item anyway 
+	/* so, if page != NULL, we have a buffer head for the offset at
+	 ** the end of the file. if the bh is mapped, and bh->b_blocknr != 0,
+	 ** then we have an unformatted node.  Otherwise, we have a direct item,
+	 ** and no zeroing is required on disk.  We zero after the truncate,
+	 ** because the truncate might pack the item anyway
 	 ** (it will unmap bh if it packs).
 	 */
 	/* it is enough to reserve space in transaction for 2 balancings:
 	   one for "save" link adding and another for the first
 	   cut_from_item. 1 is for update_sd */
-	error = journal_begin(&th, p_s_inode->i_sb,
+	error = journal_begin(&th, inode->i_sb,
 			      JOURNAL_PER_BALANCE_CNT * 2 + 1);
 	if (error)
 		goto out;
-	reiserfs_update_inode_transaction(p_s_inode);
+	reiserfs_update_inode_transaction(inode);
 	if (update_timestamps)
 		/* we are doing real truncate: if the system crashes before the last
 		   transaction of truncating gets committed - on reboot the file
 		   either appears truncated properly or not truncated at all */
-		add_save_link(&th, p_s_inode, 1);
-	err2 = reiserfs_do_truncate(&th, p_s_inode, page, update_timestamps);
+		add_save_link(&th, inode, 1);
+	err2 = reiserfs_do_truncate(&th, inode, page, update_timestamps);
 	error =
-	    journal_end(&th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
+	    journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 2 + 1);
 	if (error)
 		goto out;
 
@@ -2130,7 +2127,7 @@
 	}
 	
 	if (update_timestamps) {
-		error = remove_save_link(p_s_inode, 1 /* truncate */ );
+		error = remove_save_link(inode, 1 /* truncate */);
 		if (error)
 			goto out;
 	}
@@ -2149,14 +2146,14 @@
 		page_cache_release(page);
 	}
 
-	reiserfs_write_unlock(p_s_inode->i_sb);
+	reiserfs_write_unlock(inode->i_sb);
 	return 0;
       out:
 	if (page) {
 		unlock_page(page);
 		page_cache_release(page);
 	}
-	reiserfs_write_unlock(p_s_inode->i_sb);
+	reiserfs_write_unlock(inode->i_sb);
 	return error;
 }
 
@@ -2208,9 +2205,8 @@
 	/* we've found an unformatted node */
 	if (indirect_item_found(retval, ih)) {
 		if (bytes_copied > 0) {
-			reiserfs_warning(inode->i_sb,
-					 "clm-6002: bytes_copied %d",
-					 bytes_copied);
+			reiserfs_warning(inode->i_sb, "clm-6002",
+					 "bytes_copied %d", bytes_copied);
 		}
 		if (!get_block_num(item, pos_in_item)) {
 			/* crap, we are writing to a hole */
@@ -2267,9 +2263,8 @@
 			goto research;
 		}
 	} else {
-		reiserfs_warning(inode->i_sb,
-				 "clm-6003: bad item inode %lu, device %s",
-				 inode->i_ino, reiserfs_bdevname(inode->i_sb));
+		reiserfs_warning(inode->i_sb, "clm-6003",
+				 "bad item inode %lu", inode->i_ino);
 		retval = -EIO;
 		goto out;
 	}
@@ -2312,8 +2307,8 @@
 	return retval;
 }
 
-/* 
- * mason@suse.com: updated in 2.5.54 to follow the same general io 
+/*
+ * mason@suse.com: updated in 2.5.54 to follow the same general io
  * start/recovery path as __block_write_full_page, along with special
  * code to handle reiserfs tails.
  */
@@ -2453,7 +2448,7 @@
 	unlock_page(page);
 
 	/*
-	 * since any buffer might be the only dirty buffer on the page, 
+	 * since any buffer might be the only dirty buffer on the page,
 	 * the first submit_bh can bring the page out of writeback.
 	 * be careful with the buffers.
 	 */
@@ -2472,8 +2467,8 @@
 	if (nr == 0) {
 		/*
 		 * if this page only had a direct item, it is very possible for
-		 * no io to be required without there being an error.  Or, 
-		 * someone else could have locked them and sent them down the 
+		 * no io to be required without there being an error.  Or,
+		 * someone else could have locked them and sent them down the
 		 * pipe without locking the page
 		 */
 		bh = head;
@@ -2492,7 +2487,7 @@
 
       fail:
 	/* catches various errors, we need to make sure any valid dirty blocks
-	 * get to the media.  The page is currently locked and not marked for 
+	 * get to the media.  The page is currently locked and not marked for
 	 * writeback
 	 */
 	ClearPageUptodate(page);
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 8303320..0ccc3fd 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -189,7 +189,7 @@
 	}
 
 	/* we unpack by finding the page with the tail, and calling
-	 ** reiserfs_prepare_write on that page.  This will force a 
+	 ** reiserfs_prepare_write on that page.  This will force a
 	 ** reiserfs_get_block to unpack the tail for us.
 	 */
 	index = inode->i_size >> PAGE_CACHE_SHIFT;
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
index 9475557..72cb1cc 100644
--- a/fs/reiserfs/item_ops.c
+++ b/fs/reiserfs/item_ops.c
@@ -97,7 +97,8 @@
 
 static void sd_print_vi(struct virtual_item *vi)
 {
-	reiserfs_warning(NULL, "STATDATA, index %d, type 0x%x, %h",
+	reiserfs_warning(NULL, "reiserfs-16100",
+			 "STATDATA, index %d, type 0x%x, %h",
 			 vi->vi_index, vi->vi_type, vi->vi_ih);
 }
 
@@ -190,7 +191,8 @@
 
 static void direct_print_vi(struct virtual_item *vi)
 {
-	reiserfs_warning(NULL, "DIRECT, index %d, type 0x%x, %h",
+	reiserfs_warning(NULL, "reiserfs-16101",
+			 "DIRECT, index %d, type 0x%x, %h",
 			 vi->vi_index, vi->vi_type, vi->vi_ih);
 }
 
@@ -278,7 +280,7 @@
 	unp = (__le32 *) item;
 
 	if (ih_item_len(ih) % UNFM_P_SIZE)
-		reiserfs_warning(NULL, "indirect_print_item: invalid item len");
+		reiserfs_warning(NULL, "reiserfs-16102", "invalid item len");
 
 	printk("%d pointers\n[ ", (int)I_UNFM_NUM(ih));
 	for (j = 0; j < I_UNFM_NUM(ih); j++) {
@@ -334,7 +336,8 @@
 
 static void indirect_print_vi(struct virtual_item *vi)
 {
-	reiserfs_warning(NULL, "INDIRECT, index %d, type 0x%x, %h",
+	reiserfs_warning(NULL, "reiserfs-16103",
+			 "INDIRECT, index %d, type 0x%x, %h",
 			 vi->vi_index, vi->vi_type, vi->vi_ih);
 }
 
@@ -359,7 +362,7 @@
 
 static int direntry_bytes_number(struct item_head *ih, int block_size)
 {
-	reiserfs_warning(NULL, "vs-16090: direntry_bytes_number: "
+	reiserfs_warning(NULL, "vs-16090",
 			 "bytes number is asked for direntry");
 	return 0;
 }
@@ -514,8 +517,9 @@
 		    ((is_affected
 		      && (vn->vn_mode == M_PASTE
 			  || vn->vn_mode == M_CUT)) ? insert_size : 0)) {
-			reiserfs_panic(NULL,
-				       "vs-8025: set_entry_sizes: (mode==%c, insert_size==%d), invalid length of directory item",
+			reiserfs_panic(NULL, "vs-8025", "(mode==%c, "
+				       "insert_size==%d), invalid length of "
+				       "directory item",
 				       vn->vn_mode, insert_size);
 		}
 	}
@@ -546,7 +550,8 @@
 	}
 
 	if (entries == dir_u->entry_count) {
-		reiserfs_panic(NULL, "free space %d, entry_count %d\n", free,
+		reiserfs_panic(NULL, "item_ops-1",
+			       "free space %d, entry_count %d", free,
 			       dir_u->entry_count);
 	}
 
@@ -614,7 +619,8 @@
 	int i;
 	struct direntry_uarea *dir_u = vi->vi_uarea;
 
-	reiserfs_warning(NULL, "DIRENTRY, index %d, type 0x%x, %h, flags 0x%x",
+	reiserfs_warning(NULL, "reiserfs-16104",
+			 "DIRENTRY, index %d, type 0x%x, %h, flags 0x%x",
 			 vi->vi_index, vi->vi_type, vi->vi_ih, dir_u->flags);
 	printk("%d entries: ", dir_u->entry_count);
 	for (i = 0; i < dir_u->entry_count; i++)
@@ -642,43 +648,43 @@
 //
 static int errcatch_bytes_number(struct item_head *ih, int block_size)
 {
-	reiserfs_warning(NULL,
-			 "green-16001: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16001",
+			 "Invalid item type observed, run fsck ASAP");
 	return 0;
 }
 
 static void errcatch_decrement_key(struct cpu_key *key)
 {
-	reiserfs_warning(NULL,
-			 "green-16002: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16002",
+			 "Invalid item type observed, run fsck ASAP");
 }
 
 static int errcatch_is_left_mergeable(struct reiserfs_key *key,
 				      unsigned long bsize)
 {
-	reiserfs_warning(NULL,
-			 "green-16003: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16003",
+			 "Invalid item type observed, run fsck ASAP");
 	return 0;
 }
 
 static void errcatch_print_item(struct item_head *ih, char *item)
 {
-	reiserfs_warning(NULL,
-			 "green-16004: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16004",
+			 "Invalid item type observed, run fsck ASAP");
 }
 
 static void errcatch_check_item(struct item_head *ih, char *item)
 {
-	reiserfs_warning(NULL,
-			 "green-16005: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16005",
+			 "Invalid item type observed, run fsck ASAP");
 }
 
 static int errcatch_create_vi(struct virtual_node *vn,
 			      struct virtual_item *vi,
 			      int is_affected, int insert_size)
 {
-	reiserfs_warning(NULL,
-			 "green-16006: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16006",
+			 "Invalid item type observed, run fsck ASAP");
 	return 0;		// We might return -1 here as well, but it won't help as create_virtual_node() from where
 	// this operation is called from is of return type void.
 }
@@ -686,36 +692,36 @@
 static int errcatch_check_left(struct virtual_item *vi, int free,
 			       int start_skip, int end_skip)
 {
-	reiserfs_warning(NULL,
-			 "green-16007: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16007",
+			 "Invalid item type observed, run fsck ASAP");
 	return -1;
 }
 
 static int errcatch_check_right(struct virtual_item *vi, int free)
 {
-	reiserfs_warning(NULL,
-			 "green-16008: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16008",
+			 "Invalid item type observed, run fsck ASAP");
 	return -1;
 }
 
 static int errcatch_part_size(struct virtual_item *vi, int first, int count)
 {
-	reiserfs_warning(NULL,
-			 "green-16009: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16009",
+			 "Invalid item type observed, run fsck ASAP");
 	return 0;
 }
 
 static int errcatch_unit_num(struct virtual_item *vi)
 {
-	reiserfs_warning(NULL,
-			 "green-16010: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16010",
+			 "Invalid item type observed, run fsck ASAP");
 	return 0;
 }
 
 static void errcatch_print_vi(struct virtual_item *vi)
 {
-	reiserfs_warning(NULL,
-			 "green-16011: Invalid item type observed, run fsck ASAP");
+	reiserfs_warning(NULL, "green-16011",
+			 "Invalid item type observed, run fsck ASAP");
 }
 
 static struct item_operations errcatch_ops = {
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 9643c3b..77f5bb7 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1,36 +1,36 @@
 /*
 ** Write ahead logging implementation copyright Chris Mason 2000
 **
-** The background commits make this code very interelated, and 
+** The background commits make this code very interelated, and
 ** overly complex.  I need to rethink things a bit....The major players:
 **
-** journal_begin -- call with the number of blocks you expect to log.  
+** journal_begin -- call with the number of blocks you expect to log.
 **                  If the current transaction is too
-** 		    old, it will block until the current transaction is 
+** 		    old, it will block until the current transaction is
 ** 		    finished, and then start a new one.
-**		    Usually, your transaction will get joined in with 
+**		    Usually, your transaction will get joined in with
 **                  previous ones for speed.
 **
-** journal_join  -- same as journal_begin, but won't block on the current 
+** journal_join  -- same as journal_begin, but won't block on the current
 **                  transaction regardless of age.  Don't ever call
-**                  this.  Ever.  There are only two places it should be 
+**                  this.  Ever.  There are only two places it should be
 **                  called from, and they are both inside this file.
 **
-** journal_mark_dirty -- adds blocks into this transaction.  clears any flags 
+** journal_mark_dirty -- adds blocks into this transaction.  clears any flags
 **                       that might make them get sent to disk
-**                       and then marks them BH_JDirty.  Puts the buffer head 
-**                       into the current transaction hash.  
+**                       and then marks them BH_JDirty.  Puts the buffer head
+**                       into the current transaction hash.
 **
 ** journal_end -- if the current transaction is batchable, it does nothing
 **                   otherwise, it could do an async/synchronous commit, or
-**                   a full flush of all log and real blocks in the 
+**                   a full flush of all log and real blocks in the
 **                   transaction.
 **
-** flush_old_commits -- if the current transaction is too old, it is ended and 
-**                      commit blocks are sent to disk.  Forces commit blocks 
-**                      to disk for all backgrounded commits that have been 
+** flush_old_commits -- if the current transaction is too old, it is ended and
+**                      commit blocks are sent to disk.  Forces commit blocks
+**                      to disk for all backgrounded commits that have been
 **                      around too long.
-**		     -- Note, if you call this as an immediate flush from 
+**		     -- Note, if you call this as an immediate flush from
 **		        from within kupdate, it will ignore the immediate flag
 */
 
@@ -97,7 +97,7 @@
 			     struct reiserfs_journal_list *jl, int flushall);
 static int can_dirty(struct reiserfs_journal_cnode *cn);
 static int journal_join(struct reiserfs_transaction_handle *th,
-			struct super_block *p_s_sb, unsigned long nblocks);
+			struct super_block *sb, unsigned long nblocks);
 static int release_journal_dev(struct super_block *super,
 			       struct reiserfs_journal *journal);
 static int dirty_one_transaction(struct super_block *s,
@@ -113,12 +113,12 @@
 };
 
 static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
-			      struct super_block *p_s_sb,
+			      struct super_block *sb,
 			      unsigned long nblocks, int join);
 
-static void init_journal_hash(struct super_block *p_s_sb)
+static void init_journal_hash(struct super_block *sb)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	memset(journal->j_hash_table, 0,
 	       JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *));
 }
@@ -145,7 +145,7 @@
 }
 
 static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block
-							 *p_s_sb)
+							 *sb)
 {
 	struct reiserfs_bitmap_node *bn;
 	static int id;
@@ -154,7 +154,7 @@
 	if (!bn) {
 		return NULL;
 	}
-	bn->data = kzalloc(p_s_sb->s_blocksize, GFP_NOFS);
+	bn->data = kzalloc(sb->s_blocksize, GFP_NOFS);
 	if (!bn->data) {
 		kfree(bn);
 		return NULL;
@@ -164,9 +164,9 @@
 	return bn;
 }
 
-static struct reiserfs_bitmap_node *get_bitmap_node(struct super_block *p_s_sb)
+static struct reiserfs_bitmap_node *get_bitmap_node(struct super_block *sb)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_bitmap_node *bn = NULL;
 	struct list_head *entry = journal->j_bitmap_nodes.next;
 
@@ -176,21 +176,21 @@
 	if (entry != &journal->j_bitmap_nodes) {
 		bn = list_entry(entry, struct reiserfs_bitmap_node, list);
 		list_del(entry);
-		memset(bn->data, 0, p_s_sb->s_blocksize);
+		memset(bn->data, 0, sb->s_blocksize);
 		journal->j_free_bitmap_nodes--;
 		return bn;
 	}
-	bn = allocate_bitmap_node(p_s_sb);
+	bn = allocate_bitmap_node(sb);
 	if (!bn) {
 		yield();
 		goto repeat;
 	}
 	return bn;
 }
-static inline void free_bitmap_node(struct super_block *p_s_sb,
+static inline void free_bitmap_node(struct super_block *sb,
 				    struct reiserfs_bitmap_node *bn)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	journal->j_used_bitmap_nodes--;
 	if (journal->j_free_bitmap_nodes > REISERFS_MAX_BITMAP_NODES) {
 		kfree(bn->data);
@@ -201,46 +201,46 @@
 	}
 }
 
-static void allocate_bitmap_nodes(struct super_block *p_s_sb)
+static void allocate_bitmap_nodes(struct super_block *sb)
 {
 	int i;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_bitmap_node *bn = NULL;
 	for (i = 0; i < REISERFS_MIN_BITMAP_NODES; i++) {
-		bn = allocate_bitmap_node(p_s_sb);
+		bn = allocate_bitmap_node(sb);
 		if (bn) {
 			list_add(&bn->list, &journal->j_bitmap_nodes);
 			journal->j_free_bitmap_nodes++;
 		} else {
-			break;	// this is ok, we'll try again when more are needed 
+			break;	/* this is ok, we'll try again when more are needed */
 		}
 	}
 }
 
-static int set_bit_in_list_bitmap(struct super_block *p_s_sb,
+static int set_bit_in_list_bitmap(struct super_block *sb,
 				  b_blocknr_t block,
 				  struct reiserfs_list_bitmap *jb)
 {
-	unsigned int bmap_nr = block / (p_s_sb->s_blocksize << 3);
-	unsigned int bit_nr = block % (p_s_sb->s_blocksize << 3);
+	unsigned int bmap_nr = block / (sb->s_blocksize << 3);
+	unsigned int bit_nr = block % (sb->s_blocksize << 3);
 
 	if (!jb->bitmaps[bmap_nr]) {
-		jb->bitmaps[bmap_nr] = get_bitmap_node(p_s_sb);
+		jb->bitmaps[bmap_nr] = get_bitmap_node(sb);
 	}
 	set_bit(bit_nr, (unsigned long *)jb->bitmaps[bmap_nr]->data);
 	return 0;
 }
 
-static void cleanup_bitmap_list(struct super_block *p_s_sb,
+static void cleanup_bitmap_list(struct super_block *sb,
 				struct reiserfs_list_bitmap *jb)
 {
 	int i;
 	if (jb->bitmaps == NULL)
 		return;
 
-	for (i = 0; i < reiserfs_bmap_count(p_s_sb); i++) {
+	for (i = 0; i < reiserfs_bmap_count(sb); i++) {
 		if (jb->bitmaps[i]) {
-			free_bitmap_node(p_s_sb, jb->bitmaps[i]);
+			free_bitmap_node(sb, jb->bitmaps[i]);
 			jb->bitmaps[i] = NULL;
 		}
 	}
@@ -249,7 +249,7 @@
 /*
 ** only call this on FS unmount.
 */
-static int free_list_bitmaps(struct super_block *p_s_sb,
+static int free_list_bitmaps(struct super_block *sb,
 			     struct reiserfs_list_bitmap *jb_array)
 {
 	int i;
@@ -257,16 +257,16 @@
 	for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
 		jb = jb_array + i;
 		jb->journal_list = NULL;
-		cleanup_bitmap_list(p_s_sb, jb);
+		cleanup_bitmap_list(sb, jb);
 		vfree(jb->bitmaps);
 		jb->bitmaps = NULL;
 	}
 	return 0;
 }
 
-static int free_bitmap_nodes(struct super_block *p_s_sb)
+static int free_bitmap_nodes(struct super_block *sb)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct list_head *next = journal->j_bitmap_nodes.next;
 	struct reiserfs_bitmap_node *bn;
 
@@ -283,10 +283,10 @@
 }
 
 /*
-** get memory for JOURNAL_NUM_BITMAPS worth of bitmaps. 
+** get memory for JOURNAL_NUM_BITMAPS worth of bitmaps.
 ** jb_array is the array to be filled in.
 */
-int reiserfs_allocate_list_bitmaps(struct super_block *p_s_sb,
+int reiserfs_allocate_list_bitmaps(struct super_block *sb,
 				   struct reiserfs_list_bitmap *jb_array,
 				   unsigned int bmap_nr)
 {
@@ -300,30 +300,30 @@
 		jb->journal_list = NULL;
 		jb->bitmaps = vmalloc(mem);
 		if (!jb->bitmaps) {
-			reiserfs_warning(p_s_sb,
-					 "clm-2000, unable to allocate bitmaps for journal lists");
+			reiserfs_warning(sb, "clm-2000", "unable to "
+					 "allocate bitmaps for journal lists");
 			failed = 1;
 			break;
 		}
 		memset(jb->bitmaps, 0, mem);
 	}
 	if (failed) {
-		free_list_bitmaps(p_s_sb, jb_array);
+		free_list_bitmaps(sb, jb_array);
 		return -1;
 	}
 	return 0;
 }
 
 /*
-** find an available list bitmap.  If you can't find one, flush a commit list 
+** find an available list bitmap.  If you can't find one, flush a commit list
 ** and try again
 */
-static struct reiserfs_list_bitmap *get_list_bitmap(struct super_block *p_s_sb,
+static struct reiserfs_list_bitmap *get_list_bitmap(struct super_block *sb,
 						    struct reiserfs_journal_list
 						    *jl)
 {
 	int i, j;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_list_bitmap *jb = NULL;
 
 	for (j = 0; j < (JOURNAL_NUM_BITMAPS * 3); j++) {
@@ -331,7 +331,7 @@
 		journal->j_list_bitmap_index = (i + 1) % JOURNAL_NUM_BITMAPS;
 		jb = journal->j_list_bitmap + i;
 		if (journal->j_list_bitmap[i].journal_list) {
-			flush_commit_list(p_s_sb,
+			flush_commit_list(sb,
 					  journal->j_list_bitmap[i].
 					  journal_list, 1);
 			if (!journal->j_list_bitmap[i].journal_list) {
@@ -348,7 +348,7 @@
 	return jb;
 }
 
-/* 
+/*
 ** allocates a new chunk of X nodes, and links them all together as a list.
 ** Uses the cnode->next and cnode->prev pointers
 ** returns NULL on failure
@@ -376,14 +376,14 @@
 }
 
 /*
-** pulls a cnode off the free list, or returns NULL on failure 
+** pulls a cnode off the free list, or returns NULL on failure
 */
-static struct reiserfs_journal_cnode *get_cnode(struct super_block *p_s_sb)
+static struct reiserfs_journal_cnode *get_cnode(struct super_block *sb)
 {
 	struct reiserfs_journal_cnode *cn;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
-	reiserfs_check_lock_depth(p_s_sb, "get_cnode");
+	reiserfs_check_lock_depth(sb, "get_cnode");
 
 	if (journal->j_cnode_free <= 0) {
 		return NULL;
@@ -403,14 +403,14 @@
 }
 
 /*
-** returns a cnode to the free list 
+** returns a cnode to the free list
 */
-static void free_cnode(struct super_block *p_s_sb,
+static void free_cnode(struct super_block *sb,
 		       struct reiserfs_journal_cnode *cn)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
-	reiserfs_check_lock_depth(p_s_sb, "free_cnode");
+	reiserfs_check_lock_depth(sb, "free_cnode");
 
 	journal->j_cnode_used--;
 	journal->j_cnode_free++;
@@ -436,8 +436,8 @@
 {
 #ifdef CONFIG_SMP
 	if (current->lock_depth < 0) {
-		reiserfs_panic(sb, "%s called without kernel lock held",
-			       caller);
+		reiserfs_panic(sb, "journal-1", "%s called without kernel "
+			       "lock held", caller);
 	}
 #else
 	;
@@ -481,11 +481,11 @@
 ** reject it on the next call to reiserfs_in_journal
 **
 */
-int reiserfs_in_journal(struct super_block *p_s_sb,
+int reiserfs_in_journal(struct super_block *sb,
 			unsigned int bmap_nr, int bit_nr, int search_all,
 			b_blocknr_t * next_zero_bit)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_cnode *cn;
 	struct reiserfs_list_bitmap *jb;
 	int i;
@@ -493,14 +493,14 @@
 
 	*next_zero_bit = 0;	/* always start this at zero. */
 
-	PROC_INFO_INC(p_s_sb, journal.in_journal);
+	PROC_INFO_INC(sb, journal.in_journal);
 	/* If we aren't doing a search_all, this is a metablock, and it will be logged before use.
 	 ** if we crash before the transaction that freed it commits,  this transaction won't
 	 ** have committed either, and the block will never be written
 	 */
 	if (search_all) {
 		for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
-			PROC_INFO_INC(p_s_sb, journal.in_journal_bitmap);
+			PROC_INFO_INC(sb, journal.in_journal_bitmap);
 			jb = journal->j_list_bitmap + i;
 			if (jb->journal_list && jb->bitmaps[bmap_nr] &&
 			    test_bit(bit_nr,
@@ -510,28 +510,28 @@
 				    find_next_zero_bit((unsigned long *)
 						       (jb->bitmaps[bmap_nr]->
 							data),
-						       p_s_sb->s_blocksize << 3,
+						       sb->s_blocksize << 3,
 						       bit_nr + 1);
 				return 1;
 			}
 		}
 	}
 
-	bl = bmap_nr * (p_s_sb->s_blocksize << 3) + bit_nr;
+	bl = bmap_nr * (sb->s_blocksize << 3) + bit_nr;
 	/* is it in any old transactions? */
 	if (search_all
 	    && (cn =
-		get_journal_hash_dev(p_s_sb, journal->j_list_hash_table, bl))) {
+		get_journal_hash_dev(sb, journal->j_list_hash_table, bl))) {
 		return 1;
 	}
 
 	/* is it in the current transaction.  This should never happen */
-	if ((cn = get_journal_hash_dev(p_s_sb, journal->j_hash_table, bl))) {
+	if ((cn = get_journal_hash_dev(sb, journal->j_hash_table, bl))) {
 		BUG();
 		return 1;
 	}
 
-	PROC_INFO_INC(p_s_sb, journal.in_journal_reusable);
+	PROC_INFO_INC(sb, journal.in_journal_reusable);
 	/* safe for reuse */
 	return 0;
 }
@@ -553,16 +553,16 @@
 }
 
 /* lock the current transaction */
-static inline void lock_journal(struct super_block *p_s_sb)
+static inline void lock_journal(struct super_block *sb)
 {
-	PROC_INFO_INC(p_s_sb, journal.lock_journal);
-	mutex_lock(&SB_JOURNAL(p_s_sb)->j_mutex);
+	PROC_INFO_INC(sb, journal.lock_journal);
+	mutex_lock(&SB_JOURNAL(sb)->j_mutex);
 }
 
 /* unlock the current transaction */
-static inline void unlock_journal(struct super_block *p_s_sb)
+static inline void unlock_journal(struct super_block *sb)
 {
-	mutex_unlock(&SB_JOURNAL(p_s_sb)->j_mutex);
+	mutex_unlock(&SB_JOURNAL(sb)->j_mutex);
 }
 
 static inline void get_journal_list(struct reiserfs_journal_list *jl)
@@ -574,7 +574,7 @@
 				    struct reiserfs_journal_list *jl)
 {
 	if (jl->j_refcount < 1) {
-		reiserfs_panic(s, "trans id %lu, refcount at %d",
+		reiserfs_panic(s, "journal-2", "trans id %u, refcount at %d",
 			       jl->j_trans_id, jl->j_refcount);
 	}
 	if (--jl->j_refcount == 0)
@@ -586,20 +586,20 @@
 ** it gets called by flush_commit_list, and cleans up any data stored about blocks freed during a
 ** transaction.
 */
-static void cleanup_freed_for_journal_list(struct super_block *p_s_sb,
+static void cleanup_freed_for_journal_list(struct super_block *sb,
 					   struct reiserfs_journal_list *jl)
 {
 
 	struct reiserfs_list_bitmap *jb = jl->j_list_bitmap;
 	if (jb) {
-		cleanup_bitmap_list(p_s_sb, jb);
+		cleanup_bitmap_list(sb, jb);
 	}
 	jl->j_list_bitmap->journal_list = NULL;
 	jl->j_list_bitmap = NULL;
 }
 
 static int journal_list_still_alive(struct super_block *s,
-				    unsigned long trans_id)
+				    unsigned int trans_id)
 {
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
 	struct list_head *entry = &journal->j_journal_list;
@@ -644,8 +644,8 @@
 	char b[BDEVNAME_SIZE];
 
 	if (buffer_journaled(bh)) {
-		reiserfs_warning(NULL,
-				 "clm-2084: pinned buffer %lu:%s sent to disk",
+		reiserfs_warning(NULL, "clm-2084",
+				 "pinned buffer %lu:%s sent to disk",
 				 bh->b_blocknr, bdevname(bh->b_bdev, b));
 	}
 	if (uptodate)
@@ -933,9 +933,9 @@
 	struct reiserfs_journal_list *other_jl;
 	struct reiserfs_journal_list *first_jl;
 	struct list_head *entry;
-	unsigned long trans_id = jl->j_trans_id;
-	unsigned long other_trans_id;
-	unsigned long first_trans_id;
+	unsigned int trans_id = jl->j_trans_id;
+	unsigned int other_trans_id;
+	unsigned int first_trans_id;
 
       find_first:
 	/*
@@ -1014,7 +1014,7 @@
 	int i;
 	b_blocknr_t bn;
 	struct buffer_head *tbh = NULL;
-	unsigned long trans_id = jl->j_trans_id;
+	unsigned int trans_id = jl->j_trans_id;
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
 	int barrier = 0;
 	int retval = 0;
@@ -1122,7 +1122,8 @@
 			sync_dirty_buffer(tbh);
 		if (unlikely(!buffer_uptodate(tbh))) {
 #ifdef CONFIG_REISERFS_CHECK
-			reiserfs_warning(s, "journal-601, buffer write failed");
+			reiserfs_warning(s, "journal-601",
+					 "buffer write failed");
 #endif
 			retval = -EIO;
 		}
@@ -1154,14 +1155,14 @@
 	 * up propagating the write error out to the filesystem. */
 	if (unlikely(!buffer_uptodate(jl->j_commit_bh))) {
 #ifdef CONFIG_REISERFS_CHECK
-		reiserfs_warning(s, "journal-615: buffer write failed");
+		reiserfs_warning(s, "journal-615", "buffer write failed");
 #endif
 		retval = -EIO;
 	}
 	bforget(jl->j_commit_bh);
 	if (journal->j_last_commit_id != 0 &&
 	    (jl->j_trans_id - journal->j_last_commit_id) != 1) {
-		reiserfs_warning(s, "clm-2200: last commit %lu, current %lu",
+		reiserfs_warning(s, "clm-2200", "last commit %lu, current %lu",
 				 journal->j_last_commit_id, jl->j_trans_id);
 	}
 	journal->j_last_commit_id = jl->j_trans_id;
@@ -1191,8 +1192,8 @@
 }
 
 /*
-** flush_journal_list frequently needs to find a newer transaction for a given block.  This does that, or 
-** returns NULL if it can't find anything 
+** flush_journal_list frequently needs to find a newer transaction for a given block.  This does that, or
+** returns NULL if it can't find anything
 */
 static struct reiserfs_journal_list *find_newer_jl_for_cn(struct
 							  reiserfs_journal_cnode
@@ -1236,11 +1237,11 @@
 ** journal list for this transaction.  Aside from freeing the cnode, this also allows the
 ** block to be reallocated for data blocks if it had been deleted.
 */
-static void remove_all_from_journal_list(struct super_block *p_s_sb,
+static void remove_all_from_journal_list(struct super_block *sb,
 					 struct reiserfs_journal_list *jl,
 					 int debug)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_cnode *cn, *last;
 	cn = jl->j_realblock;
 
@@ -1250,18 +1251,18 @@
 	while (cn) {
 		if (cn->blocknr != 0) {
 			if (debug) {
-				reiserfs_warning(p_s_sb,
+				reiserfs_warning(sb, "reiserfs-2201",
 						 "block %u, bh is %d, state %ld",
 						 cn->blocknr, cn->bh ? 1 : 0,
 						 cn->state);
 			}
 			cn->state = 0;
-			remove_journal_hash(p_s_sb, journal->j_list_hash_table,
+			remove_journal_hash(sb, journal->j_list_hash_table,
 					    jl, cn->blocknr, 1);
 		}
 		last = cn;
 		cn = cn->next;
-		free_cnode(p_s_sb, last);
+		free_cnode(sb, last);
 	}
 	jl->j_realblock = NULL;
 }
@@ -1273,12 +1274,12 @@
 ** called by flush_journal_list, before it calls remove_all_from_journal_list
 **
 */
-static int _update_journal_header_block(struct super_block *p_s_sb,
+static int _update_journal_header_block(struct super_block *sb,
 					unsigned long offset,
-					unsigned long trans_id)
+					unsigned int trans_id)
 {
 	struct reiserfs_journal_header *jh;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
 	if (reiserfs_is_journal_aborted(journal))
 		return -EIO;
@@ -1288,8 +1289,8 @@
 			wait_on_buffer((journal->j_header_bh));
 			if (unlikely(!buffer_uptodate(journal->j_header_bh))) {
 #ifdef CONFIG_REISERFS_CHECK
-				reiserfs_warning(p_s_sb,
-						 "journal-699: buffer write failed");
+				reiserfs_warning(sb, "journal-699",
+						 "buffer write failed");
 #endif
 				return -EIO;
 			}
@@ -1302,49 +1303,49 @@
 		jh->j_first_unflushed_offset = cpu_to_le32(offset);
 		jh->j_mount_id = cpu_to_le32(journal->j_mount_id);
 
-		if (reiserfs_barrier_flush(p_s_sb)) {
+		if (reiserfs_barrier_flush(sb)) {
 			int ret;
 			lock_buffer(journal->j_header_bh);
 			ret = submit_barrier_buffer(journal->j_header_bh);
 			if (ret == -EOPNOTSUPP) {
 				set_buffer_uptodate(journal->j_header_bh);
-				disable_barrier(p_s_sb);
+				disable_barrier(sb);
 				goto sync;
 			}
 			wait_on_buffer(journal->j_header_bh);
-			check_barrier_completion(p_s_sb, journal->j_header_bh);
+			check_barrier_completion(sb, journal->j_header_bh);
 		} else {
 		      sync:
 			set_buffer_dirty(journal->j_header_bh);
 			sync_dirty_buffer(journal->j_header_bh);
 		}
 		if (!buffer_uptodate(journal->j_header_bh)) {
-			reiserfs_warning(p_s_sb,
-					 "journal-837: IO error during journal replay");
+			reiserfs_warning(sb, "journal-837",
+					 "IO error during journal replay");
 			return -EIO;
 		}
 	}
 	return 0;
 }
 
-static int update_journal_header_block(struct super_block *p_s_sb,
+static int update_journal_header_block(struct super_block *sb,
 				       unsigned long offset,
-				       unsigned long trans_id)
+				       unsigned int trans_id)
 {
-	return _update_journal_header_block(p_s_sb, offset, trans_id);
+	return _update_journal_header_block(sb, offset, trans_id);
 }
 
-/* 
-** flush any and all journal lists older than you are 
+/*
+** flush any and all journal lists older than you are
 ** can only be called from flush_journal_list
 */
-static int flush_older_journal_lists(struct super_block *p_s_sb,
+static int flush_older_journal_lists(struct super_block *sb,
 				     struct reiserfs_journal_list *jl)
 {
 	struct list_head *entry;
 	struct reiserfs_journal_list *other_jl;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
-	unsigned long trans_id = jl->j_trans_id;
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
+	unsigned int trans_id = jl->j_trans_id;
 
 	/* we know we are the only ones flushing things, no extra race
 	 * protection is required.
@@ -1358,7 +1359,7 @@
 	if (other_jl->j_trans_id < trans_id) {
 		BUG_ON(other_jl->j_refcount <= 0);
 		/* do not flush all */
-		flush_journal_list(p_s_sb, other_jl, 0);
+		flush_journal_list(sb, other_jl, 0);
 
 		/* other_jl is now deleted from the list */
 		goto restart;
@@ -1381,8 +1382,8 @@
 ** always set flushall to 1, unless you are calling from inside
 ** flush_journal_list
 **
-** IMPORTANT.  This can only be called while there are no journal writers, 
-** and the journal is locked.  That means it can only be called from 
+** IMPORTANT.  This can only be called while there are no journal writers,
+** and the journal is locked.  That means it can only be called from
 ** do_journal_end, or by journal_release
 */
 static int flush_journal_list(struct super_block *s,
@@ -1401,8 +1402,7 @@
 	BUG_ON(j_len_saved <= 0);
 
 	if (atomic_read(&journal->j_wcount) != 0) {
-		reiserfs_warning(s,
-				 "clm-2048: flush_journal_list called with wcount %d",
+		reiserfs_warning(s, "clm-2048", "called with wcount %d",
 				 atomic_read(&journal->j_wcount));
 	}
 	BUG_ON(jl->j_trans_id == 0);
@@ -1416,8 +1416,7 @@
 
 	count = 0;
 	if (j_len_saved > journal->j_trans_max) {
-		reiserfs_panic(s,
-			       "journal-715: flush_journal_list, length is %lu, trans id %lu\n",
+		reiserfs_panic(s, "journal-715", "length is %lu, trans id %lu",
 			       j_len_saved, jl->j_trans_id);
 		return 0;
 	}
@@ -1430,7 +1429,7 @@
 		goto flush_older_and_return;
 	}
 
-	/* start by putting the commit list on disk.  This will also flush 
+	/* start by putting the commit list on disk.  This will also flush
 	 ** the commit lists of any olders transactions
 	 */
 	flush_commit_list(s, jl, 1);
@@ -1445,12 +1444,12 @@
 		goto flush_older_and_return;
 	}
 
-	/* loop through each cnode, see if we need to write it, 
-	 ** or wait on a more recent transaction, or just ignore it 
+	/* loop through each cnode, see if we need to write it,
+	 ** or wait on a more recent transaction, or just ignore it
 	 */
 	if (atomic_read(&(journal->j_wcount)) != 0) {
-		reiserfs_panic(s,
-			       "journal-844: panic journal list is flushing, wcount is not 0\n");
+		reiserfs_panic(s, "journal-844", "journal list is flushing, "
+			       "wcount is not 0");
 	}
 	cn = jl->j_realblock;
 	while (cn) {
@@ -1474,8 +1473,8 @@
 		if (!pjl && cn->bh) {
 			saved_bh = cn->bh;
 
-			/* we do this to make sure nobody releases the buffer while 
-			 ** we are working with it 
+			/* we do this to make sure nobody releases the buffer while
+			 ** we are working with it
 			 */
 			get_bh(saved_bh);
 
@@ -1498,8 +1497,8 @@
 			goto free_cnode;
 		}
 
-		/* bh == NULL when the block got to disk on its own, OR, 
-		 ** the block got freed in a future transaction 
+		/* bh == NULL when the block got to disk on its own, OR,
+		 ** the block got freed in a future transaction
 		 */
 		if (saved_bh == NULL) {
 			goto free_cnode;
@@ -1510,8 +1509,8 @@
 		 ** is not marked JDirty_wait
 		 */
 		if ((!was_jwait) && !buffer_locked(saved_bh)) {
-			reiserfs_warning(s,
-					 "journal-813: BAD! buffer %llu %cdirty %cjwait, "
+			reiserfs_warning(s, "journal-813",
+					 "BAD! buffer %llu %cdirty %cjwait, "
 					 "not in a newer tranasction",
 					 (unsigned long long)saved_bh->
 					 b_blocknr, was_dirty ? ' ' : '!',
@@ -1529,8 +1528,8 @@
 				unlock_buffer(saved_bh);
 			count++;
 		} else {
-			reiserfs_warning(s,
-					 "clm-2082: Unable to flush buffer %llu in %s",
+			reiserfs_warning(s, "clm-2082",
+					 "Unable to flush buffer %llu in %s",
 					 (unsigned long long)saved_bh->
 					 b_blocknr, __func__);
 		}
@@ -1541,8 +1540,8 @@
 			/* we incremented this to keep others from taking the buffer head away */
 			put_bh(saved_bh);
 			if (atomic_read(&(saved_bh->b_count)) < 0) {
-				reiserfs_warning(s,
-						 "journal-945: saved_bh->b_count < 0");
+				reiserfs_warning(s, "journal-945",
+						 "saved_bh->b_count < 0");
 			}
 		}
 	}
@@ -1551,18 +1550,18 @@
 		while (cn) {
 			if (test_bit(BLOCK_NEEDS_FLUSH, &cn->state)) {
 				if (!cn->bh) {
-					reiserfs_panic(s,
-						       "journal-1011: cn->bh is NULL\n");
+					reiserfs_panic(s, "journal-1011",
+						       "cn->bh is NULL");
 				}
 				wait_on_buffer(cn->bh);
 				if (!cn->bh) {
-					reiserfs_panic(s,
-						       "journal-1012: cn->bh is NULL\n");
+					reiserfs_panic(s, "journal-1012",
+						       "cn->bh is NULL");
 				}
 				if (unlikely(!buffer_uptodate(cn->bh))) {
 #ifdef CONFIG_REISERFS_CHECK
-					reiserfs_warning(s,
-							 "journal-949: buffer write failed\n");
+					reiserfs_warning(s, "journal-949",
+							 "buffer write failed");
 #endif
 					err = -EIO;
 				}
@@ -1587,7 +1586,7 @@
 			       __func__);
       flush_older_and_return:
 
-	/* before we can update the journal header block, we _must_ flush all 
+	/* before we can update the journal header block, we _must_ flush all
 	 ** real blocks from all older transactions to disk.  This is because
 	 ** once the header block is updated, this transaction will not be
 	 ** replayed after a crash
@@ -1597,7 +1596,7 @@
 	}
 
 	err = journal->j_errno;
-	/* before we can remove everything from the hash tables for this 
+	/* before we can remove everything from the hash tables for this
 	 ** transaction, we must make sure it can never be replayed
 	 **
 	 ** since we are only called from do_journal_end, we know for sure there
@@ -1623,7 +1622,7 @@
 
 	if (journal->j_last_flush_id != 0 &&
 	    (jl->j_trans_id - journal->j_last_flush_id) != 1) {
-		reiserfs_warning(s, "clm-2201: last flush %lu, current %lu",
+		reiserfs_warning(s, "clm-2201", "last flush %lu, current %lu",
 				 journal->j_last_flush_id, jl->j_trans_id);
 	}
 	journal->j_last_flush_id = jl->j_trans_id;
@@ -1758,13 +1757,13 @@
 static int kupdate_transactions(struct super_block *s,
 				struct reiserfs_journal_list *jl,
 				struct reiserfs_journal_list **next_jl,
-				unsigned long *next_trans_id,
+				unsigned int *next_trans_id,
 				int num_blocks, int num_trans)
 {
 	int ret = 0;
 	int written = 0;
 	int transactions_flushed = 0;
-	unsigned long orig_trans_id = jl->j_trans_id;
+	unsigned int orig_trans_id = jl->j_trans_id;
 	struct buffer_chunk chunk;
 	struct list_head *entry;
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
@@ -1833,7 +1832,7 @@
 	int limit = 256;
 	struct reiserfs_journal_list *tjl;
 	struct reiserfs_journal_list *flush_jl;
-	unsigned long trans_id;
+	unsigned int trans_id;
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
 
 	flush_jl = tjl = jl;
@@ -1909,22 +1908,22 @@
 	}
 }
 
-static void free_journal_ram(struct super_block *p_s_sb)
+static void free_journal_ram(struct super_block *sb)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	kfree(journal->j_current_jl);
 	journal->j_num_lists--;
 
 	vfree(journal->j_cnode_free_orig);
-	free_list_bitmaps(p_s_sb, journal->j_list_bitmap);
-	free_bitmap_nodes(p_s_sb);	/* must be after free_list_bitmaps */
+	free_list_bitmaps(sb, journal->j_list_bitmap);
+	free_bitmap_nodes(sb);	/* must be after free_list_bitmaps */
 	if (journal->j_header_bh) {
 		brelse(journal->j_header_bh);
 	}
 	/* j_header_bh is on the journal dev, make sure not to release the journal
 	 * dev until we brelse j_header_bh
 	 */
-	release_journal_dev(p_s_sb, journal);
+	release_journal_dev(sb, journal);
 	vfree(journal);
 }
 
@@ -1933,27 +1932,27 @@
 ** of read_super() yet.  Any other caller must keep error at 0.
 */
 static int do_journal_release(struct reiserfs_transaction_handle *th,
-			      struct super_block *p_s_sb, int error)
+			      struct super_block *sb, int error)
 {
 	struct reiserfs_transaction_handle myth;
 	int flushed = 0;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
 	/* we only want to flush out transactions if we were called with error == 0
 	 */
-	if (!error && !(p_s_sb->s_flags & MS_RDONLY)) {
+	if (!error && !(sb->s_flags & MS_RDONLY)) {
 		/* end the current trans */
 		BUG_ON(!th->t_trans_id);
-		do_journal_end(th, p_s_sb, 10, FLUSH_ALL);
+		do_journal_end(th, sb, 10, FLUSH_ALL);
 
 		/* make sure something gets logged to force our way into the flush code */
-		if (!journal_join(&myth, p_s_sb, 1)) {
-			reiserfs_prepare_for_journal(p_s_sb,
-						     SB_BUFFER_WITH_SB(p_s_sb),
+		if (!journal_join(&myth, sb, 1)) {
+			reiserfs_prepare_for_journal(sb,
+						     SB_BUFFER_WITH_SB(sb),
 						     1);
-			journal_mark_dirty(&myth, p_s_sb,
-					   SB_BUFFER_WITH_SB(p_s_sb));
-			do_journal_end(&myth, p_s_sb, 1, FLUSH_ALL);
+			journal_mark_dirty(&myth, sb,
+					   SB_BUFFER_WITH_SB(sb));
+			do_journal_end(&myth, sb, 1, FLUSH_ALL);
 			flushed = 1;
 		}
 	}
@@ -1961,26 +1960,26 @@
 	/* this also catches errors during the do_journal_end above */
 	if (!error && reiserfs_is_journal_aborted(journal)) {
 		memset(&myth, 0, sizeof(myth));
-		if (!journal_join_abort(&myth, p_s_sb, 1)) {
-			reiserfs_prepare_for_journal(p_s_sb,
-						     SB_BUFFER_WITH_SB(p_s_sb),
+		if (!journal_join_abort(&myth, sb, 1)) {
+			reiserfs_prepare_for_journal(sb,
+						     SB_BUFFER_WITH_SB(sb),
 						     1);
-			journal_mark_dirty(&myth, p_s_sb,
-					   SB_BUFFER_WITH_SB(p_s_sb));
-			do_journal_end(&myth, p_s_sb, 1, FLUSH_ALL);
+			journal_mark_dirty(&myth, sb,
+					   SB_BUFFER_WITH_SB(sb));
+			do_journal_end(&myth, sb, 1, FLUSH_ALL);
 		}
 	}
 
 	reiserfs_mounted_fs_count--;
 	/* wait for all commits to finish */
-	cancel_delayed_work(&SB_JOURNAL(p_s_sb)->j_work);
+	cancel_delayed_work(&SB_JOURNAL(sb)->j_work);
 	flush_workqueue(commit_wq);
 	if (!reiserfs_mounted_fs_count) {
 		destroy_workqueue(commit_wq);
 		commit_wq = NULL;
 	}
 
-	free_journal_ram(p_s_sb);
+	free_journal_ram(sb);
 
 	return 0;
 }
@@ -1989,41 +1988,41 @@
 ** call on unmount.  flush all journal trans, release all alloc'd ram
 */
 int journal_release(struct reiserfs_transaction_handle *th,
-		    struct super_block *p_s_sb)
+		    struct super_block *sb)
 {
-	return do_journal_release(th, p_s_sb, 0);
+	return do_journal_release(th, sb, 0);
 }
 
 /*
 ** only call from an error condition inside reiserfs_read_super!
 */
 int journal_release_error(struct reiserfs_transaction_handle *th,
-			  struct super_block *p_s_sb)
+			  struct super_block *sb)
 {
-	return do_journal_release(th, p_s_sb, 1);
+	return do_journal_release(th, sb, 1);
 }
 
 /* compares description block with commit block.  returns 1 if they differ, 0 if they are the same */
-static int journal_compare_desc_commit(struct super_block *p_s_sb,
+static int journal_compare_desc_commit(struct super_block *sb,
 				       struct reiserfs_journal_desc *desc,
 				       struct reiserfs_journal_commit *commit)
 {
 	if (get_commit_trans_id(commit) != get_desc_trans_id(desc) ||
 	    get_commit_trans_len(commit) != get_desc_trans_len(desc) ||
-	    get_commit_trans_len(commit) > SB_JOURNAL(p_s_sb)->j_trans_max ||
+	    get_commit_trans_len(commit) > SB_JOURNAL(sb)->j_trans_max ||
 	    get_commit_trans_len(commit) <= 0) {
 		return 1;
 	}
 	return 0;
 }
 
-/* returns 0 if it did not find a description block  
+/* returns 0 if it did not find a description block
 ** returns -1 if it found a corrupt commit block
-** returns 1 if both desc and commit were valid 
+** returns 1 if both desc and commit were valid
 */
-static int journal_transaction_is_valid(struct super_block *p_s_sb,
+static int journal_transaction_is_valid(struct super_block *sb,
 					struct buffer_head *d_bh,
-					unsigned long *oldest_invalid_trans_id,
+					unsigned int *oldest_invalid_trans_id,
 					unsigned long *newest_mount_id)
 {
 	struct reiserfs_journal_desc *desc;
@@ -2039,7 +2038,7 @@
 	    && !memcmp(get_journal_desc_magic(d_bh), JOURNAL_DESC_MAGIC, 8)) {
 		if (oldest_invalid_trans_id && *oldest_invalid_trans_id
 		    && get_desc_trans_id(desc) > *oldest_invalid_trans_id) {
-			reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 				       "journal-986: transaction "
 				       "is valid returning because trans_id %d is greater than "
 				       "oldest_invalid %lu",
@@ -2049,7 +2048,7 @@
 		}
 		if (newest_mount_id
 		    && *newest_mount_id > get_desc_mount_id(desc)) {
-			reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 				       "journal-1087: transaction "
 				       "is valid returning because mount_id %d is less than "
 				       "newest_mount_id %lu",
@@ -2057,36 +2056,37 @@
 				       *newest_mount_id);
 			return -1;
 		}
-		if (get_desc_trans_len(desc) > SB_JOURNAL(p_s_sb)->j_trans_max) {
-			reiserfs_warning(p_s_sb,
-					 "journal-2018: Bad transaction length %d encountered, ignoring transaction",
+		if (get_desc_trans_len(desc) > SB_JOURNAL(sb)->j_trans_max) {
+			reiserfs_warning(sb, "journal-2018",
+					 "Bad transaction length %d "
+					 "encountered, ignoring transaction",
 					 get_desc_trans_len(desc));
 			return -1;
 		}
-		offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb);
+		offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
 
 		/* ok, we have a journal description block, lets see if the transaction was valid */
 		c_bh =
-		    journal_bread(p_s_sb,
-				  SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+		    journal_bread(sb,
+				  SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 				  ((offset + get_desc_trans_len(desc) +
-				    1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb)));
+				    1) % SB_ONDISK_JOURNAL_SIZE(sb)));
 		if (!c_bh)
 			return 0;
 		commit = (struct reiserfs_journal_commit *)c_bh->b_data;
-		if (journal_compare_desc_commit(p_s_sb, desc, commit)) {
-			reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+		if (journal_compare_desc_commit(sb, desc, commit)) {
+			reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 				       "journal_transaction_is_valid, commit offset %ld had bad "
 				       "time %d or length %d",
 				       c_bh->b_blocknr -
-				       SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+				       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 				       get_commit_trans_id(commit),
 				       get_commit_trans_len(commit));
 			brelse(c_bh);
 			if (oldest_invalid_trans_id) {
 				*oldest_invalid_trans_id =
 				    get_desc_trans_id(desc);
-				reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 					       "journal-1004: "
 					       "transaction_is_valid setting oldest invalid trans_id "
 					       "to %d",
@@ -2095,11 +2095,11 @@
 			return -1;
 		}
 		brelse(c_bh);
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 			       "journal-1006: found valid "
 			       "transaction start offset %llu, len %d id %d",
 			       d_bh->b_blocknr -
-			       SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+			       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 			       get_desc_trans_len(desc),
 			       get_desc_trans_id(desc));
 		return 1;
@@ -2121,63 +2121,63 @@
 ** this either reads in a replays a transaction, or returns because the transaction
 ** is invalid, or too old.
 */
-static int journal_read_transaction(struct super_block *p_s_sb,
+static int journal_read_transaction(struct super_block *sb,
 				    unsigned long cur_dblock,
 				    unsigned long oldest_start,
-				    unsigned long oldest_trans_id,
+				    unsigned int oldest_trans_id,
 				    unsigned long newest_mount_id)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_desc *desc;
 	struct reiserfs_journal_commit *commit;
-	unsigned long trans_id = 0;
+	unsigned int trans_id = 0;
 	struct buffer_head *c_bh;
 	struct buffer_head *d_bh;
 	struct buffer_head **log_blocks = NULL;
 	struct buffer_head **real_blocks = NULL;
-	unsigned long trans_offset;
+	unsigned int trans_offset;
 	int i;
 	int trans_half;
 
-	d_bh = journal_bread(p_s_sb, cur_dblock);
+	d_bh = journal_bread(sb, cur_dblock);
 	if (!d_bh)
 		return 1;
 	desc = (struct reiserfs_journal_desc *)d_bh->b_data;
-	trans_offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb);
-	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1037: "
+	trans_offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
+	reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1037: "
 		       "journal_read_transaction, offset %llu, len %d mount_id %d",
-		       d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+		       d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 		       get_desc_trans_len(desc), get_desc_mount_id(desc));
 	if (get_desc_trans_id(desc) < oldest_trans_id) {
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1039: "
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1039: "
 			       "journal_read_trans skipping because %lu is too old",
 			       cur_dblock -
-			       SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb));
+			       SB_ONDISK_JOURNAL_1st_BLOCK(sb));
 		brelse(d_bh);
 		return 1;
 	}
 	if (get_desc_mount_id(desc) != newest_mount_id) {
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1146: "
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1146: "
 			       "journal_read_trans skipping because %d is != "
 			       "newest_mount_id %lu", get_desc_mount_id(desc),
 			       newest_mount_id);
 		brelse(d_bh);
 		return 1;
 	}
-	c_bh = journal_bread(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+	c_bh = journal_bread(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 			     ((trans_offset + get_desc_trans_len(desc) + 1) %
-			      SB_ONDISK_JOURNAL_SIZE(p_s_sb)));
+			      SB_ONDISK_JOURNAL_SIZE(sb)));
 	if (!c_bh) {
 		brelse(d_bh);
 		return 1;
 	}
 	commit = (struct reiserfs_journal_commit *)c_bh->b_data;
-	if (journal_compare_desc_commit(p_s_sb, desc, commit)) {
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+	if (journal_compare_desc_commit(sb, desc, commit)) {
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 			       "journal_read_transaction, "
 			       "commit offset %llu had bad time %d or length %d",
 			       c_bh->b_blocknr -
-			       SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+			       SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 			       get_commit_trans_id(commit),
 			       get_commit_trans_len(commit));
 		brelse(c_bh);
@@ -2195,38 +2195,41 @@
 		brelse(d_bh);
 		kfree(log_blocks);
 		kfree(real_blocks);
-		reiserfs_warning(p_s_sb,
-				 "journal-1169: kmalloc failed, unable to mount FS");
+		reiserfs_warning(sb, "journal-1169",
+				 "kmalloc failed, unable to mount FS");
 		return -1;
 	}
 	/* get all the buffer heads */
-	trans_half = journal_trans_half(p_s_sb->s_blocksize);
+	trans_half = journal_trans_half(sb->s_blocksize);
 	for (i = 0; i < get_desc_trans_len(desc); i++) {
 		log_blocks[i] =
-		    journal_getblk(p_s_sb,
-				   SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+		    journal_getblk(sb,
+				   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 				   (trans_offset + 1 +
-				    i) % SB_ONDISK_JOURNAL_SIZE(p_s_sb));
+				    i) % SB_ONDISK_JOURNAL_SIZE(sb));
 		if (i < trans_half) {
 			real_blocks[i] =
-			    sb_getblk(p_s_sb,
+			    sb_getblk(sb,
 				      le32_to_cpu(desc->j_realblock[i]));
 		} else {
 			real_blocks[i] =
-			    sb_getblk(p_s_sb,
+			    sb_getblk(sb,
 				      le32_to_cpu(commit->
 						  j_realblock[i - trans_half]));
 		}
-		if (real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(p_s_sb)) {
-			reiserfs_warning(p_s_sb,
-					 "journal-1207: REPLAY FAILURE fsck required! Block to replay is outside of filesystem");
+		if (real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(sb)) {
+			reiserfs_warning(sb, "journal-1207",
+					 "REPLAY FAILURE fsck required! "
+					 "Block to replay is outside of "
+					 "filesystem");
 			goto abort_replay;
 		}
 		/* make sure we don't try to replay onto log or reserved area */
 		if (is_block_in_log_or_reserved_area
-		    (p_s_sb, real_blocks[i]->b_blocknr)) {
-			reiserfs_warning(p_s_sb,
-					 "journal-1204: REPLAY FAILURE fsck required! Trying to replay onto a log block");
+		    (sb, real_blocks[i]->b_blocknr)) {
+			reiserfs_warning(sb, "journal-1204",
+					 "REPLAY FAILURE fsck required! "
+					 "Trying to replay onto a log block");
 		      abort_replay:
 			brelse_array(log_blocks, i);
 			brelse_array(real_blocks, i);
@@ -2242,8 +2245,9 @@
 	for (i = 0; i < get_desc_trans_len(desc); i++) {
 		wait_on_buffer(log_blocks[i]);
 		if (!buffer_uptodate(log_blocks[i])) {
-			reiserfs_warning(p_s_sb,
-					 "journal-1212: REPLAY FAILURE fsck required! buffer write failed");
+			reiserfs_warning(sb, "journal-1212",
+					 "REPLAY FAILURE fsck required! "
+					 "buffer write failed");
 			brelse_array(log_blocks + i,
 				     get_desc_trans_len(desc) - i);
 			brelse_array(real_blocks, get_desc_trans_len(desc));
@@ -2266,8 +2270,9 @@
 	for (i = 0; i < get_desc_trans_len(desc); i++) {
 		wait_on_buffer(real_blocks[i]);
 		if (!buffer_uptodate(real_blocks[i])) {
-			reiserfs_warning(p_s_sb,
-					 "journal-1226: REPLAY FAILURE, fsck required! buffer write failed");
+			reiserfs_warning(sb, "journal-1226",
+					 "REPLAY FAILURE, fsck required! "
+					 "buffer write failed");
 			brelse_array(real_blocks + i,
 				     get_desc_trans_len(desc) - i);
 			brelse(c_bh);
@@ -2279,15 +2284,15 @@
 		brelse(real_blocks[i]);
 	}
 	cur_dblock =
-	    SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+	    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 	    ((trans_offset + get_desc_trans_len(desc) +
-	      2) % SB_ONDISK_JOURNAL_SIZE(p_s_sb));
-	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+	      2) % SB_ONDISK_JOURNAL_SIZE(sb));
+	reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 		       "journal-1095: setting journal " "start to offset %ld",
-		       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb));
+		       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb));
 
 	/* init starting values for the first transaction, in case this is the last transaction to be replayed. */
-	journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb);
+	journal->j_start = cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb);
 	journal->j_last_flush_trans_id = trans_id;
 	journal->j_trans_id = trans_id + 1;
 	/* check for trans_id overflow */
@@ -2352,12 +2357,12 @@
 **
 ** On exit, it sets things up so the first transaction will work correctly.
 */
-static int journal_read(struct super_block *p_s_sb)
+static int journal_read(struct super_block *sb)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_desc *desc;
-	unsigned long oldest_trans_id = 0;
-	unsigned long oldest_invalid_trans_id = 0;
+	unsigned int oldest_trans_id = 0;
+	unsigned int oldest_invalid_trans_id = 0;
 	time_t start;
 	unsigned long oldest_start = 0;
 	unsigned long cur_dblock = 0;
@@ -2370,46 +2375,46 @@
 	int ret;
 	char b[BDEVNAME_SIZE];
 
-	cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb);
-	reiserfs_info(p_s_sb, "checking transaction log (%s)\n",
+	cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb);
+	reiserfs_info(sb, "checking transaction log (%s)\n",
 		      bdevname(journal->j_dev_bd, b));
 	start = get_seconds();
 
-	/* step 1, read in the journal header block.  Check the transaction it says 
-	 ** is the first unflushed, and if that transaction is not valid, 
+	/* step 1, read in the journal header block.  Check the transaction it says
+	 ** is the first unflushed, and if that transaction is not valid,
 	 ** replay is done
 	 */
-	journal->j_header_bh = journal_bread(p_s_sb,
-					     SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb)
-					     + SB_ONDISK_JOURNAL_SIZE(p_s_sb));
+	journal->j_header_bh = journal_bread(sb,
+					     SB_ONDISK_JOURNAL_1st_BLOCK(sb)
+					     + SB_ONDISK_JOURNAL_SIZE(sb));
 	if (!journal->j_header_bh) {
 		return 1;
 	}
 	jh = (struct reiserfs_journal_header *)(journal->j_header_bh->b_data);
 	if (le32_to_cpu(jh->j_first_unflushed_offset) <
-	    SB_ONDISK_JOURNAL_SIZE(p_s_sb)
+	    SB_ONDISK_JOURNAL_SIZE(sb)
 	    && le32_to_cpu(jh->j_last_flush_trans_id) > 0) {
 		oldest_start =
-		    SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+		    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 		    le32_to_cpu(jh->j_first_unflushed_offset);
 		oldest_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) + 1;
 		newest_mount_id = le32_to_cpu(jh->j_mount_id);
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 			       "journal-1153: found in "
 			       "header: first_unflushed_offset %d, last_flushed_trans_id "
 			       "%lu", le32_to_cpu(jh->j_first_unflushed_offset),
 			       le32_to_cpu(jh->j_last_flush_trans_id));
 		valid_journal_header = 1;
 
-		/* now, we try to read the first unflushed offset.  If it is not valid, 
-		 ** there is nothing more we can do, and it makes no sense to read 
+		/* now, we try to read the first unflushed offset.  If it is not valid,
+		 ** there is nothing more we can do, and it makes no sense to read
 		 ** through the whole log.
 		 */
 		d_bh =
-		    journal_bread(p_s_sb,
-				  SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+		    journal_bread(sb,
+				  SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 				  le32_to_cpu(jh->j_first_unflushed_offset));
-		ret = journal_transaction_is_valid(p_s_sb, d_bh, NULL, NULL);
+		ret = journal_transaction_is_valid(sb, d_bh, NULL, NULL);
 		if (!ret) {
 			continue_replay = 0;
 		}
@@ -2417,9 +2422,9 @@
 		goto start_log_replay;
 	}
 
-	if (continue_replay && bdev_read_only(p_s_sb->s_bdev)) {
-		reiserfs_warning(p_s_sb,
-				 "clm-2076: device is readonly, unable to replay log");
+	if (continue_replay && bdev_read_only(sb->s_bdev)) {
+		reiserfs_warning(sb, "clm-2076",
+				 "device is readonly, unable to replay log");
 		return -1;
 	}
 
@@ -2428,17 +2433,17 @@
 	 */
 	while (continue_replay
 	       && cur_dblock <
-	       (SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
-		SB_ONDISK_JOURNAL_SIZE(p_s_sb))) {
+	       (SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
+		SB_ONDISK_JOURNAL_SIZE(sb))) {
 		/* Note that it is required for blocksize of primary fs device and journal
 		   device to be the same */
 		d_bh =
 		    reiserfs_breada(journal->j_dev_bd, cur_dblock,
-				    p_s_sb->s_blocksize,
-				    SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
-				    SB_ONDISK_JOURNAL_SIZE(p_s_sb));
+				    sb->s_blocksize,
+				    SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
+				    SB_ONDISK_JOURNAL_SIZE(sb));
 		ret =
-		    journal_transaction_is_valid(p_s_sb, d_bh,
+		    journal_transaction_is_valid(sb, d_bh,
 						 &oldest_invalid_trans_id,
 						 &newest_mount_id);
 		if (ret == 1) {
@@ -2447,26 +2452,26 @@
 				oldest_trans_id = get_desc_trans_id(desc);
 				oldest_start = d_bh->b_blocknr;
 				newest_mount_id = get_desc_mount_id(desc);
-				reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 					       "journal-1179: Setting "
 					       "oldest_start to offset %llu, trans_id %lu",
 					       oldest_start -
 					       SB_ONDISK_JOURNAL_1st_BLOCK
-					       (p_s_sb), oldest_trans_id);
+					       (sb), oldest_trans_id);
 			} else if (oldest_trans_id > get_desc_trans_id(desc)) {
 				/* one we just read was older */
 				oldest_trans_id = get_desc_trans_id(desc);
 				oldest_start = d_bh->b_blocknr;
-				reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 					       "journal-1180: Resetting "
 					       "oldest_start to offset %lu, trans_id %lu",
 					       oldest_start -
 					       SB_ONDISK_JOURNAL_1st_BLOCK
-					       (p_s_sb), oldest_trans_id);
+					       (sb), oldest_trans_id);
 			}
 			if (newest_mount_id < get_desc_mount_id(desc)) {
 				newest_mount_id = get_desc_mount_id(desc);
-				reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+				reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 					       "journal-1299: Setting "
 					       "newest_mount_id to %d",
 					       get_desc_mount_id(desc));
@@ -2481,17 +2486,17 @@
       start_log_replay:
 	cur_dblock = oldest_start;
 	if (oldest_trans_id) {
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 			       "journal-1206: Starting replay "
 			       "from offset %llu, trans_id %lu",
-			       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+			       cur_dblock - SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 			       oldest_trans_id);
 
 	}
 	replay_count = 0;
 	while (continue_replay && oldest_trans_id > 0) {
 		ret =
-		    journal_read_transaction(p_s_sb, cur_dblock, oldest_start,
+		    journal_read_transaction(sb, cur_dblock, oldest_start,
 					     oldest_trans_id, newest_mount_id);
 		if (ret < 0) {
 			return ret;
@@ -2499,14 +2504,14 @@
 			break;
 		}
 		cur_dblock =
-		    SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + journal->j_start;
+		    SB_ONDISK_JOURNAL_1st_BLOCK(sb) + journal->j_start;
 		replay_count++;
 		if (cur_dblock == oldest_start)
 			break;
 	}
 
 	if (oldest_trans_id == 0) {
-		reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+		reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 			       "journal-1225: No valid " "transactions found");
 	}
 	/* j_start does not get set correctly if we don't replay any transactions.
@@ -2526,16 +2531,16 @@
 	} else {
 		journal->j_mount_id = newest_mount_id + 1;
 	}
-	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "
+	reiserfs_debug(sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "
 		       "newest_mount_id to %lu", journal->j_mount_id);
 	journal->j_first_unflushed_offset = journal->j_start;
 	if (replay_count > 0) {
-		reiserfs_info(p_s_sb,
+		reiserfs_info(sb,
 			      "replayed %d transactions in %lu seconds\n",
 			      replay_count, get_seconds() - start);
 	}
-	if (!bdev_read_only(p_s_sb->s_bdev) &&
-	    _update_journal_header_block(p_s_sb, journal->j_start,
+	if (!bdev_read_only(sb->s_bdev) &&
+	    _update_journal_header_block(sb, journal->j_start,
 					 journal->j_last_flush_trans_id)) {
 		/* replay failed, caller must call free_journal_ram and abort
 		 ** the mount
@@ -2560,9 +2565,9 @@
 	return jl;
 }
 
-static void journal_list_init(struct super_block *p_s_sb)
+static void journal_list_init(struct super_block *sb)
 {
-	SB_JOURNAL(p_s_sb)->j_current_jl = alloc_journal_list(p_s_sb);
+	SB_JOURNAL(sb)->j_current_jl = alloc_journal_list(sb);
 }
 
 static int release_journal_dev(struct super_block *super,
@@ -2580,9 +2585,8 @@
 	}
 
 	if (result != 0) {
-		reiserfs_warning(super,
-				 "sh-457: release_journal_dev: Cannot release journal device: %i",
-				 result);
+		reiserfs_warning(super, "sh-457",
+				 "Cannot release journal device: %i", result);
 	}
 	return result;
 }
@@ -2612,7 +2616,7 @@
 		if (IS_ERR(journal->j_dev_bd)) {
 			result = PTR_ERR(journal->j_dev_bd);
 			journal->j_dev_bd = NULL;
-			reiserfs_warning(super, "sh-458: journal_init_dev: "
+			reiserfs_warning(super, "sh-458",
 					 "cannot init journal device '%s': %i",
 					 __bdevname(jdev, b), result);
 			return result;
@@ -2662,30 +2666,30 @@
  */
 #define REISERFS_STANDARD_BLKSIZE (4096)
 
-static int check_advise_trans_params(struct super_block *p_s_sb,
+static int check_advise_trans_params(struct super_block *sb,
 				     struct reiserfs_journal *journal)
 {
         if (journal->j_trans_max) {
 	        /* Non-default journal params.
 		   Do sanity check for them. */
 	        int ratio = 1;
-		if (p_s_sb->s_blocksize < REISERFS_STANDARD_BLKSIZE)
-		        ratio = REISERFS_STANDARD_BLKSIZE / p_s_sb->s_blocksize;
+		if (sb->s_blocksize < REISERFS_STANDARD_BLKSIZE)
+		        ratio = REISERFS_STANDARD_BLKSIZE / sb->s_blocksize;
 
 		if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio ||
 		    journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio ||
-		    SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max <
+		    SB_ONDISK_JOURNAL_SIZE(sb) / journal->j_trans_max <
 		    JOURNAL_MIN_RATIO) {
-		        reiserfs_warning(p_s_sb,
-				 "sh-462: bad transaction max size (%u). FSCK?",
-				 journal->j_trans_max);
+			reiserfs_warning(sb, "sh-462",
+					 "bad transaction max size (%u). "
+					 "FSCK?", journal->j_trans_max);
 			return 1;
 		}
 		if (journal->j_max_batch != (journal->j_trans_max) *
 		        JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) {
-		        reiserfs_warning(p_s_sb,
-				"sh-463: bad transaction max batch (%u). FSCK?",
-				journal->j_max_batch);
+			reiserfs_warning(sb, "sh-463",
+					 "bad transaction max batch (%u). "
+					 "FSCK?", journal->j_max_batch);
 			return 1;
 		}
 	} else {
@@ -2693,9 +2697,11 @@
                    The file system was created by old version
 		   of mkreiserfs, so some fields contain zeros,
 		   and we need to advise proper values for them */
-	        if (p_s_sb->s_blocksize != REISERFS_STANDARD_BLKSIZE)
-	                reiserfs_panic(p_s_sb, "sh-464: bad blocksize (%u)",
-				       p_s_sb->s_blocksize);
+		if (sb->s_blocksize != REISERFS_STANDARD_BLKSIZE) {
+			reiserfs_warning(sb, "sh-464", "bad blocksize (%u)",
+					 sb->s_blocksize);
+			return 1;
+		}
 		journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT;
 		journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT;
 		journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE;
@@ -2706,10 +2712,10 @@
 /*
 ** must be called once on fs mount.  calls journal_read for you
 */
-int journal_init(struct super_block *p_s_sb, const char *j_dev_name,
+int journal_init(struct super_block *sb, const char *j_dev_name,
 		 int old_format, unsigned int commit_max_age)
 {
-	int num_cnodes = SB_ONDISK_JOURNAL_SIZE(p_s_sb) * 2;
+	int num_cnodes = SB_ONDISK_JOURNAL_SIZE(sb) * 2;
 	struct buffer_head *bhjh;
 	struct reiserfs_super_block *rs;
 	struct reiserfs_journal_header *jh;
@@ -2717,10 +2723,10 @@
 	struct reiserfs_journal_list *jl;
 	char b[BDEVNAME_SIZE];
 
-	journal = SB_JOURNAL(p_s_sb) = vmalloc(sizeof(struct reiserfs_journal));
+	journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal));
 	if (!journal) {
-		reiserfs_warning(p_s_sb,
-				 "journal-1256: unable to get memory for journal structure");
+		reiserfs_warning(sb, "journal-1256",
+				 "unable to get memory for journal structure");
 		return 1;
 	}
 	memset(journal, 0, sizeof(struct reiserfs_journal));
@@ -2729,51 +2735,51 @@
 	INIT_LIST_HEAD(&journal->j_working_list);
 	INIT_LIST_HEAD(&journal->j_journal_list);
 	journal->j_persistent_trans = 0;
-	if (reiserfs_allocate_list_bitmaps(p_s_sb,
+	if (reiserfs_allocate_list_bitmaps(sb,
 					   journal->j_list_bitmap,
-					   reiserfs_bmap_count(p_s_sb)))
+					   reiserfs_bmap_count(sb)))
 		goto free_and_return;
-	allocate_bitmap_nodes(p_s_sb);
+	allocate_bitmap_nodes(sb);
 
 	/* reserved for journal area support */
-	SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) = (old_format ?
+	SB_JOURNAL_1st_RESERVED_BLOCK(sb) = (old_format ?
 						 REISERFS_OLD_DISK_OFFSET_IN_BYTES
-						 / p_s_sb->s_blocksize +
-						 reiserfs_bmap_count(p_s_sb) +
+						 / sb->s_blocksize +
+						 reiserfs_bmap_count(sb) +
 						 1 :
 						 REISERFS_DISK_OFFSET_IN_BYTES /
-						 p_s_sb->s_blocksize + 2);
+						 sb->s_blocksize + 2);
 
 	/* Sanity check to see is the standard journal fitting withing first bitmap
 	   (actual for small blocksizes) */
-	if (!SB_ONDISK_JOURNAL_DEVICE(p_s_sb) &&
-	    (SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb) +
-	     SB_ONDISK_JOURNAL_SIZE(p_s_sb) > p_s_sb->s_blocksize * 8)) {
-		reiserfs_warning(p_s_sb,
-				 "journal-1393: journal does not fit for area "
-				 "addressed by first of bitmap blocks. It starts at "
+	if (!SB_ONDISK_JOURNAL_DEVICE(sb) &&
+	    (SB_JOURNAL_1st_RESERVED_BLOCK(sb) +
+	     SB_ONDISK_JOURNAL_SIZE(sb) > sb->s_blocksize * 8)) {
+		reiserfs_warning(sb, "journal-1393",
+				 "journal does not fit for area addressed "
+				 "by first of bitmap blocks. It starts at "
 				 "%u and its size is %u. Block size %ld",
-				 SB_JOURNAL_1st_RESERVED_BLOCK(p_s_sb),
-				 SB_ONDISK_JOURNAL_SIZE(p_s_sb),
-				 p_s_sb->s_blocksize);
+				 SB_JOURNAL_1st_RESERVED_BLOCK(sb),
+				 SB_ONDISK_JOURNAL_SIZE(sb),
+				 sb->s_blocksize);
 		goto free_and_return;
 	}
 
-	if (journal_init_dev(p_s_sb, journal, j_dev_name) != 0) {
-		reiserfs_warning(p_s_sb,
-				 "sh-462: unable to initialize jornal device");
+	if (journal_init_dev(sb, journal, j_dev_name) != 0) {
+		reiserfs_warning(sb, "sh-462",
+				 "unable to initialize jornal device");
 		goto free_and_return;
 	}
 
-	rs = SB_DISK_SUPER_BLOCK(p_s_sb);
+	rs = SB_DISK_SUPER_BLOCK(sb);
 
 	/* read journal header */
-	bhjh = journal_bread(p_s_sb,
-			     SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
-			     SB_ONDISK_JOURNAL_SIZE(p_s_sb));
+	bhjh = journal_bread(sb,
+			     SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
+			     SB_ONDISK_JOURNAL_SIZE(sb));
 	if (!bhjh) {
-		reiserfs_warning(p_s_sb,
-				 "sh-459: unable to read journal header");
+		reiserfs_warning(sb, "sh-459",
+				 "unable to read journal header");
 		goto free_and_return;
 	}
 	jh = (struct reiserfs_journal_header *)(bhjh->b_data);
@@ -2782,10 +2788,10 @@
 	if (is_reiserfs_jr(rs)
 	    && (le32_to_cpu(jh->jh_journal.jp_journal_magic) !=
 		sb_jp_journal_magic(rs))) {
-		reiserfs_warning(p_s_sb,
-				 "sh-460: journal header magic %x "
-				 "(device %s) does not match to magic found in super "
-				 "block %x", jh->jh_journal.jp_journal_magic,
+		reiserfs_warning(sb, "sh-460",
+				 "journal header magic %x (device %s) does "
+				 "not match to magic found in super block %x",
+				 jh->jh_journal.jp_journal_magic,
 				 bdevname(journal->j_dev_bd, b),
 				 sb_jp_journal_magic(rs));
 		brelse(bhjh);
@@ -2798,7 +2804,7 @@
 	    le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age);
 	journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE;
 
-	if (check_advise_trans_params(p_s_sb, journal) != 0)
+	if (check_advise_trans_params(sb, journal) != 0)
 	        goto free_and_return;
 	journal->j_default_max_commit_age = journal->j_max_commit_age;
 
@@ -2807,12 +2813,12 @@
 		journal->j_max_trans_age = commit_max_age;
 	}
 
-	reiserfs_info(p_s_sb, "journal params: device %s, size %u, "
+	reiserfs_info(sb, "journal params: device %s, size %u, "
 		      "journal first block %u, max trans len %u, max batch %u, "
 		      "max commit age %u, max trans age %u\n",
 		      bdevname(journal->j_dev_bd, b),
-		      SB_ONDISK_JOURNAL_SIZE(p_s_sb),
-		      SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb),
+		      SB_ONDISK_JOURNAL_SIZE(sb),
+		      SB_ONDISK_JOURNAL_1st_BLOCK(sb),
 		      journal->j_trans_max,
 		      journal->j_max_batch,
 		      journal->j_max_commit_age, journal->j_max_trans_age);
@@ -2820,7 +2826,7 @@
 	brelse(bhjh);
 
 	journal->j_list_bitmap_index = 0;
-	journal_list_init(p_s_sb);
+	journal_list_init(sb);
 
 	memset(journal->j_list_hash_table, 0,
 	       JOURNAL_HASH_SIZE * sizeof(struct reiserfs_journal_cnode *));
@@ -2852,7 +2858,7 @@
 	journal->j_must_wait = 0;
 
 	if (journal->j_cnode_free == 0) {
-        	reiserfs_warning(p_s_sb, "journal-2004: Journal cnode memory "
+		reiserfs_warning(sb, "journal-2004", "Journal cnode memory "
 		                 "allocation failed (%ld bytes). Journal is "
 		                 "too large for available memory. Usually "
 		                 "this is due to a journal that is too large.",
@@ -2860,16 +2866,17 @@
         	goto free_and_return;
 	}
 
-	init_journal_hash(p_s_sb);
+	init_journal_hash(sb);
 	jl = journal->j_current_jl;
-	jl->j_list_bitmap = get_list_bitmap(p_s_sb, jl);
+	jl->j_list_bitmap = get_list_bitmap(sb, jl);
 	if (!jl->j_list_bitmap) {
-		reiserfs_warning(p_s_sb,
-				 "journal-2005, get_list_bitmap failed for journal list 0");
+		reiserfs_warning(sb, "journal-2005",
+				 "get_list_bitmap failed for journal list 0");
 		goto free_and_return;
 	}
-	if (journal_read(p_s_sb) < 0) {
-		reiserfs_warning(p_s_sb, "Replay Failure, unable to mount");
+	if (journal_read(sb) < 0) {
+		reiserfs_warning(sb, "reiserfs-2006",
+				 "Replay Failure, unable to mount");
 		goto free_and_return;
 	}
 
@@ -2878,10 +2885,10 @@
 		commit_wq = create_workqueue("reiserfs");
 
 	INIT_DELAYED_WORK(&journal->j_work, flush_async_commits);
-	journal->j_work_sb = p_s_sb;
+	journal->j_work_sb = sb;
 	return 0;
       free_and_return:
-	free_journal_ram(p_s_sb);
+	free_journal_ram(sb);
 	return 1;
 }
 
@@ -2912,7 +2919,7 @@
 	return 0;
 }
 
-/* this must be called inside a transaction, and requires the 
+/* this must be called inside a transaction, and requires the
 ** kernel_lock to be held
 */
 void reiserfs_block_writes(struct reiserfs_transaction_handle *th)
@@ -2970,7 +2977,7 @@
 		wake_up(&journal->j_join_wait);
 }
 
-static void let_transaction_grow(struct super_block *sb, unsigned long trans_id)
+static void let_transaction_grow(struct super_block *sb, unsigned int trans_id)
 {
 	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	unsigned long bcount = journal->j_bcount;
@@ -2997,43 +3004,43 @@
 ** expect to use in nblocks.
 */
 static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
-			      struct super_block *p_s_sb, unsigned long nblocks,
+			      struct super_block *sb, unsigned long nblocks,
 			      int join)
 {
 	time_t now = get_seconds();
-	int old_trans_id;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	unsigned int old_trans_id;
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_transaction_handle myth;
 	int sched_count = 0;
 	int retval;
 
-	reiserfs_check_lock_depth(p_s_sb, "journal_begin");
+	reiserfs_check_lock_depth(sb, "journal_begin");
 	BUG_ON(nblocks > journal->j_trans_max);
 
-	PROC_INFO_INC(p_s_sb, journal.journal_being);
+	PROC_INFO_INC(sb, journal.journal_being);
 	/* set here for journal_join */
 	th->t_refcount = 1;
-	th->t_super = p_s_sb;
+	th->t_super = sb;
 
       relock:
-	lock_journal(p_s_sb);
+	lock_journal(sb);
 	if (join != JBEGIN_ABORT && reiserfs_is_journal_aborted(journal)) {
-		unlock_journal(p_s_sb);
+		unlock_journal(sb);
 		retval = journal->j_errno;
 		goto out_fail;
 	}
 	journal->j_bcount++;
 
 	if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) {
-		unlock_journal(p_s_sb);
-		reiserfs_wait_on_write_block(p_s_sb);
-		PROC_INFO_INC(p_s_sb, journal.journal_relock_writers);
+		unlock_journal(sb);
+		reiserfs_wait_on_write_block(sb);
+		PROC_INFO_INC(sb, journal.journal_relock_writers);
 		goto relock;
 	}
 	now = get_seconds();
 
 	/* if there is no room in the journal OR
-	 ** if this transaction is too old, and we weren't called joinable, wait for it to finish before beginning 
+	 ** if this transaction is too old, and we weren't called joinable, wait for it to finish before beginning
 	 ** we don't sleep if there aren't other writers
 	 */
 
@@ -3048,7 +3055,7 @@
 	    || (!join && journal->j_cnode_free < (journal->j_trans_max * 3))) {
 
 		old_trans_id = journal->j_trans_id;
-		unlock_journal(p_s_sb);	/* allow others to finish this transaction */
+		unlock_journal(sb);	/* allow others to finish this transaction */
 
 		if (!join && (journal->j_len_alloc + nblocks + 2) >=
 		    journal->j_max_batch &&
@@ -3056,7 +3063,7 @@
 		    (journal->j_len_alloc * 75)) {
 			if (atomic_read(&journal->j_wcount) > 10) {
 				sched_count++;
-				queue_log_writer(p_s_sb);
+				queue_log_writer(sb);
 				goto relock;
 			}
 		}
@@ -3066,25 +3073,25 @@
 		if (atomic_read(&journal->j_jlock)) {
 			while (journal->j_trans_id == old_trans_id &&
 			       atomic_read(&journal->j_jlock)) {
-				queue_log_writer(p_s_sb);
+				queue_log_writer(sb);
 			}
 			goto relock;
 		}
-		retval = journal_join(&myth, p_s_sb, 1);
+		retval = journal_join(&myth, sb, 1);
 		if (retval)
 			goto out_fail;
 
 		/* someone might have ended the transaction while we joined */
 		if (old_trans_id != journal->j_trans_id) {
-			retval = do_journal_end(&myth, p_s_sb, 1, 0);
+			retval = do_journal_end(&myth, sb, 1, 0);
 		} else {
-			retval = do_journal_end(&myth, p_s_sb, 1, COMMIT_NOW);
+			retval = do_journal_end(&myth, sb, 1, COMMIT_NOW);
 		}
 
 		if (retval)
 			goto out_fail;
 
-		PROC_INFO_INC(p_s_sb, journal.journal_relock_wcount);
+		PROC_INFO_INC(sb, journal.journal_relock_wcount);
 		goto relock;
 	}
 	/* we are the first writer, set trans_id */
@@ -3096,7 +3103,7 @@
 	th->t_blocks_logged = 0;
 	th->t_blocks_allocated = nblocks;
 	th->t_trans_id = journal->j_trans_id;
-	unlock_journal(p_s_sb);
+	unlock_journal(sb);
 	INIT_LIST_HEAD(&th->t_list);
 	get_fs_excl();
 	return 0;
@@ -3106,7 +3113,7 @@
 	/* Re-set th->t_super, so we can properly keep track of how many
 	 * persistent transactions there are. We need to do this so if this
 	 * call is part of a failed restart_transaction, we can free it later */
-	th->t_super = p_s_sb;
+	th->t_super = sb;
 	return retval;
 }
 
@@ -3157,7 +3164,7 @@
 }
 
 static int journal_join(struct reiserfs_transaction_handle *th,
-			struct super_block *p_s_sb, unsigned long nblocks)
+			struct super_block *sb, unsigned long nblocks)
 {
 	struct reiserfs_transaction_handle *cur_th = current->journal_info;
 
@@ -3166,11 +3173,11 @@
 	 */
 	th->t_handle_save = cur_th;
 	BUG_ON(cur_th && cur_th->t_refcount > 1);
-	return do_journal_begin_r(th, p_s_sb, nblocks, JBEGIN_JOIN);
+	return do_journal_begin_r(th, sb, nblocks, JBEGIN_JOIN);
 }
 
 int journal_join_abort(struct reiserfs_transaction_handle *th,
-		       struct super_block *p_s_sb, unsigned long nblocks)
+		       struct super_block *sb, unsigned long nblocks)
 {
 	struct reiserfs_transaction_handle *cur_th = current->journal_info;
 
@@ -3179,11 +3186,11 @@
 	 */
 	th->t_handle_save = cur_th;
 	BUG_ON(cur_th && cur_th->t_refcount > 1);
-	return do_journal_begin_r(th, p_s_sb, nblocks, JBEGIN_ABORT);
+	return do_journal_begin_r(th, sb, nblocks, JBEGIN_ABORT);
 }
 
 int journal_begin(struct reiserfs_transaction_handle *th,
-		  struct super_block *p_s_sb, unsigned long nblocks)
+		  struct super_block *sb, unsigned long nblocks)
 {
 	struct reiserfs_transaction_handle *cur_th = current->journal_info;
 	int ret;
@@ -3191,28 +3198,29 @@
 	th->t_handle_save = NULL;
 	if (cur_th) {
 		/* we are nesting into the current transaction */
-		if (cur_th->t_super == p_s_sb) {
+		if (cur_th->t_super == sb) {
 			BUG_ON(!cur_th->t_refcount);
 			cur_th->t_refcount++;
 			memcpy(th, cur_th, sizeof(*th));
 			if (th->t_refcount <= 1)
-				reiserfs_warning(p_s_sb,
-						 "BAD: refcount <= 1, but journal_info != 0");
+				reiserfs_warning(sb, "reiserfs-2005",
+						 "BAD: refcount <= 1, but "
+						 "journal_info != 0");
 			return 0;
 		} else {
 			/* we've ended up with a handle from a different filesystem.
 			 ** save it and restore on journal_end.  This should never
 			 ** really happen...
 			 */
-			reiserfs_warning(p_s_sb,
-					 "clm-2100: nesting info a different FS");
+			reiserfs_warning(sb, "clm-2100",
+					 "nesting info a different FS");
 			th->t_handle_save = current->journal_info;
 			current->journal_info = th;
 		}
 	} else {
 		current->journal_info = th;
 	}
-	ret = do_journal_begin_r(th, p_s_sb, nblocks, JBEGIN_REG);
+	ret = do_journal_begin_r(th, sb, nblocks, JBEGIN_REG);
 	BUG_ON(current->journal_info != th);
 
 	/* I guess this boils down to being the reciprocal of clm-2100 above.
@@ -3232,32 +3240,32 @@
 **
 ** if it was dirty, cleans and files onto the clean list.  I can't let it be dirty again until the
 ** transaction is committed.
-** 
+**
 ** if j_len, is bigger than j_len_alloc, it pushes j_len_alloc to 10 + j_len.
 */
 int journal_mark_dirty(struct reiserfs_transaction_handle *th,
-		       struct super_block *p_s_sb, struct buffer_head *bh)
+		       struct super_block *sb, struct buffer_head *bh)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_cnode *cn = NULL;
 	int count_already_incd = 0;
 	int prepared = 0;
 	BUG_ON(!th->t_trans_id);
 
-	PROC_INFO_INC(p_s_sb, journal.mark_dirty);
+	PROC_INFO_INC(sb, journal.mark_dirty);
 	if (th->t_trans_id != journal->j_trans_id) {
-		reiserfs_panic(th->t_super,
-			       "journal-1577: handle trans id %ld != current trans id %ld\n",
+		reiserfs_panic(th->t_super, "journal-1577",
+			       "handle trans id %ld != current trans id %ld",
 			       th->t_trans_id, journal->j_trans_id);
 	}
 
-	p_s_sb->s_dirt = 1;
+	sb->s_dirt = 1;
 
 	prepared = test_clear_buffer_journal_prepared(bh);
 	clear_buffer_journal_restore_dirty(bh);
 	/* already in this transaction, we are done */
 	if (buffer_journaled(bh)) {
-		PROC_INFO_INC(p_s_sb, journal.mark_dirty_already);
+		PROC_INFO_INC(sb, journal.mark_dirty_already);
 		return 0;
 	}
 
@@ -3266,7 +3274,8 @@
 	 ** could get to disk too early.  NOT GOOD.
 	 */
 	if (!prepared || buffer_dirty(bh)) {
-		reiserfs_warning(p_s_sb, "journal-1777: buffer %llu bad state "
+		reiserfs_warning(sb, "journal-1777",
+				 "buffer %llu bad state "
 				 "%cPREPARED %cLOCKED %cDIRTY %cJDIRTY_WAIT",
 				 (unsigned long long)bh->b_blocknr,
 				 prepared ? ' ' : '!',
@@ -3276,23 +3285,23 @@
 	}
 
 	if (atomic_read(&(journal->j_wcount)) <= 0) {
-		reiserfs_warning(p_s_sb,
-				 "journal-1409: journal_mark_dirty returning because j_wcount was %d",
+		reiserfs_warning(sb, "journal-1409",
+				 "returning because j_wcount was %d",
 				 atomic_read(&(journal->j_wcount)));
 		return 1;
 	}
-	/* this error means I've screwed up, and we've overflowed the transaction.  
+	/* this error means I've screwed up, and we've overflowed the transaction.
 	 ** Nothing can be done here, except make the FS readonly or panic.
 	 */
 	if (journal->j_len >= journal->j_trans_max) {
-		reiserfs_panic(th->t_super,
-			       "journal-1413: journal_mark_dirty: j_len (%lu) is too big\n",
+		reiserfs_panic(th->t_super, "journal-1413",
+			       "j_len (%lu) is too big",
 			       journal->j_len);
 	}
 
 	if (buffer_journal_dirty(bh)) {
 		count_already_incd = 1;
-		PROC_INFO_INC(p_s_sb, journal.mark_dirty_notjournal);
+		PROC_INFO_INC(sb, journal.mark_dirty_notjournal);
 		clear_buffer_journal_dirty(bh);
 	}
 
@@ -3304,9 +3313,9 @@
 
 	/* now put this guy on the end */
 	if (!cn) {
-		cn = get_cnode(p_s_sb);
+		cn = get_cnode(sb);
 		if (!cn) {
-			reiserfs_panic(p_s_sb, "get_cnode failed!\n");
+			reiserfs_panic(sb, "journal-4", "get_cnode failed!");
 		}
 
 		if (th->t_blocks_logged == th->t_blocks_allocated) {
@@ -3318,7 +3327,7 @@
 
 		cn->bh = bh;
 		cn->blocknr = bh->b_blocknr;
-		cn->sb = p_s_sb;
+		cn->sb = sb;
 		cn->jlist = NULL;
 		insert_journal_hash(journal->j_hash_table, cn);
 		if (!count_already_incd) {
@@ -3339,11 +3348,11 @@
 }
 
 int journal_end(struct reiserfs_transaction_handle *th,
-		struct super_block *p_s_sb, unsigned long nblocks)
+		struct super_block *sb, unsigned long nblocks)
 {
 	if (!current->journal_info && th->t_refcount > 1)
-		reiserfs_warning(p_s_sb, "REISER-NESTING: th NULL, refcount %d",
-				 th->t_refcount);
+		reiserfs_warning(sb, "REISER-NESTING",
+				 "th NULL, refcount %d", th->t_refcount);
 
 	if (!th->t_trans_id) {
 		WARN_ON(1);
@@ -3366,26 +3375,26 @@
 		}
 		return 0;
 	} else {
-		return do_journal_end(th, p_s_sb, nblocks, 0);
+		return do_journal_end(th, sb, nblocks, 0);
 	}
 }
 
-/* removes from the current transaction, relsing and descrementing any counters.  
+/* removes from the current transaction, relsing and descrementing any counters.
 ** also files the removed buffer directly onto the clean list
 **
 ** called by journal_mark_freed when a block has been deleted
 **
 ** returns 1 if it cleaned and relsed the buffer. 0 otherwise
 */
-static int remove_from_transaction(struct super_block *p_s_sb,
+static int remove_from_transaction(struct super_block *sb,
 				   b_blocknr_t blocknr, int already_cleaned)
 {
 	struct buffer_head *bh;
 	struct reiserfs_journal_cnode *cn;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	int ret = 0;
 
-	cn = get_journal_hash_dev(p_s_sb, journal->j_hash_table, blocknr);
+	cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr);
 	if (!cn || !cn->bh) {
 		return ret;
 	}
@@ -3403,7 +3412,7 @@
 		journal->j_last = cn->prev;
 	}
 	if (bh)
-		remove_journal_hash(p_s_sb, journal->j_hash_table, NULL,
+		remove_journal_hash(sb, journal->j_hash_table, NULL,
 				    bh->b_blocknr, 0);
 	clear_buffer_journaled(bh);	/* don't log this one */
 
@@ -3413,14 +3422,14 @@
 		clear_buffer_journal_test(bh);
 		put_bh(bh);
 		if (atomic_read(&(bh->b_count)) < 0) {
-			reiserfs_warning(p_s_sb,
-					 "journal-1752: remove from trans, b_count < 0");
+			reiserfs_warning(sb, "journal-1752",
+					 "b_count < 0");
 		}
 		ret = 1;
 	}
 	journal->j_len--;
 	journal->j_len_alloc--;
-	free_cnode(p_s_sb, cn);
+	free_cnode(sb, cn);
 	return ret;
 }
 
@@ -3468,22 +3477,22 @@
 }
 
 /* syncs the commit blocks, but does not force the real buffers to disk
-** will wait until the current transaction is done/committed before returning 
+** will wait until the current transaction is done/committed before returning
 */
 int journal_end_sync(struct reiserfs_transaction_handle *th,
-		     struct super_block *p_s_sb, unsigned long nblocks)
+		     struct super_block *sb, unsigned long nblocks)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
 	BUG_ON(!th->t_trans_id);
 	/* you can sync while nested, very, very bad */
 	BUG_ON(th->t_refcount > 1);
 	if (journal->j_len == 0) {
-		reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb),
+		reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb),
 					     1);
-		journal_mark_dirty(th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb));
+		journal_mark_dirty(th, sb, SB_BUFFER_WITH_SB(sb));
 	}
-	return do_journal_end(th, p_s_sb, nblocks, COMMIT_NOW | WAIT);
+	return do_journal_end(th, sb, nblocks, COMMIT_NOW | WAIT);
 }
 
 /*
@@ -3493,7 +3502,7 @@
 {
 	struct reiserfs_journal *journal =
 		container_of(work, struct reiserfs_journal, j_work.work);
-	struct super_block *p_s_sb = journal->j_work_sb;
+	struct super_block *sb = journal->j_work_sb;
 	struct reiserfs_journal_list *jl;
 	struct list_head *entry;
 
@@ -3502,7 +3511,7 @@
 		/* last entry is the youngest, commit it and you get everything */
 		entry = journal->j_journal_list.prev;
 		jl = JOURNAL_LIST_ENTRY(entry);
-		flush_commit_list(p_s_sb, jl, 1);
+		flush_commit_list(sb, jl, 1);
 	}
 	unlock_kernel();
 }
@@ -3511,11 +3520,11 @@
 ** flushes any old transactions to disk
 ** ends the current transaction if it is too old
 */
-int reiserfs_flush_old_commits(struct super_block *p_s_sb)
+int reiserfs_flush_old_commits(struct super_block *sb)
 {
 	time_t now;
 	struct reiserfs_transaction_handle th;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
 	now = get_seconds();
 	/* safety check so we don't flush while we are replaying the log during
@@ -3532,35 +3541,35 @@
 	    journal->j_trans_start_time > 0 &&
 	    journal->j_len > 0 &&
 	    (now - journal->j_trans_start_time) > journal->j_max_trans_age) {
-		if (!journal_join(&th, p_s_sb, 1)) {
-			reiserfs_prepare_for_journal(p_s_sb,
-						     SB_BUFFER_WITH_SB(p_s_sb),
+		if (!journal_join(&th, sb, 1)) {
+			reiserfs_prepare_for_journal(sb,
+						     SB_BUFFER_WITH_SB(sb),
 						     1);
-			journal_mark_dirty(&th, p_s_sb,
-					   SB_BUFFER_WITH_SB(p_s_sb));
+			journal_mark_dirty(&th, sb,
+					   SB_BUFFER_WITH_SB(sb));
 
 			/* we're only being called from kreiserfsd, it makes no sense to do
 			 ** an async commit so that kreiserfsd can do it later
 			 */
-			do_journal_end(&th, p_s_sb, 1, COMMIT_NOW | WAIT);
+			do_journal_end(&th, sb, 1, COMMIT_NOW | WAIT);
 		}
 	}
-	return p_s_sb->s_dirt;
+	return sb->s_dirt;
 }
 
 /*
 ** returns 0 if do_journal_end should return right away, returns 1 if do_journal_end should finish the commit
-** 
-** if the current transaction is too old, but still has writers, this will wait on j_join_wait until all 
+**
+** if the current transaction is too old, but still has writers, this will wait on j_join_wait until all
 ** the writers are done.  By the time it wakes up, the transaction it was called has already ended, so it just
 ** flushes the commit list and returns 0.
 **
 ** Won't batch when flush or commit_now is set.  Also won't batch when others are waiting on j_join_wait.
-** 
+**
 ** Note, we can't allow the journal_end to proceed while there are still writers in the log.
 */
 static int check_journal_end(struct reiserfs_transaction_handle *th,
-			     struct super_block *p_s_sb, unsigned long nblocks,
+			     struct super_block *sb, unsigned long nblocks,
 			     int flags)
 {
 
@@ -3569,13 +3578,13 @@
 	int commit_now = flags & COMMIT_NOW;
 	int wait_on_commit = flags & WAIT;
 	struct reiserfs_journal_list *jl;
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
 	BUG_ON(!th->t_trans_id);
 
 	if (th->t_trans_id != journal->j_trans_id) {
-		reiserfs_panic(th->t_super,
-			       "journal-1577: handle trans id %ld != current trans id %ld\n",
+		reiserfs_panic(th->t_super, "journal-1577",
+			       "handle trans id %ld != current trans id %ld",
 			       th->t_trans_id, journal->j_trans_id);
 	}
 
@@ -3584,7 +3593,7 @@
 		atomic_dec(&(journal->j_wcount));
 	}
 
-	/* BUG, deal with case where j_len is 0, but people previously freed blocks need to be released 
+	/* BUG, deal with case where j_len is 0, but people previously freed blocks need to be released
 	 ** will be dealt with by next transaction that actually writes something, but should be taken
 	 ** care of in this trans
 	 */
@@ -3593,7 +3602,7 @@
 	/* if wcount > 0, and we are called to with flush or commit_now,
 	 ** we wait on j_join_wait.  We will wake up when the last writer has
 	 ** finished the transaction, and started it on its way to the disk.
-	 ** Then, we flush the commit or journal list, and just return 0 
+	 ** Then, we flush the commit or journal list, and just return 0
 	 ** because the rest of journal end was already done for this transaction.
 	 */
 	if (atomic_read(&(journal->j_wcount)) > 0) {
@@ -3608,31 +3617,31 @@
 			if (flush) {
 				journal->j_next_full_flush = 1;
 			}
-			unlock_journal(p_s_sb);
+			unlock_journal(sb);
 
 			/* sleep while the current transaction is still j_jlocked */
 			while (journal->j_trans_id == trans_id) {
 				if (atomic_read(&journal->j_jlock)) {
-					queue_log_writer(p_s_sb);
+					queue_log_writer(sb);
 				} else {
-					lock_journal(p_s_sb);
+					lock_journal(sb);
 					if (journal->j_trans_id == trans_id) {
 						atomic_set(&(journal->j_jlock),
 							   1);
 					}
-					unlock_journal(p_s_sb);
+					unlock_journal(sb);
 				}
 			}
 			BUG_ON(journal->j_trans_id == trans_id);
 			
 			if (commit_now
-			    && journal_list_still_alive(p_s_sb, trans_id)
+			    && journal_list_still_alive(sb, trans_id)
 			    && wait_on_commit) {
-				flush_commit_list(p_s_sb, jl, 1);
+				flush_commit_list(sb, jl, 1);
 			}
 			return 0;
 		}
-		unlock_journal(p_s_sb);
+		unlock_journal(sb);
 		return 0;
 	}
 
@@ -3649,13 +3658,13 @@
 	    && journal->j_len_alloc < journal->j_max_batch
 	    && journal->j_cnode_free > (journal->j_trans_max * 3)) {
 		journal->j_bcount++;
-		unlock_journal(p_s_sb);
+		unlock_journal(sb);
 		return 0;
 	}
 
-	if (journal->j_start > SB_ONDISK_JOURNAL_SIZE(p_s_sb)) {
-		reiserfs_panic(p_s_sb,
-			       "journal-003: journal_end: j_start (%ld) is too high\n",
+	if (journal->j_start > SB_ONDISK_JOURNAL_SIZE(sb)) {
+		reiserfs_panic(sb, "journal-003",
+			       "j_start (%ld) is too high",
 			       journal->j_start);
 	}
 	return 1;
@@ -3664,7 +3673,7 @@
 /*
 ** Does all the work that makes deleting blocks safe.
 ** when deleting a block mark BH_JNew, just remove it from the current transaction, clean it's buffer_head and move on.
-** 
+**
 ** otherwise:
 ** set a bit for the block in the journal bitmap.  That will prevent it from being allocated for unformatted nodes
 ** before this transaction has finished.
@@ -3676,16 +3685,16 @@
 ** Then remove it from the current transaction, decrementing any counters and filing it on the clean list.
 */
 int journal_mark_freed(struct reiserfs_transaction_handle *th,
-		       struct super_block *p_s_sb, b_blocknr_t blocknr)
+		       struct super_block *sb, b_blocknr_t blocknr)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_cnode *cn = NULL;
 	struct buffer_head *bh = NULL;
 	struct reiserfs_list_bitmap *jb = NULL;
 	int cleaned = 0;
 	BUG_ON(!th->t_trans_id);
 
-	cn = get_journal_hash_dev(p_s_sb, journal->j_hash_table, blocknr);
+	cn = get_journal_hash_dev(sb, journal->j_hash_table, blocknr);
 	if (cn && cn->bh) {
 		bh = cn->bh;
 		get_bh(bh);
@@ -3695,15 +3704,15 @@
 		clear_buffer_journal_new(bh);
 		clear_prepared_bits(bh);
 		reiserfs_clean_and_file_buffer(bh);
-		cleaned = remove_from_transaction(p_s_sb, blocknr, cleaned);
+		cleaned = remove_from_transaction(sb, blocknr, cleaned);
 	} else {
 		/* set the bit for this block in the journal bitmap for this transaction */
 		jb = journal->j_current_jl->j_list_bitmap;
 		if (!jb) {
-			reiserfs_panic(p_s_sb,
-				       "journal-1702: journal_mark_freed, journal_list_bitmap is NULL\n");
+			reiserfs_panic(sb, "journal-1702",
+				       "journal_list_bitmap is NULL");
 		}
-		set_bit_in_list_bitmap(p_s_sb, blocknr, jb);
+		set_bit_in_list_bitmap(sb, blocknr, jb);
 
 		/* Note, the entire while loop is not allowed to schedule.  */
 
@@ -3711,13 +3720,13 @@
 			clear_prepared_bits(bh);
 			reiserfs_clean_and_file_buffer(bh);
 		}
-		cleaned = remove_from_transaction(p_s_sb, blocknr, cleaned);
+		cleaned = remove_from_transaction(sb, blocknr, cleaned);
 
 		/* find all older transactions with this block, make sure they don't try to write it out */
-		cn = get_journal_hash_dev(p_s_sb, journal->j_list_hash_table,
+		cn = get_journal_hash_dev(sb, journal->j_list_hash_table,
 					  blocknr);
 		while (cn) {
-			if (p_s_sb == cn->sb && blocknr == cn->blocknr) {
+			if (sb == cn->sb && blocknr == cn->blocknr) {
 				set_bit(BLOCK_FREED, &cn->state);
 				if (cn->bh) {
 					if (!cleaned) {
@@ -3733,8 +3742,9 @@
 						put_bh(cn->bh);
 						if (atomic_read
 						    (&(cn->bh->b_count)) < 0) {
-							reiserfs_warning(p_s_sb,
-									 "journal-2138: cn->bh->b_count < 0");
+							reiserfs_warning(sb,
+								 "journal-2138",
+								 "cn->bh->b_count < 0");
 						}
 					}
 					if (cn->jlist) {	/* since we are clearing the bh, we MUST dec nonzerolen */
@@ -3824,7 +3834,7 @@
 
 int reiserfs_commit_for_inode(struct inode *inode)
 {
-	unsigned long id = REISERFS_I(inode)->i_trans_id;
+	unsigned int id = REISERFS_I(inode)->i_trans_id;
 	struct reiserfs_journal_list *jl = REISERFS_I(inode)->i_jl;
 
 	/* for the whole inode, assume unset id means it was
@@ -3839,18 +3849,18 @@
 	return __commit_trans_jl(inode, id, jl);
 }
 
-void reiserfs_restore_prepared_buffer(struct super_block *p_s_sb,
+void reiserfs_restore_prepared_buffer(struct super_block *sb,
 				      struct buffer_head *bh)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
-	PROC_INFO_INC(p_s_sb, journal.restore_prepared);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
+	PROC_INFO_INC(sb, journal.restore_prepared);
 	if (!bh) {
 		return;
 	}
 	if (test_clear_buffer_journal_restore_dirty(bh) &&
 	    buffer_journal_dirty(bh)) {
 		struct reiserfs_journal_cnode *cn;
-		cn = get_journal_hash_dev(p_s_sb,
+		cn = get_journal_hash_dev(sb,
 					  journal->j_list_hash_table,
 					  bh->b_blocknr);
 		if (cn && can_dirty(cn)) {
@@ -3867,12 +3877,12 @@
 ** be written to disk while we are altering it.  So, we must:
 ** clean it
 ** wait on it.
-** 
+**
 */
-int reiserfs_prepare_for_journal(struct super_block *p_s_sb,
+int reiserfs_prepare_for_journal(struct super_block *sb,
 				 struct buffer_head *bh, int wait)
 {
-	PROC_INFO_INC(p_s_sb, journal.prepare);
+	PROC_INFO_INC(sb, journal.prepare);
 
 	if (!trylock_buffer(bh)) {
 		if (!wait)
@@ -3909,7 +3919,7 @@
 	}
 }
 
-/* 
+/*
 ** long and ugly.  If flush, will not return until all commit
 ** blocks and all real buffers in the trans are on disk.
 ** If no_async, won't return until all commit blocks are on disk.
@@ -3920,10 +3930,10 @@
 ** journal lists, etc just won't happen.
 */
 static int do_journal_end(struct reiserfs_transaction_handle *th,
-			  struct super_block *p_s_sb, unsigned long nblocks,
+			  struct super_block *sb, unsigned long nblocks,
 			  int flags)
 {
-	struct reiserfs_journal *journal = SB_JOURNAL(p_s_sb);
+	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	struct reiserfs_journal_cnode *cn, *next, *jl_cn;
 	struct reiserfs_journal_cnode *last_cn = NULL;
 	struct reiserfs_journal_desc *desc;
@@ -3938,7 +3948,7 @@
 	struct reiserfs_journal_list *jl, *temp_jl;
 	struct list_head *entry, *safe;
 	unsigned long jindex;
-	unsigned long commit_trans_id;
+	unsigned int commit_trans_id;
 	int trans_half;
 
 	BUG_ON(th->t_refcount > 1);
@@ -3946,21 +3956,21 @@
 
 	/* protect flush_older_commits from doing mistakes if the
            transaction ID counter gets overflowed.  */
-	if (th->t_trans_id == ~0UL)
+	if (th->t_trans_id == ~0U)
 		flags |= FLUSH_ALL | COMMIT_NOW | WAIT;
 	flush = flags & FLUSH_ALL;
 	wait_on_commit = flags & WAIT;
 
 	put_fs_excl();
 	current->journal_info = th->t_handle_save;
-	reiserfs_check_lock_depth(p_s_sb, "journal end");
+	reiserfs_check_lock_depth(sb, "journal end");
 	if (journal->j_len == 0) {
-		reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb),
+		reiserfs_prepare_for_journal(sb, SB_BUFFER_WITH_SB(sb),
 					     1);
-		journal_mark_dirty(th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb));
+		journal_mark_dirty(th, sb, SB_BUFFER_WITH_SB(sb));
 	}
 
-	lock_journal(p_s_sb);
+	lock_journal(sb);
 	if (journal->j_next_full_flush) {
 		flags |= FLUSH_ALL;
 		flush = 1;
@@ -3970,13 +3980,13 @@
 		wait_on_commit = 1;
 	}
 
-	/* check_journal_end locks the journal, and unlocks if it does not return 1 
+	/* check_journal_end locks the journal, and unlocks if it does not return 1
 	 ** it tells us if we should continue with the journal_end, or just return
 	 */
-	if (!check_journal_end(th, p_s_sb, nblocks, flags)) {
-		p_s_sb->s_dirt = 1;
-		wake_queued_writers(p_s_sb);
-		reiserfs_async_progress_wait(p_s_sb);
+	if (!check_journal_end(th, sb, nblocks, flags)) {
+		sb->s_dirt = 1;
+		wake_queued_writers(sb);
+		reiserfs_async_progress_wait(sb);
 		goto out;
 	}
 
@@ -4005,8 +4015,8 @@
 
 	/* setup description block */
 	d_bh =
-	    journal_getblk(p_s_sb,
-			   SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+	    journal_getblk(sb,
+			   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 			   journal->j_start);
 	set_buffer_uptodate(d_bh);
 	desc = (struct reiserfs_journal_desc *)(d_bh)->b_data;
@@ -4015,9 +4025,9 @@
 	set_desc_trans_id(desc, journal->j_trans_id);
 
 	/* setup commit block.  Don't write (keep it clean too) this one until after everyone else is written */
-	c_bh = journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+	c_bh = journal_getblk(sb, SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 			      ((journal->j_start + journal->j_len +
-				1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb)));
+				1) % SB_ONDISK_JOURNAL_SIZE(sb)));
 	commit = (struct reiserfs_journal_commit *)c_bh->b_data;
 	memset(c_bh->b_data, 0, c_bh->b_size);
 	set_commit_trans_id(commit, journal->j_trans_id);
@@ -4050,13 +4060,13 @@
 	 **  for each real block, add it to the journal list hash,
 	 ** copy into real block index array in the commit or desc block
 	 */
-	trans_half = journal_trans_half(p_s_sb->s_blocksize);
+	trans_half = journal_trans_half(sb->s_blocksize);
 	for (i = 0, cn = journal->j_first; cn; cn = cn->next, i++) {
 		if (buffer_journaled(cn->bh)) {
-			jl_cn = get_cnode(p_s_sb);
+			jl_cn = get_cnode(sb);
 			if (!jl_cn) {
-				reiserfs_panic(p_s_sb,
-					       "journal-1676, get_cnode returned NULL\n");
+				reiserfs_panic(sb, "journal-1676",
+					       "get_cnode returned NULL");
 			}
 			if (i == 0) {
 				jl->j_realblock = jl_cn;
@@ -4067,18 +4077,19 @@
 				last_cn->next = jl_cn;
 			}
 			last_cn = jl_cn;
-			/* make sure the block we are trying to log is not a block 
+			/* make sure the block we are trying to log is not a block
 			   of journal or reserved area */
 
 			if (is_block_in_log_or_reserved_area
-			    (p_s_sb, cn->bh->b_blocknr)) {
-				reiserfs_panic(p_s_sb,
-					       "journal-2332: Trying to log block %lu, which is a log block\n",
+			    (sb, cn->bh->b_blocknr)) {
+				reiserfs_panic(sb, "journal-2332",
+					       "Trying to log block %lu, "
+					       "which is a log block",
 					       cn->bh->b_blocknr);
 			}
 			jl_cn->blocknr = cn->bh->b_blocknr;
 			jl_cn->state = 0;
-			jl_cn->sb = p_s_sb;
+			jl_cn->sb = sb;
 			jl_cn->bh = cn->bh;
 			jl_cn->jlist = jl;
 			insert_journal_hash(journal->j_list_hash_table, jl_cn);
@@ -4119,11 +4130,11 @@
 			char *addr;
 			struct page *page;
 			tmp_bh =
-			    journal_getblk(p_s_sb,
-					   SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) +
+			    journal_getblk(sb,
+					   SB_ONDISK_JOURNAL_1st_BLOCK(sb) +
 					   ((cur_write_start +
 					     jindex) %
-					    SB_ONDISK_JOURNAL_SIZE(p_s_sb)));
+					    SB_ONDISK_JOURNAL_SIZE(sb)));
 			set_buffer_uptodate(tmp_bh);
 			page = cn->bh->b_page;
 			addr = kmap(page);
@@ -4137,12 +4148,13 @@
 			clear_buffer_journaled(cn->bh);
 		} else {
 			/* JDirty cleared sometime during transaction.  don't log this one */
-			reiserfs_warning(p_s_sb,
-					 "journal-2048: do_journal_end: BAD, buffer in journal hash, but not JDirty!");
+			reiserfs_warning(sb, "journal-2048",
+					 "BAD, buffer in journal hash, "
+					 "but not JDirty!");
 			brelse(cn->bh);
 		}
 		next = cn->next;
-		free_cnode(p_s_sb, cn);
+		free_cnode(sb, cn);
 		cn = next;
 		cond_resched();
 	}
@@ -4152,7 +4164,7 @@
 	 ** so we dirty/relse c_bh in flush_commit_list, with commit_left <= 1.
 	 */
 
-	journal->j_current_jl = alloc_journal_list(p_s_sb);
+	journal->j_current_jl = alloc_journal_list(sb);
 
 	/* now it is safe to insert this transaction on the main list */
 	list_add_tail(&jl->j_list, &journal->j_journal_list);
@@ -4163,7 +4175,7 @@
 	old_start = journal->j_start;
 	journal->j_start =
 	    (journal->j_start + journal->j_len +
-	     2) % SB_ONDISK_JOURNAL_SIZE(p_s_sb);
+	     2) % SB_ONDISK_JOURNAL_SIZE(sb);
 	atomic_set(&(journal->j_wcount), 0);
 	journal->j_bcount = 0;
 	journal->j_last = NULL;
@@ -4178,7 +4190,7 @@
 	journal->j_len_alloc = 0;
 	journal->j_next_full_flush = 0;
 	journal->j_next_async_flush = 0;
-	init_journal_hash(p_s_sb);
+	init_journal_hash(sb);
 
 	// make sure reiserfs_add_jh sees the new current_jl before we
 	// write out the tails
@@ -4207,14 +4219,14 @@
 	 ** queue don't wait for this proc to flush journal lists and such.
 	 */
 	if (flush) {
-		flush_commit_list(p_s_sb, jl, 1);
-		flush_journal_list(p_s_sb, jl, 1);
+		flush_commit_list(sb, jl, 1);
+		flush_journal_list(sb, jl, 1);
 	} else if (!(jl->j_state & LIST_COMMIT_PENDING))
 		queue_delayed_work(commit_wq, &journal->j_work, HZ / 10);
 
-	/* if the next transaction has any chance of wrapping, flush 
-	 ** transactions that might get overwritten.  If any journal lists are very 
-	 ** old flush them as well.  
+	/* if the next transaction has any chance of wrapping, flush
+	 ** transactions that might get overwritten.  If any journal lists are very
+	 ** old flush them as well.
 	 */
       first_jl:
 	list_for_each_safe(entry, safe, &journal->j_journal_list) {
@@ -4222,11 +4234,11 @@
 		if (journal->j_start <= temp_jl->j_start) {
 			if ((journal->j_start + journal->j_trans_max + 1) >=
 			    temp_jl->j_start) {
-				flush_used_journal_lists(p_s_sb, temp_jl);
+				flush_used_journal_lists(sb, temp_jl);
 				goto first_jl;
 			} else if ((journal->j_start +
 				    journal->j_trans_max + 1) <
-				   SB_ONDISK_JOURNAL_SIZE(p_s_sb)) {
+				   SB_ONDISK_JOURNAL_SIZE(sb)) {
 				/* if we don't cross into the next transaction and we don't
 				 * wrap, there is no way we can overlap any later transactions
 				 * break now
@@ -4235,11 +4247,11 @@
 			}
 		} else if ((journal->j_start +
 			    journal->j_trans_max + 1) >
-			   SB_ONDISK_JOURNAL_SIZE(p_s_sb)) {
+			   SB_ONDISK_JOURNAL_SIZE(sb)) {
 			if (((journal->j_start + journal->j_trans_max + 1) %
-			     SB_ONDISK_JOURNAL_SIZE(p_s_sb)) >=
+			     SB_ONDISK_JOURNAL_SIZE(sb)) >=
 			    temp_jl->j_start) {
-				flush_used_journal_lists(p_s_sb, temp_jl);
+				flush_used_journal_lists(sb, temp_jl);
 				goto first_jl;
 			} else {
 				/* we don't overlap anything from out start to the end of the
@@ -4250,46 +4262,47 @@
 			}
 		}
 	}
-	flush_old_journal_lists(p_s_sb);
+	flush_old_journal_lists(sb);
 
 	journal->j_current_jl->j_list_bitmap =
-	    get_list_bitmap(p_s_sb, journal->j_current_jl);
+	    get_list_bitmap(sb, journal->j_current_jl);
 
 	if (!(journal->j_current_jl->j_list_bitmap)) {
-		reiserfs_panic(p_s_sb,
-			       "journal-1996: do_journal_end, could not get a list bitmap\n");
+		reiserfs_panic(sb, "journal-1996",
+			       "could not get a list bitmap");
 	}
 
 	atomic_set(&(journal->j_jlock), 0);
-	unlock_journal(p_s_sb);
+	unlock_journal(sb);
 	/* wake up any body waiting to join. */
 	clear_bit(J_WRITERS_QUEUED, &journal->j_state);
 	wake_up(&(journal->j_join_wait));
 
 	if (!flush && wait_on_commit &&
-	    journal_list_still_alive(p_s_sb, commit_trans_id)) {
-		flush_commit_list(p_s_sb, jl, 1);
+	    journal_list_still_alive(sb, commit_trans_id)) {
+		flush_commit_list(sb, jl, 1);
 	}
       out:
-	reiserfs_check_lock_depth(p_s_sb, "journal end2");
+	reiserfs_check_lock_depth(sb, "journal end2");
 
 	memset(th, 0, sizeof(*th));
 	/* Re-set th->t_super, so we can properly keep track of how many
 	 * persistent transactions there are. We need to do this so if this
 	 * call is part of a failed restart_transaction, we can free it later */
-	th->t_super = p_s_sb;
+	th->t_super = sb;
 
 	return journal->j_errno;
 }
 
-static void __reiserfs_journal_abort_hard(struct super_block *sb)
+/* Send the file system read only and refuse new transactions */
+void reiserfs_abort_journal(struct super_block *sb, int errno)
 {
 	struct reiserfs_journal *journal = SB_JOURNAL(sb);
 	if (test_bit(J_ABORTED, &journal->j_state))
 		return;
 
-	printk(KERN_CRIT "REISERFS: Aborting journal for filesystem on %s\n",
-	       reiserfs_bdevname(sb));
+	if (!journal->j_errno)
+		journal->j_errno = errno;
 
 	sb->s_flags |= MS_RDONLY;
 	set_bit(J_ABORTED, &journal->j_state);
@@ -4299,19 +4312,3 @@
 #endif
 }
 
-static void __reiserfs_journal_abort_soft(struct super_block *sb, int errno)
-{
-	struct reiserfs_journal *journal = SB_JOURNAL(sb);
-	if (test_bit(J_ABORTED, &journal->j_state))
-		return;
-
-	if (!journal->j_errno)
-		journal->j_errno = errno;
-
-	__reiserfs_journal_abort_hard(sb);
-}
-
-void reiserfs_journal_abort(struct super_block *sb, int errno)
-{
-	__reiserfs_journal_abort_soft(sb, errno);
-}
diff --git a/fs/reiserfs/lbalance.c b/fs/reiserfs/lbalance.c
index 6de060a..381750a 100644
--- a/fs/reiserfs/lbalance.c
+++ b/fs/reiserfs/lbalance.c
@@ -111,7 +111,7 @@
 	item_num_in_dest =
 	    (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest) - 1) : 0;
 
-	leaf_paste_entries(dest_bi->bi_bh, item_num_in_dest,
+	leaf_paste_entries(dest_bi, item_num_in_dest,
 			   (last_first ==
 			    FIRST_TO_LAST) ? I_ENTRY_COUNT(B_N_PITEM_HEAD(dest,
 									  item_num_in_dest))
@@ -119,8 +119,8 @@
 			   DEH_SIZE * copy_count + copy_records_len);
 }
 
-/* Copy the first (if last_first == FIRST_TO_LAST) or last (last_first == LAST_TO_FIRST) item or 
-   part of it or nothing (see the return 0 below) from SOURCE to the end 
+/* Copy the first (if last_first == FIRST_TO_LAST) or last (last_first == LAST_TO_FIRST) item or
+   part of it or nothing (see the return 0 below) from SOURCE to the end
    (if last_first) or beginning (!last_first) of the DEST */
 /* returns 1 if anything was copied, else 0 */
 static int leaf_copy_boundary_item(struct buffer_info *dest_bi,
@@ -168,10 +168,11 @@
 			if (bytes_or_entries == ih_item_len(ih)
 			    && is_indirect_le_ih(ih))
 				if (get_ih_free_space(ih))
-					reiserfs_panic(NULL,
-						       "vs-10020: leaf_copy_boundary_item: "
-						       "last unformatted node must be filled entirely (%h)",
-						       ih);
+					reiserfs_panic(sb_from_bi(dest_bi),
+						       "vs-10020",
+						       "last unformatted node "
+						       "must be filled "
+						       "entirely (%h)", ih);
 		}
 #endif
 
@@ -395,7 +396,7 @@
 		else {
 			struct item_head n_ih;
 
-			/* copy part of the body of the item number 'item_num' of SOURCE to the end of the DEST 
+			/* copy part of the body of the item number 'item_num' of SOURCE to the end of the DEST
 			   part defined by 'cpy_bytes'; create new item header; change old item_header (????);
 			   n_ih = new item_header;
 			 */
@@ -425,7 +426,7 @@
 		else {
 			struct item_head n_ih;
 
-			/* copy part of the body of the item number 'item_num' of SOURCE to the begin of the DEST 
+			/* copy part of the body of the item number 'item_num' of SOURCE to the begin of the DEST
 			   part defined by 'cpy_bytes'; create new item header;
 			   n_ih = new item_header;
 			 */
@@ -622,9 +623,8 @@
 		break;
 
 	default:
-		reiserfs_panic(NULL,
-			       "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)",
-			       shift_mode);
+		reiserfs_panic(sb_from_bi(src_bi), "vs-10250",
+			       "shift type is unknown (%d)", shift_mode);
 	}
 	RFALSE(!src_bi->bi_bh || !dest_bi->bi_bh,
 	       "vs-10260: mode==%d, source (%p) or dest (%p) buffer is initialized incorrectly",
@@ -674,9 +674,9 @@
 #ifdef CONFIG_REISERFS_CHECK
 			if (tb->tb_mode == M_PASTE || tb->tb_mode == M_INSERT) {
 				print_cur_tb("vs-10275");
-				reiserfs_panic(tb->tb_sb,
-					       "vs-10275: leaf_shift_left: balance condition corrupted (%c)",
-					       tb->tb_mode);
+				reiserfs_panic(tb->tb_sb, "vs-10275",
+					       "balance condition corrupted "
+					       "(%c)", tb->tb_mode);
 			}
 #endif
 
@@ -724,7 +724,7 @@
 static void leaf_delete_items_entirely(struct buffer_info *bi,
 				       int first, int del_num);
 /*  If del_bytes == -1, starting from position 'first' delete del_num items in whole in buffer CUR.
-    If not. 
+    If not.
     If last_first == 0. Starting from position 'first' delete del_num-1 items in whole. Delete part of body of
     the first item. Part defined by del_bytes. Don't delete first item header
     If last_first == 1. Starting from position 'first+1' delete del_num-1 items in whole. Delete part of body of
@@ -783,7 +783,7 @@
 				/* len = body len of item */
 				len = ih_item_len(ih);
 
-			/* delete the part of the last item of the bh 
+			/* delete the part of the last item of the bh
 			   do not delete item header
 			 */
 			leaf_cut_from_buffer(cur_bi, B_NR_ITEMS(bh) - 1,
@@ -865,7 +865,7 @@
 	}
 }
 
-/* paste paste_size bytes to affected_item_num-th item. 
+/* paste paste_size bytes to affected_item_num-th item.
    When item is a directory, this only prepare space for new entries */
 void leaf_paste_in_buffer(struct buffer_info *bi, int affected_item_num,
 			  int pos_in_item, int paste_size,
@@ -889,9 +889,12 @@
 
 #ifdef CONFIG_REISERFS_CHECK
 	if (zeros_number > paste_size) {
+		struct super_block *sb = NULL;
+		if (bi && bi->tb)
+			sb = bi->tb->tb_sb;
 		print_cur_tb("10177");
-		reiserfs_panic(NULL,
-			       "vs-10177: leaf_paste_in_buffer: ero number == %d, paste_size == %d",
+		reiserfs_panic(sb, "vs-10177",
+			       "zeros_number == %d, paste_size == %d",
 			       zeros_number, paste_size);
 	}
 #endif				/* CONFIG_REISERFS_CHECK */
@@ -1019,7 +1022,7 @@
 /*  when cut item is part of regular file
         pos_in_item - first byte that must be cut
         cut_size - number of bytes to be cut beginning from pos_in_item
- 
+
    when cut item is part of directory
         pos_in_item - number of first deleted entry
         cut_size - count of deleted entries
@@ -1191,7 +1194,7 @@
 }
 
 /* paste new_entry_count entries (new_dehs, records) into position before to item_num-th item */
-void leaf_paste_entries(struct buffer_head *bh,
+void leaf_paste_entries(struct buffer_info *bi,
 			int item_num,
 			int before,
 			int new_entry_count,
@@ -1203,6 +1206,7 @@
 	struct reiserfs_de_head *deh;
 	char *insert_point;
 	int i, old_entry_num;
+	struct buffer_head *bh = bi->bi_bh;
 
 	if (new_entry_count == 0)
 		return;
@@ -1271,7 +1275,7 @@
 	/* change item key if necessary (when we paste before 0-th entry */
 	if (!before) {
 		set_le_ih_k_offset(ih, deh_offset(new_dehs));
-/*      memcpy (&ih->ih_key.k_offset, 
+/*      memcpy (&ih->ih_key.k_offset,
 		       &new_dehs->deh_offset, SHORT_KEY_SIZE);*/
 	}
 #ifdef CONFIG_REISERFS_CHECK
@@ -1287,13 +1291,17 @@
 			prev = (i != 0) ? deh_location(&(deh[i - 1])) : 0;
 
 			if (prev && prev <= deh_location(&(deh[i])))
-				reiserfs_warning(NULL,
-						 "vs-10240: leaf_paste_entries: directory item (%h) corrupted (prev %a, cur(%d) %a)",
-						 ih, deh + i - 1, i, deh + i);
+				reiserfs_error(sb_from_bi(bi), "vs-10240",
+					       "directory item (%h) "
+					       "corrupted (prev %a, "
+					       "cur(%d) %a)",
+					       ih, deh + i - 1, i, deh + i);
 			if (next && next >= deh_location(&(deh[i])))
-				reiserfs_warning(NULL,
-						 "vs-10250: leaf_paste_entries: directory item (%h) corrupted (cur(%d) %a, next %a)",
-						 ih, i, deh + i, deh + i + 1);
+				reiserfs_error(sb_from_bi(bi), "vs-10250",
+					       "directory item (%h) "
+					       "corrupted (cur(%d) %a, "
+					       "next %a)",
+					       ih, i, deh + i, deh + i + 1);
 		}
 	}
 #endif
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 639d635..efd4d72 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -106,7 +106,7 @@
 This function first calls search_by_key, then, if item whose first
 entry matches is not found it looks for the entry inside directory
 item found by search_by_key. Fills the path to the entry, and to the
-entry position in the item 
+entry position in the item
 
 */
 
@@ -120,8 +120,8 @@
 	switch (retval) {
 	case ITEM_NOT_FOUND:
 		if (!PATH_LAST_POSITION(path)) {
-			reiserfs_warning(sb,
-					 "vs-7000: search_by_entry_key: search_by_key returned item position == 0");
+			reiserfs_error(sb, "vs-7000", "search_by_key "
+				       "returned item position == 0");
 			pathrelse(path);
 			return IO_ERROR;
 		}
@@ -135,8 +135,7 @@
 
 	default:
 		pathrelse(path);
-		reiserfs_warning(sb,
-				 "vs-7002: search_by_entry_key: no path to here");
+		reiserfs_error(sb, "vs-7002", "no path to here");
 		return IO_ERROR;
 	}
 
@@ -146,10 +145,9 @@
 	if (!is_direntry_le_ih(de->de_ih) ||
 	    COMP_SHORT_KEYS(&(de->de_ih->ih_key), key)) {
 		print_block(de->de_bh, 0, -1, -1);
-		reiserfs_panic(sb,
-			       "vs-7005: search_by_entry_key: found item %h is not directory item or "
-			       "does not belong to the same directory as key %K",
-			       de->de_ih, key);
+		reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
+			       "item or does not belong to the same directory "
+			       "as key %K", de->de_ih, key);
 	}
 #endif				/* CONFIG_REISERFS_CHECK */
 
@@ -300,8 +298,7 @@
 		    search_by_entry_key(dir->i_sb, &key_to_search,
 					path_to_entry, de);
 		if (retval == IO_ERROR) {
-			reiserfs_warning(dir->i_sb, "zam-7001: io error in %s",
-					 __func__);
+			reiserfs_error(dir->i_sb, "zam-7001", "io error");
 			return IO_ERROR;
 		}
 
@@ -361,9 +358,10 @@
 			return ERR_PTR(-EACCES);
 		}
 
-		/* Propogate the priv_object flag so we know we're in the priv tree */
-		if (is_reiserfs_priv_object(dir))
-			reiserfs_mark_inode_private(inode);
+		/* Propagate the private flag so we know we're
+		 * in the priv tree */
+		if (IS_PRIVATE(dir))
+			inode->i_flags |= S_PRIVATE;
 	}
 	reiserfs_write_unlock(dir->i_sb);
 	if (retval == IO_ERROR) {
@@ -373,7 +371,7 @@
 	return d_splice_alias(inode, dentry);
 }
 
-/* 
+/*
 ** looks up the dentry of the parent directory for child.
 ** taken from ext2_get_parent
 */
@@ -403,7 +401,7 @@
 	return d_obtain_alias(inode);
 }
 
-/* add entry to the directory (entry can be hidden). 
+/* add entry to the directory (entry can be hidden).
 
 insert definition of when hidden directories are used here -Hans
 
@@ -484,10 +482,9 @@
 		}
 
 		if (retval != NAME_FOUND) {
-			reiserfs_warning(dir->i_sb,
-					 "zam-7002:%s: \"reiserfs_find_entry\" "
-					 "has returned unexpected value (%d)",
-					 __func__, retval);
+			reiserfs_error(dir->i_sb, "zam-7002",
+				       "reiserfs_find_entry() returned "
+				       "unexpected value (%d)", retval);
 		}
 
 		return -EEXIST;
@@ -498,8 +495,9 @@
 				MAX_GENERATION_NUMBER + 1);
 	if (gen_number > MAX_GENERATION_NUMBER) {
 		/* there is no free generation number */
-		reiserfs_warning(dir->i_sb,
-				 "reiserfs_add_entry: Congratulations! we have got hash function screwed up");
+		reiserfs_warning(dir->i_sb, "reiserfs-7010",
+				 "Congratulations! we have got hash function "
+				 "screwed up");
 		if (buffer != small_buf)
 			kfree(buffer);
 		pathrelse(&path);
@@ -515,10 +513,9 @@
 	if (gen_number != 0) {	/* we need to re-search for the insertion point */
 		if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) !=
 		    NAME_NOT_FOUND) {
-			reiserfs_warning(dir->i_sb,
-					 "vs-7032: reiserfs_add_entry: "
-					 "entry with this key (%K) already exists",
-					 &entry_key);
+			reiserfs_warning(dir->i_sb, "vs-7032",
+					 "entry with this key (%K) already "
+					 "exists", &entry_key);
 
 			if (buffer != small_buf)
 				kfree(buffer);
@@ -562,7 +559,7 @@
 	return 0;
 }
 
-/* utility function that does setup for reiserfs_new_inode.  
+/* utility function that does setup for reiserfs_new_inode.
 ** vfs_dq_init needs lots of credits so it's better to have it
 ** outside of a transaction, so we had to pull some bits of
 ** reiserfs_new_inode out into this func.
@@ -601,20 +598,22 @@
 	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
 		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
 	struct reiserfs_transaction_handle th;
-	int locked;
+	struct reiserfs_security_handle security;
 
 	if (!(inode = new_inode(dir->i_sb))) {
 		return -ENOMEM;
 	}
 	new_inode_init(inode, dir, mode);
 
-	locked = reiserfs_cache_default_acl(dir);
-
+	jbegin_count += reiserfs_cache_default_acl(dir);
+	retval = reiserfs_security_init(dir, inode, &security);
+	if (retval < 0) {
+		drop_new_inode(inode);
+		return retval;
+	}
+	jbegin_count += retval;
 	reiserfs_write_lock(dir->i_sb);
 
-	if (locked)
-		reiserfs_write_lock_xattrs(dir->i_sb);
-
 	retval = journal_begin(&th, dir->i_sb, jbegin_count);
 	if (retval) {
 		drop_new_inode(inode);
@@ -623,15 +622,10 @@
 
 	retval =
 	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
-			       inode);
+			       inode, &security);
 	if (retval)
 		goto out_failed;
 
-	if (locked) {
-		reiserfs_write_unlock_xattrs(dir->i_sb);
-		locked = 0;
-	}
-
 	inode->i_op = &reiserfs_file_inode_operations;
 	inode->i_fop = &reiserfs_file_operations;
 	inode->i_mapping->a_ops = &reiserfs_address_space_operations;
@@ -658,8 +652,6 @@
 	retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
-	if (locked)
-		reiserfs_write_unlock_xattrs(dir->i_sb);
 	reiserfs_write_unlock(dir->i_sb);
 	return retval;
 }
@@ -670,12 +662,12 @@
 	int retval;
 	struct inode *inode;
 	struct reiserfs_transaction_handle th;
+	struct reiserfs_security_handle security;
 	/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
 	int jbegin_count =
 	    JOURNAL_PER_BALANCE_CNT * 3 +
 	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
 		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
-	int locked;
 
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
@@ -685,13 +677,15 @@
 	}
 	new_inode_init(inode, dir, mode);
 
-	locked = reiserfs_cache_default_acl(dir);
-
+	jbegin_count += reiserfs_cache_default_acl(dir);
+	retval = reiserfs_security_init(dir, inode, &security);
+	if (retval < 0) {
+		drop_new_inode(inode);
+		return retval;
+	}
+	jbegin_count += retval;
 	reiserfs_write_lock(dir->i_sb);
 
-	if (locked)
-		reiserfs_write_lock_xattrs(dir->i_sb);
-
 	retval = journal_begin(&th, dir->i_sb, jbegin_count);
 	if (retval) {
 		drop_new_inode(inode);
@@ -700,16 +694,11 @@
 
 	retval =
 	    reiserfs_new_inode(&th, dir, mode, NULL, 0 /*i_size */ , dentry,
-			       inode);
+			       inode, &security);
 	if (retval) {
 		goto out_failed;
 	}
 
-	if (locked) {
-		reiserfs_write_unlock_xattrs(dir->i_sb);
-		locked = 0;
-	}
-
 	inode->i_op = &reiserfs_special_inode_operations;
 	init_special_inode(inode, inode->i_mode, rdev);
 
@@ -739,8 +728,6 @@
 	retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
-	if (locked)
-		reiserfs_write_unlock_xattrs(dir->i_sb);
 	reiserfs_write_unlock(dir->i_sb);
 	return retval;
 }
@@ -750,12 +737,12 @@
 	int retval;
 	struct inode *inode;
 	struct reiserfs_transaction_handle th;
+	struct reiserfs_security_handle security;
 	/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
 	int jbegin_count =
 	    JOURNAL_PER_BALANCE_CNT * 3 +
 	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
 		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
-	int locked;
 
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
 	/* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
@@ -767,11 +754,14 @@
 	}
 	new_inode_init(inode, dir, mode);
 
-	locked = reiserfs_cache_default_acl(dir);
-
+	jbegin_count += reiserfs_cache_default_acl(dir);
+	retval = reiserfs_security_init(dir, inode, &security);
+	if (retval < 0) {
+		drop_new_inode(inode);
+		return retval;
+	}
+	jbegin_count += retval;
 	reiserfs_write_lock(dir->i_sb);
-	if (locked)
-		reiserfs_write_lock_xattrs(dir->i_sb);
 
 	retval = journal_begin(&th, dir->i_sb, jbegin_count);
 	if (retval) {
@@ -787,17 +777,12 @@
 	    retval = reiserfs_new_inode(&th, dir, mode, NULL /*symlink */ ,
 					old_format_only(dir->i_sb) ?
 					EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
-					dentry, inode);
+					dentry, inode, &security);
 	if (retval) {
 		dir->i_nlink--;
 		goto out_failed;
 	}
 
-	if (locked) {
-		reiserfs_write_unlock_xattrs(dir->i_sb);
-		locked = 0;
-	}
-
 	reiserfs_update_inode_transaction(inode);
 	reiserfs_update_inode_transaction(dir);
 
@@ -827,8 +812,6 @@
 	unlock_new_inode(inode);
 	retval = journal_end(&th, dir->i_sb, jbegin_count);
       out_failed:
-	if (locked)
-		reiserfs_write_unlock_xattrs(dir->i_sb);
 	reiserfs_write_unlock(dir->i_sb);
 	return retval;
 }
@@ -837,7 +820,7 @@
 {
 	/* we can cheat because an old format dir cannot have
 	 ** EMPTY_DIR_SIZE, and a new format dir cannot have
-	 ** EMPTY_DIR_SIZE_V1.  So, if the inode is either size, 
+	 ** EMPTY_DIR_SIZE_V1.  So, if the inode is either size,
 	 ** regardless of disk format version, the directory is empty.
 	 */
 	if (inode->i_size != EMPTY_DIR_SIZE &&
@@ -903,8 +886,9 @@
 		goto end_rmdir;
 
 	if (inode->i_nlink != 2 && inode->i_nlink != 1)
-		reiserfs_warning(inode->i_sb, "%s: empty directory has nlink "
-				 "!= 2 (%d)", __func__, inode->i_nlink);
+		reiserfs_error(inode->i_sb, "reiserfs-7040",
+			       "empty directory has nlink != 2 (%d)",
+			       inode->i_nlink);
 
 	clear_nlink(inode);
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
@@ -980,10 +964,9 @@
 	}
 
 	if (!inode->i_nlink) {
-		reiserfs_warning(inode->i_sb, "%s: deleting nonexistent file "
-				 "(%s:%lu), %d", __func__,
-				 reiserfs_bdevname(inode->i_sb), inode->i_ino,
-				 inode->i_nlink);
+		reiserfs_warning(inode->i_sb, "reiserfs-7042",
+				 "deleting nonexistent file (%lu), %d",
+				 inode->i_ino, inode->i_nlink);
 		inode->i_nlink = 1;
 	}
 
@@ -1037,6 +1020,7 @@
 	char *name;
 	int item_len;
 	struct reiserfs_transaction_handle th;
+	struct reiserfs_security_handle security;
 	int mode = S_IFLNK | S_IRWXUGO;
 	/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
 	int jbegin_count =
@@ -1049,6 +1033,13 @@
 	}
 	new_inode_init(inode, parent_dir, mode);
 
+	retval = reiserfs_security_init(parent_dir, inode, &security);
+	if (retval < 0) {
+		drop_new_inode(inode);
+		return retval;
+	}
+	jbegin_count += retval;
+
 	reiserfs_write_lock(parent_dir->i_sb);
 	item_len = ROUND_UP(strlen(symname));
 	if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
@@ -1066,8 +1057,6 @@
 	memcpy(name, symname, strlen(symname));
 	padd_item(name, item_len, strlen(symname));
 
-	/* We would inherit the default ACL here, but symlinks don't get ACLs */
-
 	retval = journal_begin(&th, parent_dir->i_sb, jbegin_count);
 	if (retval) {
 		drop_new_inode(inode);
@@ -1077,7 +1066,7 @@
 
 	retval =
 	    reiserfs_new_inode(&th, parent_dir, mode, name, strlen(symname),
-			       dentry, inode);
+			       dentry, inode, &security);
 	kfree(name);
 	if (retval) {		/* reiserfs_new_inode iputs for us */
 		goto out_failed;
@@ -1173,7 +1162,7 @@
 	return retval;
 }
 
-// de contains information pointing to an entry which 
+/* de contains information pointing to an entry which */
 static int de_still_valid(const char *name, int len,
 			  struct reiserfs_dir_entry *de)
 {
@@ -1196,15 +1185,14 @@
 
 	if (inode) {
 		if (!de_visible(de->de_deh + de->de_entry_num))
-			reiserfs_panic(NULL,
-				       "vs-7042: entry_points_to_object: entry must be visible");
+			reiserfs_panic(inode->i_sb, "vs-7042",
+				       "entry must be visible");
 		return (de->de_objectid == inode->i_ino) ? 1 : 0;
 	}
 
 	/* this must be added hidden entry */
 	if (de_visible(de->de_deh + de->de_entry_num))
-		reiserfs_panic(NULL,
-			       "vs-7043: entry_points_to_object: entry must be visible");
+		reiserfs_panic(NULL, "vs-7043", "entry must be visible");
 
 	return 1;
 }
@@ -1218,10 +1206,10 @@
 	de->de_deh[de->de_entry_num].deh_objectid = key->k_objectid;
 }
 
-/* 
+/*
  * process, that is going to call fix_nodes/do_balance must hold only
  * one path. If it holds 2 or more, it can get into endless waiting in
- * get_empty_nodes or its clones 
+ * get_empty_nodes or its clones
  */
 static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			   struct inode *new_dir, struct dentry *new_dentry)
@@ -1275,7 +1263,7 @@
 
 	old_inode_mode = old_inode->i_mode;
 	if (S_ISDIR(old_inode_mode)) {
-		// make sure, that directory being renamed has correct ".." 
+		// make sure, that directory being renamed has correct ".."
 		// and that its new parent directory has not too many links
 		// already
 
@@ -1286,8 +1274,8 @@
 			}
 		}
 
-		/* directory is renamed, its parent directory will be changed, 
-		 ** so find ".." entry 
+		/* directory is renamed, its parent directory will be changed,
+		 ** so find ".." entry
 		 */
 		dot_dot_de.de_gen_number_bit_string = NULL;
 		retval =
@@ -1318,8 +1306,8 @@
 			       new_dentry->d_name.len, old_inode, 0);
 	if (retval == -EEXIST) {
 		if (!new_dentry_inode) {
-			reiserfs_panic(old_dir->i_sb,
-				       "vs-7050: new entry is found, new inode == 0\n");
+			reiserfs_panic(old_dir->i_sb, "vs-7050",
+				       "new entry is found, new inode == 0");
 		}
 	} else if (retval) {
 		int err = journal_end(&th, old_dir->i_sb, jbegin_count);
@@ -1397,9 +1385,9 @@
 		   this stuff, yes? Then, having
 		   gathered everything into RAM we
 		   should lock the buffers, yes?  -Hans */
-		/* probably.  our rename needs to hold more 
-		 ** than one path at once.  The seals would 
-		 ** have to be written to deal with multi-path 
+		/* probably.  our rename needs to hold more
+		 ** than one path at once.  The seals would
+		 ** have to be written to deal with multi-path
 		 ** issues -chris
 		 */
 		/* sanity checking before doing the rename - avoid races many
@@ -1477,7 +1465,7 @@
 	}
 
 	if (S_ISDIR(old_inode_mode)) {
-		// adjust ".." of renamed directory 
+		/* adjust ".." of renamed directory */
 		set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
 		journal_mark_dirty(&th, new_dir->i_sb, dot_dot_de.de_bh);
 
@@ -1499,8 +1487,8 @@
 	if (reiserfs_cut_from_item
 	    (&th, &old_entry_path, &(old_de.de_entry_key), old_dir, NULL,
 	     0) < 0)
-		reiserfs_warning(old_dir->i_sb,
-				 "vs-7060: reiserfs_rename: couldn't not cut old name. Fsck later?");
+		reiserfs_error(old_dir->i_sb, "vs-7060",
+			       "couldn't not cut old name. Fsck later?");
 
 	old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
 
diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c
index ea0cf8c..3a6de81 100644
--- a/fs/reiserfs/objectid.c
+++ b/fs/reiserfs/objectid.c
@@ -18,8 +18,7 @@
 static void check_objectid_map(struct super_block *s, __le32 * map)
 {
 	if (le32_to_cpu(map[0]) != 1)
-		reiserfs_panic(s,
-			       "vs-15010: check_objectid_map: map corrupted: %lx",
+		reiserfs_panic(s, "vs-15010", "map corrupted: %lx",
 			       (long unsigned int)le32_to_cpu(map[0]));
 
 	// FIXME: add something else here
@@ -61,7 +60,7 @@
 	/* comment needed -Hans */
 	unused_objectid = le32_to_cpu(map[1]);
 	if (unused_objectid == U32_MAX) {
-		reiserfs_warning(s, "%s: no more object ids", __func__);
+		reiserfs_warning(s, "reiserfs-15100", "no more object ids");
 		reiserfs_restore_prepared_buffer(s, SB_BUFFER_WITH_SB(s));
 		return 0;
 	}
@@ -160,9 +159,8 @@
 		i += 2;
 	}
 
-	reiserfs_warning(s,
-			 "vs-15011: reiserfs_release_objectid: tried to free free object id (%lu)",
-			 (long unsigned)objectid_to_release);
+	reiserfs_error(s, "vs-15011", "tried to free free object id (%lu)",
+		       (long unsigned)objectid_to_release);
 }
 
 int reiserfs_convert_objectid_map_v1(struct super_block *s)
@@ -182,7 +180,7 @@
 
 	if (cur_size > new_size) {
 		/* mark everyone used that was listed as free at the end of the objectid
-		 ** map 
+		 ** map
 		 */
 		objectid_map[new_size - 1] = objectid_map[cur_size - 1];
 		set_sb_oid_cursize(disk_sb, new_size);
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index 740bb8c..536eaca 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -157,19 +157,16 @@
 		dc_size(dc));
 }
 
-static char *is_there_reiserfs_struct(char *fmt, int *what, int *skip)
+static char *is_there_reiserfs_struct(char *fmt, int *what)
 {
 	char *k = fmt;
 
-	*skip = 0;
-
 	while ((k = strchr(k, '%')) != NULL) {
 		if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' ||
 		    k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a') {
 			*what = k[1];
 			break;
 		}
-		(*skip)++;
 		k++;
 	}
 	return k;
@@ -181,30 +178,29 @@
    appropriative printk. With this reiserfs_warning you can use format
    specification for complex structures like you used to do with
    printfs for integers, doubles and pointers. For instance, to print
-   out key structure you have to write just: 
-   reiserfs_warning ("bad key %k", key); 
-   instead of 
-   printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid, 
-           key->k_offset, key->k_uniqueness); 
+   out key structure you have to write just:
+   reiserfs_warning ("bad key %k", key);
+   instead of
+   printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid,
+           key->k_offset, key->k_uniqueness);
 */
-
+static DEFINE_SPINLOCK(error_lock);
 static void prepare_error_buf(const char *fmt, va_list args)
 {
 	char *fmt1 = fmt_buf;
 	char *k;
 	char *p = error_buf;
-	int i, j, what, skip;
+	int what;
+
+	spin_lock(&error_lock);
 
 	strcpy(fmt1, fmt);
 
-	while ((k = is_there_reiserfs_struct(fmt1, &what, &skip)) != NULL) {
+	while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) {
 		*k = 0;
 
 		p += vsprintf(p, fmt1, args);
 
-		for (i = 0; i < skip; i++)
-			j = va_arg(args, int);
-
 		switch (what) {
 		case 'k':
 			sprintf_le_key(p, va_arg(args, struct reiserfs_key *));
@@ -243,15 +239,16 @@
 		fmt1 = k + 2;
 	}
 	vsprintf(p, fmt1, args);
+	spin_unlock(&error_lock);
 
 }
 
 /* in addition to usual conversion specifiers this accepts reiserfs
-   specific conversion specifiers: 
-   %k to print little endian key, 
-   %K to print cpu key, 
+   specific conversion specifiers:
+   %k to print little endian key,
+   %K to print cpu key,
    %h to print item_head,
-   %t to print directory entry 
+   %t to print directory entry
    %z to print block head (arg must be struct buffer_head *
    %b to print buffer_head
 */
@@ -264,14 +261,17 @@
     va_end( args );\
 }
 
-void reiserfs_warning(struct super_block *sb, const char *fmt, ...)
+void __reiserfs_warning(struct super_block *sb, const char *id,
+			 const char *function, const char *fmt, ...)
 {
 	do_reiserfs_warning(fmt);
 	if (sb)
-		printk(KERN_WARNING "ReiserFS: %s: warning: %s\n",
-		       reiserfs_bdevname(sb), error_buf);
+		printk(KERN_WARNING "REISERFS warning (device %s): %s%s%s: "
+		       "%s\n", sb->s_id, id ? id : "", id ? " " : "",
+		       function, error_buf);
 	else
-		printk(KERN_WARNING "ReiserFS: warning: %s\n", error_buf);
+		printk(KERN_WARNING "REISERFS warning: %s%s%s: %s\n",
+		       id ? id : "", id ? " " : "", function, error_buf);
 }
 
 /* No newline.. reiserfs_info calls can be followed by printk's */
@@ -279,10 +279,10 @@
 {
 	do_reiserfs_warning(fmt);
 	if (sb)
-		printk(KERN_NOTICE "ReiserFS: %s: %s",
-		       reiserfs_bdevname(sb), error_buf);
+		printk(KERN_NOTICE "REISERFS (device %s): %s",
+		       sb->s_id, error_buf);
 	else
-		printk(KERN_NOTICE "ReiserFS: %s", error_buf);
+		printk(KERN_NOTICE "REISERFS %s:", error_buf);
 }
 
 /* No newline.. reiserfs_printk calls can be followed by printk's */
@@ -297,10 +297,10 @@
 #ifdef CONFIG_REISERFS_CHECK
 	do_reiserfs_warning(fmt);
 	if (s)
-		printk(KERN_DEBUG "ReiserFS: %s: %s\n",
-		       reiserfs_bdevname(s), error_buf);
+		printk(KERN_DEBUG "REISERFS debug (device %s): %s\n",
+		       s->s_id, error_buf);
 	else
-		printk(KERN_DEBUG "ReiserFS: %s\n", error_buf);
+		printk(KERN_DEBUG "REISERFS debug: %s\n", error_buf);
 #endif
 }
 
@@ -314,17 +314,17 @@
     maintainer-errorid.  Don't bother with reusing errorids, there are
     lots of numbers out there.
 
-    Example: 
-    
+    Example:
+
     reiserfs_panic(
 	p_sb, "reiser-29: reiserfs_new_blocknrs: "
 	"one of search_start or rn(%d) is equal to MAX_B_NUM,"
-	"which means that we are optimizing location based on the bogus location of a temp buffer (%p).", 
+	"which means that we are optimizing location based on the bogus location of a temp buffer (%p).",
 	rn, bh
     );
 
     Regular panic()s sometimes clear the screen before the message can
-    be read, thus the need for the while loop.  
+    be read, thus the need for the while loop.
 
     Numbering scheme for panic used by Vladimir and Anatoly( Hans completely ignores this scheme, and considers it
     pointless complexity):
@@ -353,14 +353,46 @@
 extern struct tree_balance *cur_tb;
 #endif
 
-void reiserfs_panic(struct super_block *sb, const char *fmt, ...)
+void __reiserfs_panic(struct super_block *sb, const char *id,
+		      const char *function, const char *fmt, ...)
 {
 	do_reiserfs_warning(fmt);
 
+#ifdef CONFIG_REISERFS_CHECK
 	dump_stack();
+#endif
+	if (sb)
+		panic(KERN_WARNING "REISERFS panic (device %s): %s%s%s: %s\n",
+		      sb->s_id, id ? id : "", id ? " " : "",
+		      function, error_buf);
+	else
+		panic(KERN_WARNING "REISERFS panic: %s%s%s: %s\n",
+		      id ? id : "", id ? " " : "", function, error_buf);
+}
 
-	panic(KERN_EMERG "REISERFS: panic (device %s): %s\n",
-	       reiserfs_bdevname(sb), error_buf);
+void __reiserfs_error(struct super_block *sb, const char *id,
+		      const char *function, const char *fmt, ...)
+{
+	do_reiserfs_warning(fmt);
+
+	BUG_ON(sb == NULL);
+
+	if (reiserfs_error_panic(sb))
+		__reiserfs_panic(sb, id, function, error_buf);
+
+	if (id && id[0])
+		printk(KERN_CRIT "REISERFS error (device %s): %s %s: %s\n",
+		       sb->s_id, id, function, error_buf);
+	else
+		printk(KERN_CRIT "REISERFS error (device %s): %s: %s\n",
+		       sb->s_id, function, error_buf);
+
+	if (sb->s_flags & MS_RDONLY)
+		return;
+
+	reiserfs_info(sb, "Remounting filesystem read-only\n");
+	sb->s_flags |= MS_RDONLY;
+	reiserfs_abort_journal(sb, -EIO);
 }
 
 void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...)
@@ -368,18 +400,18 @@
 	do_reiserfs_warning(fmt);
 
 	if (reiserfs_error_panic(sb)) {
-		panic(KERN_CRIT "REISERFS: panic (device %s): %s\n",
-		      reiserfs_bdevname(sb), error_buf);
+		panic(KERN_CRIT "REISERFS panic (device %s): %s\n", sb->s_id,
+		      error_buf);
 	}
 
-	if (sb->s_flags & MS_RDONLY)
+	if (reiserfs_is_journal_aborted(SB_JOURNAL(sb)))
 		return;
 
-	printk(KERN_CRIT "REISERFS: abort (device %s): %s\n",
-	       reiserfs_bdevname(sb), error_buf);
+	printk(KERN_CRIT "REISERFS abort (device %s): %s\n", sb->s_id,
+	       error_buf);
 
 	sb->s_flags |= MS_RDONLY;
-	reiserfs_journal_abort(sb, errno);
+	reiserfs_abort_journal(sb, errno);
 }
 
 /* this prints internal nodes (4 keys/items in line) (dc_number,
@@ -681,12 +713,10 @@
 	blkh = B_BLK_HEAD(bh);
 	nr = blkh_nr_item(blkh);
 	if (nr > (bh->b_size - BLKH_SIZE) / IH_SIZE)
-		reiserfs_panic(NULL,
-			       "vs-6010: check_leaf_block_head: invalid item number %z",
+		reiserfs_panic(NULL, "vs-6010", "invalid item number %z",
 			       bh);
 	if (blkh_free_space(blkh) > bh->b_size - BLKH_SIZE - IH_SIZE * nr)
-		reiserfs_panic(NULL,
-			       "vs-6020: check_leaf_block_head: invalid free space %z",
+		reiserfs_panic(NULL, "vs-6020", "invalid free space %z",
 			       bh);
 
 }
@@ -697,21 +727,15 @@
 
 	blkh = B_BLK_HEAD(bh);
 	if (!(B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL(bh) <= MAX_HEIGHT))
-		reiserfs_panic(NULL,
-			       "vs-6025: check_internal_block_head: invalid level %z",
-			       bh);
+		reiserfs_panic(NULL, "vs-6025", "invalid level %z", bh);
 
 	if (B_NR_ITEMS(bh) > (bh->b_size - BLKH_SIZE) / IH_SIZE)
-		reiserfs_panic(NULL,
-			       "vs-6030: check_internal_block_head: invalid item number %z",
-			       bh);
+		reiserfs_panic(NULL, "vs-6030", "invalid item number %z", bh);
 
 	if (B_FREE_SPACE(bh) !=
 	    bh->b_size - BLKH_SIZE - KEY_SIZE * B_NR_ITEMS(bh) -
 	    DC_SIZE * (B_NR_ITEMS(bh) + 1))
-		reiserfs_panic(NULL,
-			       "vs-6040: check_internal_block_head: invalid free space %z",
-			       bh);
+		reiserfs_panic(NULL, "vs-6040", "invalid free space %z", bh);
 
 }
 
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 37173fa..d506640 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -321,7 +321,7 @@
 		   /* incore fields */
 		   "j_1st_reserved_block: \t%i\n"
 		   "j_state: \t%li\n"
-		   "j_trans_id: \t%lu\n"
+		   "j_trans_id: \t%u\n"
 		   "j_mount_id: \t%lu\n"
 		   "j_start: \t%lu\n"
 		   "j_len: \t%lu\n"
@@ -329,7 +329,7 @@
 		   "j_wcount: \t%i\n"
 		   "j_bcount: \t%lu\n"
 		   "j_first_unflushed_offset: \t%lu\n"
-		   "j_last_flush_trans_id: \t%lu\n"
+		   "j_last_flush_trans_id: \t%u\n"
 		   "j_trans_start_time: \t%li\n"
 		   "j_list_bitmap_index: \t%i\n"
 		   "j_must_wait: \t%i\n"
@@ -503,7 +503,7 @@
 		add_file(sb, "journal", show_journal);
 		return 0;
 	}
-	reiserfs_warning(sb, "reiserfs: cannot create /proc/%s/%s",
+	reiserfs_warning(sb, "cannot create /proc/%s/%s",
 			 proc_info_root_name, b);
 	return 1;
 }
@@ -559,8 +559,7 @@
 		if (proc_info_root) {
 			proc_info_root->owner = THIS_MODULE;
 		} else {
-			reiserfs_warning(NULL,
-					 "reiserfs: cannot create /proc/%s",
+			reiserfs_warning(NULL, "cannot create /proc/%s",
 					 proc_info_root_name);
 			return 1;
 		}
@@ -634,7 +633,7 @@
  *
  */
 
-/* 
+/*
  * Make Linus happy.
  * Local variables:
  * c-indentation-style: "K&R"
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index f71c394..238e9d9 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -1,8 +1,8 @@
-/* 
+/*
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
 
-/* 
+/*
  * Written by Alexander Zarochentcev.
  *
  * The kernel part of the (on-line) reiserfs resizer.
@@ -101,7 +101,7 @@
 			memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size);
 
 			/* just in case vfree schedules on us, copy the new
-			 ** pointer into the journal struct before freeing the 
+			 ** pointer into the journal struct before freeing the
 			 ** old one
 			 */
 			node_tmp = jb->bitmaps;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 73aaa33..d036ee5 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -23,7 +23,6 @@
  * get_rkey
  * key_in_buffer
  * decrement_bcount
- * decrement_counters_in_path
  * reiserfs_check_path
  * pathrelse_and_restore
  * pathrelse
@@ -57,28 +56,28 @@
 #include <linux/quotaops.h>
 
 /* Does the buffer contain a disk block which is in the tree. */
-inline int B_IS_IN_TREE(const struct buffer_head *p_s_bh)
+inline int B_IS_IN_TREE(const struct buffer_head *bh)
 {
 
-	RFALSE(B_LEVEL(p_s_bh) > MAX_HEIGHT,
-	       "PAP-1010: block (%b) has too big level (%z)", p_s_bh, p_s_bh);
+	RFALSE(B_LEVEL(bh) > MAX_HEIGHT,
+	       "PAP-1010: block (%b) has too big level (%z)", bh, bh);
 
-	return (B_LEVEL(p_s_bh) != FREE_LEVEL);
+	return (B_LEVEL(bh) != FREE_LEVEL);
 }
 
 //
 // to gets item head in le form
 //
-inline void copy_item_head(struct item_head *p_v_to,
-			   const struct item_head *p_v_from)
+inline void copy_item_head(struct item_head *to,
+			   const struct item_head *from)
 {
-	memcpy(p_v_to, p_v_from, IH_SIZE);
+	memcpy(to, from, IH_SIZE);
 }
 
 /* k1 is pointer to on-disk structure which is stored in little-endian
    form. k2 is pointer to cpu variable. For key of items of the same
    object this returns 0.
-   Returns: -1 if key1 < key2 
+   Returns: -1 if key1 < key2
    0 if key1 == key2
    1 if key1 > key2 */
 inline int comp_short_keys(const struct reiserfs_key *le_key,
@@ -136,15 +135,15 @@
 inline int comp_short_le_keys(const struct reiserfs_key *key1,
 			      const struct reiserfs_key *key2)
 {
-	__u32 *p_s_1_u32, *p_s_2_u32;
-	int n_key_length = REISERFS_SHORT_KEY_LEN;
+	__u32 *k1_u32, *k2_u32;
+	int key_length = REISERFS_SHORT_KEY_LEN;
 
-	p_s_1_u32 = (__u32 *) key1;
-	p_s_2_u32 = (__u32 *) key2;
-	for (; n_key_length--; ++p_s_1_u32, ++p_s_2_u32) {
-		if (le32_to_cpu(*p_s_1_u32) < le32_to_cpu(*p_s_2_u32))
+	k1_u32 = (__u32 *) key1;
+	k2_u32 = (__u32 *) key2;
+	for (; key_length--; ++k1_u32, ++k2_u32) {
+		if (le32_to_cpu(*k1_u32) < le32_to_cpu(*k2_u32))
 			return -1;
-		if (le32_to_cpu(*p_s_1_u32) > le32_to_cpu(*p_s_2_u32))
+		if (le32_to_cpu(*k1_u32) > le32_to_cpu(*k2_u32))
 			return 1;
 	}
 	return 0;
@@ -175,52 +174,51 @@
  *  Binary search toolkit function                                        *
  *  Search for an item in the array by the item key                       *
  *  Returns:    1 if found,  0 if not found;                              *
- *        *p_n_pos = number of the searched element if found, else the    *
- *        number of the first element that is larger than p_v_key.        *
+ *        *pos = number of the searched element if found, else the        *
+ *        number of the first element that is larger than key.            *
  **************************************************************************/
-/* For those not familiar with binary search: n_lbound is the leftmost item that it
- could be, n_rbound the rightmost item that it could be.  We examine the item
- halfway between n_lbound and n_rbound, and that tells us either that we can increase
- n_lbound, or decrease n_rbound, or that we have found it, or if n_lbound <= n_rbound that
+/* For those not familiar with binary search: lbound is the leftmost item that it
+ could be, rbound the rightmost item that it could be.  We examine the item
+ halfway between lbound and rbound, and that tells us either that we can increase
+ lbound, or decrease rbound, or that we have found it, or if lbound <= rbound that
  there are no possible items, and we have not found it. With each examination we
  cut the number of possible items it could be by one more than half rounded down,
  or we find it. */
-static inline int bin_search(const void *p_v_key,	/* Key to search for.                   */
-			     const void *p_v_base,	/* First item in the array.             */
-			     int p_n_num,	/* Number of items in the array.        */
-			     int p_n_width,	/* Item size in the array.
-						   searched. Lest the reader be
-						   confused, note that this is crafted
-						   as a general function, and when it
-						   is applied specifically to the array
-						   of item headers in a node, p_n_width
-						   is actually the item header size not
-						   the item size.                      */
-			     int *p_n_pos	/* Number of the searched for element. */
+static inline int bin_search(const void *key,	/* Key to search for. */
+			     const void *base,	/* First item in the array. */
+			     int num,	/* Number of items in the array. */
+			     int width,	/* Item size in the array.
+					   searched. Lest the reader be
+					   confused, note that this is crafted
+					   as a general function, and when it
+					   is applied specifically to the array
+					   of item headers in a node, width
+					   is actually the item header size not
+					   the item size. */
+			     int *pos /* Number of the searched for element. */
     )
 {
-	int n_rbound, n_lbound, n_j;
+	int rbound, lbound, j;
 
-	for (n_j = ((n_rbound = p_n_num - 1) + (n_lbound = 0)) / 2;
-	     n_lbound <= n_rbound; n_j = (n_rbound + n_lbound) / 2)
+	for (j = ((rbound = num - 1) + (lbound = 0)) / 2;
+	     lbound <= rbound; j = (rbound + lbound) / 2)
 		switch (comp_keys
-			((struct reiserfs_key *)((char *)p_v_base +
-						 n_j * p_n_width),
-			 (struct cpu_key *)p_v_key)) {
+			((struct reiserfs_key *)((char *)base + j * width),
+			 (struct cpu_key *)key)) {
 		case -1:
-			n_lbound = n_j + 1;
+			lbound = j + 1;
 			continue;
 		case 1:
-			n_rbound = n_j - 1;
+			rbound = j - 1;
 			continue;
 		case 0:
-			*p_n_pos = n_j;
+			*pos = j;
 			return ITEM_FOUND;	/* Key found in the array.  */
 		}
 
 	/* bin_search did not find given key, it returns position of key,
 	   that is minimal and greater than the given one. */
-	*p_n_pos = n_lbound;
+	*pos = lbound;
 	return ITEM_NOT_FOUND;
 }
 
@@ -243,90 +241,88 @@
    of the path, and going upwards.  We must check the path's validity at each step.  If the key is not in
    the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this
    case we return a special key, either MIN_KEY or MAX_KEY. */
-static inline const struct reiserfs_key *get_lkey(const struct treepath
-						  *p_s_chk_path,
-						  const struct super_block
-						  *p_s_sb)
+static inline const struct reiserfs_key *get_lkey(const struct treepath *chk_path,
+						  const struct super_block *sb)
 {
-	int n_position, n_path_offset = p_s_chk_path->path_length;
-	struct buffer_head *p_s_parent;
+	int position, path_offset = chk_path->path_length;
+	struct buffer_head *parent;
 
-	RFALSE(n_path_offset < FIRST_PATH_ELEMENT_OFFSET,
+	RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
 	       "PAP-5010: invalid offset in the path");
 
 	/* While not higher in path than first element. */
-	while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
+	while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
 
 		RFALSE(!buffer_uptodate
-		       (PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)),
+		       (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
 		       "PAP-5020: parent is not uptodate");
 
 		/* Parent at the path is not in the tree now. */
 		if (!B_IS_IN_TREE
-		    (p_s_parent =
-		     PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)))
+		    (parent =
+		     PATH_OFFSET_PBUFFER(chk_path, path_offset)))
 			return &MAX_KEY;
 		/* Check whether position in the parent is correct. */
-		if ((n_position =
-		     PATH_OFFSET_POSITION(p_s_chk_path,
-					  n_path_offset)) >
-		    B_NR_ITEMS(p_s_parent))
+		if ((position =
+		     PATH_OFFSET_POSITION(chk_path,
+					  path_offset)) >
+		    B_NR_ITEMS(parent))
 			return &MAX_KEY;
 		/* Check whether parent at the path really points to the child. */
-		if (B_N_CHILD_NUM(p_s_parent, n_position) !=
-		    PATH_OFFSET_PBUFFER(p_s_chk_path,
-					n_path_offset + 1)->b_blocknr)
+		if (B_N_CHILD_NUM(parent, position) !=
+		    PATH_OFFSET_PBUFFER(chk_path,
+					path_offset + 1)->b_blocknr)
 			return &MAX_KEY;
 		/* Return delimiting key if position in the parent is not equal to zero. */
-		if (n_position)
-			return B_N_PDELIM_KEY(p_s_parent, n_position - 1);
+		if (position)
+			return B_N_PDELIM_KEY(parent, position - 1);
 	}
 	/* Return MIN_KEY if we are in the root of the buffer tree. */
-	if (PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->
-	    b_blocknr == SB_ROOT_BLOCK(p_s_sb))
+	if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
+	    b_blocknr == SB_ROOT_BLOCK(sb))
 		return &MIN_KEY;
 	return &MAX_KEY;
 }
 
 /* Get delimiting key of the buffer at the path and its right neighbor. */
-inline const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
-					   const struct super_block *p_s_sb)
+inline const struct reiserfs_key *get_rkey(const struct treepath *chk_path,
+					   const struct super_block *sb)
 {
-	int n_position, n_path_offset = p_s_chk_path->path_length;
-	struct buffer_head *p_s_parent;
+	int position, path_offset = chk_path->path_length;
+	struct buffer_head *parent;
 
-	RFALSE(n_path_offset < FIRST_PATH_ELEMENT_OFFSET,
+	RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET,
 	       "PAP-5030: invalid offset in the path");
 
-	while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
+	while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
 
 		RFALSE(!buffer_uptodate
-		       (PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)),
+		       (PATH_OFFSET_PBUFFER(chk_path, path_offset)),
 		       "PAP-5040: parent is not uptodate");
 
 		/* Parent at the path is not in the tree now. */
 		if (!B_IS_IN_TREE
-		    (p_s_parent =
-		     PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)))
+		    (parent =
+		     PATH_OFFSET_PBUFFER(chk_path, path_offset)))
 			return &MIN_KEY;
 		/* Check whether position in the parent is correct. */
-		if ((n_position =
-		     PATH_OFFSET_POSITION(p_s_chk_path,
-					  n_path_offset)) >
-		    B_NR_ITEMS(p_s_parent))
+		if ((position =
+		     PATH_OFFSET_POSITION(chk_path,
+					  path_offset)) >
+		    B_NR_ITEMS(parent))
 			return &MIN_KEY;
 		/* Check whether parent at the path really points to the child. */
-		if (B_N_CHILD_NUM(p_s_parent, n_position) !=
-		    PATH_OFFSET_PBUFFER(p_s_chk_path,
-					n_path_offset + 1)->b_blocknr)
+		if (B_N_CHILD_NUM(parent, position) !=
+		    PATH_OFFSET_PBUFFER(chk_path,
+					path_offset + 1)->b_blocknr)
 			return &MIN_KEY;
 		/* Return delimiting key if position in the parent is not the last one. */
-		if (n_position != B_NR_ITEMS(p_s_parent))
-			return B_N_PDELIM_KEY(p_s_parent, n_position);
+		if (position != B_NR_ITEMS(parent))
+			return B_N_PDELIM_KEY(parent, position);
 	}
 	/* Return MAX_KEY if we are in the root of the buffer tree. */
-	if (PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->
-	    b_blocknr == SB_ROOT_BLOCK(p_s_sb))
+	if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)->
+	    b_blocknr == SB_ROOT_BLOCK(sb))
 		return &MAX_KEY;
 	return &MIN_KEY;
 }
@@ -336,60 +332,29 @@
    the path.  These delimiting keys are stored at least one level above that buffer in the tree. If the
    buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
    this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
-static inline int key_in_buffer(struct treepath *p_s_chk_path,	/* Path which should be checked.  */
-				const struct cpu_key *p_s_key,	/* Key which should be checked.   */
-				struct super_block *p_s_sb	/* Super block pointer.           */
+static inline int key_in_buffer(struct treepath *chk_path,	/* Path which should be checked.  */
+				const struct cpu_key *key,	/* Key which should be checked.   */
+				struct super_block *sb
     )
 {
 
-	RFALSE(!p_s_key || p_s_chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET
-	       || p_s_chk_path->path_length > MAX_HEIGHT,
+	RFALSE(!key || chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET
+	       || chk_path->path_length > MAX_HEIGHT,
 	       "PAP-5050: pointer to the key(%p) is NULL or invalid path length(%d)",
-	       p_s_key, p_s_chk_path->path_length);
-	RFALSE(!PATH_PLAST_BUFFER(p_s_chk_path)->b_bdev,
+	       key, chk_path->path_length);
+	RFALSE(!PATH_PLAST_BUFFER(chk_path)->b_bdev,
 	       "PAP-5060: device must not be NODEV");
 
-	if (comp_keys(get_lkey(p_s_chk_path, p_s_sb), p_s_key) == 1)
+	if (comp_keys(get_lkey(chk_path, sb), key) == 1)
 		/* left delimiting key is bigger, that the key we look for */
 		return 0;
-	//  if ( comp_keys(p_s_key, get_rkey(p_s_chk_path, p_s_sb)) != -1 )
-	if (comp_keys(get_rkey(p_s_chk_path, p_s_sb), p_s_key) != 1)
-		/* p_s_key must be less than right delimitiing key */
+	/*  if ( comp_keys(key, get_rkey(chk_path, sb)) != -1 ) */
+	if (comp_keys(get_rkey(chk_path, sb), key) != 1)
+		/* key must be less than right delimitiing key */
 		return 0;
 	return 1;
 }
 
-inline void decrement_bcount(struct buffer_head *p_s_bh)
-{
-	if (p_s_bh) {
-		if (atomic_read(&(p_s_bh->b_count))) {
-			put_bh(p_s_bh);
-			return;
-		}
-		reiserfs_panic(NULL,
-			       "PAP-5070: decrement_bcount: trying to free free buffer %b",
-			       p_s_bh);
-	}
-}
-
-/* Decrement b_count field of the all buffers in the path. */
-void decrement_counters_in_path(struct treepath *p_s_search_path)
-{
-	int n_path_offset = p_s_search_path->path_length;
-
-	RFALSE(n_path_offset < ILLEGAL_PATH_ELEMENT_OFFSET ||
-	       n_path_offset > EXTENDED_MAX_HEIGHT - 1,
-	       "PAP-5080: invalid path offset of %d", n_path_offset);
-
-	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
-		struct buffer_head *bh;
-
-		bh = PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--);
-		decrement_bcount(bh);
-	}
-	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
-}
-
 int reiserfs_check_path(struct treepath *p)
 {
 	RFALSE(p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET,
@@ -397,40 +362,38 @@
 	return 0;
 }
 
-/* Release all buffers in the path. Restore dirty bits clean
-** when preparing the buffer for the log
-**
-** only called from fix_nodes()
-*/
-void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path)
+/* Drop the reference to each buffer in a path and restore
+ * dirty bits clean when preparing the buffer for the log.
+ * This version should only be called from fix_nodes() */
+void pathrelse_and_restore(struct super_block *sb,
+			   struct treepath *search_path)
 {
-	int n_path_offset = p_s_search_path->path_length;
+	int path_offset = search_path->path_length;
 
-	RFALSE(n_path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
+	RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
 	       "clm-4000: invalid path offset");
 
-	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
-		reiserfs_restore_prepared_buffer(s,
-						 PATH_OFFSET_PBUFFER
-						 (p_s_search_path,
-						  n_path_offset));
-		brelse(PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--));
+	while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
+		struct buffer_head *bh;
+		bh = PATH_OFFSET_PBUFFER(search_path, path_offset--);
+		reiserfs_restore_prepared_buffer(sb, bh);
+		brelse(bh);
 	}
-	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
+	search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
 }
 
-/* Release all buffers in the path. */
-void pathrelse(struct treepath *p_s_search_path)
+/* Drop the reference to each buffer in a path */
+void pathrelse(struct treepath *search_path)
 {
-	int n_path_offset = p_s_search_path->path_length;
+	int path_offset = search_path->path_length;
 
-	RFALSE(n_path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
+	RFALSE(path_offset < ILLEGAL_PATH_ELEMENT_OFFSET,
 	       "PAP-5090: invalid path offset");
 
-	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET)
-		brelse(PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--));
+	while (path_offset > ILLEGAL_PATH_ELEMENT_OFFSET)
+		brelse(PATH_OFFSET_PBUFFER(search_path, path_offset--));
 
-	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
+	search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
 }
 
 static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
@@ -444,23 +407,24 @@
 
 	blkh = (struct block_head *)buf;
 	if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
-		reiserfs_warning(NULL,
-				 "is_leaf: this should be caught earlier");
+		reiserfs_warning(NULL, "reiserfs-5080",
+				 "this should be caught earlier");
 		return 0;
 	}
 
 	nr = blkh_nr_item(blkh);
 	if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
 		/* item number is too big or too small */
-		reiserfs_warning(NULL, "is_leaf: nr_item seems wrong: %z", bh);
+		reiserfs_warning(NULL, "reiserfs-5081",
+				 "nr_item seems wrong: %z", bh);
 		return 0;
 	}
 	ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
 	used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location(ih));
 	if (used_space != blocksize - blkh_free_space(blkh)) {
 		/* free space does not match to calculated amount of use space */
-		reiserfs_warning(NULL, "is_leaf: free space seems wrong: %z",
-				 bh);
+		reiserfs_warning(NULL, "reiserfs-5082",
+				 "free space seems wrong: %z", bh);
 		return 0;
 	}
 	// FIXME: it is_leaf will hit performance too much - we may have
@@ -471,29 +435,29 @@
 	prev_location = blocksize;
 	for (i = 0; i < nr; i++, ih++) {
 		if (le_ih_k_type(ih) == TYPE_ANY) {
-			reiserfs_warning(NULL,
-					 "is_leaf: wrong item type for item %h",
+			reiserfs_warning(NULL, "reiserfs-5083",
+					 "wrong item type for item %h",
 					 ih);
 			return 0;
 		}
 		if (ih_location(ih) >= blocksize
 		    || ih_location(ih) < IH_SIZE * nr) {
-			reiserfs_warning(NULL,
-					 "is_leaf: item location seems wrong: %h",
+			reiserfs_warning(NULL, "reiserfs-5084",
+					 "item location seems wrong: %h",
 					 ih);
 			return 0;
 		}
 		if (ih_item_len(ih) < 1
 		    || ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
-			reiserfs_warning(NULL,
-					 "is_leaf: item length seems wrong: %h",
+			reiserfs_warning(NULL, "reiserfs-5085",
+					 "item length seems wrong: %h",
 					 ih);
 			return 0;
 		}
 		if (prev_location - ih_location(ih) != ih_item_len(ih)) {
-			reiserfs_warning(NULL,
-					 "is_leaf: item location seems wrong (second one): %h",
-					 ih);
+			reiserfs_warning(NULL, "reiserfs-5086",
+					 "item location seems wrong "
+					 "(second one): %h", ih);
 			return 0;
 		}
 		prev_location = ih_location(ih);
@@ -514,24 +478,23 @@
 	nr = blkh_level(blkh);
 	if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
 		/* this level is not possible for internal nodes */
-		reiserfs_warning(NULL,
-				 "is_internal: this should be caught earlier");
+		reiserfs_warning(NULL, "reiserfs-5087",
+				 "this should be caught earlier");
 		return 0;
 	}
 
 	nr = blkh_nr_item(blkh);
 	if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
 		/* for internal which is not root we might check min number of keys */
-		reiserfs_warning(NULL,
-				 "is_internal: number of key seems wrong: %z",
-				 bh);
+		reiserfs_warning(NULL, "reiserfs-5088",
+				 "number of key seems wrong: %z", bh);
 		return 0;
 	}
 
 	used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
 	if (used_space != blocksize - blkh_free_space(blkh)) {
-		reiserfs_warning(NULL,
-				 "is_internal: free space seems wrong: %z", bh);
+		reiserfs_warning(NULL, "reiserfs-5089",
+				 "free space seems wrong: %z", bh);
 		return 0;
 	}
 	// one may imagine much more checks
@@ -543,8 +506,8 @@
 static int is_tree_node(struct buffer_head *bh, int level)
 {
 	if (B_LEVEL(bh) != level) {
-		reiserfs_warning(NULL,
-				 "is_tree_node: node level %d does not match to the expected one %d",
+		reiserfs_warning(NULL, "reiserfs-5090", "node level %d does "
+				 "not match to the expected one %d",
 				 B_LEVEL(bh), level);
 		return 0;
 	}
@@ -580,10 +543,10 @@
 /**************************************************************************
  * Algorithm   SearchByKey                                                *
  *             look for item in the Disk S+Tree by its key                *
- * Input:  p_s_sb   -  super block                                        *
- *         p_s_key  - pointer to the key to search                        *
+ * Input:  sb   -  super block                                            *
+ *         key  - pointer to the key to search                            *
  * Output: ITEM_FOUND, ITEM_NOT_FOUND or IO_ERROR                         *
- *         p_s_search_path - path from the root to the needed leaf        *
+ *         search_path - path from the root to the needed leaf            *
  **************************************************************************/
 
 /* This function fills up the path from the root to the leaf as it
@@ -600,22 +563,22 @@
    correctness of the top of the path but need not be checked for the
    correctness of the bottom of the path */
 /* The function is NOT SCHEDULE-SAFE! */
-int search_by_key(struct super_block *p_s_sb, const struct cpu_key *p_s_key,	/* Key to search. */
-		  struct treepath *p_s_search_path,/* This structure was
+int search_by_key(struct super_block *sb, const struct cpu_key *key,	/* Key to search. */
+		  struct treepath *search_path,/* This structure was
 						   allocated and initialized
 						   by the calling
 						   function. It is filled up
 						   by this function.  */
-		  int n_stop_level	/* How far down the tree to search. To
+		  int stop_level	/* How far down the tree to search. To
 					   stop at leaf level - set to
 					   DISK_LEAF_NODE_LEVEL */
     )
 {
-	b_blocknr_t n_block_number;
+	b_blocknr_t block_number;
 	int expected_level;
-	struct buffer_head *p_s_bh;
-	struct path_element *p_s_last_element;
-	int n_node_level, n_retval;
+	struct buffer_head *bh;
+	struct path_element *last_element;
+	int node_level, retval;
 	int right_neighbor_of_leaf_node;
 	int fs_gen;
 	struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
@@ -623,80 +586,79 @@
 	int reada_count = 0;
 
 #ifdef CONFIG_REISERFS_CHECK
-	int n_repeat_counter = 0;
+	int repeat_counter = 0;
 #endif
 
-	PROC_INFO_INC(p_s_sb, search_by_key);
+	PROC_INFO_INC(sb, search_by_key);
 
 	/* As we add each node to a path we increase its count.  This means that
 	   we must be careful to release all nodes in a path before we either
 	   discard the path struct or re-use the path struct, as we do here. */
 
-	decrement_counters_in_path(p_s_search_path);
+	pathrelse(search_path);
 
 	right_neighbor_of_leaf_node = 0;
 
 	/* With each iteration of this loop we search through the items in the
 	   current node, and calculate the next current node(next path element)
 	   for the next iteration of this loop.. */
-	n_block_number = SB_ROOT_BLOCK(p_s_sb);
+	block_number = SB_ROOT_BLOCK(sb);
 	expected_level = -1;
 	while (1) {
 
 #ifdef CONFIG_REISERFS_CHECK
-		if (!(++n_repeat_counter % 50000))
-			reiserfs_warning(p_s_sb, "PAP-5100: search_by_key: %s:"
-					 "there were %d iterations of while loop "
-					 "looking for key %K",
-					 current->comm, n_repeat_counter,
-					 p_s_key);
+		if (!(++repeat_counter % 50000))
+			reiserfs_warning(sb, "PAP-5100",
+					 "%s: there were %d iterations of "
+					 "while loop looking for key %K",
+					 current->comm, repeat_counter,
+					 key);
 #endif
 
 		/* prep path to have another element added to it. */
-		p_s_last_element =
-		    PATH_OFFSET_PELEMENT(p_s_search_path,
-					 ++p_s_search_path->path_length);
-		fs_gen = get_generation(p_s_sb);
+		last_element =
+		    PATH_OFFSET_PELEMENT(search_path,
+					 ++search_path->path_length);
+		fs_gen = get_generation(sb);
 
 		/* Read the next tree node, and set the last element in the path to
 		   have a pointer to it. */
-		if ((p_s_bh = p_s_last_element->pe_buffer =
-		     sb_getblk(p_s_sb, n_block_number))) {
-			if (!buffer_uptodate(p_s_bh) && reada_count > 1) {
-				search_by_key_reada(p_s_sb, reada_bh,
+		if ((bh = last_element->pe_buffer =
+		     sb_getblk(sb, block_number))) {
+			if (!buffer_uptodate(bh) && reada_count > 1)
+				search_by_key_reada(sb, reada_bh,
 						    reada_blocks, reada_count);
-			}
-			ll_rw_block(READ, 1, &p_s_bh);
-			wait_on_buffer(p_s_bh);
-			if (!buffer_uptodate(p_s_bh))
+			ll_rw_block(READ, 1, &bh);
+			wait_on_buffer(bh);
+			if (!buffer_uptodate(bh))
 				goto io_error;
 		} else {
 		      io_error:
-			p_s_search_path->path_length--;
-			pathrelse(p_s_search_path);
+			search_path->path_length--;
+			pathrelse(search_path);
 			return IO_ERROR;
 		}
 		reada_count = 0;
 		if (expected_level == -1)
-			expected_level = SB_TREE_HEIGHT(p_s_sb);
+			expected_level = SB_TREE_HEIGHT(sb);
 		expected_level--;
 
 		/* It is possible that schedule occurred. We must check whether the key
 		   to search is still in the tree rooted from the current buffer. If
 		   not then repeat search from the root. */
-		if (fs_changed(fs_gen, p_s_sb) &&
-		    (!B_IS_IN_TREE(p_s_bh) ||
-		     B_LEVEL(p_s_bh) != expected_level ||
-		     !key_in_buffer(p_s_search_path, p_s_key, p_s_sb))) {
-			PROC_INFO_INC(p_s_sb, search_by_key_fs_changed);
-			PROC_INFO_INC(p_s_sb, search_by_key_restarted);
-			PROC_INFO_INC(p_s_sb,
+		if (fs_changed(fs_gen, sb) &&
+		    (!B_IS_IN_TREE(bh) ||
+		     B_LEVEL(bh) != expected_level ||
+		     !key_in_buffer(search_path, key, sb))) {
+			PROC_INFO_INC(sb, search_by_key_fs_changed);
+			PROC_INFO_INC(sb, search_by_key_restarted);
+			PROC_INFO_INC(sb,
 				      sbk_restarted[expected_level - 1]);
-			decrement_counters_in_path(p_s_search_path);
+			pathrelse(search_path);
 
 			/* Get the root block number so that we can repeat the search
 			   starting from the root. */
-			n_block_number = SB_ROOT_BLOCK(p_s_sb);
+			block_number = SB_ROOT_BLOCK(sb);
 			expected_level = -1;
 			right_neighbor_of_leaf_node = 0;
 
@@ -704,53 +666,53 @@
 			continue;
 		}
 
-		/* only check that the key is in the buffer if p_s_key is not
+		/* only check that the key is in the buffer if key is not
 		   equal to the MAX_KEY. Latter case is only possible in
 		   "finish_unfinished()" processing during mount. */
-		RFALSE(comp_keys(&MAX_KEY, p_s_key) &&
-		       !key_in_buffer(p_s_search_path, p_s_key, p_s_sb),
+		RFALSE(comp_keys(&MAX_KEY, key) &&
+		       !key_in_buffer(search_path, key, sb),
 		       "PAP-5130: key is not in the buffer");
 #ifdef CONFIG_REISERFS_CHECK
 		if (cur_tb) {
 			print_cur_tb("5140");
-			reiserfs_panic(p_s_sb,
-				       "PAP-5140: search_by_key: schedule occurred in do_balance!");
+			reiserfs_panic(sb, "PAP-5140",
+				       "schedule occurred in do_balance!");
 		}
 #endif
 
 		// make sure, that the node contents look like a node of
 		// certain level
-		if (!is_tree_node(p_s_bh, expected_level)) {
-			reiserfs_warning(p_s_sb, "vs-5150: search_by_key: "
-					 "invalid format found in block %ld. Fsck?",
-					 p_s_bh->b_blocknr);
-			pathrelse(p_s_search_path);
+		if (!is_tree_node(bh, expected_level)) {
+			reiserfs_error(sb, "vs-5150",
+				       "invalid format found in block %ld. "
+				       "Fsck?", bh->b_blocknr);
+			pathrelse(search_path);
 			return IO_ERROR;
 		}
 
 		/* ok, we have acquired next formatted node in the tree */
-		n_node_level = B_LEVEL(p_s_bh);
+		node_level = B_LEVEL(bh);
 
-		PROC_INFO_BH_STAT(p_s_sb, p_s_bh, n_node_level - 1);
+		PROC_INFO_BH_STAT(sb, bh, node_level - 1);
 
-		RFALSE(n_node_level < n_stop_level,
+		RFALSE(node_level < stop_level,
 		       "vs-5152: tree level (%d) is less than stop level (%d)",
-		       n_node_level, n_stop_level);
+		       node_level, stop_level);
 
-		n_retval = bin_search(p_s_key, B_N_PITEM_HEAD(p_s_bh, 0),
-				      B_NR_ITEMS(p_s_bh),
-				      (n_node_level ==
+		retval = bin_search(key, B_N_PITEM_HEAD(bh, 0),
+				      B_NR_ITEMS(bh),
+				      (node_level ==
 				       DISK_LEAF_NODE_LEVEL) ? IH_SIZE :
 				      KEY_SIZE,
-				      &(p_s_last_element->pe_position));
-		if (n_node_level == n_stop_level) {
-			return n_retval;
+				      &(last_element->pe_position));
+		if (node_level == stop_level) {
+			return retval;
 		}
 
 		/* we are not in the stop level */
-		if (n_retval == ITEM_FOUND)
+		if (retval == ITEM_FOUND)
 			/* item has been found, so we choose the pointer which is to the right of the found one */
-			p_s_last_element->pe_position++;
+			last_element->pe_position++;
 
 		/* if item was not found we choose the position which is to
 		   the left of the found item. This requires no code,
@@ -759,24 +721,24 @@
 		/* So we have chosen a position in the current node which is
 		   an internal node.  Now we calculate child block number by
 		   position in the node. */
-		n_block_number =
-		    B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position);
+		block_number =
+		    B_N_CHILD_NUM(bh, last_element->pe_position);
 
 		/* if we are going to read leaf nodes, try for read ahead as well */
-		if ((p_s_search_path->reada & PATH_READA) &&
-		    n_node_level == DISK_LEAF_NODE_LEVEL + 1) {
-			int pos = p_s_last_element->pe_position;
-			int limit = B_NR_ITEMS(p_s_bh);
+		if ((search_path->reada & PATH_READA) &&
+		    node_level == DISK_LEAF_NODE_LEVEL + 1) {
+			int pos = last_element->pe_position;
+			int limit = B_NR_ITEMS(bh);
 			struct reiserfs_key *le_key;
 
-			if (p_s_search_path->reada & PATH_READA_BACK)
+			if (search_path->reada & PATH_READA_BACK)
 				limit = 0;
 			while (reada_count < SEARCH_BY_KEY_READA) {
 				if (pos == limit)
 					break;
 				reada_blocks[reada_count++] =
-				    B_N_CHILD_NUM(p_s_bh, pos);
-				if (p_s_search_path->reada & PATH_READA_BACK)
+				    B_N_CHILD_NUM(bh, pos);
+				if (search_path->reada & PATH_READA_BACK)
 					pos--;
 				else
 					pos++;
@@ -784,9 +746,9 @@
 				/*
 				 * check to make sure we're in the same object
 				 */
-				le_key = B_N_PDELIM_KEY(p_s_bh, pos);
+				le_key = B_N_PDELIM_KEY(bh, pos);
 				if (le32_to_cpu(le_key->k_objectid) !=
-				    p_s_key->on_disk_key.k_objectid) {
+				    key->on_disk_key.k_objectid) {
 					break;
 				}
 			}
@@ -795,11 +757,11 @@
 }
 
 /* Form the path to an item and position in this item which contains
-   file byte defined by p_s_key. If there is no such item
+   file byte defined by key. If there is no such item
    corresponding to the key, we point the path to the item with
-   maximal key less than p_s_key, and *p_n_pos_in_item is set to one
+   maximal key less than key, and *pos_in_item is set to one
    past the last entry/byte in the item.  If searching for entry in a
-   directory item, and it is not found, *p_n_pos_in_item is set to one
+   directory item, and it is not found, *pos_in_item is set to one
    entry more than the entry with maximal key which is less than the
    sought key.
 
@@ -810,48 +772,48 @@
    units of directory entries.  */
 
 /* The function is NOT SCHEDULE-SAFE! */
-int search_for_position_by_key(struct super_block *p_s_sb,	/* Pointer to the super block.          */
+int search_for_position_by_key(struct super_block *sb,	/* Pointer to the super block.          */
 			       const struct cpu_key *p_cpu_key,	/* Key to search (cpu variable)         */
-			       struct treepath *p_s_search_path	/* Filled up by this function.          */
+			       struct treepath *search_path	/* Filled up by this function.          */
     )
 {
 	struct item_head *p_le_ih;	/* pointer to on-disk structure */
-	int n_blk_size;
+	int blk_size;
 	loff_t item_offset, offset;
 	struct reiserfs_dir_entry de;
 	int retval;
 
 	/* If searching for directory entry. */
 	if (is_direntry_cpu_key(p_cpu_key))
-		return search_by_entry_key(p_s_sb, p_cpu_key, p_s_search_path,
+		return search_by_entry_key(sb, p_cpu_key, search_path,
 					   &de);
 
 	/* If not searching for directory entry. */
 
 	/* If item is found. */
-	retval = search_item(p_s_sb, p_cpu_key, p_s_search_path);
+	retval = search_item(sb, p_cpu_key, search_path);
 	if (retval == IO_ERROR)
 		return retval;
 	if (retval == ITEM_FOUND) {
 
 		RFALSE(!ih_item_len
 		       (B_N_PITEM_HEAD
-			(PATH_PLAST_BUFFER(p_s_search_path),
-			 PATH_LAST_POSITION(p_s_search_path))),
+			(PATH_PLAST_BUFFER(search_path),
+			 PATH_LAST_POSITION(search_path))),
 		       "PAP-5165: item length equals zero");
 
-		pos_in_item(p_s_search_path) = 0;
+		pos_in_item(search_path) = 0;
 		return POSITION_FOUND;
 	}
 
-	RFALSE(!PATH_LAST_POSITION(p_s_search_path),
+	RFALSE(!PATH_LAST_POSITION(search_path),
 	       "PAP-5170: position equals zero");
 
 	/* Item is not found. Set path to the previous item. */
 	p_le_ih =
-	    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_search_path),
-			   --PATH_LAST_POSITION(p_s_search_path));
-	n_blk_size = p_s_sb->s_blocksize;
+	    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(search_path),
+			   --PATH_LAST_POSITION(search_path));
+	blk_size = sb->s_blocksize;
 
 	if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
 		return FILE_NOT_FOUND;
@@ -863,10 +825,10 @@
 
 	/* Needed byte is contained in the item pointed to by the path. */
 	if (item_offset <= offset &&
-	    item_offset + op_bytes_number(p_le_ih, n_blk_size) > offset) {
-		pos_in_item(p_s_search_path) = offset - item_offset;
+	    item_offset + op_bytes_number(p_le_ih, blk_size) > offset) {
+		pos_in_item(search_path) = offset - item_offset;
 		if (is_indirect_le_ih(p_le_ih)) {
-			pos_in_item(p_s_search_path) /= n_blk_size;
+			pos_in_item(search_path) /= blk_size;
 		}
 		return POSITION_FOUND;
 	}
@@ -874,30 +836,30 @@
 	/* Needed byte is not contained in the item pointed to by the
 	   path. Set pos_in_item out of the item. */
 	if (is_indirect_le_ih(p_le_ih))
-		pos_in_item(p_s_search_path) =
+		pos_in_item(search_path) =
 		    ih_item_len(p_le_ih) / UNFM_P_SIZE;
 	else
-		pos_in_item(p_s_search_path) = ih_item_len(p_le_ih);
+		pos_in_item(search_path) = ih_item_len(p_le_ih);
 
 	return POSITION_NOT_FOUND;
 }
 
 /* Compare given item and item pointed to by the path. */
-int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path)
+int comp_items(const struct item_head *stored_ih, const struct treepath *path)
 {
-	struct buffer_head *p_s_bh;
+	struct buffer_head *bh = PATH_PLAST_BUFFER(path);
 	struct item_head *ih;
 
 	/* Last buffer at the path is not in the tree. */
-	if (!B_IS_IN_TREE(p_s_bh = PATH_PLAST_BUFFER(p_s_path)))
+	if (!B_IS_IN_TREE(bh))
 		return 1;
 
 	/* Last path position is invalid. */
-	if (PATH_LAST_POSITION(p_s_path) >= B_NR_ITEMS(p_s_bh))
+	if (PATH_LAST_POSITION(path) >= B_NR_ITEMS(bh))
 		return 1;
 
 	/* we need only to know, whether it is the same item */
-	ih = get_ih(p_s_path);
+	ih = get_ih(path);
 	return memcmp(stored_ih, ih, IH_SIZE);
 }
 
@@ -924,9 +886,9 @@
 	}
 	// new file gets truncated
 	if (get_inode_item_key_version(inode) == KEY_FORMAT_3_6) {
-		// 
+		//
 		round_len = ROUND_UP(new_file_length);
-		/* this was n_new_file_length < le_ih ... */
+		/* this was new_file_length < le_ih ... */
 		if (round_len < le_ih_k_offset(le_ih)) {
 			*cut_size = -(IH_SIZE + ih_item_len(le_ih));
 			return M_DELETE;	/* Delete this item. */
@@ -986,96 +948,95 @@
     In case of file truncate calculate whether this item must be deleted/truncated or last
     unformatted node of this item will be converted to a direct item.
     This function returns a determination of what balance mode the calling function should employ. */
-static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *p_s_path, const struct cpu_key *p_s_item_key, int *p_n_removed,	/* Number of unformatted nodes which were removed
+static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, const struct cpu_key *item_key, int *removed,	/* Number of unformatted nodes which were removed
 																						   from end of the file. */
-				      int *p_n_cut_size, unsigned long long n_new_file_length	/* MAX_KEY_OFFSET in case of delete. */
+				      int *cut_size, unsigned long long new_file_length	/* MAX_KEY_OFFSET in case of delete. */
     )
 {
-	struct super_block *p_s_sb = inode->i_sb;
-	struct item_head *p_le_ih = PATH_PITEM_HEAD(p_s_path);
-	struct buffer_head *p_s_bh = PATH_PLAST_BUFFER(p_s_path);
+	struct super_block *sb = inode->i_sb;
+	struct item_head *p_le_ih = PATH_PITEM_HEAD(path);
+	struct buffer_head *bh = PATH_PLAST_BUFFER(path);
 
 	BUG_ON(!th->t_trans_id);
 
 	/* Stat_data item. */
 	if (is_statdata_le_ih(p_le_ih)) {
 
-		RFALSE(n_new_file_length != max_reiserfs_offset(inode),
+		RFALSE(new_file_length != max_reiserfs_offset(inode),
 		       "PAP-5210: mode must be M_DELETE");
 
-		*p_n_cut_size = -(IH_SIZE + ih_item_len(p_le_ih));
+		*cut_size = -(IH_SIZE + ih_item_len(p_le_ih));
 		return M_DELETE;
 	}
 
 	/* Directory item. */
 	if (is_direntry_le_ih(p_le_ih))
-		return prepare_for_direntry_item(p_s_path, p_le_ih, inode,
-						 n_new_file_length,
-						 p_n_cut_size);
+		return prepare_for_direntry_item(path, p_le_ih, inode,
+						 new_file_length,
+						 cut_size);
 
 	/* Direct item. */
 	if (is_direct_le_ih(p_le_ih))
-		return prepare_for_direct_item(p_s_path, p_le_ih, inode,
-					       n_new_file_length, p_n_cut_size);
+		return prepare_for_direct_item(path, p_le_ih, inode,
+					       new_file_length, cut_size);
 
 	/* Case of an indirect item. */
 	{
-	    int blk_size = p_s_sb->s_blocksize;
+	    int blk_size = sb->s_blocksize;
 	    struct item_head s_ih;
 	    int need_re_search;
 	    int delete = 0;
 	    int result = M_CUT;
 	    int pos = 0;
 
-	    if ( n_new_file_length == max_reiserfs_offset (inode) ) {
+	    if ( new_file_length == max_reiserfs_offset (inode) ) {
 		/* prepare_for_delete_or_cut() is called by
 		 * reiserfs_delete_item() */
-		n_new_file_length = 0;
+		new_file_length = 0;
 		delete = 1;
 	    }
 
 	    do {
 		need_re_search = 0;
-		*p_n_cut_size = 0;
-		p_s_bh = PATH_PLAST_BUFFER(p_s_path);
-		copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
+		*cut_size = 0;
+		bh = PATH_PLAST_BUFFER(path);
+		copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
 		pos = I_UNFM_NUM(&s_ih);
 
-		while (le_ih_k_offset (&s_ih) + (pos - 1) * blk_size > n_new_file_length) {
+		while (le_ih_k_offset (&s_ih) + (pos - 1) * blk_size > new_file_length) {
 		    __le32 *unfm;
 		    __u32 block;
 
 		    /* Each unformatted block deletion may involve one additional
 		     * bitmap block into the transaction, thereby the initial
 		     * journal space reservation might not be enough. */
-		    if (!delete && (*p_n_cut_size) != 0 &&
-			reiserfs_transaction_free_space(th) < JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
+		    if (!delete && (*cut_size) != 0 &&
+			reiserfs_transaction_free_space(th) < JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD)
 			break;
-		    }
 
-		    unfm = (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + pos - 1;
+		    unfm = (__le32 *)B_I_PITEM(bh, &s_ih) + pos - 1;
 		    block = get_block_num(unfm, 0);
 
 		    if (block != 0) {
-			reiserfs_prepare_for_journal(p_s_sb, p_s_bh, 1);
+			reiserfs_prepare_for_journal(sb, bh, 1);
 			put_block_num(unfm, 0, 0);
-			journal_mark_dirty (th, p_s_sb, p_s_bh);
+			journal_mark_dirty(th, sb, bh);
 			reiserfs_free_block(th, inode, block, 1);
 		    }
 
 		    cond_resched();
 
-		    if (item_moved (&s_ih, p_s_path))  {
+		    if (item_moved (&s_ih, path))  {
 			need_re_search = 1;
 			break;
 		    }
 
 		    pos --;
-		    (*p_n_removed) ++;
-		    (*p_n_cut_size) -= UNFM_P_SIZE;
+		    (*removed)++;
+		    (*cut_size) -= UNFM_P_SIZE;
 
 		    if (pos == 0) {
-			(*p_n_cut_size) -= IH_SIZE;
+			(*cut_size) -= IH_SIZE;
 			result = M_DELETE;
 			break;
 		    }
@@ -1083,12 +1044,12 @@
 		/* a trick.  If the buffer has been logged, this will do nothing.  If
 		** we've broken the loop without logging it, it will restore the
 		** buffer */
-		reiserfs_restore_prepared_buffer(p_s_sb, p_s_bh);
+		reiserfs_restore_prepared_buffer(sb, bh);
 	    } while (need_re_search &&
-		     search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path) == POSITION_FOUND);
-	    pos_in_item(p_s_path) = pos * UNFM_P_SIZE;
+		     search_for_position_by_key(sb, item_key, path) == POSITION_FOUND);
+	    pos_in_item(path) = pos * UNFM_P_SIZE;
 
-	    if (*p_n_cut_size == 0) {
+	    if (*cut_size == 0) {
 		/* Nothing were cut. maybe convert last unformatted node to the
 		 * direct item? */
 		result = M_CONVERT;
@@ -1098,45 +1059,45 @@
 }
 
 /* Calculate number of bytes which will be deleted or cut during balance */
-static int calc_deleted_bytes_number(struct tree_balance *p_s_tb, char c_mode)
+static int calc_deleted_bytes_number(struct tree_balance *tb, char mode)
 {
-	int n_del_size;
-	struct item_head *p_le_ih = PATH_PITEM_HEAD(p_s_tb->tb_path);
+	int del_size;
+	struct item_head *p_le_ih = PATH_PITEM_HEAD(tb->tb_path);
 
 	if (is_statdata_le_ih(p_le_ih))
 		return 0;
 
-	n_del_size =
-	    (c_mode ==
-	     M_DELETE) ? ih_item_len(p_le_ih) : -p_s_tb->insert_size[0];
+	del_size =
+	    (mode ==
+	     M_DELETE) ? ih_item_len(p_le_ih) : -tb->insert_size[0];
 	if (is_direntry_le_ih(p_le_ih)) {
-		// return EMPTY_DIR_SIZE; /* We delete emty directoris only. */
-		// we can't use EMPTY_DIR_SIZE, as old format dirs have a different
-		// empty size.  ick. FIXME, is this right?
-		//
-		return n_del_size;
+		/* return EMPTY_DIR_SIZE; We delete emty directoris only.
+		 * we can't use EMPTY_DIR_SIZE, as old format dirs have a different
+		 * empty size.  ick. FIXME, is this right? */
+		return del_size;
 	}
 
 	if (is_indirect_le_ih(p_le_ih))
-		n_del_size = (n_del_size / UNFM_P_SIZE) * (PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_size);	// - get_ih_free_space (p_le_ih);
-	return n_del_size;
+		del_size = (del_size / UNFM_P_SIZE) *
+				(PATH_PLAST_BUFFER(tb->tb_path)->b_size);
+	return del_size;
 }
 
 static void init_tb_struct(struct reiserfs_transaction_handle *th,
-			   struct tree_balance *p_s_tb,
-			   struct super_block *p_s_sb,
-			   struct treepath *p_s_path, int n_size)
+			   struct tree_balance *tb,
+			   struct super_block *sb,
+			   struct treepath *path, int size)
 {
 
 	BUG_ON(!th->t_trans_id);
 
-	memset(p_s_tb, '\0', sizeof(struct tree_balance));
-	p_s_tb->transaction_handle = th;
-	p_s_tb->tb_sb = p_s_sb;
-	p_s_tb->tb_path = p_s_path;
-	PATH_OFFSET_PBUFFER(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
-	PATH_OFFSET_POSITION(p_s_path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;
-	p_s_tb->insert_size[0] = n_size;
+	memset(tb, '\0', sizeof(struct tree_balance));
+	tb->transaction_handle = th;
+	tb->tb_sb = sb;
+	tb->tb_path = path;
+	PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
+	PATH_OFFSET_POSITION(path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;
+	tb->insert_size[0] = size;
 }
 
 void padd_item(char *item, int total_length, int length)
@@ -1175,73 +1136,77 @@
 }
 #endif
 
-/* Delete object item. */
-int reiserfs_delete_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,	/* Path to the deleted item. */
-			 const struct cpu_key *p_s_item_key,	/* Key to search for the deleted item.  */
-			 struct inode *p_s_inode,	/* inode is here just to update i_blocks and quotas */
-			 struct buffer_head *p_s_un_bh)
-{				/* NULL or unformatted node pointer.    */
-	struct super_block *p_s_sb = p_s_inode->i_sb;
+/* Delete object item.
+ * th       - active transaction handle
+ * path     - path to the deleted item
+ * item_key - key to search for the deleted item
+ * indode   - used for updating i_blocks and quotas
+ * un_bh    - NULL or unformatted node pointer
+ */
+int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
+			 struct treepath *path, const struct cpu_key *item_key,
+			 struct inode *inode, struct buffer_head *un_bh)
+{
+	struct super_block *sb = inode->i_sb;
 	struct tree_balance s_del_balance;
 	struct item_head s_ih;
 	struct item_head *q_ih;
 	int quota_cut_bytes;
-	int n_ret_value, n_del_size, n_removed;
+	int ret_value, del_size, removed;
 
 #ifdef CONFIG_REISERFS_CHECK
-	char c_mode;
-	int n_iter = 0;
+	char mode;
+	int iter = 0;
 #endif
 
 	BUG_ON(!th->t_trans_id);
 
-	init_tb_struct(th, &s_del_balance, p_s_sb, p_s_path,
+	init_tb_struct(th, &s_del_balance, sb, path,
 		       0 /*size is unknown */ );
 
 	while (1) {
-		n_removed = 0;
+		removed = 0;
 
 #ifdef CONFIG_REISERFS_CHECK
-		n_iter++;
-		c_mode =
+		iter++;
+		mode =
 #endif
-		    prepare_for_delete_or_cut(th, p_s_inode, p_s_path,
-					      p_s_item_key, &n_removed,
-					      &n_del_size,
-					      max_reiserfs_offset(p_s_inode));
+		    prepare_for_delete_or_cut(th, inode, path,
+					      item_key, &removed,
+					      &del_size,
+					      max_reiserfs_offset(inode));
 
-		RFALSE(c_mode != M_DELETE, "PAP-5320: mode must be M_DELETE");
+		RFALSE(mode != M_DELETE, "PAP-5320: mode must be M_DELETE");
 
-		copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
-		s_del_balance.insert_size[0] = n_del_size;
+		copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
+		s_del_balance.insert_size[0] = del_size;
 
-		n_ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);
-		if (n_ret_value != REPEAT_SEARCH)
+		ret_value = fix_nodes(M_DELETE, &s_del_balance, NULL, NULL);
+		if (ret_value != REPEAT_SEARCH)
 			break;
 
-		PROC_INFO_INC(p_s_sb, delete_item_restarted);
+		PROC_INFO_INC(sb, delete_item_restarted);
 
 		// file system changed, repeat search
-		n_ret_value =
-		    search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);
-		if (n_ret_value == IO_ERROR)
+		ret_value =
+		    search_for_position_by_key(sb, item_key, path);
+		if (ret_value == IO_ERROR)
 			break;
-		if (n_ret_value == FILE_NOT_FOUND) {
-			reiserfs_warning(p_s_sb,
-					 "vs-5340: reiserfs_delete_item: "
+		if (ret_value == FILE_NOT_FOUND) {
+			reiserfs_warning(sb, "vs-5340",
 					 "no items of the file %K found",
-					 p_s_item_key);
+					 item_key);
 			break;
 		}
 	}			/* while (1) */
 
-	if (n_ret_value != CARRY_ON) {
+	if (ret_value != CARRY_ON) {
 		unfix_nodes(&s_del_balance);
 		return 0;
 	}
 	// reiserfs_delete_item returns item length when success
-	n_ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
-	q_ih = get_ih(p_s_path);
+	ret_value = calc_deleted_bytes_number(&s_del_balance, M_DELETE);
+	q_ih = get_ih(path);
 	quota_cut_bytes = ih_item_len(q_ih);
 
 	/* hack so the quota code doesn't have to guess if the file
@@ -1250,15 +1215,15 @@
 	 ** split into multiple items, and we only want to decrement for
 	 ** the unfm node once
 	 */
-	if (!S_ISLNK(p_s_inode->i_mode) && is_direct_le_ih(q_ih)) {
-		if ((le_ih_k_offset(q_ih) & (p_s_sb->s_blocksize - 1)) == 1) {
-			quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;
+	if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(q_ih)) {
+		if ((le_ih_k_offset(q_ih) & (sb->s_blocksize - 1)) == 1) {
+			quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
 		} else {
 			quota_cut_bytes = 0;
 		}
 	}
 
-	if (p_s_un_bh) {
+	if (un_bh) {
 		int off;
 		char *data;
 
@@ -1276,31 +1241,31 @@
 		 ** The unformatted node must be dirtied later on.  We can't be
 		 ** sure here if the entire tail has been deleted yet.
 		 **
-		 ** p_s_un_bh is from the page cache (all unformatted nodes are
+		 ** un_bh is from the page cache (all unformatted nodes are
 		 ** from the page cache) and might be a highmem page.  So, we
-		 ** can't use p_s_un_bh->b_data.
+		 ** can't use un_bh->b_data.
 		 ** -clm
 		 */
 
-		data = kmap_atomic(p_s_un_bh->b_page, KM_USER0);
+		data = kmap_atomic(un_bh->b_page, KM_USER0);
 		off = ((le_ih_k_offset(&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));
 		memcpy(data + off,
-		       B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih),
-		       n_ret_value);
+		       B_I_PITEM(PATH_PLAST_BUFFER(path), &s_ih),
+		       ret_value);
 		kunmap_atomic(data, KM_USER0);
 	}
 	/* Perform balancing after all resources have been collected at once. */
 	do_balance(&s_del_balance, NULL, NULL, M_DELETE);
 
 #ifdef REISERQUOTA_DEBUG
-	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE,
+	reiserfs_debug(sb, REISERFS_DEBUG_CODE,
 		       "reiserquota delete_item(): freeing %u, id=%u type=%c",
-		       quota_cut_bytes, p_s_inode->i_uid, head2type(&s_ih));
+		       quota_cut_bytes, inode->i_uid, head2type(&s_ih));
 #endif
-	vfs_dq_free_space_nodirty(p_s_inode, quota_cut_bytes);
+	vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
 
 	/* Return deleted body length */
-	return n_ret_value;
+	return ret_value;
 }
 
 /* Summary Of Mechanisms For Handling Collisions Between Processes:
@@ -1338,10 +1303,9 @@
 	while (1) {
 		retval = search_item(th->t_super, &cpu_key, &path);
 		if (retval == IO_ERROR) {
-			reiserfs_warning(th->t_super,
-					 "vs-5350: reiserfs_delete_solid_item: "
-					 "i/o failure occurred trying to delete %K",
-					 &cpu_key);
+			reiserfs_error(th->t_super, "vs-5350",
+				       "i/o failure occurred trying "
+				       "to delete %K", &cpu_key);
 			break;
 		}
 		if (retval != ITEM_FOUND) {
@@ -1355,9 +1319,8 @@
 			     GET_GENERATION_NUMBER(le_key_k_offset
 						   (le_key_version(key),
 						    key)) == 1))
-				reiserfs_warning(th->t_super,
-						 "vs-5355: reiserfs_delete_solid_item: %k not found",
-						 key);
+				reiserfs_warning(th->t_super, "vs-5355",
+						 "%k not found", key);
 			break;
 		}
 		if (!tb_init) {
@@ -1389,8 +1352,7 @@
 			break;
 		}
 		// IO_ERROR, NO_DISK_SPACE, etc
-		reiserfs_warning(th->t_super,
-				 "vs-5360: reiserfs_delete_solid_item: "
+		reiserfs_warning(th->t_super, "vs-5360",
 				 "could not delete %K due to fix_nodes failure",
 				 &cpu_key);
 		unfix_nodes(&tb);
@@ -1462,36 +1424,37 @@
 }
 
 static int maybe_indirect_to_direct(struct reiserfs_transaction_handle *th,
-				    struct inode *p_s_inode,
+				    struct inode *inode,
 				    struct page *page,
-				    struct treepath *p_s_path,
-				    const struct cpu_key *p_s_item_key,
-				    loff_t n_new_file_size, char *p_c_mode)
+				    struct treepath *path,
+				    const struct cpu_key *item_key,
+				    loff_t new_file_size, char *mode)
 {
-	struct super_block *p_s_sb = p_s_inode->i_sb;
-	int n_block_size = p_s_sb->s_blocksize;
+	struct super_block *sb = inode->i_sb;
+	int block_size = sb->s_blocksize;
 	int cut_bytes;
 	BUG_ON(!th->t_trans_id);
-	BUG_ON(n_new_file_size != p_s_inode->i_size);
+	BUG_ON(new_file_size != inode->i_size);
 
 	/* the page being sent in could be NULL if there was an i/o error
 	 ** reading in the last block.  The user will hit problems trying to
 	 ** read the file, but for now we just skip the indirect2direct
 	 */
-	if (atomic_read(&p_s_inode->i_count) > 1 ||
-	    !tail_has_to_be_packed(p_s_inode) ||
-	    !page || (REISERFS_I(p_s_inode)->i_flags & i_nopack_mask)) {
-		// leave tail in an unformatted node    
-		*p_c_mode = M_SKIP_BALANCING;
+	if (atomic_read(&inode->i_count) > 1 ||
+	    !tail_has_to_be_packed(inode) ||
+	    !page || (REISERFS_I(inode)->i_flags & i_nopack_mask)) {
+		/* leave tail in an unformatted node */
+		*mode = M_SKIP_BALANCING;
 		cut_bytes =
-		    n_block_size - (n_new_file_size & (n_block_size - 1));
-		pathrelse(p_s_path);
+		    block_size - (new_file_size & (block_size - 1));
+		pathrelse(path);
 		return cut_bytes;
 	}
-	/* Permorm the conversion to a direct_item. */
-	/*return indirect_to_direct (p_s_inode, p_s_path, p_s_item_key, n_new_file_size, p_c_mode); */
-	return indirect2direct(th, p_s_inode, page, p_s_path, p_s_item_key,
-			       n_new_file_size, p_c_mode);
+	/* Perform the conversion to a direct_item. */
+	/* return indirect_to_direct(inode, path, item_key,
+				  new_file_size, mode); */
+	return indirect2direct(th, inode, page, path, item_key,
+			       new_file_size, mode);
 }
 
 /* we did indirect_to_direct conversion. And we have inserted direct
@@ -1515,8 +1478,8 @@
 		/* look for the last byte of the tail */
 		if (search_for_position_by_key(inode->i_sb, &tail_key, path) ==
 		    POSITION_NOT_FOUND)
-			reiserfs_panic(inode->i_sb,
-				       "vs-5615: indirect_to_direct_roll_back: found invalid item");
+			reiserfs_panic(inode->i_sb, "vs-5615",
+				       "found invalid item");
 		RFALSE(path->pos_in_item !=
 		       ih_item_len(PATH_PITEM_HEAD(path)) - 1,
 		       "vs-5616: appended bytes found");
@@ -1533,38 +1496,39 @@
 		set_cpu_key_k_offset(&tail_key,
 				     cpu_key_k_offset(&tail_key) - removed);
 	}
-	reiserfs_warning(inode->i_sb,
-			 "indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space");
+	reiserfs_warning(inode->i_sb, "reiserfs-5091", "indirect_to_direct "
+			 "conversion has been rolled back due to "
+			 "lack of disk space");
 	//mark_file_without_tail (inode);
 	mark_inode_dirty(inode);
 }
 
 /* (Truncate or cut entry) or delete object item. Returns < 0 on failure */
 int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
-			   struct treepath *p_s_path,
-			   struct cpu_key *p_s_item_key,
-			   struct inode *p_s_inode,
-			   struct page *page, loff_t n_new_file_size)
+			   struct treepath *path,
+			   struct cpu_key *item_key,
+			   struct inode *inode,
+			   struct page *page, loff_t new_file_size)
 {
-	struct super_block *p_s_sb = p_s_inode->i_sb;
+	struct super_block *sb = inode->i_sb;
 	/* Every function which is going to call do_balance must first
 	   create a tree_balance structure.  Then it must fill up this
 	   structure by using the init_tb_struct and fix_nodes functions.
 	   After that we can make tree balancing. */
 	struct tree_balance s_cut_balance;
 	struct item_head *p_le_ih;
-	int n_cut_size = 0,	/* Amount to be cut. */
-	    n_ret_value = CARRY_ON, n_removed = 0,	/* Number of the removed unformatted nodes. */
-	    n_is_inode_locked = 0;
-	char c_mode;		/* Mode of the balance. */
+	int cut_size = 0,	/* Amount to be cut. */
+	    ret_value = CARRY_ON, removed = 0,	/* Number of the removed unformatted nodes. */
+	    is_inode_locked = 0;
+	char mode;		/* Mode of the balance. */
 	int retval2 = -1;
 	int quota_cut_bytes;
 	loff_t tail_pos = 0;
 
 	BUG_ON(!th->t_trans_id);
 
-	init_tb_struct(th, &s_cut_balance, p_s_inode->i_sb, p_s_path,
-		       n_cut_size);
+	init_tb_struct(th, &s_cut_balance, inode->i_sb, path,
+		       cut_size);
 
 	/* Repeat this loop until we either cut the item without needing
 	   to balance, or we fix_nodes without schedule occurring */
@@ -1574,144 +1538,142 @@
 		   free unformatted nodes which are pointed to by the cut
 		   pointers. */
 
-		c_mode =
-		    prepare_for_delete_or_cut(th, p_s_inode, p_s_path,
-					      p_s_item_key, &n_removed,
-					      &n_cut_size, n_new_file_size);
-		if (c_mode == M_CONVERT) {
+		mode =
+		    prepare_for_delete_or_cut(th, inode, path,
+					      item_key, &removed,
+					      &cut_size, new_file_size);
+		if (mode == M_CONVERT) {
 			/* convert last unformatted node to direct item or leave
 			   tail in the unformatted node */
-			RFALSE(n_ret_value != CARRY_ON,
+			RFALSE(ret_value != CARRY_ON,
 			       "PAP-5570: can not convert twice");
 
-			n_ret_value =
-			    maybe_indirect_to_direct(th, p_s_inode, page,
-						     p_s_path, p_s_item_key,
-						     n_new_file_size, &c_mode);
-			if (c_mode == M_SKIP_BALANCING)
+			ret_value =
+			    maybe_indirect_to_direct(th, inode, page,
+						     path, item_key,
+						     new_file_size, &mode);
+			if (mode == M_SKIP_BALANCING)
 				/* tail has been left in the unformatted node */
-				return n_ret_value;
+				return ret_value;
 
-			n_is_inode_locked = 1;
+			is_inode_locked = 1;
 
 			/* removing of last unformatted node will change value we
 			   have to return to truncate. Save it */
-			retval2 = n_ret_value;
-			/*retval2 = p_s_sb->s_blocksize - (n_new_file_size & (p_s_sb->s_blocksize - 1)); */
+			retval2 = ret_value;
+			/*retval2 = sb->s_blocksize - (new_file_size & (sb->s_blocksize - 1)); */
 
 			/* So, we have performed the first part of the conversion:
 			   inserting the new direct item.  Now we are removing the
 			   last unformatted node pointer. Set key to search for
 			   it. */
-			set_cpu_key_k_type(p_s_item_key, TYPE_INDIRECT);
-			p_s_item_key->key_length = 4;
-			n_new_file_size -=
-			    (n_new_file_size & (p_s_sb->s_blocksize - 1));
-			tail_pos = n_new_file_size;
-			set_cpu_key_k_offset(p_s_item_key, n_new_file_size + 1);
+			set_cpu_key_k_type(item_key, TYPE_INDIRECT);
+			item_key->key_length = 4;
+			new_file_size -=
+			    (new_file_size & (sb->s_blocksize - 1));
+			tail_pos = new_file_size;
+			set_cpu_key_k_offset(item_key, new_file_size + 1);
 			if (search_for_position_by_key
-			    (p_s_sb, p_s_item_key,
-			     p_s_path) == POSITION_NOT_FOUND) {
-				print_block(PATH_PLAST_BUFFER(p_s_path), 3,
-					    PATH_LAST_POSITION(p_s_path) - 1,
-					    PATH_LAST_POSITION(p_s_path) + 1);
-				reiserfs_panic(p_s_sb,
-					       "PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%K)",
-					       p_s_item_key);
+			    (sb, item_key,
+			     path) == POSITION_NOT_FOUND) {
+				print_block(PATH_PLAST_BUFFER(path), 3,
+					    PATH_LAST_POSITION(path) - 1,
+					    PATH_LAST_POSITION(path) + 1);
+				reiserfs_panic(sb, "PAP-5580", "item to "
+					       "convert does not exist (%K)",
+					       item_key);
 			}
 			continue;
 		}
-		if (n_cut_size == 0) {
-			pathrelse(p_s_path);
+		if (cut_size == 0) {
+			pathrelse(path);
 			return 0;
 		}
 
-		s_cut_balance.insert_size[0] = n_cut_size;
+		s_cut_balance.insert_size[0] = cut_size;
 
-		n_ret_value = fix_nodes(c_mode, &s_cut_balance, NULL, NULL);
-		if (n_ret_value != REPEAT_SEARCH)
+		ret_value = fix_nodes(mode, &s_cut_balance, NULL, NULL);
+		if (ret_value != REPEAT_SEARCH)
 			break;
 
-		PROC_INFO_INC(p_s_sb, cut_from_item_restarted);
+		PROC_INFO_INC(sb, cut_from_item_restarted);
 
-		n_ret_value =
-		    search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);
-		if (n_ret_value == POSITION_FOUND)
+		ret_value =
+		    search_for_position_by_key(sb, item_key, path);
+		if (ret_value == POSITION_FOUND)
 			continue;
 
-		reiserfs_warning(p_s_sb,
-				 "PAP-5610: reiserfs_cut_from_item: item %K not found",
-				 p_s_item_key);
+		reiserfs_warning(sb, "PAP-5610", "item %K not found",
+				 item_key);
 		unfix_nodes(&s_cut_balance);
-		return (n_ret_value == IO_ERROR) ? -EIO : -ENOENT;
+		return (ret_value == IO_ERROR) ? -EIO : -ENOENT;
 	}			/* while */
 
 	// check fix_nodes results (IO_ERROR or NO_DISK_SPACE)
-	if (n_ret_value != CARRY_ON) {
-		if (n_is_inode_locked) {
+	if (ret_value != CARRY_ON) {
+		if (is_inode_locked) {
 			// FIXME: this seems to be not needed: we are always able
 			// to cut item
-			indirect_to_direct_roll_back(th, p_s_inode, p_s_path);
+			indirect_to_direct_roll_back(th, inode, path);
 		}
-		if (n_ret_value == NO_DISK_SPACE)
-			reiserfs_warning(p_s_sb, "NO_DISK_SPACE");
+		if (ret_value == NO_DISK_SPACE)
+			reiserfs_warning(sb, "reiserfs-5092",
+					 "NO_DISK_SPACE");
 		unfix_nodes(&s_cut_balance);
 		return -EIO;
 	}
 
 	/* go ahead and perform balancing */
 
-	RFALSE(c_mode == M_PASTE || c_mode == M_INSERT, "invalid mode");
+	RFALSE(mode == M_PASTE || mode == M_INSERT, "invalid mode");
 
 	/* Calculate number of bytes that need to be cut from the item. */
 	quota_cut_bytes =
-	    (c_mode ==
-	     M_DELETE) ? ih_item_len(get_ih(p_s_path)) : -s_cut_balance.
+	    (mode ==
+	     M_DELETE) ? ih_item_len(get_ih(path)) : -s_cut_balance.
 	    insert_size[0];
 	if (retval2 == -1)
-		n_ret_value = calc_deleted_bytes_number(&s_cut_balance, c_mode);
+		ret_value = calc_deleted_bytes_number(&s_cut_balance, mode);
 	else
-		n_ret_value = retval2;
+		ret_value = retval2;
 
 	/* For direct items, we only change the quota when deleting the last
 	 ** item.
 	 */
 	p_le_ih = PATH_PITEM_HEAD(s_cut_balance.tb_path);
-	if (!S_ISLNK(p_s_inode->i_mode) && is_direct_le_ih(p_le_ih)) {
-		if (c_mode == M_DELETE &&
-		    (le_ih_k_offset(p_le_ih) & (p_s_sb->s_blocksize - 1)) ==
+	if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(p_le_ih)) {
+		if (mode == M_DELETE &&
+		    (le_ih_k_offset(p_le_ih) & (sb->s_blocksize - 1)) ==
 		    1) {
 			// FIXME: this is to keep 3.5 happy
-			REISERFS_I(p_s_inode)->i_first_direct_byte = U32_MAX;
-			quota_cut_bytes = p_s_sb->s_blocksize + UNFM_P_SIZE;
+			REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
+			quota_cut_bytes = sb->s_blocksize + UNFM_P_SIZE;
 		} else {
 			quota_cut_bytes = 0;
 		}
 	}
 #ifdef CONFIG_REISERFS_CHECK
-	if (n_is_inode_locked) {
+	if (is_inode_locked) {
 		struct item_head *le_ih =
 		    PATH_PITEM_HEAD(s_cut_balance.tb_path);
 		/* we are going to complete indirect2direct conversion. Make
 		   sure, that we exactly remove last unformatted node pointer
 		   of the item */
 		if (!is_indirect_le_ih(le_ih))
-			reiserfs_panic(p_s_sb,
-				       "vs-5652: reiserfs_cut_from_item: "
+			reiserfs_panic(sb, "vs-5652",
 				       "item must be indirect %h", le_ih);
 
-		if (c_mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)
-			reiserfs_panic(p_s_sb,
-				       "vs-5653: reiserfs_cut_from_item: "
-				       "completing indirect2direct conversion indirect item %h "
-				       "being deleted must be of 4 byte long",
-				       le_ih);
+		if (mode == M_DELETE && ih_item_len(le_ih) != UNFM_P_SIZE)
+			reiserfs_panic(sb, "vs-5653", "completing "
+				       "indirect2direct conversion indirect "
+				       "item %h being deleted must be of "
+				       "4 byte long", le_ih);
 
-		if (c_mode == M_CUT
+		if (mode == M_CUT
 		    && s_cut_balance.insert_size[0] != -UNFM_P_SIZE) {
-			reiserfs_panic(p_s_sb,
-				       "vs-5654: reiserfs_cut_from_item: "
-				       "can not complete indirect2direct conversion of %h (CUT, insert_size==%d)",
+			reiserfs_panic(sb, "vs-5654", "can not complete "
+				       "indirect2direct conversion of %h "
+				       "(CUT, insert_size==%d)",
 				       le_ih, s_cut_balance.insert_size[0]);
 		}
 		/* it would be useful to make sure, that right neighboring
@@ -1719,23 +1681,23 @@
 	}
 #endif
 
-	do_balance(&s_cut_balance, NULL, NULL, c_mode);
-	if (n_is_inode_locked) {
+	do_balance(&s_cut_balance, NULL, NULL, mode);
+	if (is_inode_locked) {
 		/* we've done an indirect->direct conversion.  when the data block
 		 ** was freed, it was removed from the list of blocks that must
 		 ** be flushed before the transaction commits, make sure to
 		 ** unmap and invalidate it
 		 */
 		unmap_buffers(page, tail_pos);
-		REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask;
+		REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
 	}
 #ifdef REISERQUOTA_DEBUG
-	reiserfs_debug(p_s_inode->i_sb, REISERFS_DEBUG_CODE,
+	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
 		       "reiserquota cut_from_item(): freeing %u id=%u type=%c",
-		       quota_cut_bytes, p_s_inode->i_uid, '?');
+		       quota_cut_bytes, inode->i_uid, '?');
 #endif
-	vfs_dq_free_space_nodirty(p_s_inode, quota_cut_bytes);
-	return n_ret_value;
+	vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
+	return ret_value;
 }
 
 static void truncate_directory(struct reiserfs_transaction_handle *th,
@@ -1743,8 +1705,7 @@
 {
 	BUG_ON(!th->t_trans_id);
 	if (inode->i_nlink)
-		reiserfs_warning(inode->i_sb,
-				 "vs-5655: truncate_directory: link count != 0");
+		reiserfs_error(inode->i_sb, "vs-5655", "link count != 0");
 
 	set_le_key_k_offset(KEY_FORMAT_3_5, INODE_PKEY(inode), DOT_OFFSET);
 	set_le_key_k_type(KEY_FORMAT_3_5, INODE_PKEY(inode), TYPE_DIRENTRY);
@@ -1756,8 +1717,8 @@
 
 /* Truncate file to the new size. Note, this must be called with a transaction
    already started */
-int reiserfs_do_truncate(struct reiserfs_transaction_handle *th, struct inode *p_s_inode,	/* ->i_size contains new
-												   size */
+int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
+			  struct inode *inode,	/* ->i_size contains new size */
 			 struct page *page,	/* up to date for last block */
 			 int update_timestamps	/* when it is called by
 						   file_release to convert
@@ -1768,47 +1729,45 @@
 	INITIALIZE_PATH(s_search_path);	/* Path to the current object item. */
 	struct item_head *p_le_ih;	/* Pointer to an item header. */
 	struct cpu_key s_item_key;	/* Key to search for a previous file item. */
-	loff_t n_file_size,	/* Old file size. */
-	 n_new_file_size;	/* New file size. */
-	int n_deleted;		/* Number of deleted or truncated bytes. */
+	loff_t file_size,	/* Old file size. */
+	 new_file_size;	/* New file size. */
+	int deleted;		/* Number of deleted or truncated bytes. */
 	int retval;
 	int err = 0;
 
 	BUG_ON(!th->t_trans_id);
 	if (!
-	    (S_ISREG(p_s_inode->i_mode) || S_ISDIR(p_s_inode->i_mode)
-	     || S_ISLNK(p_s_inode->i_mode)))
+	    (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
+	     || S_ISLNK(inode->i_mode)))
 		return 0;
 
-	if (S_ISDIR(p_s_inode->i_mode)) {
+	if (S_ISDIR(inode->i_mode)) {
 		// deletion of directory - no need to update timestamps
-		truncate_directory(th, p_s_inode);
+		truncate_directory(th, inode);
 		return 0;
 	}
 
 	/* Get new file size. */
-	n_new_file_size = p_s_inode->i_size;
+	new_file_size = inode->i_size;
 
 	// FIXME: note, that key type is unimportant here
-	make_cpu_key(&s_item_key, p_s_inode, max_reiserfs_offset(p_s_inode),
+	make_cpu_key(&s_item_key, inode, max_reiserfs_offset(inode),
 		     TYPE_DIRECT, 3);
 
 	retval =
-	    search_for_position_by_key(p_s_inode->i_sb, &s_item_key,
+	    search_for_position_by_key(inode->i_sb, &s_item_key,
 				       &s_search_path);
 	if (retval == IO_ERROR) {
-		reiserfs_warning(p_s_inode->i_sb,
-				 "vs-5657: reiserfs_do_truncate: "
-				 "i/o failure occurred trying to truncate %K",
-				 &s_item_key);
+		reiserfs_error(inode->i_sb, "vs-5657",
+			       "i/o failure occurred trying to truncate %K",
+			       &s_item_key);
 		err = -EIO;
 		goto out;
 	}
 	if (retval == POSITION_FOUND || retval == FILE_NOT_FOUND) {
-		reiserfs_warning(p_s_inode->i_sb,
-				 "PAP-5660: reiserfs_do_truncate: "
-				 "wrong result %d of search for %K", retval,
-				 &s_item_key);
+		reiserfs_error(inode->i_sb, "PAP-5660",
+			       "wrong result %d of search for %K", retval,
+			       &s_item_key);
 
 		err = -EIO;
 		goto out;
@@ -1819,56 +1778,56 @@
 	/* Get real file size (total length of all file items) */
 	p_le_ih = PATH_PITEM_HEAD(&s_search_path);
 	if (is_statdata_le_ih(p_le_ih))
-		n_file_size = 0;
+		file_size = 0;
 	else {
 		loff_t offset = le_ih_k_offset(p_le_ih);
 		int bytes =
-		    op_bytes_number(p_le_ih, p_s_inode->i_sb->s_blocksize);
+		    op_bytes_number(p_le_ih, inode->i_sb->s_blocksize);
 
 		/* this may mismatch with real file size: if last direct item
 		   had no padding zeros and last unformatted node had no free
 		   space, this file would have this file size */
-		n_file_size = offset + bytes - 1;
+		file_size = offset + bytes - 1;
 	}
 	/*
 	 * are we doing a full truncate or delete, if so
 	 * kick in the reada code
 	 */
-	if (n_new_file_size == 0)
+	if (new_file_size == 0)
 		s_search_path.reada = PATH_READA | PATH_READA_BACK;
 
-	if (n_file_size == 0 || n_file_size < n_new_file_size) {
+	if (file_size == 0 || file_size < new_file_size) {
 		goto update_and_out;
 	}
 
 	/* Update key to search for the last file item. */
-	set_cpu_key_k_offset(&s_item_key, n_file_size);
+	set_cpu_key_k_offset(&s_item_key, file_size);
 
 	do {
 		/* Cut or delete file item. */
-		n_deleted =
+		deleted =
 		    reiserfs_cut_from_item(th, &s_search_path, &s_item_key,
-					   p_s_inode, page, n_new_file_size);
-		if (n_deleted < 0) {
-			reiserfs_warning(p_s_inode->i_sb,
-					 "vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed");
+					   inode, page, new_file_size);
+		if (deleted < 0) {
+			reiserfs_warning(inode->i_sb, "vs-5665",
+					 "reiserfs_cut_from_item failed");
 			reiserfs_check_path(&s_search_path);
 			return 0;
 		}
 
-		RFALSE(n_deleted > n_file_size,
+		RFALSE(deleted > file_size,
 		       "PAP-5670: reiserfs_cut_from_item: too many bytes deleted: deleted %d, file_size %lu, item_key %K",
-		       n_deleted, n_file_size, &s_item_key);
+		       deleted, file_size, &s_item_key);
 
 		/* Change key to search the last file item. */
-		n_file_size -= n_deleted;
+		file_size -= deleted;
 
-		set_cpu_key_k_offset(&s_item_key, n_file_size);
+		set_cpu_key_k_offset(&s_item_key, file_size);
 
 		/* While there are bytes to truncate and previous file item is presented in the tree. */
 
 		/*
-		 ** This loop could take a really long time, and could log 
+		 ** This loop could take a really long time, and could log
 		 ** many more blocks than a transaction can hold.  So, we do a polite
 		 ** journal end here, and if the transaction needs ending, we make
 		 ** sure the file is consistent before ending the current trans
@@ -1877,37 +1836,38 @@
 		if (journal_transaction_should_end(th, 0) ||
 		    reiserfs_transaction_free_space(th) <= JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD) {
 			int orig_len_alloc = th->t_blocks_allocated;
-			decrement_counters_in_path(&s_search_path);
+			pathrelse(&s_search_path);
 
 			if (update_timestamps) {
-				p_s_inode->i_mtime = p_s_inode->i_ctime =
-				    CURRENT_TIME_SEC;
+				inode->i_mtime = CURRENT_TIME_SEC;
+				inode->i_ctime = CURRENT_TIME_SEC;
 			}
-			reiserfs_update_sd(th, p_s_inode);
+			reiserfs_update_sd(th, inode);
 
-			err = journal_end(th, p_s_inode->i_sb, orig_len_alloc);
+			err = journal_end(th, inode->i_sb, orig_len_alloc);
 			if (err)
 				goto out;
-			err = journal_begin(th, p_s_inode->i_sb,
+			err = journal_begin(th, inode->i_sb,
 					    JOURNAL_FOR_FREE_BLOCK_AND_UPDATE_SD + JOURNAL_PER_BALANCE_CNT * 4) ;
 			if (err)
 				goto out;
-			reiserfs_update_inode_transaction(p_s_inode);
+			reiserfs_update_inode_transaction(inode);
 		}
-	} while (n_file_size > ROUND_UP(n_new_file_size) &&
-		 search_for_position_by_key(p_s_inode->i_sb, &s_item_key,
+	} while (file_size > ROUND_UP(new_file_size) &&
+		 search_for_position_by_key(inode->i_sb, &s_item_key,
 					    &s_search_path) == POSITION_FOUND);
 
-	RFALSE(n_file_size > ROUND_UP(n_new_file_size),
+	RFALSE(file_size > ROUND_UP(new_file_size),
 	       "PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d",
-	       n_new_file_size, n_file_size, s_item_key.on_disk_key.k_objectid);
+	       new_file_size, file_size, s_item_key.on_disk_key.k_objectid);
 
       update_and_out:
 	if (update_timestamps) {
 		// this is truncate, not file closing
-		p_s_inode->i_mtime = p_s_inode->i_ctime = CURRENT_TIME_SEC;
+		inode->i_mtime = CURRENT_TIME_SEC;
+		inode->i_ctime = CURRENT_TIME_SEC;
 	}
-	reiserfs_update_sd(th, p_s_inode);
+	reiserfs_update_sd(th, inode);
 
       out:
 	pathrelse(&s_search_path);
@@ -1917,7 +1877,7 @@
 #ifdef CONFIG_REISERFS_CHECK
 // this makes sure, that we __append__, not overwrite or add holes
 static void check_research_for_paste(struct treepath *path,
-				     const struct cpu_key *p_s_key)
+				     const struct cpu_key *key)
 {
 	struct item_head *found_ih = get_ih(path);
 
@@ -1925,36 +1885,36 @@
 		if (le_ih_k_offset(found_ih) +
 		    op_bytes_number(found_ih,
 				    get_last_bh(path)->b_size) !=
-		    cpu_key_k_offset(p_s_key)
+		    cpu_key_k_offset(key)
 		    || op_bytes_number(found_ih,
 				       get_last_bh(path)->b_size) !=
 		    pos_in_item(path))
-			reiserfs_panic(NULL,
-				       "PAP-5720: check_research_for_paste: "
-				       "found direct item %h or position (%d) does not match to key %K",
-				       found_ih, pos_in_item(path), p_s_key);
+			reiserfs_panic(NULL, "PAP-5720", "found direct item "
+				       "%h or position (%d) does not match "
+				       "to key %K", found_ih,
+				       pos_in_item(path), key);
 	}
 	if (is_indirect_le_ih(found_ih)) {
 		if (le_ih_k_offset(found_ih) +
 		    op_bytes_number(found_ih,
 				    get_last_bh(path)->b_size) !=
-		    cpu_key_k_offset(p_s_key)
+		    cpu_key_k_offset(key)
 		    || I_UNFM_NUM(found_ih) != pos_in_item(path)
 		    || get_ih_free_space(found_ih) != 0)
-			reiserfs_panic(NULL,
-				       "PAP-5730: check_research_for_paste: "
-				       "found indirect item (%h) or position (%d) does not match to key (%K)",
-				       found_ih, pos_in_item(path), p_s_key);
+			reiserfs_panic(NULL, "PAP-5730", "found indirect "
+				       "item (%h) or position (%d) does not "
+				       "match to key (%K)",
+				       found_ih, pos_in_item(path), key);
 	}
 }
 #endif				/* config reiserfs check */
 
 /* Paste bytes to the existing item. Returns bytes number pasted into the item. */
-int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_search_path,	/* Path to the pasted item.          */
-			     const struct cpu_key *p_s_key,	/* Key to search for the needed item. */
+int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct treepath *search_path,	/* Path to the pasted item.	  */
+			     const struct cpu_key *key,	/* Key to search for the needed item. */
 			     struct inode *inode,	/* Inode item belongs to */
-			     const char *p_c_body,	/* Pointer to the bytes to paste.    */
-			     int n_pasted_size)
+			     const char *body,	/* Pointer to the bytes to paste.    */
+			     int pasted_size)
 {				/* Size of pasted bytes.             */
 	struct tree_balance s_paste_balance;
 	int retval;
@@ -1967,18 +1927,18 @@
 #ifdef REISERQUOTA_DEBUG
 	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
 		       "reiserquota paste_into_item(): allocating %u id=%u type=%c",
-		       n_pasted_size, inode->i_uid,
-		       key2type(&(p_s_key->on_disk_key)));
+		       pasted_size, inode->i_uid,
+		       key2type(&(key->on_disk_key)));
 #endif
 
-	if (vfs_dq_alloc_space_nodirty(inode, n_pasted_size)) {
-		pathrelse(p_s_search_path);
+	if (vfs_dq_alloc_space_nodirty(inode, pasted_size)) {
+		pathrelse(search_path);
 		return -EDQUOT;
 	}
-	init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path,
-		       n_pasted_size);
+	init_tb_struct(th, &s_paste_balance, th->t_super, search_path,
+		       pasted_size);
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
-	s_paste_balance.key = p_s_key->on_disk_key;
+	s_paste_balance.key = key->on_disk_key;
 #endif
 
 	/* DQUOT_* can schedule, must check before the fix_nodes */
@@ -1988,33 +1948,33 @@
 
 	while ((retval =
 		fix_nodes(M_PASTE, &s_paste_balance, NULL,
-			  p_c_body)) == REPEAT_SEARCH) {
+			  body)) == REPEAT_SEARCH) {
 	      search_again:
 		/* file system changed while we were in the fix_nodes */
 		PROC_INFO_INC(th->t_super, paste_into_item_restarted);
 		retval =
-		    search_for_position_by_key(th->t_super, p_s_key,
-					       p_s_search_path);
+		    search_for_position_by_key(th->t_super, key,
+					       search_path);
 		if (retval == IO_ERROR) {
 			retval = -EIO;
 			goto error_out;
 		}
 		if (retval == POSITION_FOUND) {
-			reiserfs_warning(inode->i_sb,
-					 "PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists",
-					 p_s_key);
+			reiserfs_warning(inode->i_sb, "PAP-5710",
+					 "entry or pasted byte (%K) exists",
+					 key);
 			retval = -EEXIST;
 			goto error_out;
 		}
 #ifdef CONFIG_REISERFS_CHECK
-		check_research_for_paste(p_s_search_path, p_s_key);
+		check_research_for_paste(search_path, key);
 #endif
 	}
 
 	/* Perform balancing after all resources are collected by fix_nodes, and
 	   accessing them will not risk triggering schedule. */
 	if (retval == CARRY_ON) {
-		do_balance(&s_paste_balance, NULL /*ih */ , p_c_body, M_PASTE);
+		do_balance(&s_paste_balance, NULL /*ih */ , body, M_PASTE);
 		return 0;
 	}
 	retval = (retval == NO_DISK_SPACE) ? -ENOSPC : -EIO;
@@ -2024,18 +1984,24 @@
 #ifdef REISERQUOTA_DEBUG
 	reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
 		       "reiserquota paste_into_item(): freeing %u id=%u type=%c",
-		       n_pasted_size, inode->i_uid,
-		       key2type(&(p_s_key->on_disk_key)));
+		       pasted_size, inode->i_uid,
+		       key2type(&(key->on_disk_key)));
 #endif
-	vfs_dq_free_space_nodirty(inode, n_pasted_size);
+	vfs_dq_free_space_nodirty(inode, pasted_size);
 	return retval;
 }
 
-/* Insert new item into the buffer at the path. */
-int reiserfs_insert_item(struct reiserfs_transaction_handle *th, struct treepath *p_s_path,	/* Path to the inserteded item.         */
-			 const struct cpu_key *key, struct item_head *p_s_ih,	/* Pointer to the item header to insert. */
-			 struct inode *inode, const char *p_c_body)
-{				/* Pointer to the bytes to insert.      */
+/* Insert new item into the buffer at the path.
+ * th   - active transaction handle
+ * path - path to the inserted item
+ * ih   - pointer to the item header to insert
+ * body - pointer to the bytes to insert
+ */
+int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
+			 struct treepath *path, const struct cpu_key *key,
+			 struct item_head *ih, struct inode *inode,
+			 const char *body)
+{
 	struct tree_balance s_ins_balance;
 	int retval;
 	int fs_gen = 0;
@@ -2045,28 +2011,27 @@
 
 	if (inode) {		/* Do we count quotas for item? */
 		fs_gen = get_generation(inode->i_sb);
-		quota_bytes = ih_item_len(p_s_ih);
+		quota_bytes = ih_item_len(ih);
 
 		/* hack so the quota code doesn't have to guess if the file has
 		 ** a tail, links are always tails, so there's no guessing needed
 		 */
-		if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(p_s_ih)) {
+		if (!S_ISLNK(inode->i_mode) && is_direct_le_ih(ih))
 			quota_bytes = inode->i_sb->s_blocksize + UNFM_P_SIZE;
-		}
 #ifdef REISERQUOTA_DEBUG
 		reiserfs_debug(inode->i_sb, REISERFS_DEBUG_CODE,
 			       "reiserquota insert_item(): allocating %u id=%u type=%c",
-			       quota_bytes, inode->i_uid, head2type(p_s_ih));
+			       quota_bytes, inode->i_uid, head2type(ih));
 #endif
 		/* We can't dirty inode here. It would be immediately written but
 		 * appropriate stat item isn't inserted yet... */
 		if (vfs_dq_alloc_space_nodirty(inode, quota_bytes)) {
-			pathrelse(p_s_path);
+			pathrelse(path);
 			return -EDQUOT;
 		}
 	}
-	init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path,
-		       IH_SIZE + ih_item_len(p_s_ih));
+	init_tb_struct(th, &s_ins_balance, th->t_super, path,
+		       IH_SIZE + ih_item_len(ih));
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
 	s_ins_balance.key = key->on_disk_key;
 #endif
@@ -2076,19 +2041,18 @@
 	}
 
 	while ((retval =
-		fix_nodes(M_INSERT, &s_ins_balance, p_s_ih,
-			  p_c_body)) == REPEAT_SEARCH) {
+		fix_nodes(M_INSERT, &s_ins_balance, ih,
+			  body)) == REPEAT_SEARCH) {
 	      search_again:
 		/* file system changed while we were in the fix_nodes */
 		PROC_INFO_INC(th->t_super, insert_item_restarted);
-		retval = search_item(th->t_super, key, p_s_path);
+		retval = search_item(th->t_super, key, path);
 		if (retval == IO_ERROR) {
 			retval = -EIO;
 			goto error_out;
 		}
 		if (retval == ITEM_FOUND) {
-			reiserfs_warning(th->t_super,
-					 "PAP-5760: reiserfs_insert_item: "
+			reiserfs_warning(th->t_super, "PAP-5760",
 					 "key %K already exists in the tree",
 					 key);
 			retval = -EEXIST;
@@ -2098,7 +2062,7 @@
 
 	/* make balancing after all resources will be collected at a time */
 	if (retval == CARRY_ON) {
-		do_balance(&s_ins_balance, p_s_ih, p_c_body, M_INSERT);
+		do_balance(&s_ins_balance, ih, body, M_INSERT);
 		return 0;
 	}
 
@@ -2109,7 +2073,7 @@
 #ifdef REISERQUOTA_DEBUG
 	reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
 		       "reiserquota insert_item(): freeing %u id=%u type=%c",
-		       quota_bytes, inode->i_uid, head2type(p_s_ih));
+		       quota_bytes, inode->i_uid, head2type(ih));
 #endif
 	if (inode)
 		vfs_dq_free_space_nodirty(inode, quota_bytes);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 5dbafb7..972250c6 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -183,9 +183,9 @@
 		if (REISERFS_SB(s)->s_qf_names[i]) {
 			int ret = reiserfs_quota_on_mount(s, i);
 			if (ret < 0)
-				reiserfs_warning(s,
-						 "reiserfs: cannot turn on journaled quota: error %d",
-						 ret);
+				reiserfs_warning(s, "reiserfs-2500",
+						 "cannot turn on journaled "
+						 "quota: error %d", ret);
 		}
 	}
 #endif
@@ -195,17 +195,16 @@
 	while (!retval) {
 		retval = search_item(s, &max_cpu_key, &path);
 		if (retval != ITEM_NOT_FOUND) {
-			reiserfs_warning(s,
-					 "vs-2140: finish_unfinished: search_by_key returned %d",
-					 retval);
+			reiserfs_error(s, "vs-2140",
+				       "search_by_key returned %d", retval);
 			break;
 		}
 
 		bh = get_last_bh(&path);
 		item_pos = get_item_pos(&path);
 		if (item_pos != B_NR_ITEMS(bh)) {
-			reiserfs_warning(s,
-					 "vs-2060: finish_unfinished: wrong position found");
+			reiserfs_warning(s, "vs-2060",
+					 "wrong position found");
 			break;
 		}
 		item_pos--;
@@ -235,8 +234,7 @@
 		if (!inode) {
 			/* the unlink almost completed, it just did not manage to remove
 			   "save" link and release objectid */
-			reiserfs_warning(s,
-					 "vs-2180: finish_unfinished: iget failed for %K",
+			reiserfs_warning(s, "vs-2180", "iget failed for %K",
 					 &obj_key);
 			retval = remove_save_link_only(s, &save_link_key, 1);
 			continue;
@@ -244,8 +242,8 @@
 
 		if (!truncate && inode->i_nlink) {
 			/* file is not unlinked */
-			reiserfs_warning(s,
-					 "vs-2185: finish_unfinished: file %K is not unlinked",
+			reiserfs_warning(s, "vs-2185",
+					 "file %K is not unlinked",
 					 &obj_key);
 			retval = remove_save_link_only(s, &save_link_key, 0);
 			continue;
@@ -257,8 +255,9 @@
 			   The only imaginable way is to execute unfinished truncate request
 			   then boot into old kernel, remove the file and create dir with
 			   the same key. */
-			reiserfs_warning(s,
-					 "green-2101: impossible truncate on a directory %k. Please report",
+			reiserfs_warning(s, "green-2101",
+					 "impossible truncate on a "
+					 "directory %k. Please report",
 					 INODE_PKEY(inode));
 			retval = remove_save_link_only(s, &save_link_key, 0);
 			truncate = 0;
@@ -288,9 +287,10 @@
 				/* removal gets completed in iput */
 				retval = 0;
 			} else {
-				reiserfs_warning(s, "Dead loop in "
-						"finish_unfinished detected, "
-						"just remove save link\n");
+				reiserfs_warning(s, "super-2189", "Dead loop "
+						 "in finish_unfinished "
+						 "detected, just remove "
+						 "save link\n");
 				retval = remove_save_link_only(s,
 							&save_link_key, 0);
 			}
@@ -360,8 +360,9 @@
 	} else {
 		/* truncate */
 		if (S_ISDIR(inode->i_mode))
-			reiserfs_warning(inode->i_sb,
-					 "green-2102: Adding a truncate savelink for a directory %k! Please report",
+			reiserfs_warning(inode->i_sb, "green-2102",
+					 "Adding a truncate savelink for "
+					 "a directory %k! Please report",
 					 INODE_PKEY(inode));
 		set_cpu_key_k_offset(&key, 1);
 		set_cpu_key_k_type(&key, TYPE_INDIRECT);
@@ -376,9 +377,9 @@
 	retval = search_item(inode->i_sb, &key, &path);
 	if (retval != ITEM_NOT_FOUND) {
 		if (retval != -ENOSPC)
-			reiserfs_warning(inode->i_sb, "vs-2100: add_save_link:"
-					 "search_by_key (%K) returned %d", &key,
-					 retval);
+			reiserfs_error(inode->i_sb, "vs-2100",
+				       "search_by_key (%K) returned %d", &key,
+				       retval);
 		pathrelse(&path);
 		return;
 	}
@@ -391,9 +392,8 @@
 	    reiserfs_insert_item(th, &path, &key, &ih, NULL, (char *)&link);
 	if (retval) {
 		if (retval != -ENOSPC)
-			reiserfs_warning(inode->i_sb,
-					 "vs-2120: add_save_link: insert_item returned %d",
-					 retval);
+			reiserfs_error(inode->i_sb, "vs-2120",
+				       "insert_item returned %d", retval);
 	} else {
 		if (truncate)
 			REISERFS_I(inode)->i_flags |=
@@ -492,8 +492,7 @@
 	print_statistics(s);
 
 	if (REISERFS_SB(s)->reserved_blocks != 0) {
-		reiserfs_warning(s,
-				 "green-2005: reiserfs_put_super: reserved blocks left %d",
+		reiserfs_warning(s, "green-2005", "reserved blocks left %d",
 				 REISERFS_SB(s)->reserved_blocks);
 	}
 
@@ -559,8 +558,8 @@
 
 	int err = 0;
 	if (inode->i_sb->s_flags & MS_RDONLY) {
-		reiserfs_warning(inode->i_sb,
-				 "clm-6006: writing inode %lu on readonly FS",
+		reiserfs_warning(inode->i_sb, "clm-6006",
+				 "writing inode %lu on readonly FS",
 				 inode->i_ino);
 		return;
 	}
@@ -757,7 +756,7 @@
 			   char **opt_arg, unsigned long *bit_flags)
 {
 	char *p;
-	/* foo=bar, 
+	/* foo=bar,
 	   ^   ^  ^
 	   |   |  +-- option_end
 	   |   +-- arg_start
@@ -792,13 +791,15 @@
 			if (bit_flags) {
 				if (opt->clrmask ==
 				    (1 << REISERFS_UNSUPPORTED_OPT))
-					reiserfs_warning(s, "%s not supported.",
+					reiserfs_warning(s, "super-6500",
+							 "%s not supported.\n",
 							 p);
 				else
 					*bit_flags &= ~opt->clrmask;
 				if (opt->setmask ==
 				    (1 << REISERFS_UNSUPPORTED_OPT))
-					reiserfs_warning(s, "%s not supported.",
+					reiserfs_warning(s, "super-6501",
+							 "%s not supported.\n",
 							 p);
 				else
 					*bit_flags |= opt->setmask;
@@ -807,7 +808,8 @@
 		}
 	}
 	if (!opt->option_name) {
-		reiserfs_warning(s, "unknown mount option \"%s\"", p);
+		reiserfs_warning(s, "super-6502",
+				 "unknown mount option \"%s\"", p);
 		return -1;
 	}
 
@@ -815,8 +817,9 @@
 	switch (*p) {
 	case '=':
 		if (!opt->arg_required) {
-			reiserfs_warning(s,
-					 "the option \"%s\" does not require an argument",
+			reiserfs_warning(s, "super-6503",
+					 "the option \"%s\" does not "
+					 "require an argument\n",
 					 opt->option_name);
 			return -1;
 		}
@@ -824,14 +827,15 @@
 
 	case 0:
 		if (opt->arg_required) {
-			reiserfs_warning(s,
-					 "the option \"%s\" requires an argument",
-					 opt->option_name);
+			reiserfs_warning(s, "super-6504",
+					 "the option \"%s\" requires an "
+					 "argument\n", opt->option_name);
 			return -1;
 		}
 		break;
 	default:
-		reiserfs_warning(s, "head of option \"%s\" is only correct",
+		reiserfs_warning(s, "super-6505",
+				 "head of option \"%s\" is only correct\n",
 				 opt->option_name);
 		return -1;
 	}
@@ -843,7 +847,8 @@
 	    && !(opt->arg_required & (1 << REISERFS_OPT_ALLOWEMPTY))
 	    && !strlen(p)) {
 		/* this catches "option=," if not allowed */
-		reiserfs_warning(s, "empty argument for \"%s\"",
+		reiserfs_warning(s, "super-6506",
+				 "empty argument for \"%s\"\n",
 				 opt->option_name);
 		return -1;
 	}
@@ -865,7 +870,8 @@
 		}
 	}
 
-	reiserfs_warning(s, "bad value \"%s\" for option \"%s\"", p,
+	reiserfs_warning(s, "super-6506",
+			 "bad value \"%s\" for option \"%s\"\n", p,
 			 opt->option_name);
 	return -1;
 }
@@ -955,9 +961,9 @@
 				*blocks = simple_strtoul(arg, &p, 0);
 				if (*p != '\0') {
 					/* NNN does not look like a number */
-					reiserfs_warning(s,
-							 "reiserfs_parse_options: bad value %s",
-							 arg);
+					reiserfs_warning(s, "super-6507",
+							 "bad value %s for "
+							 "-oresize\n", arg);
 					return 0;
 				}
 			}
@@ -968,8 +974,8 @@
 			unsigned long val = simple_strtoul(arg, &p, 0);
 			/* commit=NNN (time in seconds) */
 			if (*p != '\0' || val >= (unsigned int)-1) {
-				reiserfs_warning(s,
-						 "reiserfs_parse_options: bad value %s",
+				reiserfs_warning(s, "super-6508",
+						 "bad value %s for -ocommit\n",
 						 arg);
 				return 0;
 			}
@@ -977,16 +983,18 @@
 		}
 
 		if (c == 'w') {
-			reiserfs_warning(s, "reiserfs: nolargeio option is no longer supported");
+			reiserfs_warning(s, "super-6509", "nolargeio option "
+					 "is no longer supported");
 			return 0;
 		}
 
 		if (c == 'j') {
 			if (arg && *arg && jdev_name) {
 				if (*jdev_name) {	//Hm, already assigned?
-					reiserfs_warning(s,
-							 "reiserfs_parse_options: journal device was already  specified to be %s",
-							 *jdev_name);
+					reiserfs_warning(s, "super-6510",
+							 "journal device was "
+							 "already specified to "
+							 "be %s", *jdev_name);
 					return 0;
 				}
 				*jdev_name = arg;
@@ -998,29 +1006,35 @@
 
 			if (sb_any_quota_loaded(s) &&
 			    (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
-				reiserfs_warning(s,
-						 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
+				reiserfs_warning(s, "super-6511",
+						 "cannot change journaled "
+						 "quota options when quota "
+						 "turned on.");
 				return 0;
 			}
 			if (*arg) {	/* Some filename specified? */
 				if (REISERFS_SB(s)->s_qf_names[qtype]
 				    && strcmp(REISERFS_SB(s)->s_qf_names[qtype],
 					      arg)) {
-					reiserfs_warning(s,
-							 "reiserfs_parse_options: %s quota file already specified.",
+					reiserfs_warning(s, "super-6512",
+							 "%s quota file "
+							 "already specified.",
 							 QTYPE2NAME(qtype));
 					return 0;
 				}
 				if (strchr(arg, '/')) {
-					reiserfs_warning(s,
-							 "reiserfs_parse_options: quotafile must be on filesystem root.");
+					reiserfs_warning(s, "super-6513",
+							 "quotafile must be "
+							 "on filesystem root.");
 					return 0;
 				}
 				qf_names[qtype] =
 				    kmalloc(strlen(arg) + 1, GFP_KERNEL);
 				if (!qf_names[qtype]) {
-					reiserfs_warning(s,
-							 "reiserfs_parse_options: not enough memory for storing quotafile name.");
+					reiserfs_warning(s, "reiserfs-2502",
+							 "not enough memory "
+							 "for storing "
+							 "quotafile name.");
 					return 0;
 				}
 				strcpy(qf_names[qtype], arg);
@@ -1038,21 +1052,24 @@
 			else if (!strcmp(arg, "vfsv0"))
 				*qfmt = QFMT_VFS_V0;
 			else {
-				reiserfs_warning(s,
-						 "reiserfs_parse_options: unknown quota format specified.");
+				reiserfs_warning(s, "super-6514",
+						 "unknown quota format "
+						 "specified.");
 				return 0;
 			}
 			if (sb_any_quota_loaded(s) &&
 			    *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
-				reiserfs_warning(s,
-						 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
+				reiserfs_warning(s, "super-6515",
+						 "cannot change journaled "
+						 "quota options when quota "
+						 "turned on.");
 				return 0;
 			}
 		}
 #else
 		if (c == 'u' || c == 'g' || c == 'f') {
-			reiserfs_warning(s,
-					 "reiserfs_parse_options: journaled quota options not supported.");
+			reiserfs_warning(s, "reiserfs-2503", "journaled "
+					 "quota options not supported.");
 			return 0;
 		}
 #endif
@@ -1061,15 +1078,15 @@
 #ifdef CONFIG_QUOTA
 	if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
 	    && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
-		reiserfs_warning(s,
-				 "reiserfs_parse_options: journaled quota format not specified.");
+		reiserfs_warning(s, "super-6515",
+				 "journaled quota format not specified.");
 		return 0;
 	}
 	/* This checking is not precise wrt the quota type but for our purposes it is sufficient */
 	if (!(*mount_options & (1 << REISERFS_QUOTA))
 	    && sb_any_quota_loaded(s)) {
-		reiserfs_warning(s,
-				 "reiserfs_parse_options: quota options must be present when quota is turned on.");
+		reiserfs_warning(s, "super-6516", "quota options must "
+				 "be present when quota is turned on.");
 		return 0;
 	}
 #endif
@@ -1129,14 +1146,15 @@
 
 	if (reiserfs_attrs(s)) {
 		if (old_format_only(s)) {
-			reiserfs_warning(s,
-					 "reiserfs: cannot support attributes on 3.5.x disk format");
+			reiserfs_warning(s, "super-6517", "cannot support "
+					 "attributes on 3.5.x disk format");
 			REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
 			return;
 		}
 		if (!(le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared)) {
-			reiserfs_warning(s,
-					 "reiserfs: cannot support attributes until flag is set in super-block");
+			reiserfs_warning(s, "super-6518", "cannot support "
+					 "attributes until flag is set in "
+					 "super-block");
 			REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
 		}
 	}
@@ -1278,6 +1296,8 @@
 		REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
 		s->s_flags &= ~MS_RDONLY;
 		set_sb_umount_state(rs, REISERFS_ERROR_FS);
+		if (!old_format_only(s))
+			set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
 		/* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
 		journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
 		REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS;
@@ -1312,7 +1332,7 @@
 
 	bh = sb_bread(s, offset / s->s_blocksize);
 	if (!bh) {
-		reiserfs_warning(s, "sh-2006: read_super_block: "
+		reiserfs_warning(s, "sh-2006",
 				 "bread failed (dev %s, block %lu, size %lu)",
 				 reiserfs_bdevname(s), offset / s->s_blocksize,
 				 s->s_blocksize);
@@ -1326,15 +1346,15 @@
 	}
 	//
 	// ok, reiserfs signature (old or new) found in at the given offset
-	//    
+	//
 	fs_blocksize = sb_blocksize(rs);
 	brelse(bh);
 	sb_set_blocksize(s, fs_blocksize);
 
 	bh = sb_bread(s, offset / s->s_blocksize);
 	if (!bh) {
-		reiserfs_warning(s, "sh-2007: read_super_block: "
-				 "bread failed (dev %s, block %lu, size %lu)\n",
+		reiserfs_warning(s, "sh-2007",
+				 "bread failed (dev %s, block %lu, size %lu)",
 				 reiserfs_bdevname(s), offset / s->s_blocksize,
 				 s->s_blocksize);
 		return 1;
@@ -1342,8 +1362,8 @@
 
 	rs = (struct reiserfs_super_block *)bh->b_data;
 	if (sb_blocksize(rs) != s->s_blocksize) {
-		reiserfs_warning(s, "sh-2011: read_super_block: "
-				 "can't find a reiserfs filesystem on (dev %s, block %Lu, size %lu)\n",
+		reiserfs_warning(s, "sh-2011", "can't find a reiserfs "
+				 "filesystem on (dev %s, block %Lu, size %lu)",
 				 reiserfs_bdevname(s),
 				 (unsigned long long)bh->b_blocknr,
 				 s->s_blocksize);
@@ -1353,9 +1373,10 @@
 
 	if (rs->s_v1.s_root_block == cpu_to_le32(-1)) {
 		brelse(bh);
-		reiserfs_warning(s,
-				 "Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
-				 "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
+		reiserfs_warning(s, "super-6519", "Unfinished reiserfsck "
+				 "--rebuild-tree run detected. Please run\n"
+				 "reiserfsck --rebuild-tree and wait for a "
+				 "completion. If that fails\n"
 				 "get newer reiserfsprogs package");
 		return 1;
 	}
@@ -1367,18 +1388,15 @@
 		/* magic is of non-standard journal filesystem, look at s_version to
 		   find which format is in use */
 		if (sb_version(rs) == REISERFS_VERSION_2)
-			reiserfs_warning(s,
-					 "read_super_block: found reiserfs format \"3.6\""
-					 " with non-standard journal");
+			reiserfs_info(s, "found reiserfs format \"3.6\""
+				      " with non-standard journal\n");
 		else if (sb_version(rs) == REISERFS_VERSION_1)
-			reiserfs_warning(s,
-					 "read_super_block: found reiserfs format \"3.5\""
-					 " with non-standard journal");
+			reiserfs_info(s, "found reiserfs format \"3.5\""
+				      " with non-standard journal\n");
 		else {
-			reiserfs_warning(s,
-					 "sh-2012: read_super_block: found unknown "
-					 "format \"%u\" of reiserfs with non-standard magic",
-					 sb_version(rs));
+			reiserfs_warning(s, "sh-2012", "found unknown "
+					 "format \"%u\" of reiserfs with "
+					 "non-standard magic", sb_version(rs));
 			return 1;
 		}
 	} else
@@ -1408,8 +1426,7 @@
 	ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
 	wait_on_buffer(SB_BUFFER_WITH_SB(s));
 	if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
-		reiserfs_warning(s,
-				 "reread_meta_blocks, error reading the super");
+		reiserfs_warning(s, "reiserfs-2504", "error reading the super");
 		return 1;
 	}
 
@@ -1452,8 +1469,8 @@
 			if (reiserfs_rupasov_hash(s)) {
 				hash = YURA_HASH;
 			}
-			reiserfs_warning(s, "FS seems to be empty, autodetect "
-					 "is using the default hash");
+			reiserfs_info(s, "FS seems to be empty, autodetect "
+					 "is using the default hash\n");
 			break;
 		}
 		r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen));
@@ -1473,10 +1490,10 @@
 			&& (yurahash ==
 			    GET_HASH_VALUE(deh_offset
 					   (&(de.de_deh[de.de_entry_num])))))) {
-			reiserfs_warning(s,
-					 "Unable to automatically detect hash function. "
-					 "Please mount with -o hash={tea,rupasov,r5}",
-					 reiserfs_bdevname(s));
+			reiserfs_warning(s, "reiserfs-2506", "Unable to "
+					 "automatically detect hash function. "
+					 "Please mount with -o "
+					 "hash={tea,rupasov,r5}");
 			hash = UNSET_HASH;
 			break;
 		}
@@ -1490,7 +1507,8 @@
 			 (deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash)
 			hash = R5_HASH;
 		else {
-			reiserfs_warning(s, "Unrecognised hash function");
+			reiserfs_warning(s, "reiserfs-2506",
+					 "Unrecognised hash function");
 			hash = UNSET_HASH;
 		}
 	} while (0);
@@ -1514,21 +1532,24 @@
 		code = find_hash_out(s);
 
 	if (code != UNSET_HASH && reiserfs_hash_detect(s)) {
-		/* detection has found the hash, and we must check against the 
-		 ** mount options 
+		/* detection has found the hash, and we must check against the
+		 ** mount options
 		 */
 		if (reiserfs_rupasov_hash(s) && code != YURA_HASH) {
-			reiserfs_warning(s, "Error, %s hash detected, "
+			reiserfs_warning(s, "reiserfs-2507",
+					 "Error, %s hash detected, "
 					 "unable to force rupasov hash",
 					 reiserfs_hashname(code));
 			code = UNSET_HASH;
 		} else if (reiserfs_tea_hash(s) && code != TEA_HASH) {
-			reiserfs_warning(s, "Error, %s hash detected, "
+			reiserfs_warning(s, "reiserfs-2508",
+					 "Error, %s hash detected, "
 					 "unable to force tea hash",
 					 reiserfs_hashname(code));
 			code = UNSET_HASH;
 		} else if (reiserfs_r5_hash(s) && code != R5_HASH) {
-			reiserfs_warning(s, "Error, %s hash detected, "
+			reiserfs_warning(s, "reiserfs-2509",
+					 "Error, %s hash detected, "
 					 "unable to force r5 hash",
 					 reiserfs_hashname(code));
 			code = UNSET_HASH;
@@ -1544,7 +1565,7 @@
 		}
 	}
 
-	/* if we are mounted RW, and we have a new valid hash code, update 
+	/* if we are mounted RW, and we have a new valid hash code, update
 	 ** the super
 	 */
 	if (code != UNSET_HASH &&
@@ -1587,9 +1608,9 @@
 	return 0;
 }
 
-#define SWARN(silent, s, ...)			\
+#define SWARN(silent, s, id, ...)			\
 	if (!(silent))				\
-		reiserfs_warning (s, __VA_ARGS__)
+		reiserfs_warning(s, id, __VA_ARGS__)
 
 static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 {
@@ -1623,10 +1644,6 @@
 	REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
 	/* Preallocate by 16 blocks (17-1) at once */
 	REISERFS_SB(s)->s_alloc_options.preallocsize = 17;
-#ifdef CONFIG_REISERFS_FS_XATTR
-	/* Initialize the rwsem for xattr dir */
-	init_rwsem(&REISERFS_SB(s)->xattr_dir_sem);
-#endif
 	/* setup default block allocator options */
 	reiserfs_init_alloc_options(s);
 
@@ -1641,8 +1658,7 @@
 #endif
 
 	if (blocks) {
-		SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
-		      "for remount only");
+		SWARN(silent, s, "jmacd-7", "resize option for remount only");
 		goto error;
 	}
 
@@ -1651,8 +1667,7 @@
 		old_format = 1;
 	/* try new format (64-th 1k block), which can contain reiserfs super block */
 	else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
-		SWARN(silent, s,
-		      "sh-2021: reiserfs_fill_super: can not find reiserfs on %s",
+		SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
 		      reiserfs_bdevname(s));
 		goto error;
 	}
@@ -1664,13 +1679,12 @@
 	if (s->s_bdev && s->s_bdev->bd_inode
 	    && i_size_read(s->s_bdev->bd_inode) <
 	    sb_block_count(rs) * sb_blocksize(rs)) {
-		SWARN(silent, s,
-		      "Filesystem on %s cannot be mounted because it is bigger than the device",
-		      reiserfs_bdevname(s));
-		SWARN(silent, s,
-		      "You may need to run fsck or increase size of your LVM partition");
-		SWARN(silent, s,
-		      "Or may be you forgot to reboot after fdisk when it told you to");
+		SWARN(silent, s, "", "Filesystem cannot be "
+		      "mounted because it is bigger than the device");
+		SWARN(silent, s, "", "You may need to run fsck "
+		      "or increase size of your LVM partition");
+		SWARN(silent, s, "", "Or may be you forgot to "
+		      "reboot after fdisk when it told you to");
 		goto error;
 	}
 
@@ -1678,14 +1692,13 @@
 	sbi->s_mount_state = REISERFS_VALID_FS;
 
 	if ((errval = reiserfs_init_bitmap_cache(s))) {
-		SWARN(silent, s,
-		      "jmacd-8: reiserfs_fill_super: unable to read bitmap");
+		SWARN(silent, s, "jmacd-8", "unable to read bitmap");
 		goto error;
 	}
 	errval = -EINVAL;
 #ifdef CONFIG_REISERFS_CHECK
-	SWARN(silent, s, "CONFIG_REISERFS_CHECK is set ON");
-	SWARN(silent, s, "- it is slow mode for debugging.");
+	SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON");
+	SWARN(silent, s, "", "- it is slow mode for debugging.");
 #endif
 
 	/* make data=ordered the default */
@@ -1706,8 +1719,8 @@
 	}
 	// set_device_ro(s->s_dev, 1) ;
 	if (journal_init(s, jdev_name, old_format, commit_max_age)) {
-		SWARN(silent, s,
-		      "sh-2022: reiserfs_fill_super: unable to initialize journal space");
+		SWARN(silent, s, "sh-2022",
+		      "unable to initialize journal space");
 		goto error;
 	} else {
 		jinit_done = 1;	/* once this is set, journal_release must be called
@@ -1715,8 +1728,8 @@
 				 */
 	}
 	if (reread_meta_blocks(s)) {
-		SWARN(silent, s,
-		      "jmacd-9: reiserfs_fill_super: unable to reread meta blocks after journal init");
+		SWARN(silent, s, "jmacd-9",
+		      "unable to reread meta blocks after journal init");
 		goto error;
 	}
 
@@ -1724,8 +1737,8 @@
 		goto error;
 
 	if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) {
-		SWARN(silent, s,
-		      "clm-7000: Detected readonly device, marking FS readonly");
+		SWARN(silent, s, "clm-7000",
+		      "Detected readonly device, marking FS readonly");
 		s->s_flags |= MS_RDONLY;
 	}
 	args.objectid = REISERFS_ROOT_OBJECTID;
@@ -1734,8 +1747,7 @@
 	    iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor,
 			 reiserfs_init_locked_inode, (void *)(&args));
 	if (!root_inode) {
-		SWARN(silent, s,
-		      "jmacd-10: reiserfs_fill_super: get root inode failed");
+		SWARN(silent, s, "jmacd-10", "get root inode failed");
 		goto error;
 	}
 
@@ -1784,7 +1796,7 @@
 		 * avoiding corruption. -jeffm */
 		if (bmap_would_wrap(reiserfs_bmap_count(s)) &&
 		    sb_bmap_nr(rs) != 0) {
-			reiserfs_warning(s, "super-2030: This file system "
+			reiserfs_warning(s, "super-2030", "This file system "
 					"claims to use %u bitmap blocks in "
 					"its super block, but requires %u. "
 					"Clearing to zero.", sb_bmap_nr(rs),
@@ -1817,7 +1829,9 @@
 			} else if (!silent) {
 				reiserfs_info(s, "using 3.5.x disk format\n");
 			}
-		}
+		} else
+			set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
+
 
 		journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
 		errval = journal_end(&th, s, 1);
@@ -2031,8 +2045,8 @@
 	if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
 		err = reiserfs_unpack(inode, NULL);
 		if (err) {
-			reiserfs_warning(sb,
-				"reiserfs: Unpacking tail of quota file failed"
+			reiserfs_warning(sb, "super-6520",
+				"Unpacking tail of quota file failed"
 				" (%d). Cannot turn on quotas.", err);
 			err = -EINVAL;
 			goto out;
@@ -2043,8 +2057,8 @@
 	if (REISERFS_SB(sb)->s_qf_names[type]) {
 		/* Quotafile not of fs root? */
 		if (path.dentry->d_parent != sb->s_root)
-			reiserfs_warning(sb,
-				 "reiserfs: Quota file not on filesystem root. "
+			reiserfs_warning(sb, "super-6521",
+				 "Quota file not on filesystem root. "
 				 "Journalled quota will not work.");
 	}
 
@@ -2195,9 +2209,6 @@
 		return ret;
 	}
 
-	if ((ret = reiserfs_xattr_register_handlers()))
-		goto failed_reiserfs_xattr_register_handlers;
-
 	reiserfs_proc_info_global_init();
 	reiserfs_proc_register_global("version",
 				      reiserfs_global_version_in_proc);
@@ -2208,9 +2219,6 @@
 		return 0;
 	}
 
-	reiserfs_xattr_unregister_handlers();
-
-      failed_reiserfs_xattr_register_handlers:
 	reiserfs_proc_unregister_global("version");
 	reiserfs_proc_info_global_done();
 	destroy_inodecache();
@@ -2220,7 +2228,6 @@
 
 static void __exit exit_reiserfs_fs(void)
 {
-	reiserfs_xattr_unregister_handlers();
 	reiserfs_proc_unregister_global("version");
 	reiserfs_proc_info_global_done();
 	unregister_filesystem(&reiserfs_fs_type);
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index f8121a1..d7f6e51 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -26,7 +26,7 @@
 				   converted item. */
 	struct item_head ind_ih;	/* new indirect item to be inserted or
 					   key of unfm pointer to be pasted */
-	int n_blk_size, n_retval;	/* returned value for reiserfs_insert_item and clones */
+	int blk_size, retval;	/* returned value for reiserfs_insert_item and clones */
 	unp_t unfm_ptr;		/* Handle on an unformatted node
 				   that will be inserted in the
 				   tree. */
@@ -35,7 +35,7 @@
 
 	REISERFS_SB(sb)->s_direct2indirect++;
 
-	n_blk_size = sb->s_blocksize;
+	blk_size = sb->s_blocksize;
 
 	/* and key to search for append or insert pointer to the new
 	   unformatted node. */
@@ -46,11 +46,11 @@
 	/* Set the key to search for the place for new unfm pointer */
 	make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4);
 
-	// FIXME: we could avoid this 
+	/* FIXME: we could avoid this */
 	if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) {
-		reiserfs_warning(sb, "PAP-14030: direct2indirect: "
-				 "pasted or inserted byte exists in the tree %K. "
-				 "Use fsck to repair.", &end_key);
+		reiserfs_error(sb, "PAP-14030",
+			       "pasted or inserted byte exists in "
+			       "the tree %K. Use fsck to repair.", &end_key);
 		pathrelse(path);
 		return -EIO;
 	}
@@ -64,17 +64,17 @@
 		set_ih_free_space(&ind_ih, 0);	/* delete at nearest future */
 		put_ih_item_len(&ind_ih, UNFM_P_SIZE);
 		PATH_LAST_POSITION(path)++;
-		n_retval =
+		retval =
 		    reiserfs_insert_item(th, path, &end_key, &ind_ih, inode,
 					 (char *)&unfm_ptr);
 	} else {
 		/* Paste into last indirect item of an object. */
-		n_retval = reiserfs_paste_into_item(th, path, &end_key, inode,
+		retval = reiserfs_paste_into_item(th, path, &end_key, inode,
 						    (char *)&unfm_ptr,
 						    UNFM_P_SIZE);
 	}
-	if (n_retval) {
-		return n_retval;
+	if (retval) {
+		return retval;
 	}
 	// note: from here there are two keys which have matching first
 	// three key components. They only differ by the fourth one.
@@ -92,14 +92,13 @@
 		   last item of the file */
 		if (search_for_position_by_key(sb, &end_key, path) ==
 		    POSITION_FOUND)
-			reiserfs_panic(sb,
-				       "PAP-14050: direct2indirect: "
+			reiserfs_panic(sb, "PAP-14050",
 				       "direct item (%K) not found", &end_key);
 		p_le_ih = PATH_PITEM_HEAD(path);
 		RFALSE(!is_direct_le_ih(p_le_ih),
 		       "vs-14055: direct item expected(%K), found %h",
 		       &end_key, p_le_ih);
-		tail_size = (le_ih_k_offset(p_le_ih) & (n_blk_size - 1))
+		tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1))
 		    + ih_item_len(p_le_ih) - 1;
 
 		/* we only send the unbh pointer if the buffer is not up to date.
@@ -114,11 +113,11 @@
 		} else {
 			up_to_date_bh = unbh;
 		}
-		n_retval = reiserfs_delete_item(th, path, &end_key, inode,
+		retval = reiserfs_delete_item(th, path, &end_key, inode,
 						up_to_date_bh);
 
-		total_tail += n_retval;
-		if (tail_size == n_retval)
+		total_tail += retval;
+		if (tail_size == retval)
 			// done: file does not have direct items anymore
 			break;
 
@@ -130,7 +129,7 @@
 		unsigned pgoff =
 		    (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1);
 		char *kaddr = kmap_atomic(up_to_date_bh->b_page, KM_USER0);
-		memset(kaddr + pgoff, 0, n_blk_size - total_tail);
+		memset(kaddr + pgoff, 0, blk_size - total_tail);
 		kunmap_atomic(kaddr, KM_USER0);
 	}
 
@@ -171,14 +170,18 @@
    what we expect from it (number of cut bytes). But when tail remains
    in the unformatted node, we set mode to SKIP_BALANCING and unlock
    inode */
-int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_inode, struct page *page, struct treepath *p_s_path,	/* path to the indirect item. */
-		    const struct cpu_key *p_s_item_key,	/* Key to look for unformatted node pointer to be cut. */
+int indirect2direct(struct reiserfs_transaction_handle *th,
+		    struct inode *inode, struct page *page,
+		    struct treepath *path,	/* path to the indirect item. */
+		    const struct cpu_key *item_key,	/* Key to look for
+							 * unformatted node
+							 * pointer to be cut. */
 		    loff_t n_new_file_size,	/* New file size. */
-		    char *p_c_mode)
+		    char *mode)
 {
-	struct super_block *p_s_sb = p_s_inode->i_sb;
+	struct super_block *sb = inode->i_sb;
 	struct item_head s_ih;
-	unsigned long n_block_size = p_s_sb->s_blocksize;
+	unsigned long block_size = sb->s_blocksize;
 	char *tail;
 	int tail_len, round_tail_len;
 	loff_t pos, pos1;	/* position of first byte of the tail */
@@ -186,22 +189,22 @@
 
 	BUG_ON(!th->t_trans_id);
 
-	REISERFS_SB(p_s_sb)->s_indirect2direct++;
+	REISERFS_SB(sb)->s_indirect2direct++;
 
-	*p_c_mode = M_SKIP_BALANCING;
+	*mode = M_SKIP_BALANCING;
 
 	/* store item head path points to. */
-	copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
+	copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
 
-	tail_len = (n_new_file_size & (n_block_size - 1));
-	if (get_inode_sd_version(p_s_inode) == STAT_DATA_V2)
+	tail_len = (n_new_file_size & (block_size - 1));
+	if (get_inode_sd_version(inode) == STAT_DATA_V2)
 		round_tail_len = ROUND_UP(tail_len);
 	else
 		round_tail_len = tail_len;
 
 	pos =
 	    le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE -
-					 1) * p_s_sb->s_blocksize;
+					 1) * sb->s_blocksize;
 	pos1 = pos;
 
 	// we are protected by i_mutex. The tail can not disapper, not
@@ -210,27 +213,26 @@
 
 	tail = (char *)kmap(page);	/* this can schedule */
 
-	if (path_changed(&s_ih, p_s_path)) {
+	if (path_changed(&s_ih, path)) {
 		/* re-search indirect item */
-		if (search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path)
+		if (search_for_position_by_key(sb, item_key, path)
 		    == POSITION_NOT_FOUND)
-			reiserfs_panic(p_s_sb,
-				       "PAP-5520: indirect2direct: "
+			reiserfs_panic(sb, "PAP-5520",
 				       "item to be converted %K does not exist",
-				       p_s_item_key);
-		copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
+				       item_key);
+		copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
 #ifdef CONFIG_REISERFS_CHECK
 		pos = le_ih_k_offset(&s_ih) - 1 +
 		    (ih_item_len(&s_ih) / UNFM_P_SIZE -
-		     1) * p_s_sb->s_blocksize;
+		     1) * sb->s_blocksize;
 		if (pos != pos1)
-			reiserfs_panic(p_s_sb, "vs-5530: indirect2direct: "
-				       "tail position changed while we were reading it");
+			reiserfs_panic(sb, "vs-5530", "tail position "
+				       "changed while we were reading it");
 #endif
 	}
 
 	/* Set direct item header to insert. */
-	make_le_item_head(&s_ih, NULL, get_inode_item_key_version(p_s_inode),
+	make_le_item_head(&s_ih, NULL, get_inode_item_key_version(inode),
 			  pos1 + 1, TYPE_DIRECT, round_tail_len,
 			  0xffff /*ih_free_space */ );
 
@@ -240,13 +242,13 @@
 	 */
 	tail = tail + (pos & (PAGE_CACHE_SIZE - 1));
 
-	PATH_LAST_POSITION(p_s_path)++;
+	PATH_LAST_POSITION(path)++;
 
-	key = *p_s_item_key;
+	key = *item_key;
 	set_cpu_key_k_type(&key, TYPE_DIRECT);
 	key.key_length = 4;
 	/* Insert tail as new direct item in the tree */
-	if (reiserfs_insert_item(th, p_s_path, &key, &s_ih, p_s_inode,
+	if (reiserfs_insert_item(th, path, &key, &s_ih, inode,
 				 tail ? tail : NULL) < 0) {
 		/* No disk memory. So we can not convert last unformatted node
 		   to the direct item.  In this case we used to adjust
@@ -255,12 +257,12 @@
 		   unformatted node. For now i_size is considered as guard for
 		   going out of file size */
 		kunmap(page);
-		return n_block_size - round_tail_len;
+		return block_size - round_tail_len;
 	}
 	kunmap(page);
 
 	/* make sure to get the i_blocks changes from reiserfs_insert_item */
-	reiserfs_update_sd(th, p_s_inode);
+	reiserfs_update_sd(th, inode);
 
 	// note: we have now the same as in above direct2indirect
 	// conversion: there are two keys which have matching first three
@@ -268,11 +270,11 @@
 
 	/* We have inserted new direct item and must remove last
 	   unformatted node. */
-	*p_c_mode = M_CUT;
+	*mode = M_CUT;
 
 	/* we store position of first direct item in the in-core inode */
-	//mark_file_with_tail (p_s_inode, pos1 + 1);
-	REISERFS_I(p_s_inode)->i_first_direct_byte = pos1 + 1;
+	/* mark_file_with_tail (inode, pos1 + 1); */
+	REISERFS_I(inode)->i_first_direct_byte = pos1 + 1;
 
-	return n_block_size - round_tail_len;
+	return block_size - round_tail_len;
 }
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index ae881cc..e52743e 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -27,6 +27,10 @@
  * these are special cases for filesystem ACLs, they are interpreted by the
  * kernel, in addition, they are negatively and positively cached and attached
  * to the inode so that unnecessary lookups are avoided.
+ *
+ * Locking works like so:
+ * Directory components (xattr root, xattr dir) are protectd by their i_mutex.
+ * The xattrs themselves are protected by the xattr_sem.
  */
 
 #include <linux/reiserfs_fs.h>
@@ -44,330 +48,334 @@
 #include <net/checksum.h>
 #include <linux/smp_lock.h>
 #include <linux/stat.h>
+#include <linux/quotaops.h>
 
-#define FL_READONLY 128
-#define FL_DIR_SEM_HELD 256
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
 
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
-								*prefix);
 
-/* Returns the dentry referring to the root of the extended attribute
- * directory tree. If it has already been retrieved, it is used. If it
- * hasn't been created and the flags indicate creation is allowed, we
- * attempt to create it. On error, we return a pointer-encoded error.
- */
-static struct dentry *get_xa_root(struct super_block *sb, int flags)
+/* Helpers for inode ops. We do this so that we don't have all the VFS
+ * overhead and also for proper i_mutex annotation.
+ * dir->i_mutex must be held for all of them. */
+static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root);
-	struct dentry *xaroot;
-
-	/* This needs to be created at mount-time */
-	if (!privroot)
-		return ERR_PTR(-ENODATA);
-
-	mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
-	if (REISERFS_SB(sb)->xattr_root) {
-		xaroot = dget(REISERFS_SB(sb)->xattr_root);
-		goto out;
-	}
-
-	xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME));
-	if (IS_ERR(xaroot)) {
-		goto out;
-	} else if (!xaroot->d_inode) {
-		int err = -ENODATA;
-		if (flags == 0 || flags & XATTR_CREATE)
-			err = privroot->d_inode->i_op->mkdir(privroot->d_inode,
-			                                     xaroot, 0700);
-		if (err) {
-			dput(xaroot);
-			xaroot = ERR_PTR(err);
-			goto out;
-		}
-	}
-	REISERFS_SB(sb)->xattr_root = dget(xaroot);
-
-      out:
-	mutex_unlock(&privroot->d_inode->i_mutex);
-	dput(privroot);
-	return xaroot;
+	BUG_ON(!mutex_is_locked(&dir->i_mutex));
+	vfs_dq_init(dir);
+	return dir->i_op->create(dir, dentry, mode, NULL);
 }
 
-/* Opens the directory corresponding to the inode's extended attribute store.
- * If flags allow, the tree to the directory may be created. If creation is
- * prohibited, -ENODATA is returned. */
+static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	BUG_ON(!mutex_is_locked(&dir->i_mutex));
+	vfs_dq_init(dir);
+	return dir->i_op->mkdir(dir, dentry, mode);
+}
+
+/* We use I_MUTEX_CHILD here to silence lockdep. It's safe because xattr
+ * mutation ops aren't called during rename or splace, which are the
+ * only other users of I_MUTEX_CHILD. It violates the ordering, but that's
+ * better than allocating another subclass just for this code. */
+static int xattr_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int error;
+	BUG_ON(!mutex_is_locked(&dir->i_mutex));
+	vfs_dq_init(dir);
+
+	mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+	error = dir->i_op->unlink(dir, dentry);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+
+	if (!error)
+		d_delete(dentry);
+	return error;
+}
+
+static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int error;
+	BUG_ON(!mutex_is_locked(&dir->i_mutex));
+	vfs_dq_init(dir);
+
+	mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+	dentry_unhash(dentry);
+	error = dir->i_op->rmdir(dir, dentry);
+	if (!error)
+		dentry->d_inode->i_flags |= S_DEAD;
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	if (!error)
+		d_delete(dentry);
+	dput(dentry);
+
+	return error;
+}
+
+#define xattr_may_create(flags)	(!flags || flags & XATTR_CREATE)
+
+/* Returns and possibly creates the xattr dir. */
+static struct dentry *lookup_or_create_dir(struct dentry *parent,
+					    const char *name, int flags)
+{
+	struct dentry *dentry;
+	BUG_ON(!parent);
+
+	dentry = lookup_one_len(name, parent, strlen(name));
+	if (IS_ERR(dentry))
+		return dentry;
+	else if (!dentry->d_inode) {
+		int err = -ENODATA;
+
+		if (xattr_may_create(flags)) {
+			mutex_lock_nested(&parent->d_inode->i_mutex,
+					  I_MUTEX_XATTR);
+			err = xattr_mkdir(parent->d_inode, dentry, 0700);
+			mutex_unlock(&parent->d_inode->i_mutex);
+		}
+
+		if (err) {
+			dput(dentry);
+			dentry = ERR_PTR(err);
+		}
+	}
+
+	return dentry;
+}
+
+static struct dentry *open_xa_root(struct super_block *sb, int flags)
+{
+	struct dentry *privroot = REISERFS_SB(sb)->priv_root;
+	if (!privroot)
+		return ERR_PTR(-ENODATA);
+	return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
+}
+
 static struct dentry *open_xa_dir(const struct inode *inode, int flags)
 {
 	struct dentry *xaroot, *xadir;
 	char namebuf[17];
 
-	xaroot = get_xa_root(inode->i_sb, flags);
+	xaroot = open_xa_root(inode->i_sb, flags);
 	if (IS_ERR(xaroot))
 		return xaroot;
 
-	/* ok, we have xaroot open */
 	snprintf(namebuf, sizeof(namebuf), "%X.%X",
 		 le32_to_cpu(INODE_PKEY(inode)->k_objectid),
 		 inode->i_generation);
-	xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
-	if (IS_ERR(xadir)) {
-		dput(xaroot);
-		return xadir;
-	}
 
-	if (!xadir->d_inode) {
-		int err;
-		if (flags == 0 || flags & XATTR_CREATE) {
-			/* Although there is nothing else trying to create this directory,
-			 * another directory with the same hash may be created, so we need
-			 * to protect against that */
-			err =
-			    xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir,
-							 0700);
-			if (err) {
-				dput(xaroot);
-				dput(xadir);
-				return ERR_PTR(err);
-			}
-		}
-		if (!xadir->d_inode) {
-			dput(xaroot);
-			dput(xadir);
-			return ERR_PTR(-ENODATA);
-		}
-	}
-
+	xadir = lookup_or_create_dir(xaroot, namebuf, flags);
 	dput(xaroot);
 	return xadir;
+
 }
 
+/* The following are side effects of other operations that aren't explicitly
+ * modifying extended attributes. This includes operations such as permissions
+ * or ownership changes, object deletions, etc. */
+struct reiserfs_dentry_buf {
+	struct dentry *xadir;
+	int count;
+	struct dentry *dentries[8];
+};
+
+static int
+fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
+		    u64 ino, unsigned int d_type)
+{
+	struct reiserfs_dentry_buf *dbuf = buf;
+	struct dentry *dentry;
+
+	if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
+		return -ENOSPC;
+
+	if (name[0] == '.' && (name[1] == '\0' ||
+			       (name[1] == '.' && name[2] == '\0')))
+		return 0;
+
+	dentry = lookup_one_len(name, dbuf->xadir, namelen);
+	if (IS_ERR(dentry)) {
+		return PTR_ERR(dentry);
+	} else if (!dentry->d_inode) {
+		/* A directory entry exists, but no file? */
+		reiserfs_error(dentry->d_sb, "xattr-20003",
+			       "Corrupted directory: xattr %s listed but "
+			       "not found for file %s.\n",
+			       dentry->d_name.name, dbuf->xadir->d_name.name);
+		dput(dentry);
+		return -EIO;
+	}
+
+	dbuf->dentries[dbuf->count++] = dentry;
+	return 0;
+}
+
+static void
+cleanup_dentry_buf(struct reiserfs_dentry_buf *buf)
+{
+	int i;
+	for (i = 0; i < buf->count; i++)
+		if (buf->dentries[i])
+			dput(buf->dentries[i]);
+}
+
+static int reiserfs_for_each_xattr(struct inode *inode,
+				   int (*action)(struct dentry *, void *),
+				   void *data)
+{
+	struct dentry *dir;
+	int i, err = 0;
+	loff_t pos = 0;
+	struct reiserfs_dentry_buf buf = {
+		.count = 0,
+	};
+
+	/* Skip out, an xattr has no xattrs associated with it */
+	if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
+		return 0;
+
+	dir = open_xa_dir(inode, XATTR_REPLACE);
+	if (IS_ERR(dir)) {
+		err = PTR_ERR(dir);
+		goto out;
+	} else if (!dir->d_inode) {
+		err = 0;
+		goto out_dir;
+	}
+
+	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
+	buf.xadir = dir;
+	err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos);
+	while ((err == 0 || err == -ENOSPC) && buf.count) {
+		err = 0;
+
+		for (i = 0; i < buf.count && buf.dentries[i]; i++) {
+			int lerr = 0;
+			struct dentry *dentry = buf.dentries[i];
+
+			if (err == 0 && !S_ISDIR(dentry->d_inode->i_mode))
+				lerr = action(dentry, data);
+
+			dput(dentry);
+			buf.dentries[i] = NULL;
+			err = lerr ?: err;
+		}
+		buf.count = 0;
+		if (!err)
+			err = reiserfs_readdir_dentry(dir, &buf,
+						      fill_with_dentries, &pos);
+	}
+	mutex_unlock(&dir->d_inode->i_mutex);
+
+	/* Clean up after a failed readdir */
+	cleanup_dentry_buf(&buf);
+
+	if (!err) {
+		/* We start a transaction here to avoid a ABBA situation
+		 * between the xattr root's i_mutex and the journal lock.
+		 * This doesn't incur much additional overhead since the
+		 * new transaction will just nest inside the
+		 * outer transaction. */
+		int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +
+			     4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
+		struct reiserfs_transaction_handle th;
+		err = journal_begin(&th, inode->i_sb, blocks);
+		if (!err) {
+			int jerror;
+			mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
+					  I_MUTEX_XATTR);
+			err = action(dir, data);
+			jerror = journal_end(&th, inode->i_sb, blocks);
+			mutex_unlock(&dir->d_parent->d_inode->i_mutex);
+			err = jerror ?: err;
+		}
+	}
+out_dir:
+	dput(dir);
+out:
+	/* -ENODATA isn't an error */
+	if (err == -ENODATA)
+		err = 0;
+	return err;
+}
+
+static int delete_one_xattr(struct dentry *dentry, void *data)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+
+	/* This is the xattr dir, handle specially. */
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		return xattr_rmdir(dir, dentry);
+
+	return xattr_unlink(dir, dentry);
+}
+
+static int chown_one_xattr(struct dentry *dentry, void *data)
+{
+	struct iattr *attrs = data;
+	return reiserfs_setattr(dentry, attrs);
+}
+
+/* No i_mutex, but the inode is unconnected. */
+int reiserfs_delete_xattrs(struct inode *inode)
+{
+	int err = reiserfs_for_each_xattr(inode, delete_one_xattr, NULL);
+	if (err)
+		reiserfs_warning(inode->i_sb, "jdm-20004",
+				 "Couldn't delete all xattrs (%d)\n", err);
+	return err;
+}
+
+/* inode->i_mutex: down */
+int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
+{
+	int err = reiserfs_for_each_xattr(inode, chown_one_xattr, attrs);
+	if (err)
+		reiserfs_warning(inode->i_sb, "jdm-20007",
+				 "Couldn't chown all xattrs (%d)\n", err);
+	return err;
+}
+
+#ifdef CONFIG_REISERFS_FS_XATTR
 /* Returns a dentry corresponding to a specific extended attribute file
  * for the inode. If flags allow, the file is created. Otherwise, a
  * valid or negative dentry, or an error is returned. */
-static struct dentry *get_xa_file_dentry(const struct inode *inode,
-					 const char *name, int flags)
+static struct dentry *xattr_lookup(struct inode *inode, const char *name,
+				    int flags)
 {
 	struct dentry *xadir, *xafile;
 	int err = 0;
 
 	xadir = open_xa_dir(inode, flags);
-	if (IS_ERR(xadir)) {
+	if (IS_ERR(xadir))
 		return ERR_CAST(xadir);
-	} else if (!xadir->d_inode) {
-		dput(xadir);
-		return ERR_PTR(-ENODATA);
-	}
 
 	xafile = lookup_one_len(name, xadir, strlen(name));
 	if (IS_ERR(xafile)) {
-		dput(xadir);
-		return ERR_CAST(xafile);
-	}
-
-	if (xafile->d_inode) {	/* file exists */
-		if (flags & XATTR_CREATE) {
-			err = -EEXIST;
-			dput(xafile);
-			goto out;
-		}
-	} else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
+		err = PTR_ERR(xafile);
 		goto out;
-	} else {
-		/* inode->i_mutex is down, so nothing else can try to create
-		 * the same xattr */
-		err = xadir->d_inode->i_op->create(xadir->d_inode, xafile,
-						   0700 | S_IFREG, NULL);
+	}
 
-		if (err) {
-			dput(xafile);
-			goto out;
+	if (xafile->d_inode && (flags & XATTR_CREATE))
+		err = -EEXIST;
+
+	if (!xafile->d_inode) {
+		err = -ENODATA;
+		if (xattr_may_create(flags)) {
+			mutex_lock_nested(&xadir->d_inode->i_mutex,
+					  I_MUTEX_XATTR);
+			err = xattr_create(xadir->d_inode, xafile,
+					      0700|S_IFREG);
+			mutex_unlock(&xadir->d_inode->i_mutex);
 		}
 	}
 
-      out:
+	if (err)
+		dput(xafile);
+out:
 	dput(xadir);
 	if (err)
-		xafile = ERR_PTR(err);
-	else if (!xafile->d_inode) {
-		dput(xafile);
-		xafile = ERR_PTR(-ENODATA);
-	}
+		return ERR_PTR(err);
 	return xafile;
 }
 
-/*
- * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but
- * we need to drop the path before calling the filldir struct.  That
- * would be a big performance hit to the non-xattr case, so I've copied
- * the whole thing for now. --clm
- *
- * the big difference is that I go backwards through the directory,
- * and don't mess with f->f_pos, but the idea is the same.  Do some
- * action on each and every entry in the directory.
- *
- * we're called with i_mutex held, so there are no worries about the directory
- * changing underneath us.
- */
-static int __xattr_readdir(struct inode *inode, void *dirent, filldir_t filldir)
-{
-	struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
-	INITIALIZE_PATH(path_to_entry);
-	struct buffer_head *bh;
-	int entry_num;
-	struct item_head *ih, tmp_ih;
-	int search_res;
-	char *local_buf;
-	loff_t next_pos;
-	char small_buf[32];	/* avoid kmalloc if we can */
-	struct reiserfs_de_head *deh;
-	int d_reclen;
-	char *d_name;
-	off_t d_off;
-	ino_t d_ino;
-	struct reiserfs_dir_entry de;
-
-	/* form key for search the next directory entry using f_pos field of
-	   file structure */
-	next_pos = max_reiserfs_offset(inode);
-
-	while (1) {
-	      research:
-		if (next_pos <= DOT_DOT_OFFSET)
-			break;
-		make_cpu_key(&pos_key, inode, next_pos, TYPE_DIRENTRY, 3);
-
-		search_res =
-		    search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
-					&de);
-		if (search_res == IO_ERROR) {
-			// FIXME: we could just skip part of directory which could
-			// not be read
-			pathrelse(&path_to_entry);
-			return -EIO;
-		}
-
-		if (search_res == NAME_NOT_FOUND)
-			de.de_entry_num--;
-
-		set_de_name_and_namelen(&de);
-		entry_num = de.de_entry_num;
-		deh = &(de.de_deh[entry_num]);
-
-		bh = de.de_bh;
-		ih = de.de_ih;
-
-		if (!is_direntry_le_ih(ih)) {
-			reiserfs_warning(inode->i_sb, "not direntry %h", ih);
-			break;
-		}
-		copy_item_head(&tmp_ih, ih);
-
-		/* we must have found item, that is item of this directory, */
-		RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key),
-		       "vs-9000: found item %h does not match to dir we readdir %K",
-		       ih, &pos_key);
-
-		if (deh_offset(deh) <= DOT_DOT_OFFSET) {
-			break;
-		}
-
-		/* look for the previous entry in the directory */
-		next_pos = deh_offset(deh) - 1;
-
-		if (!de_visible(deh))
-			/* it is hidden entry */
-			continue;
-
-		d_reclen = entry_length(bh, ih, entry_num);
-		d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
-		d_off = deh_offset(deh);
-		d_ino = deh_objectid(deh);
-
-		if (!d_name[d_reclen - 1])
-			d_reclen = strlen(d_name);
-
-		if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)) {
-			/* too big to send back to VFS */
-			continue;
-		}
-
-		/* Ignore the .reiserfs_priv entry */
-		if (reiserfs_xattrs(inode->i_sb) &&
-		    !old_format_only(inode->i_sb) &&
-		    deh_objectid(deh) ==
-		    le32_to_cpu(INODE_PKEY
-				(REISERFS_SB(inode->i_sb)->priv_root->d_inode)->
-				k_objectid))
-			continue;
-
-		if (d_reclen <= 32) {
-			local_buf = small_buf;
-		} else {
-			local_buf = kmalloc(d_reclen, GFP_NOFS);
-			if (!local_buf) {
-				pathrelse(&path_to_entry);
-				return -ENOMEM;
-			}
-			if (item_moved(&tmp_ih, &path_to_entry)) {
-				kfree(local_buf);
-
-				/* sigh, must retry.  Do this same offset again */
-				next_pos = d_off;
-				goto research;
-			}
-		}
-
-		// Note, that we copy name to user space via temporary
-		// buffer (local_buf) because filldir will block if
-		// user space buffer is swapped out. At that time
-		// entry can move to somewhere else
-		memcpy(local_buf, d_name, d_reclen);
-
-		/* the filldir function might need to start transactions,
-		 * or do who knows what.  Release the path now that we've
-		 * copied all the important stuff out of the deh
-		 */
-		pathrelse(&path_to_entry);
-
-		if (filldir(dirent, local_buf, d_reclen, d_off, d_ino,
-			    DT_UNKNOWN) < 0) {
-			if (local_buf != small_buf) {
-				kfree(local_buf);
-			}
-			goto end;
-		}
-		if (local_buf != small_buf) {
-			kfree(local_buf);
-		}
-	}			/* while */
-
-      end:
-	pathrelse(&path_to_entry);
-	return 0;
-}
-
-/*
- * this could be done with dedicated readdir ops for the xattr files,
- * but I want to get something working asap
- * this is stolen from vfs_readdir
- *
- */
-static
-int xattr_readdir(struct inode *inode, filldir_t filler, void *buf)
-{
-	int res = -ENOENT;
-	mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
-	if (!IS_DEADDIR(inode)) {
-		lock_kernel();
-		res = __xattr_readdir(inode, buf, filler);
-		unlock_kernel();
-	}
-	mutex_unlock(&inode->i_mutex);
-	return res;
-}
-
 /* Internal operations on file data */
 static inline void reiserfs_put_page(struct page *page)
 {
@@ -375,14 +383,14 @@
 	page_cache_release(page);
 }
 
-static struct page *reiserfs_get_page(struct inode *dir, unsigned long n)
+static struct page *reiserfs_get_page(struct inode *dir, size_t n)
 {
 	struct address_space *mapping = dir->i_mapping;
 	struct page *page;
 	/* We can deadlock if we try to free dentries,
 	   and an unlink/rmdir has just occured - GFP_NOFS avoids this */
 	mapping_set_gfp_mask(mapping, GFP_NOFS);
-	page = read_mapping_page(mapping, n, NULL);
+	page = read_mapping_page(mapping, n >> PAGE_CACHE_SHIFT, NULL);
 	if (!IS_ERR(page)) {
 		kmap(page);
 		if (PageError(page))
@@ -405,6 +413,45 @@
 int reiserfs_prepare_write(struct file *f, struct page *page,
 			   unsigned from, unsigned to);
 
+static void update_ctime(struct inode *inode)
+{
+	struct timespec now = current_fs_time(inode->i_sb);
+	if (hlist_unhashed(&inode->i_hash) || !inode->i_nlink ||
+	    timespec_equal(&inode->i_ctime, &now))
+		return;
+
+	inode->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(inode);
+}
+
+static int lookup_and_delete_xattr(struct inode *inode, const char *name)
+{
+	int err = 0;
+	struct dentry *dentry, *xadir;
+
+	xadir = open_xa_dir(inode, XATTR_REPLACE);
+	if (IS_ERR(xadir))
+		return PTR_ERR(xadir);
+
+	dentry = lookup_one_len(name, xadir, strlen(name));
+	if (IS_ERR(dentry)) {
+		err = PTR_ERR(dentry);
+		goto out_dput;
+	}
+
+	if (dentry->d_inode) {
+		mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
+		err = xattr_unlink(xadir->d_inode, dentry);
+		mutex_unlock(&xadir->d_inode->i_mutex);
+		update_ctime(inode);
+	}
+
+	dput(dentry);
+out_dput:
+	dput(xadir);
+	return err;
+}
+
 
 /* Generic extended attribute operations that can be used by xa plugins */
 
@@ -412,58 +459,32 @@
  * inode->i_mutex: down
  */
 int
-reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
-		   size_t buffer_size, int flags)
+reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
+			  struct inode *inode, const char *name,
+			  const void *buffer, size_t buffer_size, int flags)
 {
 	int err = 0;
 	struct dentry *dentry;
 	struct page *page;
 	char *data;
-	struct address_space *mapping;
 	size_t file_pos = 0;
 	size_t buffer_pos = 0;
-	struct inode *xinode;
-	struct iattr newattrs;
+	size_t new_size;
 	__u32 xahash = 0;
 
 	if (get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	/* Empty xattrs are ok, they're just empty files, no hash */
-	if (buffer && buffer_size)
-		xahash = xattr_hash(buffer, buffer_size);
+	if (!buffer)
+		return lookup_and_delete_xattr(inode, name);
 
-      open_file:
-	dentry = get_xa_file_dentry(inode, name, flags);
-	if (IS_ERR(dentry)) {
-		err = PTR_ERR(dentry);
-		goto out;
-	}
+	dentry = xattr_lookup(inode, name, flags);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
 
-	xinode = dentry->d_inode;
-	REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+	down_write(&REISERFS_I(inode)->i_xattr_sem);
 
-	/* we need to copy it off.. */
-	if (xinode->i_nlink > 1) {
-		dput(dentry);
-		err = reiserfs_xattr_del(inode, name);
-		if (err < 0)
-			goto out;
-		/* We just killed the old one, we're not replacing anymore */
-		if (flags & XATTR_REPLACE)
-			flags &= ~XATTR_REPLACE;
-		goto open_file;
-	}
-
-	/* Resize it so we're ok to write there */
-	newattrs.ia_size = buffer_size;
-	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-	mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
-	err = notify_change(dentry, &newattrs);
-	if (err)
-		goto out_filp;
-
-	mapping = xinode->i_mapping;
+	xahash = xattr_hash(buffer, buffer_size);
 	while (buffer_pos < buffer_size || buffer_pos == 0) {
 		size_t chunk;
 		size_t skip = 0;
@@ -473,10 +494,10 @@
 		else
 			chunk = buffer_size - buffer_pos;
 
-		page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT);
+		page = reiserfs_get_page(dentry->d_inode, file_pos);
 		if (IS_ERR(page)) {
 			err = PTR_ERR(page);
-			goto out_filp;
+			goto out_unlock;
 		}
 
 		lock_page(page);
@@ -510,28 +531,61 @@
 			break;
 	}
 
-	/* We can't mark the inode dirty if it's not hashed. This is the case
-	 * when we're inheriting the default ACL. If we dirty it, the inode
-	 * gets marked dirty, but won't (ever) make it onto the dirty list until
-	 * it's synced explicitly to clear I_DIRTY. This is bad. */
-	if (!hlist_unhashed(&inode->i_hash)) {
-		inode->i_ctime = CURRENT_TIME_SEC;
-		mark_inode_dirty(inode);
+	new_size = buffer_size + sizeof(struct reiserfs_xattr_header);
+	if (!err && new_size < i_size_read(dentry->d_inode)) {
+		struct iattr newattrs = {
+			.ia_ctime = current_fs_time(inode->i_sb),
+			.ia_size = buffer_size,
+			.ia_valid = ATTR_SIZE | ATTR_CTIME,
+		};
+		mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
+		down_write(&dentry->d_inode->i_alloc_sem);
+		err = reiserfs_setattr(dentry, &newattrs);
+		up_write(&dentry->d_inode->i_alloc_sem);
+		mutex_unlock(&dentry->d_inode->i_mutex);
+	} else
+		update_ctime(inode);
+out_unlock:
+	up_write(&REISERFS_I(inode)->i_xattr_sem);
+	dput(dentry);
+	return err;
+}
+
+/* We need to start a transaction to maintain lock ordering */
+int reiserfs_xattr_set(struct inode *inode, const char *name,
+		       const void *buffer, size_t buffer_size, int flags)
+{
+
+	struct reiserfs_transaction_handle th;
+	int error, error2;
+	size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size);
+
+	if (!(flags & XATTR_REPLACE))
+		jbegin_count += reiserfs_xattr_jcreate_nblocks(inode);
+
+	reiserfs_write_lock(inode->i_sb);
+	error = journal_begin(&th, inode->i_sb, jbegin_count);
+	if (error) {
+		reiserfs_write_unlock(inode->i_sb);
+		return error;
 	}
 
-      out_filp:
-	mutex_unlock(&xinode->i_mutex);
-	dput(dentry);
+	error = reiserfs_xattr_set_handle(&th, inode, name,
+					  buffer, buffer_size, flags);
 
-      out:
-	return err;
+	error2 = journal_end(&th, inode->i_sb, jbegin_count);
+	if (error == 0)
+		error = error2;
+	reiserfs_write_unlock(inode->i_sb);
+
+	return error;
 }
 
 /*
  * inode->i_mutex: down
  */
 int
-reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
+reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
 		   size_t buffer_size)
 {
 	ssize_t err = 0;
@@ -540,7 +594,6 @@
 	size_t file_pos = 0;
 	size_t buffer_pos = 0;
 	struct page *page;
-	struct inode *xinode;
 	__u32 hash = 0;
 
 	if (name == NULL)
@@ -551,25 +604,25 @@
 	if (get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	dentry = get_xa_file_dentry(inode, name, FL_READONLY);
+	dentry = xattr_lookup(inode, name, XATTR_REPLACE);
 	if (IS_ERR(dentry)) {
 		err = PTR_ERR(dentry);
 		goto out;
 	}
 
-	xinode = dentry->d_inode;
-	isize = xinode->i_size;
-	REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+	down_read(&REISERFS_I(inode)->i_xattr_sem);
+
+	isize = i_size_read(dentry->d_inode);
 
 	/* Just return the size needed */
 	if (buffer == NULL) {
 		err = isize - sizeof(struct reiserfs_xattr_header);
-		goto out_dput;
+		goto out_unlock;
 	}
 
 	if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) {
 		err = -ERANGE;
-		goto out_dput;
+		goto out_unlock;
 	}
 
 	while (file_pos < isize) {
@@ -581,10 +634,10 @@
 		else
 			chunk = isize - file_pos;
 
-		page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT);
+		page = reiserfs_get_page(dentry->d_inode, file_pos);
 		if (IS_ERR(page)) {
 			err = PTR_ERR(page);
-			goto out_dput;
+			goto out_unlock;
 		}
 
 		lock_page(page);
@@ -598,12 +651,12 @@
 			if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) {
 				unlock_page(page);
 				reiserfs_put_page(page);
-				reiserfs_warning(inode->i_sb,
+				reiserfs_warning(inode->i_sb, "jdm-20001",
 						 "Invalid magic for xattr (%s) "
 						 "associated with %k", name,
 						 INODE_PKEY(inode));
 				err = -EIO;
-				goto out_dput;
+				goto out_unlock;
 			}
 			hash = le32_to_cpu(rxh->h_hash);
 		}
@@ -618,256 +671,83 @@
 
 	if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) !=
 	    hash) {
-		reiserfs_warning(inode->i_sb,
+		reiserfs_warning(inode->i_sb, "jdm-20002",
 				 "Invalid hash for xattr (%s) associated "
 				 "with %k", name, INODE_PKEY(inode));
 		err = -EIO;
 	}
 
-      out_dput:
+out_unlock:
+	up_read(&REISERFS_I(inode)->i_xattr_sem);
 	dput(dentry);
 
-      out:
-	return err;
-}
-
-static int
-__reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen)
-{
-	struct dentry *dentry;
-	struct inode *dir = xadir->d_inode;
-	int err = 0;
-
-	dentry = lookup_one_len(name, xadir, namelen);
-	if (IS_ERR(dentry)) {
-		err = PTR_ERR(dentry);
-		goto out;
-	} else if (!dentry->d_inode) {
-		err = -ENODATA;
-		goto out_file;
-	}
-
-	/* Skip directories.. */
-	if (S_ISDIR(dentry->d_inode->i_mode))
-		goto out_file;
-
-	if (!is_reiserfs_priv_object(dentry->d_inode)) {
-		reiserfs_warning(dir->i_sb, "OID %08x [%.*s/%.*s] doesn't have "
-				 "priv flag set [parent is %sset].",
-				 le32_to_cpu(INODE_PKEY(dentry->d_inode)->
-					     k_objectid), xadir->d_name.len,
-				 xadir->d_name.name, namelen, name,
-				 is_reiserfs_priv_object(xadir->
-							 d_inode) ? "" :
-				 "not ");
-		dput(dentry);
-		return -EIO;
-	}
-
-	err = dir->i_op->unlink(dir, dentry);
-	if (!err)
-		d_delete(dentry);
-
-      out_file:
-	dput(dentry);
-
-      out:
-	return err;
-}
-
-int reiserfs_xattr_del(struct inode *inode, const char *name)
-{
-	struct dentry *dir;
-	int err;
-
-	dir = open_xa_dir(inode, FL_READONLY);
-	if (IS_ERR(dir)) {
-		err = PTR_ERR(dir);
-		goto out;
-	}
-
-	err = __reiserfs_xattr_del(dir, name, strlen(name));
-	dput(dir);
-
-	if (!err) {
-		inode->i_ctime = CURRENT_TIME_SEC;
-		mark_inode_dirty(inode);
-	}
-
-      out:
-	return err;
-}
-
-/* The following are side effects of other operations that aren't explicitly
- * modifying extended attributes. This includes operations such as permissions
- * or ownership changes, object deletions, etc. */
-
-static int
-reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
-			      loff_t offset, u64 ino, unsigned int d_type)
-{
-	struct dentry *xadir = (struct dentry *)buf;
-
-	return __reiserfs_xattr_del(xadir, name, namelen);
-
-}
-
-/* This is called w/ inode->i_mutex downed */
-int reiserfs_delete_xattrs(struct inode *inode)
-{
-	struct dentry *dir, *root;
-	int err = 0;
-
-	/* Skip out, an xattr has no xattrs associated with it */
-	if (is_reiserfs_priv_object(inode) ||
-	    get_inode_sd_version(inode) == STAT_DATA_V1 ||
-	    !reiserfs_xattrs(inode->i_sb)) {
-		return 0;
-	}
-	reiserfs_read_lock_xattrs(inode->i_sb);
-	dir = open_xa_dir(inode, FL_READONLY);
-	reiserfs_read_unlock_xattrs(inode->i_sb);
-	if (IS_ERR(dir)) {
-		err = PTR_ERR(dir);
-		goto out;
-	} else if (!dir->d_inode) {
-		dput(dir);
-		return 0;
-	}
-
-	lock_kernel();
-	err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir);
-	if (err) {
-		unlock_kernel();
-		goto out_dir;
-	}
-
-	/* Leftovers besides . and .. -- that's not good. */
-	if (dir->d_inode->i_nlink <= 2) {
-		root = get_xa_root(inode->i_sb, XATTR_REPLACE);
-		reiserfs_write_lock_xattrs(inode->i_sb);
-		err = vfs_rmdir(root->d_inode, dir);
-		reiserfs_write_unlock_xattrs(inode->i_sb);
-		dput(root);
-	} else {
-		reiserfs_warning(inode->i_sb,
-				 "Couldn't remove all entries in directory");
-	}
-	unlock_kernel();
-
-      out_dir:
-	dput(dir);
-
-      out:
-	if (!err)
-		REISERFS_I(inode)->i_flags =
-		    REISERFS_I(inode)->i_flags & ~i_has_xattr_dir;
-	return err;
-}
-
-struct reiserfs_chown_buf {
-	struct inode *inode;
-	struct dentry *xadir;
-	struct iattr *attrs;
-};
-
-/* XXX: If there is a better way to do this, I'd love to hear about it */
-static int
-reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen,
-			     loff_t offset, u64 ino, unsigned int d_type)
-{
-	struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf;
-	struct dentry *xafile, *xadir = chown_buf->xadir;
-	struct iattr *attrs = chown_buf->attrs;
-	int err = 0;
-
-	xafile = lookup_one_len(name, xadir, namelen);
-	if (IS_ERR(xafile))
-		return PTR_ERR(xafile);
-	else if (!xafile->d_inode) {
-		dput(xafile);
-		return -ENODATA;
-	}
-
-	if (!S_ISDIR(xafile->d_inode->i_mode))
-		err = notify_change(xafile, attrs);
-	dput(xafile);
-
-	return err;
-}
-
-int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
-{
-	struct dentry *dir;
-	int err = 0;
-	struct reiserfs_chown_buf buf;
-	unsigned int ia_valid = attrs->ia_valid;
-
-	/* Skip out, an xattr has no xattrs associated with it */
-	if (is_reiserfs_priv_object(inode) ||
-	    get_inode_sd_version(inode) == STAT_DATA_V1 ||
-	    !reiserfs_xattrs(inode->i_sb)) {
-		return 0;
-	}
-	reiserfs_read_lock_xattrs(inode->i_sb);
-	dir = open_xa_dir(inode, FL_READONLY);
-	reiserfs_read_unlock_xattrs(inode->i_sb);
-	if (IS_ERR(dir)) {
-		if (PTR_ERR(dir) != -ENODATA)
-			err = PTR_ERR(dir);
-		goto out;
-	} else if (!dir->d_inode) {
-		dput(dir);
-		goto out;
-	}
-
-	lock_kernel();
-
-	attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME);
-	buf.xadir = dir;
-	buf.attrs = attrs;
-	buf.inode = inode;
-
-	err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf);
-	if (err) {
-		unlock_kernel();
-		goto out_dir;
-	}
-
-	err = notify_change(dir, attrs);
-	unlock_kernel();
-
-      out_dir:
-	dput(dir);
-
-      out:
-	attrs->ia_valid = ia_valid;
+out:
 	return err;
 }
 
 /* Actual operations that are exported to VFS-land */
+struct xattr_handler *reiserfs_xattr_handlers[] = {
+	&reiserfs_xattr_user_handler,
+	&reiserfs_xattr_trusted_handler,
+#ifdef CONFIG_REISERFS_FS_SECURITY
+	&reiserfs_xattr_security_handler,
+#endif
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
+	&reiserfs_posix_acl_access_handler,
+	&reiserfs_posix_acl_default_handler,
+#endif
+	NULL
+};
+
+/*
+ * In order to implement different sets of xattr operations for each xattr
+ * prefix with the generic xattr API, a filesystem should create a
+ * null-terminated array of struct xattr_handler (one for each prefix) and
+ * hang a pointer to it off of the s_xattr field of the superblock.
+ *
+ * The generic_fooxattr() functions will use this list to dispatch xattr
+ * operations to the correct xattr_handler.
+ */
+#define for_each_xattr_handler(handlers, handler)		\
+		for ((handler) = *(handlers)++;			\
+			(handler) != NULL;			\
+			(handler) = *(handlers)++)
+
+/* This is the implementation for the xattr plugin infrastructure */
+static inline struct xattr_handler *
+find_xattr_handler_prefix(struct xattr_handler **handlers,
+			   const char *name)
+{
+	struct xattr_handler *xah;
+
+	if (!handlers)
+		return NULL;
+
+	for_each_xattr_handler(handlers, xah) {
+		if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0)
+			break;
+	}
+
+	return xah;
+}
+
 
 /*
  * Inode operation getxattr()
- * Preliminary locking: we down dentry->d_inode->i_mutex
  */
 ssize_t
 reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 		  size_t size)
 {
-	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
-	int err;
+	struct inode *inode = dentry->d_inode;
+	struct xattr_handler *handler;
 
-	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
-	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	reiserfs_read_lock_xattr_i(dentry->d_inode);
-	reiserfs_read_lock_xattrs(dentry->d_sb);
-	err = xah->get(dentry->d_inode, name, buffer, size);
-	reiserfs_read_unlock_xattrs(dentry->d_sb);
-	reiserfs_read_unlock_xattr_i(dentry->d_inode);
-	return err;
+	return handler->get(inode, name, buffer, size);
 }
 
 /*
@@ -879,27 +759,15 @@
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
-	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
-	int err;
-	int lock;
+	struct inode *inode = dentry->d_inode;
+	struct xattr_handler *handler;
 
-	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
-	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	reiserfs_write_lock_xattr_i(dentry->d_inode);
-	lock = !has_xattr_dir(dentry->d_inode);
-	if (lock)
-		reiserfs_write_lock_xattrs(dentry->d_sb);
-	else
-		reiserfs_read_lock_xattrs(dentry->d_sb);
-	err = xah->set(dentry->d_inode, name, value, size, flags);
-	if (lock)
-		reiserfs_write_unlock_xattrs(dentry->d_sb);
-	else
-		reiserfs_read_unlock_xattrs(dentry->d_sb);
-	reiserfs_write_unlock_xattr_i(dentry->d_inode);
-	return err;
+	return handler->set(inode, name, value, size, flags);
 }
 
 /*
@@ -909,86 +777,66 @@
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
-	int err;
-	struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name);
+	struct inode *inode = dentry->d_inode;
+	struct xattr_handler *handler;
+	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
 
-	if (!xah || !reiserfs_xattrs(dentry->d_sb) ||
-	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	reiserfs_write_lock_xattr_i(dentry->d_inode);
-	reiserfs_read_lock_xattrs(dentry->d_sb);
-
-	/* Deletion pre-operation */
-	if (xah->del) {
-		err = xah->del(dentry->d_inode, name);
-		if (err)
-			goto out;
-	}
-
-	err = reiserfs_xattr_del(dentry->d_inode, name);
-
-	dentry->d_inode->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dentry->d_inode);
-
-      out:
-	reiserfs_read_unlock_xattrs(dentry->d_sb);
-	reiserfs_write_unlock_xattr_i(dentry->d_inode);
-	return err;
+	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
 }
 
-/* This is what filldir will use:
- * r_pos will always contain the amount of space required for the entire
- * list. If r_pos becomes larger than r_size, we need more space and we
- * return an error indicating this. If r_pos is less than r_size, then we've
- * filled the buffer successfully and we return success */
-struct reiserfs_listxattr_buf {
-	int r_pos;
-	int r_size;
-	char *r_buf;
-	struct inode *r_inode;
+struct listxattr_buf {
+	size_t size;
+	size_t pos;
+	char *buf;
+	struct inode *inode;
 };
 
-static int
-reiserfs_listxattr_filler(void *buf, const char *name, int namelen,
-			  loff_t offset, u64 ino, unsigned int d_type)
+static int listxattr_filler(void *buf, const char *name, int namelen,
+			    loff_t offset, u64 ino, unsigned int d_type)
 {
-	struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf;
-	int len = 0;
-	if (name[0] != '.'
-	    || (namelen != 1 && (name[1] != '.' || namelen != 2))) {
-		struct reiserfs_xattr_handler *xah =
-		    find_xattr_handler_prefix(name);
-		if (!xah)
-			return 0;	/* Unsupported xattr name, skip it */
-
-		/* We call ->list() twice because the operation isn't required to just
-		 * return the name back - we want to make sure we have enough space */
-		len += xah->list(b->r_inode, name, namelen, NULL);
-
-		if (len) {
-			if (b->r_pos + len + 1 <= b->r_size) {
-				char *p = b->r_buf + b->r_pos;
-				p += xah->list(b->r_inode, name, namelen, p);
-				*p++ = '\0';
-			}
-			b->r_pos += len + 1;
+	struct listxattr_buf *b = (struct listxattr_buf *)buf;
+	size_t size;
+	if (name[0] != '.' ||
+	    (namelen != 1 && (name[1] != '.' || namelen != 2))) {
+		struct xattr_handler *handler;
+		handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
+						    name);
+		if (!handler)	/* Unsupported xattr name */
+			return 0;
+		if (b->buf) {
+			size = handler->list(b->inode, b->buf + b->pos,
+					 b->size, name, namelen);
+			if (size > b->size)
+				return -ERANGE;
+		} else {
+			size = handler->list(b->inode, NULL, 0, name, namelen);
 		}
-	}
 
+		b->pos += size;
+	}
 	return 0;
 }
 
 /*
  * Inode operation listxattr()
  *
- * Preliminary locking: we down dentry->d_inode->i_mutex
+ * We totally ignore the generic listxattr here because it would be stupid
+ * not to. Since the xattrs are organized in a directory, we can just
+ * readdir to find them.
  */
 ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
 {
 	struct dentry *dir;
 	int err = 0;
-	struct reiserfs_listxattr_buf buf;
+	loff_t pos = 0;
+	struct listxattr_buf buf = {
+		.inode = dentry->d_inode,
+		.buf = buffer,
+		.size = buffer ? size : 0,
+	};
 
 	if (!dentry->d_inode)
 		return -EINVAL;
@@ -997,129 +845,103 @@
 	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	reiserfs_read_lock_xattr_i(dentry->d_inode);
-	reiserfs_read_lock_xattrs(dentry->d_sb);
-	dir = open_xa_dir(dentry->d_inode, FL_READONLY);
-	reiserfs_read_unlock_xattrs(dentry->d_sb);
+	dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
 	if (IS_ERR(dir)) {
 		err = PTR_ERR(dir);
 		if (err == -ENODATA)
-			err = 0;	/* Not an error if there aren't any xattrs */
+			err = 0;  /* Not an error if there aren't any xattrs */
 		goto out;
 	}
 
-	buf.r_buf = buffer;
-	buf.r_size = buffer ? size : 0;
-	buf.r_pos = 0;
-	buf.r_inode = dentry->d_inode;
+	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
+	err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos);
+	mutex_unlock(&dir->d_inode->i_mutex);
 
-	REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir;
+	if (!err)
+		err = buf.pos;
 
-	err = xattr_readdir(dir->d_inode, reiserfs_listxattr_filler, &buf);
-	if (err)
-		goto out_dir;
-
-	if (buf.r_pos > buf.r_size && buffer != NULL)
-		err = -ERANGE;
-	else
-		err = buf.r_pos;
-
-      out_dir:
 	dput(dir);
-
-      out:
-	reiserfs_read_unlock_xattr_i(dentry->d_inode);
+out:
 	return err;
 }
 
-/* This is the implementation for the xattr plugin infrastructure */
-static LIST_HEAD(xattr_handlers);
-static DEFINE_RWLOCK(handler_lock);
-
-static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
-								*prefix)
+static int reiserfs_check_acl(struct inode *inode, int mask)
 {
-	struct reiserfs_xattr_handler *xah = NULL;
-	struct list_head *p;
+	struct posix_acl *acl;
+	int error = -EAGAIN; /* do regular unix permission checks by default */
 
-	read_lock(&handler_lock);
-	list_for_each(p, &xattr_handlers) {
-		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
-		if (strncmp(xah->prefix, prefix, strlen(xah->prefix)) == 0)
-			break;
-		xah = NULL;
+	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
+
+	if (acl) {
+		if (!IS_ERR(acl)) {
+			error = posix_acl_permission(inode, acl, mask);
+			posix_acl_release(acl);
+		} else if (PTR_ERR(acl) != -ENODATA)
+			error = PTR_ERR(acl);
 	}
 
-	read_unlock(&handler_lock);
-	return xah;
+	return error;
 }
 
-static void __unregister_handlers(void)
+int reiserfs_permission(struct inode *inode, int mask)
 {
-	struct reiserfs_xattr_handler *xah;
-	struct list_head *p, *tmp;
-
-	list_for_each_safe(p, tmp, &xattr_handlers) {
-		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
-		if (xah->exit)
-			xah->exit();
-
-		list_del_init(p);
-	}
-	INIT_LIST_HEAD(&xattr_handlers);
-}
-
-int __init reiserfs_xattr_register_handlers(void)
-{
-	int err = 0;
-	struct reiserfs_xattr_handler *xah;
-	struct list_head *p;
-
-	write_lock(&handler_lock);
-
-	/* If we're already initialized, nothing to do */
-	if (!list_empty(&xattr_handlers)) {
-		write_unlock(&handler_lock);
+	/*
+	 * We don't do permission checks on the internal objects.
+	 * Permissions are determined by the "owning" object.
+	 */
+	if (IS_PRIVATE(inode))
 		return 0;
+	/*
+	 * Stat data v1 doesn't support ACLs.
+	 */
+	if (get_inode_sd_version(inode) == STAT_DATA_V1)
+		return generic_permission(inode, mask, NULL);
+	else
+		return generic_permission(inode, mask, reiserfs_check_acl);
+}
+
+static int create_privroot(struct dentry *dentry)
+{
+	int err;
+	struct inode *inode = dentry->d_parent->d_inode;
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
+	err = xattr_mkdir(inode, dentry, 0700);
+	mutex_unlock(&inode->i_mutex);
+	if (err) {
+		dput(dentry);
+		dentry = NULL;
 	}
 
-	/* Add the handlers */
-	list_add_tail(&user_handler.handlers, &xattr_handlers);
-	list_add_tail(&trusted_handler.handlers, &xattr_handlers);
-#ifdef CONFIG_REISERFS_FS_SECURITY
-	list_add_tail(&security_handler.handlers, &xattr_handlers);
-#endif
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-	list_add_tail(&posix_acl_access_handler.handlers, &xattr_handlers);
-	list_add_tail(&posix_acl_default_handler.handlers, &xattr_handlers);
-#endif
+	if (dentry && dentry->d_inode)
+		reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
+			      "storage.\n", PRIVROOT_NAME);
 
-	/* Run initializers, if available */
-	list_for_each(p, &xattr_handlers) {
-		xah = list_entry(p, struct reiserfs_xattr_handler, handlers);
-		if (xah->init) {
-			err = xah->init();
-			if (err) {
-				list_del_init(p);
-				break;
-			}
+	return err;
+}
+
+static int xattr_mount_check(struct super_block *s)
+{
+	/* We need generation numbers to ensure that the oid mapping is correct
+	 * v3.5 filesystems don't have them. */
+	if (old_format_only(s)) {
+		if (reiserfs_xattrs_optional(s)) {
+			/* Old format filesystem, but optional xattrs have
+			 * been enabled. Error out. */
+			reiserfs_warning(s, "jdm-2005",
+					 "xattrs/ACLs not supported "
+					 "on pre-v3.6 format filesystems. "
+					 "Failing mount.");
+			return -EOPNOTSUPP;
 		}
 	}
 
-	/* Clean up other handlers, if any failed */
-	if (err)
-		__unregister_handlers();
-
-	write_unlock(&handler_lock);
-	return err;
+	return 0;
 }
 
-void reiserfs_xattr_unregister_handlers(void)
-{
-	write_lock(&handler_lock);
-	__unregister_handlers();
-	write_unlock(&handler_lock);
-}
+#else
+int __init reiserfs_xattr_register_handlers(void) { return 0; }
+void reiserfs_xattr_unregister_handlers(void) {}
+#endif
 
 /* This will catch lookups from the fs root to .reiserfs_priv */
 static int
@@ -1147,48 +969,23 @@
 {
 	int err = 0;
 
-	/* We need generation numbers to ensure that the oid mapping is correct
-	 * v3.5 filesystems don't have them. */
-	if (!old_format_only(s)) {
-		set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
-	} else if (reiserfs_xattrs_optional(s)) {
-		/* Old format filesystem, but optional xattrs have been enabled
-		 * at mount time. Error out. */
-		reiserfs_warning(s, "xattrs/ACLs not supported on pre v3.6 "
-				 "format filesystem. Failing mount.");
-		err = -EOPNOTSUPP;
+#ifdef CONFIG_REISERFS_FS_XATTR
+	err = xattr_mount_check(s);
+	if (err)
 		goto error;
-	} else {
-		/* Old format filesystem, but no optional xattrs have been enabled. This
-		 * means we silently disable xattrs on the filesystem. */
-		clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
-	}
+#endif
 
 	/* If we don't have the privroot located yet - go find it */
-	if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) {
+	if (!REISERFS_SB(s)->priv_root) {
 		struct dentry *dentry;
 		dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
 					strlen(PRIVROOT_NAME));
 		if (!IS_ERR(dentry)) {
-			if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
-				struct inode *inode = dentry->d_parent->d_inode;
-				mutex_lock_nested(&inode->i_mutex,
-						  I_MUTEX_XATTR);
-				err = inode->i_op->mkdir(inode, dentry, 0700);
-				mutex_unlock(&inode->i_mutex);
-				if (err) {
-					dput(dentry);
-					dentry = NULL;
-				}
-
-				if (dentry && dentry->d_inode)
-					reiserfs_warning(s,
-							 "Created %s on %s - reserved for "
-							 "xattr storage.",
-							 PRIVROOT_NAME,
-							 reiserfs_bdevname
-							 (inode->i_sb));
-			} else if (!dentry->d_inode) {
+#ifdef CONFIG_REISERFS_FS_XATTR
+			if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
+				err = create_privroot(dentry);
+#endif
+			if (!dentry->d_inode) {
 				dput(dentry);
 				dentry = NULL;
 			}
@@ -1197,73 +994,41 @@
 
 		if (!err && dentry) {
 			s->s_root->d_op = &xattr_lookup_poison_ops;
-			reiserfs_mark_inode_private(dentry->d_inode);
+			dentry->d_inode->i_flags |= S_PRIVATE;
 			REISERFS_SB(s)->priv_root = dentry;
-		} else if (!(mount_flags & MS_RDONLY)) {	/* xattrs are unavailable */
-			/* If we're read-only it just means that the dir hasn't been
-			 * created. Not an error -- just no xattrs on the fs. We'll
-			 * check again if we go read-write */
-			reiserfs_warning(s, "xattrs/ACLs enabled and couldn't "
-					 "find/create .reiserfs_priv. Failing mount.");
+#ifdef CONFIG_REISERFS_FS_XATTR
+		/* xattrs are unavailable */
+		} else if (!(mount_flags & MS_RDONLY)) {
+			/* If we're read-only it just means that the dir
+			 * hasn't been created. Not an error -- just no
+			 * xattrs on the fs. We'll check again if we
+			 * go read-write */
+			reiserfs_warning(s, "jdm-20006",
+					 "xattrs/ACLs enabled and couldn't "
+					 "find/create .reiserfs_priv. "
+					 "Failing mount.");
 			err = -EOPNOTSUPP;
+#endif
 		}
 	}
 
-      error:
-	/* This is only nonzero if there was an error initializing the xattr
-	 * directory or if there is a condition where we don't support them. */
+#ifdef CONFIG_REISERFS_FS_XATTR
+	if (!err)
+		s->s_xattr = reiserfs_xattr_handlers;
+
+error:
 	if (err) {
-		clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
 		clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt));
 		clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt));
 	}
+#endif
 
 	/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
 	s->s_flags = s->s_flags & ~MS_POSIXACL;
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 	if (reiserfs_posixacl(s))
 		s->s_flags |= MS_POSIXACL;
+#endif
 
 	return err;
 }
-
-static int reiserfs_check_acl(struct inode *inode, int mask)
-{
-	struct posix_acl *acl;
-	int error = -EAGAIN; /* do regular unix permission checks by default */
-
-	reiserfs_read_lock_xattr_i(inode);
-	reiserfs_read_lock_xattrs(inode->i_sb);
-
-	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-
-	reiserfs_read_unlock_xattrs(inode->i_sb);
-	reiserfs_read_unlock_xattr_i(inode);
-
-	if (acl) {
-		if (!IS_ERR(acl)) {
-			error = posix_acl_permission(inode, acl, mask);
-			posix_acl_release(acl);
-		} else if (PTR_ERR(acl) != -ENODATA)
-			error = PTR_ERR(acl);
-	}
-
-	return error;
-}
-
-int reiserfs_permission(struct inode *inode, int mask)
-{
-	/*
-	 * We don't do permission checks on the internal objects.
-	 * Permissions are determined by the "owning" object.
-	 */
-	if (is_reiserfs_priv_object(inode))
-		return 0;
-
-	/*
-	 * Stat data v1 doesn't support ACLs.
-	 */
-	if (get_inode_sd_version(inode) == STAT_DATA_V1)
-		return generic_permission(inode, mask, NULL);
-	else
-		return generic_permission(inode, mask, reiserfs_check_acl);
-}
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index b7e4fa4..d423416 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -10,15 +10,17 @@
 #include <linux/reiserfs_acl.h>
 #include <asm/uaccess.h>
 
-static int reiserfs_set_acl(struct inode *inode, int type,
+static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
+			    struct inode *inode, int type,
 			    struct posix_acl *acl);
 
 static int
 xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
 {
 	struct posix_acl *acl;
-	int error;
-
+	int error, error2;
+	struct reiserfs_transaction_handle th;
+	size_t jcreate_blocks;
 	if (!reiserfs_posixacl(inode->i_sb))
 		return -EOPNOTSUPP;
 	if (!is_owner_or_cap(inode))
@@ -36,7 +38,21 @@
 	} else
 		acl = NULL;
 
-	error = reiserfs_set_acl(inode, type, acl);
+	/* Pessimism: We can't assume that anything from the xattr root up
+	 * has been created. */
+
+	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
+			 reiserfs_xattr_nblocks(inode, size) * 2;
+
+	reiserfs_write_lock(inode->i_sb);
+	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
+	if (error == 0) {
+		error = reiserfs_set_acl(&th, inode, type, acl);
+		error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
+		if (error2)
+			error = error2;
+	}
+	reiserfs_write_unlock(inode->i_sb);
 
       release_and_out:
 	posix_acl_release(acl);
@@ -172,6 +188,29 @@
 	return ERR_PTR(-EINVAL);
 }
 
+static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl,
+			    struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (*i_acl != ERR_PTR(-ENODATA))
+		posix_acl_release(*i_acl);
+	*i_acl = posix_acl_dup(acl);
+	spin_unlock(&inode->i_lock);
+}
+
+static inline struct posix_acl *iget_acl(struct inode *inode,
+					 struct posix_acl **i_acl)
+{
+	struct posix_acl *acl = ERR_PTR(-ENODATA);
+
+	spin_lock(&inode->i_lock);
+	if (*i_acl != ERR_PTR(-ENODATA))
+		acl = posix_acl_dup(*i_acl);
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
 /*
  * Inode operation get_posix_acl().
  *
@@ -199,11 +238,11 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (IS_ERR(*p_acl)) {
-		if (PTR_ERR(*p_acl) == -ENODATA)
-			return NULL;
-	} else if (*p_acl != NULL)
-		return posix_acl_dup(*p_acl);
+	acl = iget_acl(inode, p_acl);
+	if (acl && !IS_ERR(acl))
+		return acl;
+	else if (PTR_ERR(acl) == -ENODATA)
+		return NULL;
 
 	size = reiserfs_xattr_get(inode, name, NULL, 0);
 	if (size < 0) {
@@ -229,7 +268,7 @@
 	} else {
 		acl = posix_acl_from_disk(value, retval);
 		if (!IS_ERR(acl))
-			*p_acl = posix_acl_dup(acl);
+			iset_acl(inode, p_acl, acl);
 	}
 
 	kfree(value);
@@ -243,12 +282,13 @@
  * BKL held [before 2.5.x]
  */
 static int
-reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
+		 int type, struct posix_acl *acl)
 {
 	char *name;
 	void *value = NULL;
 	struct posix_acl **p_acl;
-	size_t size;
+	size_t size = 0;
 	int error;
 	struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
 
@@ -285,31 +325,28 @@
 		value = posix_acl_to_disk(acl, &size);
 		if (IS_ERR(value))
 			return (int)PTR_ERR(value);
-		error = reiserfs_xattr_set(inode, name, value, size, 0);
-	} else {
-		error = reiserfs_xattr_del(inode, name);
-		if (error == -ENODATA) {
-			/* This may seem odd here, but it means that the ACL was set
-			 * with a value representable with mode bits. If there was
-			 * an ACL before, reiserfs_xattr_del already dirtied the inode.
-			 */
+	}
+
+	error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
+
+	/*
+	 * Ensure that the inode gets dirtied if we're only using
+	 * the mode bits and an old ACL didn't exist. We don't need
+	 * to check if the inode is hashed here since we won't get
+	 * called by reiserfs_inherit_default_acl().
+	 */
+	if (error == -ENODATA) {
+		error = 0;
+		if (type == ACL_TYPE_ACCESS) {
+			inode->i_ctime = CURRENT_TIME_SEC;
 			mark_inode_dirty(inode);
-			error = 0;
 		}
 	}
 
 	kfree(value);
 
-	if (!error) {
-		/* Release the old one */
-		if (!IS_ERR(*p_acl) && *p_acl)
-			posix_acl_release(*p_acl);
-
-		if (acl == NULL)
-			*p_acl = ERR_PTR(-ENODATA);
-		else
-			*p_acl = posix_acl_dup(acl);
-	}
+	if (!error)
+		iset_acl(inode, p_acl, acl);
 
 	return error;
 }
@@ -317,7 +354,8 @@
 /* dir->i_mutex: locked,
  * inode is new and not released into the wild yet */
 int
-reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
+reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
+			     struct inode *dir, struct dentry *dentry,
 			     struct inode *inode)
 {
 	struct posix_acl *acl;
@@ -335,8 +373,8 @@
 	/* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
 	 * would be useless since permissions are ignored, and a pain because
 	 * it introduces locking cycles */
-	if (is_reiserfs_priv_object(dir)) {
-		reiserfs_mark_inode_private(inode);
+	if (IS_PRIVATE(dir)) {
+		inode->i_flags |= S_PRIVATE;
 		goto apply_umask;
 	}
 
@@ -354,7 +392,8 @@
 
 		/* Copy the default ACL to the default ACL of a new directory */
 		if (S_ISDIR(inode->i_mode)) {
-			err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+			err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
+					       acl);
 			if (err)
 				goto cleanup;
 		}
@@ -375,9 +414,9 @@
 
 			/* If we need an ACL.. */
 			if (need_acl > 0) {
-				err =
-				    reiserfs_set_acl(inode, ACL_TYPE_ACCESS,
-						     acl_copy);
+				err = reiserfs_set_acl(th, inode,
+						       ACL_TYPE_ACCESS,
+						       acl_copy);
 				if (err)
 					goto cleanup_copy;
 			}
@@ -395,25 +434,45 @@
 	return err;
 }
 
-/* Looks up and caches the result of the default ACL.
- * We do this so that we don't need to carry the xattr_sem into
- * reiserfs_new_inode if we don't need to */
+/* This is used to cache the default acl before a new object is created.
+ * The biggest reason for this is to get an idea of how many blocks will
+ * actually be required for the create operation if we must inherit an ACL.
+ * An ACL write can add up to 3 object creations and an additional file write
+ * so we'd prefer not to reserve that many blocks in the journal if we can.
+ * It also has the advantage of not loading the ACL with a transaction open,
+ * this may seem silly, but if the owner of the directory is doing the
+ * creation, the ACL may not be loaded since the permissions wouldn't require
+ * it.
+ * We return the number of blocks required for the transaction.
+ */
 int reiserfs_cache_default_acl(struct inode *inode)
 {
-	int ret = 0;
-	if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) {
-		struct posix_acl *acl;
-		reiserfs_read_lock_xattr_i(inode);
-		reiserfs_read_lock_xattrs(inode->i_sb);
-		acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
-		reiserfs_read_unlock_xattrs(inode->i_sb);
-		reiserfs_read_unlock_xattr_i(inode);
-		ret = (acl && !IS_ERR(acl));
-		if (ret)
-			posix_acl_release(acl);
+	struct posix_acl *acl;
+	int nblocks = 0;
+
+	if (IS_PRIVATE(inode))
+		return 0;
+
+	acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
+
+	if (acl && !IS_ERR(acl)) {
+		int size = reiserfs_acl_size(acl->a_count);
+
+		/* Other xattrs can be created during inode creation. We don't
+		 * want to claim too many blocks, so we check to see if we
+		 * we need to create the tree to the xattrs, and then we
+		 * just want two files. */
+		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
+		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+
+		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+
+		/* We need to account for writes + bitmaps for two files */
+		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
+		posix_acl_release(acl);
 	}
 
-	return ret;
+	return nblocks;
 }
 
 int reiserfs_acl_chmod(struct inode *inode)
@@ -429,9 +488,7 @@
 		return 0;
 	}
 
-	reiserfs_read_lock_xattrs(inode->i_sb);
 	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-	reiserfs_read_unlock_xattrs(inode->i_sb);
 	if (!acl)
 		return 0;
 	if (IS_ERR(acl))
@@ -442,18 +499,20 @@
 		return -ENOMEM;
 	error = posix_acl_chmod_masq(clone, inode->i_mode);
 	if (!error) {
-		int lock = !has_xattr_dir(inode);
-		reiserfs_write_lock_xattr_i(inode);
-		if (lock)
-			reiserfs_write_lock_xattrs(inode->i_sb);
-		else
-			reiserfs_read_lock_xattrs(inode->i_sb);
-		error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
-		if (lock)
-			reiserfs_write_unlock_xattrs(inode->i_sb);
-		else
-			reiserfs_read_unlock_xattrs(inode->i_sb);
-		reiserfs_write_unlock_xattr_i(inode);
+		struct reiserfs_transaction_handle th;
+		size_t size = reiserfs_xattr_nblocks(inode,
+					     reiserfs_acl_size(clone->a_count));
+		reiserfs_write_lock(inode->i_sb);
+		error = journal_begin(&th, inode->i_sb, size * 2);
+		if (!error) {
+			int error2;
+			error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
+						 clone);
+			error2 = journal_end(&th, inode->i_sb, size * 2);
+			if (error2)
+				error = error2;
+		}
+		reiserfs_write_unlock(inode->i_sb);
 	}
 	posix_acl_release(clone);
 	return error;
@@ -477,38 +536,22 @@
 	return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
 }
 
-static int posix_acl_access_del(struct inode *inode, const char *name)
+static size_t posix_acl_access_list(struct inode *inode, char *list,
+				    size_t list_size, const char *name,
+				    size_t name_len)
 {
-	struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
-	struct posix_acl **acl = &reiserfs_i->i_acl_access;
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
-		return -EINVAL;
-	if (!IS_ERR(*acl) && *acl) {
-		posix_acl_release(*acl);
-		*acl = ERR_PTR(-ENODATA);
-	}
-
-	return 0;
-}
-
-static int
-posix_acl_access_list(struct inode *inode, const char *name, int namelen,
-		      char *out)
-{
-	int len = namelen;
+	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 	if (!reiserfs_posixacl(inode->i_sb))
 		return 0;
-	if (out)
-		memcpy(out, name, len);
-
-	return len;
+	if (list && size <= list_size)
+		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
+	return size;
 }
 
-struct reiserfs_xattr_handler posix_acl_access_handler = {
+struct xattr_handler reiserfs_posix_acl_access_handler = {
 	.prefix = POSIX_ACL_XATTR_ACCESS,
 	.get = posix_acl_access_get,
 	.set = posix_acl_access_set,
-	.del = posix_acl_access_del,
 	.list = posix_acl_access_list,
 };
 
@@ -530,37 +573,21 @@
 	return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
 }
 
-static int posix_acl_default_del(struct inode *inode, const char *name)
+static size_t posix_acl_default_list(struct inode *inode, char *list,
+				     size_t list_size, const char *name,
+				     size_t name_len)
 {
-	struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
-	struct posix_acl **acl = &reiserfs_i->i_acl_default;
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
-		return -EINVAL;
-	if (!IS_ERR(*acl) && *acl) {
-		posix_acl_release(*acl);
-		*acl = ERR_PTR(-ENODATA);
-	}
-
-	return 0;
-}
-
-static int
-posix_acl_default_list(struct inode *inode, const char *name, int namelen,
-		       char *out)
-{
-	int len = namelen;
+	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 	if (!reiserfs_posixacl(inode->i_sb))
 		return 0;
-	if (out)
-		memcpy(out, name, len);
-
-	return len;
+	if (list && size <= list_size)
+		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
+	return size;
 }
 
-struct reiserfs_xattr_handler posix_acl_default_handler = {
+struct xattr_handler reiserfs_posix_acl_default_handler = {
 	.prefix = POSIX_ACL_XATTR_DEFAULT,
 	.get = posix_acl_default_get,
 	.set = posix_acl_default_set,
-	.del = posix_acl_default_del,
 	.list = posix_acl_default_list,
 };
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 056008d..4d3c20e 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -4,6 +4,7 @@
 #include <linux/pagemap.h>
 #include <linux/xattr.h>
 #include <linux/reiserfs_xattr.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 
 static int
@@ -12,7 +13,7 @@
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (is_reiserfs_priv_object(inode))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
 	return reiserfs_xattr_get(inode, name, buffer, size);
@@ -25,41 +26,84 @@
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (is_reiserfs_priv_object(inode))
+	if (IS_PRIVATE(inode))
 		return -EPERM;
 
 	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static int security_del(struct inode *inode, const char *name)
+static size_t security_list(struct inode *inode, char *list, size_t list_len,
+			    const char *name, size_t namelen)
 {
-	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
-		return -EINVAL;
+	const size_t len = namelen + 1;
 
-	if (is_reiserfs_priv_object(inode))
-		return -EPERM;
-
-	return 0;
-}
-
-static int
-security_list(struct inode *inode, const char *name, int namelen, char *out)
-{
-	int len = namelen;
-
-	if (is_reiserfs_priv_object(inode))
+	if (IS_PRIVATE(inode))
 		return 0;
 
-	if (out)
-		memcpy(out, name, len);
+	if (list && len <= list_len) {
+		memcpy(list, name, namelen);
+		list[namelen] = '\0';
+	}
 
 	return len;
 }
 
-struct reiserfs_xattr_handler security_handler = {
+/* Initializes the security context for a new inode and returns the number
+ * of blocks needed for the transaction. If successful, reiserfs_security
+ * must be released using reiserfs_security_free when the caller is done. */
+int reiserfs_security_init(struct inode *dir, struct inode *inode,
+			   struct reiserfs_security_handle *sec)
+{
+	int blocks = 0;
+	int error = security_inode_init_security(inode, dir, &sec->name,
+						 &sec->value, &sec->length);
+	if (error) {
+		if (error == -EOPNOTSUPP)
+			error = 0;
+
+		sec->name = NULL;
+		sec->value = NULL;
+		sec->length = 0;
+		return error;
+	}
+
+	if (sec->length) {
+		blocks = reiserfs_xattr_jcreate_nblocks(inode) +
+			 reiserfs_xattr_nblocks(inode, sec->length);
+		/* We don't want to count the directories twice if we have
+		 * a default ACL. */
+		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+	}
+	return blocks;
+}
+
+int reiserfs_security_write(struct reiserfs_transaction_handle *th,
+			    struct inode *inode,
+			    struct reiserfs_security_handle *sec)
+{
+	int error;
+	if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
+		return -EINVAL;
+
+	error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
+					  sec->length, XATTR_CREATE);
+	if (error == -ENODATA || error == -EOPNOTSUPP)
+		error = 0;
+
+	return error;
+}
+
+void reiserfs_security_free(struct reiserfs_security_handle *sec)
+{
+	kfree(sec->name);
+	kfree(sec->value);
+	sec->name = NULL;
+	sec->value = NULL;
+}
+
+struct xattr_handler reiserfs_xattr_security_handler = {
 	.prefix = XATTR_SECURITY_PREFIX,
 	.get = security_get,
 	.set = security_set,
-	.del = security_del,
 	.list = security_list,
 };
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index 60abe2b..a865042 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -13,10 +13,7 @@
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!reiserfs_xattrs(inode->i_sb))
-		return -EOPNOTSUPP;
-
-	if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
 	return reiserfs_xattr_get(inode, name, buffer, size);
@@ -29,50 +26,30 @@
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!reiserfs_xattrs(inode->i_sb))
-		return -EOPNOTSUPP;
-
-	if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return -EPERM;
 
 	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static int trusted_del(struct inode *inode, const char *name)
+static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
+			   const char *name, size_t name_len)
 {
-	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
-		return -EINVAL;
+	const size_t len = name_len + 1;
 
-	if (!reiserfs_xattrs(inode->i_sb))
-		return -EOPNOTSUPP;
-
-	if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
-		return -EPERM;
-
-	return 0;
-}
-
-static int
-trusted_list(struct inode *inode, const char *name, int namelen, char *out)
-{
-	int len = namelen;
-
-	if (!reiserfs_xattrs(inode->i_sb))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
 		return 0;
 
-	if (!(capable(CAP_SYS_ADMIN) || is_reiserfs_priv_object(inode)))
-		return 0;
-
-	if (out)
-		memcpy(out, name, len);
-
+	if (list && len <= list_size) {
+		memcpy(list, name, name_len);
+		list[name_len] = '\0';
+	}
 	return len;
 }
 
-struct reiserfs_xattr_handler trusted_handler = {
+struct xattr_handler reiserfs_xattr_trusted_handler = {
 	.prefix = XATTR_TRUSTED_PREFIX,
 	.get = trusted_get,
 	.set = trusted_set,
-	.del = trusted_del,
 	.list = trusted_list,
 };
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 1384efc..e3238dc 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -6,10 +6,6 @@
 #include <linux/reiserfs_xattr.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-# include <linux/reiserfs_acl.h>
-#endif
-
 static int
 user_get(struct inode *inode, const char *name, void *buffer, size_t size)
 {
@@ -25,7 +21,6 @@
 user_set(struct inode *inode, const char *name, const void *buffer,
 	 size_t size, int flags)
 {
-
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
@@ -34,33 +29,23 @@
 	return reiserfs_xattr_set(inode, name, buffer, size, flags);
 }
 
-static int user_del(struct inode *inode, const char *name)
+static size_t user_list(struct inode *inode, char *list, size_t list_size,
+			const char *name, size_t name_len)
 {
-	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
-		return -EINVAL;
+	const size_t len = name_len + 1;
 
 	if (!reiserfs_xattrs_user(inode->i_sb))
-		return -EOPNOTSUPP;
-	return 0;
-}
-
-static int
-user_list(struct inode *inode, const char *name, int namelen, char *out)
-{
-	int len = namelen;
-	if (!reiserfs_xattrs_user(inode->i_sb))
 		return 0;
-
-	if (out)
-		memcpy(out, name, len);
-
+	if (list && len <= list_size) {
+		memcpy(list, name, name_len);
+		list[name_len] = '\0';
+	}
 	return len;
 }
 
-struct reiserfs_xattr_handler user_handler = {
+struct xattr_handler reiserfs_xattr_user_handler = {
 	.prefix = XATTR_USER_PREFIX,
 	.get = user_get,
 	.set = user_set,
-	.del = user_del,
 	.list = user_list,
 };
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e9581fd..a67b622 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -158,8 +158,6 @@
 header-y += un.h
 header-y += utime.h
 header-y += veth.h
-header-y += video_decoder.h
-header-y += video_encoder.h
 header-y += videotext.h
 header-y += x25.h
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7787773..1db9bbf 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -125,4 +125,21 @@
  */
 struct clk *clk_get_parent(struct clk *clk);
 
+/**
+ * clk_get_sys - get a clock based upon the device name
+ * @dev_id: device name
+ * @con_id: connection ID
+ *
+ * Returns a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno.  The implementation
+ * uses @dev_id and @con_id to determine the clock consumer, and
+ * thereby the clock producer. In contrast to clk_get() this function
+ * takes the device name instead of the device itself for identification.
+ *
+ * Drivers must assume that the clock source is not enabled.
+ *
+ * clk_get_sys should not be called from within interrupt context.
+ */
+struct clk *clk_get_sys(const char *dev_id, const char *con_id);
+
 #endif
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index f284407..2f34274 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -24,10 +24,10 @@
 #include <linux/acpi.h>
 #include <linux/types.h>
 #include <linux/msi.h>
+#include <linux/irqreturn.h>
 
-#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
 struct intel_iommu;
-
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
 struct dmar_drhd_unit {
 	struct list_head list;		/* list of drhd units	*/
 	struct  acpi_dmar_header *hdr;	/* ACPI header		*/
@@ -49,7 +49,7 @@
 
 /* Intel IOMMU detection */
 extern void detect_intel_iommu(void);
-
+extern int enable_drhd_fault_handling(void);
 
 extern int parse_ioapics_under_ir(void);
 extern int alloc_iommu(struct dmar_drhd_unit *);
@@ -63,12 +63,12 @@
 {
 	return -ENODEV;
 }
+static inline int enable_drhd_fault_handling(void)
+{
+	return -1;
+}
 #endif /* !CONFIG_DMAR && !CONFIG_INTR_REMAP */
 
-#ifdef CONFIG_INTR_REMAP
-extern int intr_remapping_enabled;
-extern int enable_intr_remapping(int);
-
 struct irte {
 	union {
 		struct {
@@ -97,6 +97,10 @@
 		__u64 high;
 	};
 };
+#ifdef CONFIG_INTR_REMAP
+extern int intr_remapping_enabled;
+extern int enable_intr_remapping(int);
+
 extern int get_irte(int irq, struct irte *entry);
 extern int modify_irte(int irq, struct irte *irte_modified);
 extern int alloc_irte(struct intel_iommu *iommu, int irq, u16 count);
@@ -111,14 +115,40 @@
 extern struct intel_iommu *map_dev_to_ir(struct pci_dev *dev);
 extern struct intel_iommu *map_ioapic_to_ir(int apic);
 #else
+static inline int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
+{
+	return -1;
+}
+static inline int modify_irte(int irq, struct irte *irte_modified)
+{
+	return -1;
+}
+static inline int free_irte(int irq)
+{
+	return -1;
+}
+static inline int map_irq_to_irte_handle(int irq, u16 *sub_handle)
+{
+	return -1;
+}
+static inline int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index,
+			       u16 sub_handle)
+{
+	return -1;
+}
+static inline struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
+{
+	return NULL;
+}
+static inline struct intel_iommu *map_ioapic_to_ir(int apic)
+{
+	return NULL;
+}
 #define irq_remapped(irq)		(0)
 #define enable_intr_remapping(mode)	(-1)
 #define intr_remapping_enabled		(0)
 #endif
 
-#ifdef CONFIG_DMAR
-extern const char *dmar_get_fault_reason(u8 fault_reason);
-
 /* Can't use the common MSI interrupt functions
  * since DMAR is not a pci device
  */
@@ -127,8 +157,10 @@
 extern void dmar_msi_read(int irq, struct msi_msg *msg);
 extern void dmar_msi_write(int irq, struct msi_msg *msg);
 extern int dmar_set_interrupt(struct intel_iommu *iommu);
+extern irqreturn_t dmar_fault(int irq, void *dev_id);
 extern int arch_setup_dmar_msi(unsigned int irq);
 
+#ifdef CONFIG_DMAR
 extern int iommu_detected, no_iommu;
 extern struct list_head dmar_rmrr_units;
 struct dmar_rmrr_unit {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 42436ae..87e7bfc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -849,7 +849,7 @@
 #define f_dentry	f_path.dentry
 #define f_vfsmnt	f_path.mnt
 	const struct file_operations	*f_op;
-	spinlock_t		f_lock;  /* f_ep_links, f_flags */
+	spinlock_t		f_lock;  /* f_ep_links, f_flags, no IRQ */
 	atomic_long_t		f_count;
 	unsigned int 		f_flags;
 	fmode_t			f_mode;
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index a97c053..18b467d 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -4,7 +4,10 @@
 #include <linux/path.h>
 
 struct fs_struct {
-	atomic_t count;
+	atomic_t count;	/* This usage count is used by check_unsafe_exec() for
+			 * security checking purposes - therefore it may not be
+			 * incremented, except by clone(CLONE_FS).
+			 */
 	rwlock_t lock;
 	int umask;
 	struct path root, pwd;
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 677432b..a7f8134 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -380,6 +380,30 @@
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
 /*
+ * Stack of return addresses for functions
+ * of a thread.
+ * Used in struct thread_info
+ */
+struct ftrace_ret_stack {
+	unsigned long ret;
+	unsigned long func;
+	unsigned long long calltime;
+};
+
+/*
+ * Primary handler of a function return.
+ * It relays on ftrace_return_to_handler.
+ * Defined in entry_32/64.S
+ */
+extern void return_to_handler(void);
+
+extern int
+ftrace_push_return_trace(unsigned long ret, unsigned long long time,
+			 unsigned long func, int *depth);
+extern void
+ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret);
+
+/*
  * Sometimes we don't want to trace a function with the function
  * graph tracer but we want them to keep traced by the usual function
  * tracer if the function graph tracer is not configured.
diff --git a/include/linux/i2c-algo-pca.h b/include/linux/i2c-algo-pca.h
index adcb3dc..1364d62 100644
--- a/include/linux/i2c-algo-pca.h
+++ b/include/linux/i2c-algo-pca.h
@@ -1,7 +1,14 @@
 #ifndef _LINUX_I2C_ALGO_PCA_H
 #define _LINUX_I2C_ALGO_PCA_H
 
-/* Clock speeds for the bus */
+/* Chips known to the pca algo */
+#define I2C_PCA_CHIP_9564	0x00
+#define I2C_PCA_CHIP_9665	0x01
+
+/* Internal period for PCA9665 oscilator */
+#define I2C_PCA_OSC_PER		3 /* e10-8s */
+
+/* Clock speeds for the bus for PCA9564*/
 #define I2C_PCA_CON_330kHz	0x00
 #define I2C_PCA_CON_288kHz	0x01
 #define I2C_PCA_CON_217kHz	0x02
@@ -18,6 +25,26 @@
 #define I2C_PCA_ADR		0x02 /* OWN ADR Read/Write */
 #define I2C_PCA_CON		0x03 /* CONTROL Read/Write */
 
+/* PCA9665 registers */
+#define I2C_PCA_INDPTR          0x00 /* INDIRECT Pointer Write Only */
+#define I2C_PCA_IND             0x02 /* INDIRECT Read/Write */
+
+/* PCA9665 indirect registers */
+#define I2C_PCA_ICOUNT          0x00 /* Byte Count for buffered mode */
+#define I2C_PCA_IADR            0x01 /* OWN ADR */
+#define I2C_PCA_ISCLL           0x02 /* SCL LOW period */
+#define I2C_PCA_ISCLH           0x03 /* SCL HIGH period */
+#define I2C_PCA_ITO             0x04 /* TIMEOUT */
+#define I2C_PCA_IPRESET         0x05 /* Parallel bus reset */
+#define I2C_PCA_IMODE           0x06 /* I2C Bus mode */
+
+/* PCA9665 I2C bus mode */
+#define I2C_PCA_MODE_STD        0x00 /* Standard mode */
+#define I2C_PCA_MODE_FAST       0x01 /* Fast mode */
+#define I2C_PCA_MODE_FASTP      0x02 /* Fast Plus mode */
+#define I2C_PCA_MODE_TURBO      0x03 /* Turbo mode */
+
+
 #define I2C_PCA_CON_AA		0x80 /* Assert Acknowledge */
 #define I2C_PCA_CON_ENSIO	0x40 /* Enable */
 #define I2C_PCA_CON_STA		0x20 /* Start */
@@ -31,7 +58,9 @@
 	int  (*read_byte)		(void *data, int reg);
 	int  (*wait_for_completion)	(void *data);
 	void (*reset_chip)		(void *data);
-	/* i2c_clock values are defined in linux/i2c-algo-pca.h */
+	/* For PCA9564, use one of the predefined frequencies:
+	 * 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000
+	 * For PCA9665, use the frequency you want here. */
 	unsigned int			i2c_clock;
 };
 
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 1ffc23b..f27604a 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -71,6 +71,7 @@
 #define I2C_DRIVERID_VP27SMPX	93	/* Panasonic VP27s tuner internal MPX */
 #define I2C_DRIVERID_M52790 	95      /* Mitsubishi M52790SP/FP AV switch */
 #define I2C_DRIVERID_CS5345	96	/* cs5345 audio processor	*/
+#define I2C_DRIVERID_AU8522	97	/* Auvitek au8522       */
 
 #define I2C_DRIVERID_OV7670 1048	/* Omnivision 7670 camera */
 
@@ -87,6 +88,7 @@
 #define I2C_HW_B_CX2341X	0x010020 /* Conexant CX2341X MPEG encoder cards */
 #define I2C_HW_B_CX23885	0x010022 /* conexant 23885 based tv cards (bus1) */
 #define I2C_HW_B_AU0828		0x010023 /* auvitek au0828 usb bridge */
+#define I2C_HW_B_HDPVR		0x010025 /* Hauppauge HD PVR */
 
 /* --- SGI adapters							*/
 #define I2C_HW_SGI_VINO		0x160000
diff --git a/include/linux/i2c-pca-platform.h b/include/linux/i2c-pca-platform.h
index 3d19187..aba3375 100644
--- a/include/linux/i2c-pca-platform.h
+++ b/include/linux/i2c-pca-platform.h
@@ -6,7 +6,7 @@
 				 * not supplied (negative value), but it
 				 * cannot exit some error conditions then */
 	int i2c_clock_speed;	/* values are defined in linux/i2c-algo-pca.h */
-	int timeout;		/* timeout = this value * 10us */
+	int timeout;		/* timeout in jiffies */
 };
 
 #endif /* I2C_PCA9564_PLATFORM_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 854eba8..d5d8322 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -40,6 +40,13 @@
 #define ERROR_RESET	3	/* Reset controller every 4th retry */
 #define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
 
+/* Error codes returned in rq->errors to the higher part of the driver. */
+enum {
+	IDE_DRV_ERROR_GENERAL	= 101,
+	IDE_DRV_ERROR_FILEMARK	= 102,
+	IDE_DRV_ERROR_EOD	= 103,
+};
+
 /*
  * Definitions for accessing IDE controller registers
  */
@@ -193,26 +200,8 @@
 	hw->io_ports.ctl_addr = ctl_addr;
 }
 
-#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
-    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
-#include <asm/ide.h>
-#else
-#include <asm-generic/ide_iops.h>
-#endif
-
 #define MAX_HWIFS	10
 
-/* Currently only m68k, apus and m8xx need it */
-#ifndef IDE_ARCH_ACK_INTR
-# define ide_ack_intr(hwif) (1)
-#endif
-
-/* Currently only Atari needs it */
-#ifndef IDE_ARCH_LOCK
-# define ide_release_lock()			do {} while (0)
-# define ide_get_lock(hdlr, data)		do {} while (0)
-#endif /* IDE_ARCH_LOCK */
-
 /*
  * Now for the data we need to maintain per-drive:  ide_drive_t
  */
@@ -252,56 +241,52 @@
 
 enum {
 	IDE_TFLAG_LBA48			= (1 << 0),
-	IDE_TFLAG_FLAGGED		= (1 << 2),
-	IDE_TFLAG_OUT_DATA		= (1 << 3),
-	IDE_TFLAG_OUT_HOB_FEATURE	= (1 << 4),
-	IDE_TFLAG_OUT_HOB_NSECT		= (1 << 5),
-	IDE_TFLAG_OUT_HOB_LBAL		= (1 << 6),
-	IDE_TFLAG_OUT_HOB_LBAM		= (1 << 7),
-	IDE_TFLAG_OUT_HOB_LBAH		= (1 << 8),
+	IDE_TFLAG_OUT_HOB_FEATURE	= (1 << 1),
+	IDE_TFLAG_OUT_HOB_NSECT		= (1 << 2),
+	IDE_TFLAG_OUT_HOB_LBAL		= (1 << 3),
+	IDE_TFLAG_OUT_HOB_LBAM		= (1 << 4),
+	IDE_TFLAG_OUT_HOB_LBAH		= (1 << 5),
 	IDE_TFLAG_OUT_HOB		= IDE_TFLAG_OUT_HOB_FEATURE |
 					  IDE_TFLAG_OUT_HOB_NSECT |
 					  IDE_TFLAG_OUT_HOB_LBAL |
 					  IDE_TFLAG_OUT_HOB_LBAM |
 					  IDE_TFLAG_OUT_HOB_LBAH,
-	IDE_TFLAG_OUT_FEATURE		= (1 << 9),
-	IDE_TFLAG_OUT_NSECT		= (1 << 10),
-	IDE_TFLAG_OUT_LBAL		= (1 << 11),
-	IDE_TFLAG_OUT_LBAM		= (1 << 12),
-	IDE_TFLAG_OUT_LBAH		= (1 << 13),
+	IDE_TFLAG_OUT_FEATURE		= (1 << 6),
+	IDE_TFLAG_OUT_NSECT		= (1 << 7),
+	IDE_TFLAG_OUT_LBAL		= (1 << 8),
+	IDE_TFLAG_OUT_LBAM		= (1 << 9),
+	IDE_TFLAG_OUT_LBAH		= (1 << 10),
 	IDE_TFLAG_OUT_TF		= IDE_TFLAG_OUT_FEATURE |
 					  IDE_TFLAG_OUT_NSECT |
 					  IDE_TFLAG_OUT_LBAL |
 					  IDE_TFLAG_OUT_LBAM |
 					  IDE_TFLAG_OUT_LBAH,
-	IDE_TFLAG_OUT_DEVICE		= (1 << 14),
-	IDE_TFLAG_WRITE			= (1 << 15),
-	IDE_TFLAG_FLAGGED_SET_IN_FLAGS	= (1 << 16),
-	IDE_TFLAG_IN_DATA		= (1 << 17),
-	IDE_TFLAG_CUSTOM_HANDLER	= (1 << 18),
-	IDE_TFLAG_DMA_PIO_FALLBACK	= (1 << 19),
-	IDE_TFLAG_IN_HOB_FEATURE	= (1 << 20),
-	IDE_TFLAG_IN_HOB_NSECT		= (1 << 21),
-	IDE_TFLAG_IN_HOB_LBAL		= (1 << 22),
-	IDE_TFLAG_IN_HOB_LBAM		= (1 << 23),
-	IDE_TFLAG_IN_HOB_LBAH		= (1 << 24),
+	IDE_TFLAG_OUT_DEVICE		= (1 << 11),
+	IDE_TFLAG_WRITE			= (1 << 12),
+	IDE_TFLAG_CUSTOM_HANDLER	= (1 << 13),
+	IDE_TFLAG_DMA_PIO_FALLBACK	= (1 << 14),
+	IDE_TFLAG_IN_HOB_FEATURE	= (1 << 15),
+	IDE_TFLAG_IN_HOB_NSECT		= (1 << 16),
+	IDE_TFLAG_IN_HOB_LBAL		= (1 << 17),
+	IDE_TFLAG_IN_HOB_LBAM		= (1 << 18),
+	IDE_TFLAG_IN_HOB_LBAH		= (1 << 19),
 	IDE_TFLAG_IN_HOB_LBA		= IDE_TFLAG_IN_HOB_LBAL |
 					  IDE_TFLAG_IN_HOB_LBAM |
 					  IDE_TFLAG_IN_HOB_LBAH,
 	IDE_TFLAG_IN_HOB		= IDE_TFLAG_IN_HOB_FEATURE |
 					  IDE_TFLAG_IN_HOB_NSECT |
 					  IDE_TFLAG_IN_HOB_LBA,
-	IDE_TFLAG_IN_FEATURE		= (1 << 1),
-	IDE_TFLAG_IN_NSECT		= (1 << 25),
-	IDE_TFLAG_IN_LBAL		= (1 << 26),
-	IDE_TFLAG_IN_LBAM		= (1 << 27),
-	IDE_TFLAG_IN_LBAH		= (1 << 28),
+	IDE_TFLAG_IN_FEATURE		= (1 << 20),
+	IDE_TFLAG_IN_NSECT		= (1 << 21),
+	IDE_TFLAG_IN_LBAL		= (1 << 22),
+	IDE_TFLAG_IN_LBAM		= (1 << 23),
+	IDE_TFLAG_IN_LBAH		= (1 << 24),
 	IDE_TFLAG_IN_LBA		= IDE_TFLAG_IN_LBAL |
 					  IDE_TFLAG_IN_LBAM |
 					  IDE_TFLAG_IN_LBAH,
 	IDE_TFLAG_IN_TF			= IDE_TFLAG_IN_NSECT |
 					  IDE_TFLAG_IN_LBA,
-	IDE_TFLAG_IN_DEVICE		= (1 << 29),
+	IDE_TFLAG_IN_DEVICE		= (1 << 25),
 	IDE_TFLAG_HOB			= IDE_TFLAG_OUT_HOB |
 					  IDE_TFLAG_IN_HOB,
 	IDE_TFLAG_TF			= IDE_TFLAG_OUT_TF |
@@ -309,9 +294,18 @@
 	IDE_TFLAG_DEVICE		= IDE_TFLAG_OUT_DEVICE |
 					  IDE_TFLAG_IN_DEVICE,
 	/* force 16-bit I/O operations */
-	IDE_TFLAG_IO_16BIT		= (1 << 30),
-	/* ide_task_t was allocated using kmalloc() */
-	IDE_TFLAG_DYN			= (1 << 31),
+	IDE_TFLAG_IO_16BIT		= (1 << 26),
+	/* struct ide_cmd was allocated using kmalloc() */
+	IDE_TFLAG_DYN			= (1 << 27),
+	IDE_TFLAG_FS			= (1 << 28),
+	IDE_TFLAG_MULTI_PIO		= (1 << 29),
+};
+
+enum {
+	IDE_FTFLAG_FLAGGED		= (1 << 0),
+	IDE_FTFLAG_SET_IN_FLAGS		= (1 << 1),
+	IDE_FTFLAG_OUT_DATA		= (1 << 2),
+	IDE_FTFLAG_IN_DATA		= (1 << 3),
 };
 
 struct ide_taskfile {
@@ -343,16 +337,27 @@
 	};
 };
 
-typedef struct ide_task_s {
+struct ide_cmd {
 	union {
 		struct ide_taskfile	tf;
 		u8			tf_array[14];
 	};
+	u8			ftf_flags;	/* for TASKFILE ioctl */
 	u32			tf_flags;
-	int			data_phase;
+	int			protocol;
+
+	int			sg_nents;	  /* number of sg entries */
+	int			orig_sg_nents;
+	int			sg_dma_direction; /* DMA transfer direction */
+
+	unsigned int		nbytes;
+	unsigned int		nleft;
+	struct scatterlist	*cursg;
+	unsigned int		cursg_ofs;
+
 	struct request		*rq;		/* copy of request */
 	void			*special;	/* valid_t generally */
-} ide_task_t;
+};
 
 /* ATAPI packet command flags */
 enum {
@@ -364,8 +369,6 @@
 	PC_FLAG_DMA_IN_PROGRESS		= (1 << 4),
 	PC_FLAG_DMA_ERROR		= (1 << 5),
 	PC_FLAG_WRITING			= (1 << 6),
-	/* command timed out */
-	PC_FLAG_TIMEDOUT		= (1 << 7),
 };
 
 /*
@@ -436,7 +439,6 @@
 					int);
 	ide_startstop_t	(*do_request)(struct ide_drive_s *, struct request *,
 				      sector_t);
-	int		(*end_request)(struct ide_drive_s *, int, int);
 	int		(*ioctl)(struct ide_drive_s *, struct block_device *,
 				 fmode_t, unsigned int, unsigned long);
 };
@@ -512,8 +514,6 @@
 	IDE_DFLAG_NICE1			= (1 << 5),
 	/* device is physically present */
 	IDE_DFLAG_PRESENT		= (1 << 6),
-	/* device ejected hint */
-	IDE_DFLAG_DEAD			= (1 << 7),
 	/* id read from device (synthetic if not set) */
 	IDE_DFLAG_ID_READ		= (1 << 8),
 	IDE_DFLAG_NOPROBE		= (1 << 9),
@@ -627,8 +627,11 @@
 	/* current packet command */
 	struct ide_atapi_pc *pc;
 
+	/* last failed packet command */
+	struct ide_atapi_pc *failed_pc;
+
 	/* callback for packet commands */
-	void (*pc_callback)(struct ide_drive_s *, int);
+	int  (*pc_callback)(struct ide_drive_s *, int);
 
 	void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
 	int  (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
@@ -661,13 +664,13 @@
 
 	void	(*set_irq)(struct hwif_s *, int);
 
-	void	(*tf_load)(ide_drive_t *, struct ide_task_s *);
-	void	(*tf_read)(ide_drive_t *, struct ide_task_s *);
+	void	(*tf_load)(ide_drive_t *, struct ide_cmd *);
+	void	(*tf_read)(ide_drive_t *, struct ide_cmd *);
 
-	void	(*input_data)(ide_drive_t *, struct request *, void *,
-			      unsigned int);
-	void	(*output_data)(ide_drive_t *, struct request *, void *,
-			       unsigned int);
+	void	(*input_data)(ide_drive_t *, struct ide_cmd *,
+			      void *, unsigned int);
+	void	(*output_data)(ide_drive_t *, struct ide_cmd *,
+			       void *, unsigned int);
 };
 
 extern const struct ide_tp_ops default_tp_ops;
@@ -711,12 +714,12 @@
 
 struct ide_dma_ops {
 	void	(*dma_host_set)(struct ide_drive_s *, int);
-	int	(*dma_setup)(struct ide_drive_s *);
-	void	(*dma_exec_cmd)(struct ide_drive_s *, u8);
+	int	(*dma_setup)(struct ide_drive_s *, struct ide_cmd *);
 	void	(*dma_start)(struct ide_drive_s *);
 	int	(*dma_end)(struct ide_drive_s *);
 	int	(*dma_test_irq)(struct ide_drive_s *);
 	void	(*dma_lost_irq)(struct ide_drive_s *);
+	int	(*dma_timer_expiry)(struct ide_drive_s *);
 	void	(*dma_timeout)(struct ide_drive_s *);
 	/*
 	 * The following method is optional and only required to be
@@ -780,19 +783,8 @@
 	/* Scatter-gather list used to build the above */
 	struct scatterlist *sg_table;
 	int sg_max_nents;		/* Maximum number of entries in it */
-	int sg_nents;			/* Current number of entries in it */
-	int orig_sg_nents;
-	int sg_dma_direction;		/* dma transfer direction */
 
-	/* data phase of the active command (currently only valid for PIO/DMA) */
-	int		data_phase;
-
-	struct ide_task_s task;		/* current command */
-
-	unsigned int nsect;
-	unsigned int nleft;
-	struct scatterlist *cursg;
-	unsigned int cursg_ofs;
+	struct ide_cmd cmd;		/* current command */
 
 	int		rqsize;		/* max sectors per request */
 	int		irq;		/* our irq number */
@@ -850,9 +842,18 @@
 	ide_hwif_t	*ports[MAX_HOST_PORTS + 1];
 	unsigned int	n_ports;
 	struct device	*dev[2];
+
 	int		(*init_chipset)(struct pci_dev *);
+
+	void		(*get_lock)(irq_handler_t, void *);
+	void		(*release_lock)(void);
+
 	irq_handler_t	irq_handler;
+
 	unsigned long	host_flags;
+
+	int		irq_flags;
+
 	void		*host_priv;
 	ide_hwif_t	*cur_port;	/* for hosts requiring serialization */
 
@@ -869,7 +870,7 @@
 typedef int (ide_expiry_t)(ide_drive_t *);
 
 /* used by ide-cd, ide-floppy, etc. */
-typedef void (xfer_func_t)(ide_drive_t *, struct request *rq, void *, unsigned);
+typedef void (xfer_func_t)(ide_drive_t *, struct ide_cmd *, void *, unsigned);
 
 extern struct mutex ide_setting_mtx;
 
@@ -1045,10 +1046,11 @@
 };
 
 /* DRV_NAME has to be defined in the driver before using the macro below */
-#define __ide_debug_log(lvl, fmt, args...)			\
-{								\
-	if (unlikely(drive->debug_mask & lvl))			\
-		printk(KERN_INFO DRV_NAME ": " fmt, ## args);	\
+#define __ide_debug_log(lvl, fmt, args...)				\
+{									\
+	if (unlikely(drive->debug_mask & lvl))				\
+		printk(KERN_INFO DRV_NAME ": %s: " fmt "\n",		\
+					  __func__, ## args);		\
 }
 
 /*
@@ -1087,7 +1089,7 @@
 
 void ide_complete_power_step(ide_drive_t *, struct request *);
 ide_startstop_t ide_start_power_step(ide_drive_t *, struct request *);
-void ide_complete_pm_request(ide_drive_t *, struct request *);
+void ide_complete_pm_rq(ide_drive_t *, struct request *);
 void ide_check_pm_state(ide_drive_t *, struct request *);
 
 /*
@@ -1099,7 +1101,6 @@
 struct ide_driver {
 	const char			*version;
 	ide_startstop_t	(*do_request)(ide_drive_t *, struct request *, sector_t);
-	int		(*end_request)(ide_drive_t *, int, int);
 	struct device_driver	gen_driver;
 	int		(*probe)(ide_drive_t *);
 	void		(*remove)(ide_drive_t *);
@@ -1130,19 +1131,15 @@
 extern int ide_vlb_clk;
 extern int ide_pci_clk;
 
-int ide_end_request(ide_drive_t *, int, int);
-int ide_end_dequeued_request(ide_drive_t *, struct request *, int, int);
+unsigned int ide_rq_bytes(struct request *);
+int ide_end_rq(ide_drive_t *, struct request *, int, unsigned int);
 void ide_kill_rq(ide_drive_t *, struct request *);
 
-void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
-		       ide_expiry_t *);
-void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
-		     ide_expiry_t *);
+void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int);
+void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int);
 
-void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
-			 ide_expiry_t *);
-
-void ide_execute_pkt_cmd(ide_drive_t *);
+void ide_execute_command(ide_drive_t *, struct ide_cmd *, ide_handler_t *,
+			 unsigned int);
 
 void ide_pad_transfer(ide_drive_t *, int, int);
 
@@ -1164,7 +1161,8 @@
 extern int ide_devset_execute(ide_drive_t *drive,
 			      const struct ide_devset *setting, int arg);
 
-extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
+void ide_complete_cmd(ide_drive_t *, struct ide_cmd *, u8, u8);
+int ide_complete_rq(ide_drive_t *, int, unsigned int);
 
 void ide_tf_dump(const char *, struct ide_taskfile *);
 
@@ -1174,11 +1172,11 @@
 
 void ide_set_irq(ide_hwif_t *, int);
 
-void ide_tf_load(ide_drive_t *, ide_task_t *);
-void ide_tf_read(ide_drive_t *, ide_task_t *);
+void ide_tf_load(ide_drive_t *, struct ide_cmd *);
+void ide_tf_read(ide_drive_t *, struct ide_cmd *);
 
-void ide_input_data(ide_drive_t *, struct request *, void *, unsigned int);
-void ide_output_data(ide_drive_t *, struct request *, void *, unsigned int);
+void ide_input_data(ide_drive_t *, struct ide_cmd *, void *, unsigned int);
+void ide_output_data(ide_drive_t *, struct ide_cmd *, void *, unsigned int);
 
 int ide_io_buffers(ide_drive_t *, struct ide_atapi_pc *, unsigned int, int);
 
@@ -1224,16 +1222,16 @@
 
 int ide_cd_get_xferlen(struct request *);
 
-ide_startstop_t ide_issue_pc(ide_drive_t *);
+ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_cmd *);
 
-ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
+ide_startstop_t do_rw_taskfile(ide_drive_t *, struct ide_cmd *);
 
-void task_end_request(ide_drive_t *, struct request *, u8);
+void ide_finish_cmd(ide_drive_t *, struct ide_cmd *, u8);
 
-int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *, u16);
-int ide_no_data_taskfile(ide_drive_t *, ide_task_t *);
+int ide_raw_taskfile(ide_drive_t *, struct ide_cmd *, u8 *, u16);
+int ide_no_data_taskfile(ide_drive_t *, struct ide_cmd *);
 
-int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
+int ide_taskfile_ioctl(ide_drive_t *, unsigned long);
 
 int ide_dev_read_id(ide_drive_t *, u8, u16 *);
 
@@ -1335,6 +1333,10 @@
 	IDE_HFLAG_ERROR_STOPS_FIFO	= (1 << 19),
 	/* serialize ports */
 	IDE_HFLAG_SERIALIZE		= (1 << 20),
+	/* host is DTC2278 */
+	IDE_HFLAG_DTC2278		= (1 << 21),
+	/* 4 devices on a single set of I/O ports */
+	IDE_HFLAG_4DRIVES		= (1 << 22),
 	/* host is TRM290 */
 	IDE_HFLAG_TRM290		= (1 << 23),
 	/* use 32-bit I/O ops */
@@ -1362,7 +1364,12 @@
 
 struct ide_port_info {
 	char			*name;
+
 	int			(*init_chipset)(struct pci_dev *);
+
+	void			(*get_lock)(irq_handler_t, void *);
+	void			(*release_lock)(void);
+
 	void			(*init_iops)(ide_hwif_t *);
 	void                    (*init_hwif)(ide_hwif_t *);
 	int			(*init_dma)(ide_hwif_t *,
@@ -1379,6 +1386,9 @@
 	u16			max_sectors;	/* if < than the default one */
 
 	u32			host_flags;
+
+	int			irq_flags;
+
 	u8			pio_mask;
 	u8			swdma_mask;
 	u8			mwdma_mask;
@@ -1398,8 +1408,8 @@
 #define ide_pci_resume NULL
 #endif
 
-void ide_map_sg(ide_drive_t *, struct request *);
-void ide_init_sg_cmd(ide_drive_t *, struct request *);
+void ide_map_sg(ide_drive_t *, struct ide_cmd *);
+void ide_init_sg_cmd(struct ide_cmd *, unsigned int);
 
 #define BAD_DMA_DRIVE		0
 #define GOOD_DMA_DRIVE		1
@@ -1433,18 +1443,18 @@
 int ide_allocate_dma_engine(ide_hwif_t *);
 void ide_release_dma_engine(ide_hwif_t *);
 
-int ide_build_sglist(ide_drive_t *, struct request *);
+int ide_build_sglist(ide_drive_t *, struct ide_cmd *);
 void ide_destroy_dmatable(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
 int config_drive_for_dma(ide_drive_t *);
-extern int ide_build_dmatable(ide_drive_t *, struct request *);
+int ide_build_dmatable(ide_drive_t *, struct ide_cmd *);
 void ide_dma_host_set(ide_drive_t *, int);
-extern int ide_dma_setup(ide_drive_t *);
-void ide_dma_exec_cmd(ide_drive_t *, u8);
+int ide_dma_setup(ide_drive_t *, struct ide_cmd *);
 extern void ide_dma_start(ide_drive_t *);
 int ide_dma_end(ide_drive_t *);
 int ide_dma_test_irq(ide_drive_t *);
+int ide_dma_sff_timer_expiry(ide_drive_t *);
 u8 ide_dma_sff_read_status(ide_hwif_t *);
 extern const struct ide_dma_ops sff_dma_ops;
 #else
@@ -1465,8 +1475,11 @@
 static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
 static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
 static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
+static inline ide_startstop_t ide_dma_intr(ide_drive_t *drive) { return ide_stopped; }
 static inline ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) { return ide_stopped; }
 static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
+static inline int ide_build_sglist(ide_drive_t *drive,
+				   struct ide_cmd *cmd) { return 0; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 4d6a0a2..1d6c71d 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -292,6 +292,8 @@
 	spinlock_t	register_lock; /* protect register handling */
 	int		seq_id;	/* sequence id of the iommu */
 	int		agaw; /* agaw of this iommu */
+	unsigned int 	irq;
+	unsigned char 	name[13];    /* Device Name */
 
 #ifdef CONFIG_DMAR
 	unsigned long 	*domain_ids; /* bitmap of domains */
@@ -299,8 +301,6 @@
 	spinlock_t	lock; /* protect context, domain ids */
 	struct root_entry *root_entry; /* virtual address */
 
-	unsigned int irq;
-	unsigned char name[7];    /* Device Name */
 	struct iommu_flush flush;
 #endif
 	struct q_inval  *qi;            /* Queued invalidation info */
@@ -321,6 +321,7 @@
 extern int alloc_iommu(struct dmar_drhd_unit *drhd);
 extern void free_iommu(struct intel_iommu *iommu);
 extern int dmar_enable_qi(struct intel_iommu *iommu);
+extern void dmar_disable_qi(struct intel_iommu *iommu);
 extern void qi_global_iec(struct intel_iommu *iommu);
 
 extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 873e4ac..9c62fbe 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -17,9 +17,11 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/cpumask.h>
+#include <linux/gfp.h>
 #include <linux/irqreturn.h>
 #include <linux/irqnr.h>
 #include <linux/errno.h>
+#include <linux/topology.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
diff --git a/include/linux/ivtv.h b/include/linux/ivtv.h
index f272028..062d20f 100644
--- a/include/linux/ivtv.h
+++ b/include/linux/ivtv.h
@@ -60,10 +60,10 @@
 
 #define IVTV_IOC_DMA_FRAME  _IOW ('V', BASE_VIDIOC_PRIVATE+0, struct ivtv_dma_frame)
 
-/* These are the VBI types as they appear in the embedded VBI private packets. */
-#define IVTV_SLICED_TYPE_TELETEXT_B     (1)
-#define IVTV_SLICED_TYPE_CAPTION_525    (4)
-#define IVTV_SLICED_TYPE_WSS_625        (5)
-#define IVTV_SLICED_TYPE_VPS            (7)
+/* Deprecated defines: applications should use the defines from videodev2.h */
+#define IVTV_SLICED_TYPE_TELETEXT_B     V4L2_MPEG_VBI_IVTV_TELETEXT_B
+#define IVTV_SLICED_TYPE_CAPTION_525    V4L2_MPEG_VBI_IVTV_CAPTION_525
+#define IVTV_SLICED_TYPE_WSS_625        V4L2_MPEG_VBI_IVTV_WSS_625
+#define IVTV_SLICED_TYPE_VPS            V4L2_MPEG_VBI_IVTV_VPS
 
 #endif /* _LINUX_IVTV_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 065cdf8..b1ea37f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -104,6 +104,7 @@
 #define VM_CAN_NONLINEAR 0x08000000	/* Has ->fault & does nonlinear pages */
 #define VM_MIXEDMAP	0x10000000	/* Can contain "struct page" and pure PFN pages */
 #define VM_SAO		0x20000000	/* Strong Access Ordering (powerpc) */
+#define VM_PFN_AT_MMAP	0x40000000	/* PFNMAP vma that is fully mapped at mmap time */
 
 #ifndef VM_STACK_DEFAULT_FLAGS		/* arch can override this */
 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
@@ -145,7 +146,7 @@
  */
 static inline int is_linear_pfn_mapping(struct vm_area_struct *vma)
 {
-	return ((vma->vm_flags & VM_PFNMAP) && vma->vm_pgoff);
+	return (vma->vm_flags & VM_PFN_AT_MMAP);
 }
 
 static inline int is_pfn_mapping(struct vm_area_struct *vma)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 05dfa7c..e5816dd 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1237,6 +1237,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
 #define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
 #define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS     0x0542
 #define PCI_DEVICE_ID_NVIDIA_NVENET_24              0x054C
 #define PCI_DEVICE_ID_NVIDIA_NVENET_25              0x054D
 #define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
@@ -1247,11 +1248,14 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_31              0x07DF
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS    0x0752
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 #define PCI_DEVICE_ID_NVIDIA_NVENET_32              0x0760
 #define PCI_DEVICE_ID_NVIDIA_NVENET_33              0x0761
 #define PCI_DEVICE_ID_NVIDIA_NVENET_34              0x0762
 #define PCI_DEVICE_ID_NVIDIA_NVENET_35              0x0763
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
 #define PCI_DEVICE_ID_NVIDIA_NVENET_36              0x0AB0
 #define PCI_DEVICE_ID_NVIDIA_NVENET_37              0x0AB1
 #define PCI_DEVICE_ID_NVIDIA_NVENET_38              0x0AB2
@@ -1475,6 +1479,7 @@
 #define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
+#define PCI_DEVICE_ID_SERVERWORKS_HT1100LD 0x0408
 
 #define PCI_VENDOR_ID_SBE		0x1176
 #define PCI_DEVICE_ID_SBE_WANXL100	0x0301
@@ -2227,6 +2232,14 @@
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
 #define PCI_VENDOR_ID_FREESCALE		0x1957
+#define PCI_DEVICE_ID_MPC8315E		0x00b4
+#define PCI_DEVICE_ID_MPC8315		0x00b5
+#define PCI_DEVICE_ID_MPC8314E		0x00b6
+#define PCI_DEVICE_ID_MPC8314		0x00b7
+#define PCI_DEVICE_ID_MPC8378E		0x00c4
+#define PCI_DEVICE_ID_MPC8378		0x00c5
+#define PCI_DEVICE_ID_MPC8377E		0x00c6
+#define PCI_DEVICE_ID_MPC8377		0x00c7
 #define PCI_DEVICE_ID_MPC8548E		0x0012
 #define PCI_DEVICE_ID_MPC8548		0x0013
 #define PCI_DEVICE_ID_MPC8543E		0x0014
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index fe00f78..52240e0 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -49,13 +49,12 @@
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
 struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
 int reiserfs_acl_chmod(struct inode *inode);
-int reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
+int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
+				 struct inode *dir, struct dentry *dentry,
 				 struct inode *inode);
 int reiserfs_cache_default_acl(struct inode *dir);
-extern int reiserfs_xattr_posix_acl_init(void) __init;
-extern int reiserfs_xattr_posix_acl_exit(void);
-extern struct reiserfs_xattr_handler posix_acl_default_handler;
-extern struct reiserfs_xattr_handler posix_acl_access_handler;
+extern struct xattr_handler reiserfs_posix_acl_default_handler;
+extern struct xattr_handler reiserfs_posix_acl_access_handler;
 
 static inline void reiserfs_init_acl_access(struct inode *inode)
 {
@@ -75,16 +74,6 @@
 	return NULL;
 }
 
-static inline int reiserfs_xattr_posix_acl_init(void)
-{
-	return 0;
-}
-
-static inline int reiserfs_xattr_posix_acl_exit(void)
-{
-	return 0;
-}
-
 static inline int reiserfs_acl_chmod(struct inode *inode)
 {
 	return 0;
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index e356c99..2245c78 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -58,8 +58,6 @@
 #define reiserfs_write_lock( sb ) lock_kernel()
 #define reiserfs_write_unlock( sb ) unlock_kernel()
 
-/* xattr stuff */
-#define REISERFS_XATTR_DIR_SEM(s) (REISERFS_SB(s)->xattr_dir_sem)
 struct fid;
 
 /* in reading the #defines, it may help to understand that they employ
@@ -104,15 +102,21 @@
 */
 #define REISERFS_DEBUG_CODE 5	/* extra messages to help find/debug errors */
 
-void reiserfs_warning(struct super_block *s, const char *fmt, ...);
+void __reiserfs_warning(struct super_block *s, const char *id,
+			 const char *func, const char *fmt, ...);
+#define reiserfs_warning(s, id, fmt, args...) \
+	 __reiserfs_warning(s, id, __func__, fmt, ##args)
 /* assertions handling */
 
 /** always check a condition and panic if it's false. */
-#define __RASSERT( cond, scond, format, args... )					\
-if( !( cond ) ) 								\
-  reiserfs_panic( NULL, "reiserfs[%i]: assertion " scond " failed at "	\
-		  __FILE__ ":%i:%s: " format "\n",		\
-		  in_interrupt() ? -1 : task_pid_nr(current), __LINE__ , __func__ , ##args )
+#define __RASSERT(cond, scond, format, args...)			\
+do {									\
+	if (!(cond))							\
+		reiserfs_panic(NULL, "assertion failure", "(" #cond ") at " \
+			       __FILE__ ":%i:%s: " format "\n",		\
+			       in_interrupt() ? -1 : task_pid_nr(current), \
+			       __LINE__, __func__ , ##args);		\
+} while (0)
 
 #define RASSERT(cond, format, args...) __RASSERT(cond, #cond, format, ##args)
 
@@ -196,7 +200,11 @@
 	__le32 s_flags;		/* Right now used only by inode-attributes, if enabled */
 	unsigned char s_uuid[16];	/* filesystem unique identifier */
 	unsigned char s_label[16];	/* filesystem volume label */
-	char s_unused[88];	/* zero filled by mkreiserfs and
+	__le16 s_mnt_count;		/* Count of mounts since last fsck */
+	__le16 s_max_mnt_count;		/* Maximum mounts before check */
+	__le32 s_lastcheck;		/* Timestamp of last fsck */
+	__le32 s_check_interval;	/* Interval between checks */
+	char s_unused[76];	/* zero filled by mkreiserfs and
 				 * reiserfs_convert_objectid_map_v1()
 				 * so any additions must be updated
 				 * there as well. */
@@ -578,10 +586,8 @@
 		return TYPE_DIRECT;
 	case V1_DIRENTRY_UNIQUENESS:
 		return TYPE_DIRENTRY;
-	default:
-		reiserfs_warning(NULL, "vs-500: unknown uniqueness %d",
-				 uniqueness);
 	case V1_ANY_UNIQUENESS:
+	default:
 		return TYPE_ANY;
 	}
 }
@@ -598,9 +604,8 @@
 		return V1_DIRECT_UNIQUENESS;
 	case TYPE_DIRENTRY:
 		return V1_DIRENTRY_UNIQUENESS;
-	default:
-		reiserfs_warning(NULL, "vs-501: unknown type %d", type);
 	case TYPE_ANY:
+	default:
 		return V1_ANY_UNIQUENESS;
 	}
 }
@@ -712,9 +717,9 @@
 #define is_indirect_cpu_ih(ih) (is_indirect_cpu_key (&((ih)->ih_key)))
 #define is_statdata_cpu_ih(ih) (is_statdata_cpu_key (&((ih)->ih_key)))
 
-#define I_K_KEY_IN_ITEM(p_s_ih, p_s_key, n_blocksize) \
-    ( ! COMP_SHORT_KEYS(p_s_ih, p_s_key) && \
-          I_OFF_BYTE_IN_ITEM(p_s_ih, k_offset (p_s_key), n_blocksize) )
+#define I_K_KEY_IN_ITEM(ih, key, n_blocksize) \
+    (!COMP_SHORT_KEYS(ih, key) && \
+	  I_OFF_BYTE_IN_ITEM(ih, k_offset(key), n_blocksize))
 
 /* maximal length of item */
 #define MAX_ITEM_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE)
@@ -770,25 +775,25 @@
 #define DISK_LEAF_NODE_LEVEL  1	/* Leaf node level. */
 
 /* Given the buffer head of a formatted node, resolve to the block head of that node. */
-#define B_BLK_HEAD(p_s_bh)            ((struct block_head *)((p_s_bh)->b_data))
+#define B_BLK_HEAD(bh)			((struct block_head *)((bh)->b_data))
 /* Number of items that are in buffer. */
-#define B_NR_ITEMS(p_s_bh)            (blkh_nr_item(B_BLK_HEAD(p_s_bh)))
-#define B_LEVEL(p_s_bh)               (blkh_level(B_BLK_HEAD(p_s_bh)))
-#define B_FREE_SPACE(p_s_bh)          (blkh_free_space(B_BLK_HEAD(p_s_bh)))
+#define B_NR_ITEMS(bh)			(blkh_nr_item(B_BLK_HEAD(bh)))
+#define B_LEVEL(bh)			(blkh_level(B_BLK_HEAD(bh)))
+#define B_FREE_SPACE(bh)		(blkh_free_space(B_BLK_HEAD(bh)))
 
-#define PUT_B_NR_ITEMS(p_s_bh,val)    do { set_blkh_nr_item(B_BLK_HEAD(p_s_bh),val); } while (0)
-#define PUT_B_LEVEL(p_s_bh,val)       do { set_blkh_level(B_BLK_HEAD(p_s_bh),val); } while (0)
-#define PUT_B_FREE_SPACE(p_s_bh,val)  do { set_blkh_free_space(B_BLK_HEAD(p_s_bh),val); } while (0)
+#define PUT_B_NR_ITEMS(bh, val)		do { set_blkh_nr_item(B_BLK_HEAD(bh), val); } while (0)
+#define PUT_B_LEVEL(bh, val)		do { set_blkh_level(B_BLK_HEAD(bh), val); } while (0)
+#define PUT_B_FREE_SPACE(bh, val)	do { set_blkh_free_space(B_BLK_HEAD(bh), val); } while (0)
 
 /* Get right delimiting key. -- little endian */
-#define B_PRIGHT_DELIM_KEY(p_s_bh)   (&(blk_right_delim_key(B_BLK_HEAD(p_s_bh))))
+#define B_PRIGHT_DELIM_KEY(bh)		(&(blk_right_delim_key(B_BLK_HEAD(bh))))
 
 /* Does the buffer contain a disk leaf. */
-#define B_IS_ITEMS_LEVEL(p_s_bh)     (B_LEVEL(p_s_bh) == DISK_LEAF_NODE_LEVEL)
+#define B_IS_ITEMS_LEVEL(bh)		(B_LEVEL(bh) == DISK_LEAF_NODE_LEVEL)
 
 /* Does the buffer contain a disk internal node */
-#define B_IS_KEYS_LEVEL(p_s_bh)      (B_LEVEL(p_s_bh) > DISK_LEAF_NODE_LEVEL \
-                                            && B_LEVEL(p_s_bh) <= MAX_HEIGHT)
+#define B_IS_KEYS_LEVEL(bh)      (B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL \
+					    && B_LEVEL(bh) <= MAX_HEIGHT)
 
 /***************************************************************************/
 /*                             STAT DATA                                   */
@@ -1138,12 +1143,13 @@
 #define put_dc_size(dc_p, val)   do { (dc_p)->dc_size = cpu_to_le16(val); } while(0)
 
 /* Get disk child by buffer header and position in the tree node. */
-#define B_N_CHILD(p_s_bh,n_pos)  ((struct disk_child *)\
-((p_s_bh)->b_data+BLKH_SIZE+B_NR_ITEMS(p_s_bh)*KEY_SIZE+DC_SIZE*(n_pos)))
+#define B_N_CHILD(bh, n_pos)  ((struct disk_child *)\
+((bh)->b_data + BLKH_SIZE + B_NR_ITEMS(bh) * KEY_SIZE + DC_SIZE * (n_pos)))
 
 /* Get disk child number by buffer header and position in the tree node. */
-#define B_N_CHILD_NUM(p_s_bh,n_pos) (dc_block_number(B_N_CHILD(p_s_bh,n_pos)))
-#define PUT_B_N_CHILD_NUM(p_s_bh,n_pos, val) (put_dc_block_number(B_N_CHILD(p_s_bh,n_pos), val ))
+#define B_N_CHILD_NUM(bh, n_pos) (dc_block_number(B_N_CHILD(bh, n_pos)))
+#define PUT_B_N_CHILD_NUM(bh, n_pos, val) \
+				(put_dc_block_number(B_N_CHILD(bh, n_pos), val))
 
  /* maximal value of field child_size in structure disk_child */
  /* child size is the combined size of all items and their headers */
@@ -1214,33 +1220,33 @@
 struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
 
 /* Get path element by path and path position. */
-#define PATH_OFFSET_PELEMENT(p_s_path,n_offset)  ((p_s_path)->path_elements +(n_offset))
+#define PATH_OFFSET_PELEMENT(path, n_offset)  ((path)->path_elements + (n_offset))
 
 /* Get buffer header at the path by path and path position. */
-#define PATH_OFFSET_PBUFFER(p_s_path,n_offset)   (PATH_OFFSET_PELEMENT(p_s_path,n_offset)->pe_buffer)
+#define PATH_OFFSET_PBUFFER(path, n_offset)   (PATH_OFFSET_PELEMENT(path, n_offset)->pe_buffer)
 
 /* Get position in the element at the path by path and path position. */
-#define PATH_OFFSET_POSITION(p_s_path,n_offset) (PATH_OFFSET_PELEMENT(p_s_path,n_offset)->pe_position)
+#define PATH_OFFSET_POSITION(path, n_offset) (PATH_OFFSET_PELEMENT(path, n_offset)->pe_position)
 
-#define PATH_PLAST_BUFFER(p_s_path) (PATH_OFFSET_PBUFFER((p_s_path), (p_s_path)->path_length))
+#define PATH_PLAST_BUFFER(path) (PATH_OFFSET_PBUFFER((path), (path)->path_length))
 				/* you know, to the person who didn't
 				   write this the macro name does not
 				   at first suggest what it does.
 				   Maybe POSITION_FROM_PATH_END? Or
 				   maybe we should just focus on
 				   dumping paths... -Hans */
-#define PATH_LAST_POSITION(p_s_path) (PATH_OFFSET_POSITION((p_s_path), (p_s_path)->path_length))
+#define PATH_LAST_POSITION(path) (PATH_OFFSET_POSITION((path), (path)->path_length))
 
-#define PATH_PITEM_HEAD(p_s_path)    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_path),PATH_LAST_POSITION(p_s_path))
+#define PATH_PITEM_HEAD(path)    B_N_PITEM_HEAD(PATH_PLAST_BUFFER(path), PATH_LAST_POSITION(path))
 
 /* in do_balance leaf has h == 0 in contrast with path structure,
    where root has level == 0. That is why we need these defines */
-#define PATH_H_PBUFFER(p_s_path, h) PATH_OFFSET_PBUFFER (p_s_path, p_s_path->path_length - (h))	/* tb->S[h] */
+#define PATH_H_PBUFFER(path, h) PATH_OFFSET_PBUFFER (path, path->path_length - (h))	/* tb->S[h] */
 #define PATH_H_PPARENT(path, h) PATH_H_PBUFFER (path, (h) + 1)	/* tb->F[h] or tb->S[0]->b_parent */
 #define PATH_H_POSITION(path, h) PATH_OFFSET_POSITION (path, path->path_length - (h))
 #define PATH_H_B_ITEM_ORDER(path, h) PATH_H_POSITION(path, h + 1)	/* tb->S[h]->b_item_order */
 
-#define PATH_H_PATH_OFFSET(p_s_path, n_h) ((p_s_path)->path_length - (n_h))
+#define PATH_H_PATH_OFFSET(path, n_h) ((path)->path_length - (n_h))
 
 #define get_last_bh(path) PATH_PLAST_BUFFER(path)
 #define get_ih(path) PATH_PITEM_HEAD(path)
@@ -1470,6 +1476,16 @@
 	int bi_position;
 };
 
+static inline struct super_block *sb_from_tb(struct tree_balance *tb)
+{
+	return tb ? tb->tb_sb : NULL;
+}
+
+static inline struct super_block *sb_from_bi(struct buffer_info *bi)
+{
+	return bi ? sb_from_tb(bi->tb) : NULL;
+}
+
 /* there are 4 types of items: stat data, directory item, indirect, direct.
 +-------------------+------------+--------------+------------+
 |	            |  k_offset  | k_uniqueness | mergeable? |
@@ -1520,7 +1536,7 @@
 #define COMP_SHORT_KEYS comp_short_keys
 
 /* number of blocks pointed to by the indirect item */
-#define I_UNFM_NUM(p_s_ih)	( ih_item_len(p_s_ih) / UNFM_P_SIZE )
+#define I_UNFM_NUM(ih)	(ih_item_len(ih) / UNFM_P_SIZE)
 
 /* the used space within the unformatted node corresponding to pos within the item pointed to by ih */
 #define I_POS_UNFM_SIZE(ih,pos,size) (((pos) == I_UNFM_NUM(ih) - 1 ) ? (size) - ih_free_space(ih) : (size))
@@ -1623,6 +1639,10 @@
 #define JOURNAL_MAX_COMMIT_AGE 30
 #define JOURNAL_MAX_TRANS_AGE 30
 #define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
+#define JOURNAL_BLOCKS_PER_OBJECT(sb)  (JOURNAL_PER_BALANCE_CNT * 3 + \
+					 2 * (REISERFS_QUOTA_INIT_BLOCKS(sb) + \
+					      REISERFS_QUOTA_TRANS_BLOCKS(sb)))
+
 #ifdef CONFIG_QUOTA
 /* We need to update data and inode (atime) */
 #define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
@@ -1697,7 +1717,7 @@
 	int t_refcount;
 	int t_blocks_logged;	/* number of blocks this writer has logged */
 	int t_blocks_allocated;	/* number of blocks this writer allocated */
-	unsigned long t_trans_id;	/* sanity check, equals the current trans id */
+	unsigned int t_trans_id;	/* sanity check, equals the current trans id */
 	void *t_handle_save;	/* save existing current->journal_info */
 	unsigned displace_new_blocks:1;	/* if new block allocation occurres, that block
 					   should be displaced from others */
@@ -1773,13 +1793,13 @@
 int journal_mark_freed(struct reiserfs_transaction_handle *,
 		       struct super_block *, b_blocknr_t blocknr);
 int journal_transaction_should_end(struct reiserfs_transaction_handle *, int);
-int reiserfs_in_journal(struct super_block *p_s_sb, unsigned int bmap_nr,
-			int bit_nr, int searchall, b_blocknr_t *next);
+int reiserfs_in_journal(struct super_block *sb, unsigned int bmap_nr,
+			 int bit_nr, int searchall, b_blocknr_t *next);
 int journal_begin(struct reiserfs_transaction_handle *,
-		  struct super_block *p_s_sb, unsigned long);
+		  struct super_block *sb, unsigned long);
 int journal_join_abort(struct reiserfs_transaction_handle *,
-		       struct super_block *p_s_sb, unsigned long);
-void reiserfs_journal_abort(struct super_block *sb, int errno);
+		       struct super_block *sb, unsigned long);
+void reiserfs_abort_journal(struct super_block *sb, int errno);
 void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...);
 int reiserfs_allocate_list_bitmaps(struct super_block *s,
 				   struct reiserfs_list_bitmap *, unsigned int);
@@ -1796,8 +1816,8 @@
 
 /* stree.c */
 int B_IS_IN_TREE(const struct buffer_head *);
-extern void copy_item_head(struct item_head *p_v_to,
-			   const struct item_head *p_v_from);
+extern void copy_item_head(struct item_head *to,
+			   const struct item_head *from);
 
 // first key is in cpu form, second - le
 extern int comp_short_keys(const struct reiserfs_key *le_key,
@@ -1832,20 +1852,20 @@
 	memcpy(to, from, KEY_SIZE);
 }
 
-int comp_items(const struct item_head *stored_ih, const struct treepath *p_s_path);
-const struct reiserfs_key *get_rkey(const struct treepath *p_s_chk_path,
-				    const struct super_block *p_s_sb);
+int comp_items(const struct item_head *stored_ih, const struct treepath *path);
+const struct reiserfs_key *get_rkey(const struct treepath *chk_path,
+				    const struct super_block *sb);
 int search_by_key(struct super_block *, const struct cpu_key *,
 		  struct treepath *, int);
 #define search_item(s,key,path) search_by_key (s, key, path, DISK_LEAF_NODE_LEVEL)
-int search_for_position_by_key(struct super_block *p_s_sb,
-			       const struct cpu_key *p_s_cpu_key,
-			       struct treepath *p_s_search_path);
-extern void decrement_bcount(struct buffer_head *p_s_bh);
-void decrement_counters_in_path(struct treepath *p_s_search_path);
-void pathrelse(struct treepath *p_s_search_path);
+int search_for_position_by_key(struct super_block *sb,
+			       const struct cpu_key *cpu_key,
+			       struct treepath *search_path);
+extern void decrement_bcount(struct buffer_head *bh);
+void decrement_counters_in_path(struct treepath *search_path);
+void pathrelse(struct treepath *search_path);
 int reiserfs_check_path(struct treepath *p);
-void pathrelse_and_restore(struct super_block *s, struct treepath *p_s_search_path);
+void pathrelse_and_restore(struct super_block *s, struct treepath *search_path);
 
 int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
 			 struct treepath *path,
@@ -1868,14 +1888,14 @@
 int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
 			 struct treepath *path,
 			 const struct cpu_key *key,
-			 struct inode *inode, struct buffer_head *p_s_un_bh);
+			 struct inode *inode, struct buffer_head *un_bh);
 
 void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
 				struct inode *inode, struct reiserfs_key *key);
 int reiserfs_delete_object(struct reiserfs_transaction_handle *th,
-			   struct inode *p_s_inode);
+			   struct inode *inode);
 int reiserfs_do_truncate(struct reiserfs_transaction_handle *th,
-			 struct inode *p_s_inode, struct page *,
+			 struct inode *inode, struct page *,
 			 int update_timestamps);
 
 #define i_block_size(inode) ((inode)->i_sb->s_blocksize)
@@ -1919,10 +1939,12 @@
 		       loff_t offset, int type, int length, int entry_count);
 struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key);
 
+struct reiserfs_security_handle;
 int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 		       struct inode *dir, int mode,
 		       const char *symname, loff_t i_size,
-		       struct dentry *dentry, struct inode *inode);
+		       struct dentry *dentry, struct inode *inode,
+		       struct reiserfs_security_handle *security);
 
 void reiserfs_update_sd_size(struct reiserfs_transaction_handle *th,
 			     struct inode *inode, loff_t size);
@@ -1980,7 +2002,7 @@
 #define PROC_INFO_MAX( sb, field, value ) VOID_V
 #define PROC_INFO_INC( sb, field ) VOID_V
 #define PROC_INFO_ADD( sb, field, val ) VOID_V
-#define PROC_INFO_BH_STAT( p_s_sb, p_s_bh, n_node_level ) VOID_V
+#define PROC_INFO_BH_STAT(sb, bh, n_node_level) VOID_V
 #endif
 
 /* dir.c */
@@ -1988,6 +2010,7 @@
 extern const struct inode_operations reiserfs_symlink_inode_operations;
 extern const struct inode_operations reiserfs_special_inode_operations;
 extern const struct file_operations reiserfs_dir_operations;
+int reiserfs_readdir_dentry(struct dentry *, void *, filldir_t, loff_t *);
 
 /* tail_conversion.c */
 int direct2indirect(struct reiserfs_transaction_handle *, struct inode *,
@@ -2004,13 +2027,20 @@
 
 /* fix_nodes.c */
 
-int fix_nodes(int n_op_mode, struct tree_balance *p_s_tb,
-	      struct item_head *p_s_ins_ih, const void *);
+int fix_nodes(int n_op_mode, struct tree_balance *tb,
+	      struct item_head *ins_ih, const void *);
 void unfix_nodes(struct tree_balance *);
 
 /* prints.c */
-void reiserfs_panic(struct super_block *s, const char *fmt, ...)
+void __reiserfs_panic(struct super_block *s, const char *id,
+		      const char *function, const char *fmt, ...)
     __attribute__ ((noreturn));
+#define reiserfs_panic(s, id, fmt, args...) \
+	__reiserfs_panic(s, id, __func__, fmt, ##args)
+void __reiserfs_error(struct super_block *s, const char *id,
+		      const char *function, const char *fmt, ...);
+#define reiserfs_error(s, id, fmt, args...) \
+	 __reiserfs_error(s, id, __func__, fmt, ##args)
 void reiserfs_info(struct super_block *s, const char *fmt, ...);
 void reiserfs_debug(struct super_block *s, int level, const char *fmt, ...);
 void print_indirect_item(struct buffer_head *bh, int item_num);
@@ -2047,7 +2077,7 @@
 			  int zeros_number);
 void leaf_cut_from_buffer(struct buffer_info *bi, int cut_item_num,
 			  int pos_in_item, int cut_size);
-void leaf_paste_entries(struct buffer_head *bh, int item_num, int before,
+void leaf_paste_entries(struct buffer_info *bi, int item_num, int before,
 			int new_entry_count, struct reiserfs_de_head *new_dehs,
 			const char *records, int paste_size);
 /* ibalance.c */
@@ -2203,6 +2233,6 @@
 		   unsigned int cmd, unsigned long arg);
 int reiserfs_unpack(struct inode *inode, struct file *filp);
 
-
 #endif /* __KERNEL__ */
+
 #endif				/* _LINUX_REISER_FS_H */
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index ce3663f..76360b3 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -51,7 +51,7 @@
 	/* we use these for fsync or O_SYNC to decide which transaction
 	 ** needs to be committed in order for this inode to be properly
 	 ** flushed */
-	unsigned long i_trans_id;
+	unsigned int i_trans_id;
 	struct reiserfs_journal_list *i_jl;
 	struct mutex i_mmap;
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
@@ -59,7 +59,7 @@
 	struct posix_acl *i_acl_default;
 #endif
 #ifdef CONFIG_REISERFS_FS_XATTR
-	struct rw_semaphore xattr_sem;
+	struct rw_semaphore i_xattr_sem;
 #endif
 	struct inode vfs_inode;
 };
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index bda6b56..5621d87 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -14,7 +14,7 @@
 } reiserfs_super_block_flags;
 
 /* struct reiserfs_super_block accessors/mutators
- * since this is a disk structure, it will always be in 
+ * since this is a disk structure, it will always be in
  * little endian format. */
 #define sb_block_count(sbp)         (le32_to_cpu((sbp)->s_v1.s_block_count))
 #define set_sb_block_count(sbp,v)   ((sbp)->s_v1.s_block_count = cpu_to_le32(v))
@@ -73,6 +73,9 @@
 #define sb_version(sbp)            (le16_to_cpu((sbp)->s_v1.s_version))
 #define set_sb_version(sbp,v)      ((sbp)->s_v1.s_version = cpu_to_le16(v))
 
+#define sb_mnt_count(sbp)	   (le16_to_cpu((sbp)->s_mnt_count))
+#define set_sb_mnt_count(sbp, v)   ((sbp)->s_mnt_count = cpu_to_le16(v))
+
 #define sb_reserved_for_journal(sbp) \
               (le16_to_cpu((sbp)->s_v1.s_reserved_for_journal))
 #define set_sb_reserved_for_journal(sbp,v) \
@@ -80,16 +83,16 @@
 
 /* LOGGING -- */
 
-/* These all interelate for performance.  
+/* These all interelate for performance.
 **
-** If the journal block count is smaller than n transactions, you lose speed. 
+** If the journal block count is smaller than n transactions, you lose speed.
 ** I don't know what n is yet, I'm guessing 8-16.
 **
 ** typical transaction size depends on the application, how often fsync is
-** called, and how many metadata blocks you dirty in a 30 second period.  
+** called, and how many metadata blocks you dirty in a 30 second period.
 ** The more small files (<16k) you use, the larger your transactions will
 ** be.
-** 
+**
 ** If your journal fills faster than dirty buffers get flushed to disk, it must flush them before allowing the journal
 ** to wrap, which slows things down.  If you need high speed meta data updates, the journal should be big enough
 ** to prevent wrapping before dirty meta blocks get to disk.
@@ -153,7 +156,7 @@
 	atomic_t j_commit_left;
 	atomic_t j_older_commits_done;	/* all commits older than this on disk */
 	struct mutex j_commit_mutex;
-	unsigned long j_trans_id;
+	unsigned int j_trans_id;
 	time_t j_timestamp;
 	struct reiserfs_list_bitmap *j_list_bitmap;
 	struct buffer_head *j_commit_bh;	/* commit buffer head */
@@ -182,7 +185,7 @@
 	int j_1st_reserved_block;	/* first block on s_dev of reserved area journal */
 
 	unsigned long j_state;
-	unsigned long j_trans_id;
+	unsigned int j_trans_id;
 	unsigned long j_mount_id;
 	unsigned long j_start;	/* start of current waiting commit (index into j_ap_blocks) */
 	unsigned long j_len;	/* length of current waiting commit */
@@ -223,10 +226,10 @@
 	int j_num_work_lists;	/* number that need attention from kreiserfsd */
 
 	/* debugging to make sure things are flushed in order */
-	int j_last_flush_id;
+	unsigned int j_last_flush_id;
 
 	/* debugging to make sure things are committed in order */
-	int j_last_commit_id;
+	unsigned int j_last_commit_id;
 
 	struct list_head j_bitmap_nodes;
 	struct list_head j_dirty_buffers;
@@ -239,7 +242,7 @@
 
 	struct reiserfs_list_bitmap j_list_bitmap[JOURNAL_NUM_BITMAPS];	/* array of bitmaps to record the deleted blocks */
 	struct reiserfs_journal_cnode *j_hash_table[JOURNAL_HASH_SIZE];	/* hash table for real buffer heads in current trans */
-	struct reiserfs_journal_cnode *j_list_hash_table[JOURNAL_HASH_SIZE];	/* hash table for all the real buffer heads in all 
+	struct reiserfs_journal_cnode *j_list_hash_table[JOURNAL_HASH_SIZE];	/* hash table for all the real buffer heads in all
 										   the transactions */
 	struct list_head j_prealloc_list;	/* list of inodes which have preallocated blocks */
 	int j_persistent_trans;
@@ -399,10 +402,7 @@
 	int reserved_blocks;	/* amount of blocks reserved for further allocations */
 	spinlock_t bitmap_lock;	/* this lock on now only used to protect reserved_blocks variable */
 	struct dentry *priv_root;	/* root of /.reiserfs_priv */
-#ifdef CONFIG_REISERFS_FS_XATTR
 	struct dentry *xattr_root;	/* root of /.reiserfs_priv/.xa */
-	struct rw_semaphore xattr_dir_sem;
-#endif
 	int j_errno;
 #ifdef CONFIG_QUOTA
 	char *s_qf_names[MAXQUOTAS];
@@ -426,7 +426,7 @@
 				   partition will be dealt with in a
 				   manner of 3.5.x */
 
-/* -o hash={tea, rupasov, r5, detect} is meant for properly mounting 
+/* -o hash={tea, rupasov, r5, detect} is meant for properly mounting
 ** reiserfs disks from 3.5.19 or earlier.  99% of the time, this option
 ** is not required.  If the normal autodection code can't determine which
 ** hash to use (because both hashes had the same value for a file)
@@ -451,7 +451,6 @@
 	REISERFS_NO_UNHASHED_RELOCATION,
 	REISERFS_HASHED_RELOCATION,
 	REISERFS_ATTRS,
-	REISERFS_XATTRS,
 	REISERFS_XATTRS_USER,
 	REISERFS_POSIXACL,
 	REISERFS_BARRIER_NONE,
@@ -489,7 +488,7 @@
 #define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
 #define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
 #define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
-#define reiserfs_xattrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS))
+#define reiserfs_xattrs(s) ((s)->s_xattr != NULL)
 #define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
 #define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
 #define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index af135ae..dcae01e 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -15,6 +15,12 @@
 	__le32 h_hash;		/* hash of the value */
 };
 
+struct reiserfs_security_handle {
+	char *name;
+	void *value;
+	size_t length;
+};
+
 #ifdef __KERNEL__
 
 #include <linux/init.h>
@@ -29,22 +35,13 @@
 struct super_block;
 struct nameidata;
 
-struct reiserfs_xattr_handler {
-	char *prefix;
-	int (*init) (void);
-	void (*exit) (void);
-	int (*get) (struct inode * inode, const char *name, void *buffer,
-		    size_t size);
-	int (*set) (struct inode * inode, const char *name, const void *buffer,
-		    size_t size, int flags);
-	int (*del) (struct inode * inode, const char *name);
-	int (*list) (struct inode * inode, const char *name, int namelen,
-		     char *out);
-	struct list_head handlers;
-};
+int reiserfs_xattr_register_handlers(void) __init;
+void reiserfs_xattr_unregister_handlers(void);
+int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
+int reiserfs_delete_xattrs(struct inode *inode);
+int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
 
 #ifdef CONFIG_REISERFS_FS_XATTR
-#define is_reiserfs_priv_object(inode) IS_PRIVATE(inode)
 #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
 ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name,
 			  void *buffer, size_t size);
@@ -52,105 +49,98 @@
 		      const void *value, size_t size, int flags);
 ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
 int reiserfs_removexattr(struct dentry *dentry, const char *name);
-int reiserfs_delete_xattrs(struct inode *inode);
-int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
-int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
 int reiserfs_permission(struct inode *inode, int mask);
 
-int reiserfs_xattr_del(struct inode *, const char *);
-int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
+int reiserfs_xattr_get(struct inode *, const char *, void *, size_t);
 int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int);
+int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *,
+			      struct inode *, const char *, const void *,
+			      size_t, int);
 
-extern struct reiserfs_xattr_handler user_handler;
-extern struct reiserfs_xattr_handler trusted_handler;
-extern struct reiserfs_xattr_handler security_handler;
+extern struct xattr_handler reiserfs_xattr_user_handler;
+extern struct xattr_handler reiserfs_xattr_trusted_handler;
+extern struct xattr_handler reiserfs_xattr_security_handler;
+#ifdef CONFIG_REISERFS_FS_SECURITY
+int reiserfs_security_init(struct inode *dir, struct inode *inode,
+			   struct reiserfs_security_handle *sec);
+int reiserfs_security_write(struct reiserfs_transaction_handle *th,
+			    struct inode *inode,
+			    struct reiserfs_security_handle *sec);
+void reiserfs_security_free(struct reiserfs_security_handle *sec);
+#endif
 
-int reiserfs_xattr_register_handlers(void) __init;
-void reiserfs_xattr_unregister_handlers(void);
-
-static inline void reiserfs_write_lock_xattrs(struct super_block *sb)
+#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
+static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
 {
-	down_write(&REISERFS_XATTR_DIR_SEM(sb));
-}
-static inline void reiserfs_write_unlock_xattrs(struct super_block *sb)
-{
-	up_write(&REISERFS_XATTR_DIR_SEM(sb));
-}
-static inline void reiserfs_read_lock_xattrs(struct super_block *sb)
-{
-	down_read(&REISERFS_XATTR_DIR_SEM(sb));
+	loff_t ret = 0;
+	if (reiserfs_file_data_log(inode)) {
+		ret = _ROUND_UP(xattr_size(size), inode->i_sb->s_blocksize);
+		ret >>= inode->i_sb->s_blocksize_bits;
+	}
+	return ret;
 }
 
-static inline void reiserfs_read_unlock_xattrs(struct super_block *sb)
+/* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
+ * Let's try to be smart about it.
+ * xattr root: We cache it. If it's not cached, we may need to create it.
+ * xattr dir: If anything has been loaded for this inode, we can set a flag
+ *            saying so.
+ * xattr file: Since we don't cache xattrs, we can't tell. We always include
+ *             blocks for it.
+ *
+ * However, since root and dir can be created between calls - YOU MUST SAVE
+ * THIS VALUE.
+ */
+static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
 {
-	up_read(&REISERFS_XATTR_DIR_SEM(sb));
-}
+	size_t nblocks = JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
 
-static inline void reiserfs_write_lock_xattr_i(struct inode *inode)
-{
-	down_write(&REISERFS_I(inode)->xattr_sem);
-}
-static inline void reiserfs_write_unlock_xattr_i(struct inode *inode)
-{
-	up_write(&REISERFS_I(inode)->xattr_sem);
-}
-static inline void reiserfs_read_lock_xattr_i(struct inode *inode)
-{
-	down_read(&REISERFS_I(inode)->xattr_sem);
-}
+	if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
+		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+		if (REISERFS_SB(inode->i_sb)->xattr_root == NULL)
+			nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
+	}
 
-static inline void reiserfs_read_unlock_xattr_i(struct inode *inode)
-{
-	up_read(&REISERFS_I(inode)->xattr_sem);
-}
-
-static inline void reiserfs_mark_inode_private(struct inode *inode)
-{
-	inode->i_flags |= S_PRIVATE;
+	return nblocks;
 }
 
 static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 {
-	init_rwsem(&REISERFS_I(inode)->xattr_sem);
+	init_rwsem(&REISERFS_I(inode)->i_xattr_sem);
 }
 
 #else
 
-#define is_reiserfs_priv_object(inode) 0
-#define reiserfs_mark_inode_private(inode) do {;} while(0)
 #define reiserfs_getxattr NULL
 #define reiserfs_setxattr NULL
 #define reiserfs_listxattr NULL
 #define reiserfs_removexattr NULL
-#define reiserfs_write_lock_xattrs(sb) do {;} while(0)
-#define reiserfs_write_unlock_xattrs(sb) do {;} while(0)
-#define reiserfs_read_lock_xattrs(sb)
-#define reiserfs_read_unlock_xattrs(sb)
 
 #define reiserfs_permission NULL
 
-#define reiserfs_xattr_register_handlers() 0
-#define reiserfs_xattr_unregister_handlers()
-
-static inline int reiserfs_delete_xattrs(struct inode *inode)
-{
-	return 0;
-};
-static inline int reiserfs_chown_xattrs(struct inode *inode,
-					struct iattr *attrs)
-{
-	return 0;
-};
-static inline int reiserfs_xattr_init(struct super_block *sb, int mount_flags)
-{
-	sb->s_flags = (sb->s_flags & ~MS_POSIXACL);	/* to be sure */
-	return 0;
-};
 static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 {
 }
 #endif  /*  CONFIG_REISERFS_FS_XATTR  */
 
+#ifndef CONFIG_REISERFS_FS_SECURITY
+static inline int reiserfs_security_init(struct inode *dir,
+					 struct inode *inode,
+					 struct reiserfs_security_handle *sec)
+{
+	return 0;
+}
+static inline int
+reiserfs_security_write(struct reiserfs_transaction_handle *th,
+			struct inode *inode,
+			struct reiserfs_security_handle *sec)
+{
+	return 0;
+}
+static inline void reiserfs_security_free(struct reiserfs_security_handle *sec)
+{}
+#endif
+
 #endif  /*  __KERNEL__  */
 
 #endif  /*  _LINUX_REISERFS_XATTR_H  */
diff --git a/include/linux/security.h b/include/linux/security.h
index 1f2ab63..54ed157 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -880,11 +880,6 @@
  *	@sock contains the listening socket structure.
  *	@newsock contains the newly created server socket for connection.
  *	Return 0 if permission is granted.
- * @socket_post_accept:
- *	This hook allows a security module to copy security
- *	information into the newly created socket's inode.
- *	@sock contains the listening socket structure.
- *	@newsock contains the newly created server socket for connection.
  * @socket_sendmsg:
  *	Check permission before transmitting a message to another socket.
  *	@sock contains the socket structure.
@@ -1554,8 +1549,6 @@
 			       struct sockaddr *address, int addrlen);
 	int (*socket_listen) (struct socket *sock, int backlog);
 	int (*socket_accept) (struct socket *sock, struct socket *newsock);
-	void (*socket_post_accept) (struct socket *sock,
-				    struct socket *newsock);
 	int (*socket_sendmsg) (struct socket *sock,
 			       struct msghdr *msg, int size);
 	int (*socket_recvmsg) (struct socket *sock,
@@ -2537,7 +2530,6 @@
 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen);
 int security_socket_listen(struct socket *sock, int backlog);
 int security_socket_accept(struct socket *sock, struct socket *newsock);
-void security_socket_post_accept(struct socket *sock, struct socket *newsock);
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
 			    int size, int flags);
@@ -2616,11 +2608,6 @@
 	return 0;
 }
 
-static inline void security_socket_post_accept(struct socket *sock,
-					       struct socket *newsock)
-{
-}
-
 static inline int security_socket_sendmsg(struct socket *sock,
 					  struct msghdr *msg, int size)
 {
diff --git a/include/linux/video_decoder.h b/include/linux/video_decoder.h
deleted file mode 100644
index e26c0c8..0000000
--- a/include/linux/video_decoder.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef _LINUX_VIDEO_DECODER_H
-#define _LINUX_VIDEO_DECODER_H
-
-#include <linux/types.h>
-
-#define HAVE_VIDEO_DECODER 1
-
-struct video_decoder_capability { /* this name is too long */
-	__u32	flags;
-#define	VIDEO_DECODER_PAL	1	/* can decode PAL signal */
-#define	VIDEO_DECODER_NTSC	2	/* can decode NTSC */
-#define	VIDEO_DECODER_SECAM	4	/* can decode SECAM */
-#define	VIDEO_DECODER_AUTO	8	/* can autosense norm */
-#define	VIDEO_DECODER_CCIR	16	/* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */
-	int	inputs;			/* number of inputs */
-	int	outputs;		/* number of outputs */
-};
-
-/*
-DECODER_GET_STATUS returns the following flags.  The only one you need is
-DECODER_STATUS_GOOD, the others are just nice things to know.
-*/
-#define	DECODER_STATUS_GOOD	1	/* receiving acceptable input */
-#define	DECODER_STATUS_COLOR	2	/* receiving color information */
-#define	DECODER_STATUS_PAL	4	/* auto detected */
-#define	DECODER_STATUS_NTSC	8	/* auto detected */
-#define	DECODER_STATUS_SECAM	16	/* auto detected */
-
-struct video_decoder_init {
-	unsigned char len;
-	const unsigned char *data;
-};
-
-#define	DECODER_GET_CAPABILITIES _IOR('d', 1, struct video_decoder_capability)
-#define	DECODER_GET_STATUS    	_IOR('d', 2, int)
-#define	DECODER_SET_NORM	_IOW('d', 3, int)
-#define	DECODER_SET_INPUT	_IOW('d', 4, int)	/* 0 <= input < #inputs */
-#define	DECODER_SET_OUTPUT	_IOW('d', 5, int)	/* 0 <= output < #outputs */
-#define	DECODER_ENABLE_OUTPUT	_IOW('d', 6, int)	/* boolean output enable control */
-#define	DECODER_SET_PICTURE   	_IOW('d', 7, struct video_picture)
-#define	DECODER_SET_GPIO	_IOW('d', 8, int)	/* switch general purpose pin */
-#define	DECODER_INIT		_IOW('d', 9, struct video_decoder_init)	/* init internal registers at once */
-#define	DECODER_SET_VBI_BYPASS	_IOW('d', 10, int)	/* switch vbi bypass */
-
-#define	DECODER_DUMP		_IO('d', 192)		/* debug hook */
-
-
-#endif
diff --git a/include/linux/video_encoder.h b/include/linux/video_encoder.h
deleted file mode 100644
index b7b6423..0000000
--- a/include/linux/video_encoder.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _LINUX_VIDEO_ENCODER_H
-#define _LINUX_VIDEO_ENCODER_H
-
-#include <linux/types.h>
-
-struct video_encoder_capability { /* this name is too long */
-	__u32	flags;
-#define	VIDEO_ENCODER_PAL	1	/* can encode PAL signal */
-#define	VIDEO_ENCODER_NTSC	2	/* can encode NTSC */
-#define	VIDEO_ENCODER_SECAM	4	/* can encode SECAM */
-#define	VIDEO_ENCODER_CCIR	16	/* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */
-	int	inputs;			/* number of inputs */
-	int	outputs;		/* number of outputs */
-};
-
-#define	ENCODER_GET_CAPABILITIES _IOR('e', 1, struct video_encoder_capability)
-#define	ENCODER_SET_NORM	_IOW('e', 2, int)
-#define	ENCODER_SET_INPUT	_IOW('e', 3, int)	/* 0 <= input < #inputs */
-#define	ENCODER_SET_OUTPUT	_IOW('e', 4, int)	/* 0 <= output < #outputs */
-#define	ENCODER_ENABLE_OUTPUT	_IOW('e', 5, int)	/* boolean output enable control */
-
-
-#endif
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 837f392..b19eab1 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -16,6 +16,23 @@
 #include <linux/ioctl.h>
 #include <linux/videodev2.h>
 
+#if defined(__MIN_V4L1) && defined (__KERNEL__)
+
+/*
+ * Used by those V4L2 core functions that need a minimum V4L1 support,
+ * in order to allow V4L1 Compatibilty code compilation.
+ */
+
+struct video_mbuf
+{
+	int	size;		/* Total memory to map */
+	int	frames;		/* Frames */
+	int	offsets[VIDEO_MAX_FRAME];
+};
+
+#define VIDIOCGMBUF		_IOR('v',20, struct video_mbuf)		/* Memory map buffer info */
+
+#else
 #if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__)
 
 #define VID_TYPE_CAPTURE	1	/* Can capture */
@@ -312,6 +329,7 @@
 #define VID_PLAY_END_MARK		14
 
 #endif /* CONFIG_VIDEO_V4L1_COMPAT */
+#endif /* __MIN_V4L1 */
 
 #endif /* __LINUX_VIDEODEV_H */
 
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5571dbe..139d234 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -344,6 +344,8 @@
 #define V4L2_PIX_FMT_SPCA508  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
 #define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
 #define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_SQ905C   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
 #define V4L2_PIX_FMT_PJPG     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
 #define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16  YVU 4:2:2     */
 
@@ -829,6 +831,7 @@
 #define V4L2_CTRL_FLAG_UPDATE 		0x0008
 #define V4L2_CTRL_FLAG_INACTIVE 	0x0010
 #define V4L2_CTRL_FLAG_SLIDER 		0x0020
+#define V4L2_CTRL_FLAG_WRITE_ONLY 	0x0040
 
 /*  Query flag, to be ORed with the control ID */
 #define V4L2_CTRL_FLAG_NEXT_CTRL	0x80000000
@@ -879,8 +882,15 @@
 #define V4L2_CID_BACKLIGHT_COMPENSATION 	(V4L2_CID_BASE+28)
 #define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
 #define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
+#define V4L2_CID_COLORFX			(V4L2_CID_BASE+31)
+enum v4l2_colorfx {
+	V4L2_COLORFX_NONE	= 0,
+	V4L2_COLORFX_BW		= 1,
+	V4L2_COLORFX_SEPIA	= 2,
+};
+
 /* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+31)
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+32)
 
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1339,6 +1349,53 @@
 };
 
 /*
+ * Sliced VBI data inserted into MPEG Streams
+ */
+
+/*
+ * V4L2_MPEG_STREAM_VBI_FMT_IVTV:
+ *
+ * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an
+ * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI
+ * data
+ *
+ * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header
+ * definitions are not included here.  See the MPEG-2 specifications for details
+ * on these headers.
+ */
+
+/* Line type IDs */
+#define V4L2_MPEG_VBI_IVTV_TELETEXT_B     (1)
+#define V4L2_MPEG_VBI_IVTV_CAPTION_525    (4)
+#define V4L2_MPEG_VBI_IVTV_WSS_625        (5)
+#define V4L2_MPEG_VBI_IVTV_VPS            (7)
+
+struct v4l2_mpeg_vbi_itv0_line {
+	__u8 id;	/* One of V4L2_MPEG_VBI_IVTV_* above */
+	__u8 data[42];	/* Sliced VBI data for the line */
+} __attribute__ ((packed));
+
+struct v4l2_mpeg_vbi_itv0 {
+	__le32 linemask[2]; /* Bitmasks of VBI service lines present */
+	struct v4l2_mpeg_vbi_itv0_line line[35];
+} __attribute__ ((packed));
+
+struct v4l2_mpeg_vbi_ITV0 {
+	struct v4l2_mpeg_vbi_itv0_line line[36];
+} __attribute__ ((packed));
+
+#define V4L2_MPEG_VBI_IVTV_MAGIC0	"itv0"
+#define V4L2_MPEG_VBI_IVTV_MAGIC1	"ITV0"
+
+struct v4l2_mpeg_vbi_fmt_ivtv {
+	__u8 magic[4];
+	union {
+		struct v4l2_mpeg_vbi_itv0 itv0;
+		struct v4l2_mpeg_vbi_ITV0 ITV0;
+	};
+} __attribute__ ((packed));
+
+/*
  *	A G G R E G A T E   S T R U C T U R E S
  */
 
@@ -1403,14 +1460,6 @@
 	__u32 revision;    /* chip revision, chip specific */
 } __attribute__ ((packed));
 
-/* VIDIOC_G_CHIP_IDENT_OLD: Deprecated, do not use */
-struct v4l2_chip_ident_old {
-	__u32 match_type;  /* Match type */
-	__u32 match_chip;  /* Match this chip, meaning determined by match_type */
-	__u32 ident;       /* chip identifier as specified in <media/v4l2-chip-ident.h> */
-	__u32 revision;    /* chip revision, chip specific */
-};
-
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -1488,8 +1537,6 @@
 /* Experimental, meant for debugging, testing and internal use.
    Never use this ioctl in applications! */
 #define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident)
-/* This is deprecated and will go away in 2.6.30 */
-#define VIDIOC_G_CHIP_IDENT_OLD _IOWR('V', 81, struct v4l2_chip_ident_old)
 #endif
 
 #define VIDIOC_S_HW_FREQ_SEEK	 _IOW('V', 82, struct v4l2_hw_freq_seek)
diff --git a/include/media/bt819.h b/include/media/bt819.h
new file mode 100644
index 0000000..38f666b
--- /dev/null
+++ b/include/media/bt819.h
@@ -0,0 +1,33 @@
+/*
+    bt819.h - bt819 notifications
+
+    Copyright (C) 2009 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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.
+*/
+
+#ifndef _BT819_H_
+#define _BT819_H_
+
+#include <linux/ioctl.h>
+
+/* v4l2_device notifications. */
+
+/* Needed to reset the FIFO buffer when changing the input
+   or the video standard. */
+#define BT819_FIFO_RESET_LOW 	_IO('b', 0)
+#define BT819_FIFO_RESET_HIGH 	_IO('b', 1)
+
+#endif
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index 9ec4d58..9ebe855 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -1,5 +1,5 @@
 /*
-    cx23415/6 header containing common defines.
+    cx23415/6/8 header containing common defines.
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
 enum cx2341x_cap {
 	CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
 	CX2341X_CAP_HAS_TS 	   = 1 << 1,
+	CX2341X_CAP_HAS_AC3 	   = 1 << 2,
 };
 
 struct cx2341x_mpeg_params {
@@ -47,11 +48,12 @@
 	enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;
 	enum v4l2_mpeg_audio_encoding audio_encoding;
 	enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate;
+	enum v4l2_mpeg_audio_ac3_bitrate audio_ac3_bitrate;
 	enum v4l2_mpeg_audio_mode audio_mode;
 	enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
 	enum v4l2_mpeg_audio_emphasis audio_emphasis;
 	enum v4l2_mpeg_audio_crc audio_crc;
-	u16 audio_properties;
+	u32 audio_properties;
 	u16 audio_mute;
 
 	/* video */
diff --git a/include/media/cx25840.h b/include/media/cx25840.h
index db431d5..2c3fbaa 100644
--- a/include/media/cx25840.h
+++ b/include/media/cx25840.h
@@ -21,6 +21,18 @@
 #ifndef _CX25840_H_
 #define _CX25840_H_
 
+/* Note that the cx25840 driver requires that the bridge driver calls the
+   v4l2_subdev's init operation in order to load the driver's firmware.
+   Without this the audio standard detection will fail and you will
+   only get mono.
+
+   Since loading the firmware is often problematic when the driver is
+   compiled into the kernel I recommend postponing calling this function
+   until the first open of the video device. Another reason for
+   postponing it is that loading this firmware takes a long time (seconds)
+   due to the slow i2c bus speed. So it will speed up the boot process if
+   you can avoid loading the fw as long as the video device isn't used. */
+
 enum cx25840_video_input {
 	/* Composite video inputs In1-In8 */
 	CX25840_COMPOSITE1 = 1,
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 5bf2ea0..7b5b91f 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -111,6 +111,7 @@
 extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
@@ -159,6 +160,8 @@
 extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE];
 #endif
 
 /*
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 00fa57e..07963d7 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -14,8 +14,7 @@
 	/* Used to avoid fast repeating */
 	unsigned char          old;
 
-	struct work_struct     work;
-	struct timer_list      timer;
+	struct delayed_work    work;
 	char                   phys[32];
 	int                    (*get_key)(struct IR_i2c*, u32*, u32*);
 };
diff --git a/include/media/ov772x.h b/include/media/ov772x.h
index e391d55..57db48d 100644
--- a/include/media/ov772x.h
+++ b/include/media/ov772x.h
@@ -13,8 +13,13 @@
 
 #include <media/soc_camera.h>
 
+/* for flags */
+#define OV772X_FLAG_VFLIP     0x00000001 /* Vertical flip image */
+#define OV772X_FLAG_HFLIP     0x00000002 /* Horizontal flip image */
+
 struct ov772x_camera_info {
 	unsigned long          buswidth;
+	unsigned long          flags;
 	struct soc_camera_link link;
 };
 
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index c5a6e22..fff4235 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -13,6 +13,7 @@
 #include <linux/stringify.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
+#include <media/v4l2-device.h>
 
 #include <linux/vmalloc.h>	/* for vmalloc() */
 #include <linux/mm.h>		/* for vmalloc_to_page() */
@@ -110,6 +111,8 @@
 
 	struct list_head		item;
 
+	struct v4l2_device 		v4l2_dev;
+
 	/* different device locks */
 	spinlock_t			slock;
 	struct mutex			lock;
@@ -145,6 +148,11 @@
 	struct saa7146_dma		d_rps1;
 };
 
+static inline struct saa7146_dev *to_saa7146_dev(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct saa7146_dev, v4l2_dev);
+}
+
 /* from saa7146_i2c.c */
 int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
 
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index c8d0b23..eed5fcc 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -150,16 +150,6 @@
 	unsigned int resources;	/* resource management for device */
 };
 
-#define SAA7146_EXCLUSIVE	0x1
-#define SAA7146_BEFORE		0x2
-#define SAA7146_AFTER		0x4
-
-struct saa7146_extension_ioctls
-{
-	unsigned int	cmd;
-	int		flags;
-};
-
 /* flags */
 #define SAA7146_USE_PORT_B_FOR_VBI	0x2     /* use input port b for vbi hardware bug workaround */
 
@@ -176,8 +166,10 @@
 	int num_stds;
 	int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
 
-	struct saa7146_extension_ioctls *ioctls;
-	long (*ioctl)(struct saa7146_fh *, unsigned int cmd, void *arg);
+	/* the extension can override this */
+	struct v4l2_ioctl_ops ops;
+	/* pointer to the saa7146 core ops */
+	const struct v4l2_ioctl_ops *core_ops;
 
 	struct v4l2_file_operations vbi_fops;
 };
@@ -213,6 +205,7 @@
 void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
 
 /* from saa7146_video.c */
+extern const struct v4l2_ioctl_ops saa7146_video_ioctl_ops;
 extern struct saa7146_use_ops saa7146_video_uops;
 int saa7146_start_preview(struct saa7146_fh *fh);
 int saa7146_stop_preview(struct saa7146_fh *fh);
diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h
index b5dbefe..0f3524c 100644
--- a/include/media/sh_mobile_ceu.h
+++ b/include/media/sh_mobile_ceu.h
@@ -1,10 +1,11 @@
 #ifndef __ASM_SH_MOBILE_CEU_H__
 #define __ASM_SH_MOBILE_CEU_H__
 
-#include <media/soc_camera.h>
+#define SH_CEU_FLAG_USE_8BIT_BUS	(1 << 0) /* use  8bit bus width */
+#define SH_CEU_FLAG_USE_16BIT_BUS	(1 << 1) /* use 16bit bus width */
 
 struct sh_mobile_ceu_info {
-	unsigned long flags; /* SOCAM_... */
+	unsigned long flags;
 };
 
 #endif /* __ASM_SH_MOBILE_CEU_H__ */
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 7440d92..3701368 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -45,6 +45,7 @@
 	int num_formats;
 	struct soc_camera_format_xlate *user_formats;
 	int num_user_formats;
+	enum v4l2_field field;		/* Preserve field over close() */
 	struct module *owner;
 	void *host_priv;		/* Per-device host private data */
 	/* soc_camera.c private count. Only accessed with .video_lock held */
@@ -74,7 +75,8 @@
 	int (*resume)(struct soc_camera_device *);
 	int (*get_formats)(struct soc_camera_device *, int,
 			   struct soc_camera_format_xlate *);
-	int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *);
+	int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
+	int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
 	int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
 	void (*init_videobuf)(struct videobuf_queue *,
 			      struct soc_camera_device *);
@@ -93,13 +95,18 @@
 struct soc_camera_link {
 	/* Camera bus id, used to match a camera and a bus */
 	int bus_id;
-	/* GPIO number to switch between 8 and 10 bit modes */
-	unsigned int gpio;
 	/* Per camera SOCAM_SENSOR_* bus flags */
 	unsigned long flags;
 	/* Optional callbacks to power on or off and reset the sensor */
 	int (*power)(struct device *, int);
 	int (*reset)(struct device *);
+	/*
+	 * some platforms may support different data widths than the sensors
+	 * native ones due to different data line routing. Let the board code
+	 * overwrite the width flags.
+	 */
+	int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
+	unsigned long (*query_bus_param)(struct soc_camera_link *);
 };
 
 static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
@@ -159,7 +166,8 @@
 	int (*release)(struct soc_camera_device *);
 	int (*start_capture)(struct soc_camera_device *);
 	int (*stop_capture)(struct soc_camera_device *);
-	int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *);
+	int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
+	int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
 	int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
 	unsigned long (*query_bus_param)(struct soc_camera_device *);
 	int (*set_bus_param)(struct soc_camera_device *, unsigned long);
@@ -239,15 +247,19 @@
 static inline unsigned long soc_camera_bus_param_compatible(
 			unsigned long camera_flags, unsigned long bus_flags)
 {
-	unsigned long common_flags, hsync, vsync, pclk;
+	unsigned long common_flags, hsync, vsync, pclk, data, buswidth, mode;
 
 	common_flags = camera_flags & bus_flags;
 
 	hsync = common_flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
 	vsync = common_flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
 	pclk = common_flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING);
+	data = common_flags & (SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_LOW);
+	mode = common_flags & (SOCAM_MASTER | SOCAM_SLAVE);
+	buswidth = common_flags & SOCAM_DATAWIDTH_MASK;
 
-	return (!hsync || !vsync || !pclk) ? 0 : common_flags;
+	return (!hsync || !vsync || !pclk || !data || !mode || !buswidth) ? 0 :
+		common_flags;
 }
 
 extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 9aaf652..1be461a 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -37,10 +37,8 @@
 	/* module saa7110: just ident 100 */
 	V4L2_IDENT_SAA7110 = 100,
 
-	/* module saa7111: just ident 101 */
+	/* module saa7115: reserved range 101-149 */
 	V4L2_IDENT_SAA7111 = 101,
-
-	/* module saa7115: reserved range 102-149 */
 	V4L2_IDENT_SAA7113 = 103,
 	V4L2_IDENT_SAA7114 = 104,
 	V4L2_IDENT_SAA7115 = 105,
@@ -63,45 +61,97 @@
 	V4L2_IDENT_OV7720 = 251,
 	V4L2_IDENT_OV7725 = 252,
 
-	/* Conexant MPEG encoder/decoders: reserved range 410-420 */
+	/* module saa7146: reserved range 300-309 */
+	V4L2_IDENT_SAA7146 = 300,
+
+	/* Conexant MPEG encoder/decoders: reserved range 400-420 */
+	V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */
 	V4L2_IDENT_CX23415 = 415,
 	V4L2_IDENT_CX23416 = 416,
 	V4L2_IDENT_CX23418 = 418,
 
+	/* module au0828 */
+	V4L2_IDENT_AU0828 = 828,
+
+	/* module indycam: just ident 2000 */
+	V4L2_IDENT_INDYCAM = 2000,
+
+	/* module bt819: reserved range 810-819 */
+	V4L2_IDENT_BT815A = 815,
+	V4L2_IDENT_BT817A = 817,
+	V4L2_IDENT_BT819A = 819,
+
+	/* module bt856: just ident 856 */
+	V4L2_IDENT_BT856 = 856,
+
+	/* module bt866: just ident 866 */
+	V4L2_IDENT_BT866 = 866,
+
+	/* module ks0127: reserved range 1120-1129 */
+	V4L2_IDENT_KS0122S = 1122,
+	V4L2_IDENT_KS0127  = 1127,
+	V4L2_IDENT_KS0127B = 1128,
+
 	/* module vp27smpx: just ident 2700 */
 	V4L2_IDENT_VP27SMPX = 2700,
 
+	/* module vpx3220: reserved range: 3210-3229 */
+	V4L2_IDENT_VPX3214C = 3214,
+	V4L2_IDENT_VPX3216B = 3216,
+	V4L2_IDENT_VPX3220A = 3220,
+
 	/* module tvp5150 */
 	V4L2_IDENT_TVP5150 = 5150,
 
+	/* module saa5246a: just ident 5246 */
+	V4L2_IDENT_SAA5246A = 5246,
+
+	/* module saa5249: just ident 5249 */
+	V4L2_IDENT_SAA5249 = 5249,
+
 	/* module cs5345: just ident 5345 */
 	V4L2_IDENT_CS5345 = 5345,
 
+	/* module tea6415c: just ident 6415 */
+	V4L2_IDENT_TEA6415C = 6415,
+
+	/* module tea6420: just ident 6420 */
+	V4L2_IDENT_TEA6420 = 6420,
+
+	/* module saa6588: just ident 6588 */
+	V4L2_IDENT_SAA6588 = 6588,
+
 	/* module saa6752hs: reserved range 6750-6759 */
 	V4L2_IDENT_SAA6752HS = 6752,
 	V4L2_IDENT_SAA6752HS_AC3 = 6753,
 
+	/* module adv7170: just ident 7170 */
+	V4L2_IDENT_ADV7170 = 7170,
+
+	/* module adv7175: just ident 7175 */
+	V4L2_IDENT_ADV7175 = 7175,
+
+	/* module saa7185: just ident 7185 */
+	V4L2_IDENT_SAA7185 = 7185,
+
+	/* module saa7191: just ident 7191 */
+	V4L2_IDENT_SAA7191 = 7191,
+
 	/* module wm8739: just ident 8739 */
 	V4L2_IDENT_WM8739 = 8739,
 
 	/* module wm8775: just ident 8775 */
 	V4L2_IDENT_WM8775 = 8775,
 
+	/* module tda9840: just ident 9840 */
+	V4L2_IDENT_TDA9840 = 9840,
+
+	/* module cafe_ccic, just ident 8801 */
+	V4L2_IDENT_CAFE = 8801,
+
 	/* module tw9910: just ident 9910 */
 	V4L2_IDENT_TW9910 = 9910,
 
-	/* module cs53132a: just ident 53132 */
-	V4L2_IDENT_CS53l32A = 53132,
-
-	/* module upd64031a: just ident 64031 */
-	V4L2_IDENT_UPD64031A = 64031,
-
-	/* module upd64083: just ident 64083 */
-	V4L2_IDENT_UPD64083 = 64083,
-
-	/* module m52790: just ident 52790 */
-	V4L2_IDENT_M52790 = 52790,
-
 	/* module msp3400: reserved range 34000-34999 and 44000-44999 */
 	V4L2_IDENT_MSPX4XX  = 34000, /* generic MSPX4XX identifier, only
 					use internally (tveeprom.c). */
@@ -178,6 +228,18 @@
 	V4L2_IDENT_MT9V022IX7ATC	= 45010, /* No way to detect "normal" I77ATx */
 	V4L2_IDENT_MT9V022IX7ATM	= 45015, /* and "lead free" IA7ATx chips */
 	V4L2_IDENT_MT9T031		= 45020,
+
+	/* module cs53132a: just ident 53132 */
+	V4L2_IDENT_CS53l32A = 53132,
+
+	/* module upd64031a: just ident 64031 */
+	V4L2_IDENT_UPD64031A = 64031,
+
+	/* module upd64083: just ident 64083 */
+	V4L2_IDENT_UPD64083 = 64083,
+
+	/* module m52790: just ident 52790 */
+	V4L2_IDENT_M52790 = 52790,
 };
 
 #endif
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 95e74f1..3a69056 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -102,11 +102,15 @@
 const char *v4l2_ctrl_get_name(u32 id);
 const char **v4l2_ctrl_get_menu(u32 id);
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
-int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl);
 int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
 		struct v4l2_queryctrl *qctrl, const char **menu_items);
 #define V4L2_CTRL_MENU_IDS_END (0xffffffff)
 int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
+
+/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a
+   0-terminated array of control IDs. Each array must be sorted low to high
+   and belong to the same control class. The array of u32 pointers must also
+   be sorted, from low class IDs to high class IDs. */
 u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 /* ------------------------------------------------------------------------- */
@@ -149,6 +153,21 @@
 /* Initialize an v4l2_subdev with data from an i2c_client struct */
 void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
 		const struct v4l2_subdev_ops *ops);
+/* Return i2c client address of v4l2_subdev. */
+unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd);
+
+enum v4l2_i2c_tuner_type {
+	ADDRS_RADIO,	/* Radio tuner addresses */
+	ADDRS_DEMOD,	/* Demod tuner addresses */
+	ADDRS_TV,	/* TV tuner addresses */
+	/* TV tuner addresses if demod is present, this excludes
+	   addresses used by the demodulator from the list of
+	   candidates. */
+	ADDRS_TV_WITH_DEMOD,
+};
+/* Return a list of I2C tuner addresses to probe. Use only if the tuner
+   addresses are unknown. */
+const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type);
 
 /* ------------------------------------------------------------------------- */
 
@@ -284,4 +303,7 @@
    a v4l2_gpio struct if a direction is also needed. */
 #define VIDIOC_INT_S_GPIO		_IOW('d', 117, u32)
 
+/* Get input status. Same as the status field in the v4l2_input struct. */
+#define VIDIOC_INT_G_INPUT_STATUS	_IOR('d', 118, u32)
+
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index e36faab..2058dd4 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -40,6 +40,8 @@
 	unsigned int (*poll) (struct file *, struct poll_table_struct *);
 	long (*ioctl) (struct file *, unsigned int, unsigned long);
 	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+	unsigned long (*get_unmapped_area) (struct file *, unsigned long,
+				unsigned long, unsigned long, unsigned long);
 	int (*mmap) (struct file *, struct vm_area_struct *);
 	int (*open) (struct file *);
 	int (*release) (struct file *);
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 55e41af..0dd3e8e 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -33,7 +33,9 @@
 #define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16)
 
 struct v4l2_device {
-	/* dev->driver_data points to this struct */
+	/* dev->driver_data points to this struct.
+	   Note: dev might be NULL if there is no parent device
+	   as is the case with e.g. ISA devices. */
 	struct device *dev;
 	/* used to keep track of the registered subdevs */
 	struct list_head subdevs;
@@ -42,33 +44,43 @@
 	spinlock_t lock;
 	/* unique device name, by default the driver name + bus ID */
 	char name[V4L2_DEVICE_NAME_SIZE];
+	/* notify callback called by some sub-devices. */
+	void (*notify)(struct v4l2_subdev *sd,
+			unsigned int notification, void *arg);
 };
 
-/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev */
+/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
+   dev may be NULL in rare cases (ISA devices). In that case you
+   must fill in the v4l2_dev->name field before calling this function. */
 int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
-/* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */
+/* Set v4l2_dev->dev to NULL. Call when the USB parent disconnects.
+   Since the parent disappears this ensures that v4l2_dev doesn't have an
+   invalid parent pointer. */
+void v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
+/* Unregister all sub-devices and any other resources related to v4l2_dev. */
 void v4l2_device_unregister(struct v4l2_device *v4l2_dev);
 
 /* Register a subdev with a v4l2 device. While registered the subdev module
    is marked as in-use. An error is returned if the module is no longer
    loaded when you attempt to register it. */
-int __must_check v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd);
+int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+						struct v4l2_subdev *sd);
 /* Unregister a subdev with a v4l2 device. Can also be called if the subdev
    wasn't registered. In that case it will do nothing. */
 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
 
 /* Iterate over all subdevs. */
-#define v4l2_device_for_each_subdev(sd, dev)				\
-	list_for_each_entry(sd, &(dev)->subdevs, list)
+#define v4l2_device_for_each_subdev(sd, v4l2_dev)			\
+	list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
 
 /* Call the specified callback for all subdevs matching the condition.
    Ignore any errors. Note that you cannot add or delete a subdev
    while walking the subdevs list. */
-#define __v4l2_device_call_subdevs(dev, cond, o, f, args...) 		\
+#define __v4l2_device_call_subdevs(v4l2_dev, cond, o, f, args...) 	\
 	do { 								\
 		struct v4l2_subdev *sd; 				\
 									\
-		list_for_each_entry(sd, &(dev)->subdevs, list)   	\
+		list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)   	\
 			if ((cond) && sd->ops->o && sd->ops->o->f) 	\
 				sd->ops->o->f(sd , ##args); 		\
 	} while (0)
@@ -77,12 +89,12 @@
    If the callback returns an error other than 0 or -ENOIOCTLCMD, then
    return with that error code. Note that you cannot add or delete a
    subdev while walking the subdevs list. */
-#define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...)  \
+#define __v4l2_device_call_subdevs_until_err(v4l2_dev, cond, o, f, args...) \
 ({ 									\
 	struct v4l2_subdev *sd; 					\
 	long err = 0; 							\
 									\
-	list_for_each_entry(sd, &(dev)->subdevs, list) { 		\
+	list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) { 		\
 		if ((cond) && sd->ops->o && sd->ops->o->f) 		\
 			err = sd->ops->o->f(sd , ##args); 		\
 		if (err && err != -ENOIOCTLCMD)				\
@@ -94,16 +106,16 @@
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
    match them all). Ignore any errors. Note that you cannot add or delete
    a subdev while walking the subdevs list. */
-#define v4l2_device_call_all(dev, grpid, o, f, args...) 		\
-	__v4l2_device_call_subdevs(dev, 				\
+#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...) 		\
+	__v4l2_device_call_subdevs(v4l2_dev, 				\
 			!(grpid) || sd->grp_id == (grpid), o, f , ##args)
 
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
    match them all). If the callback returns an error other than 0 or
    -ENOIOCTLCMD, then return with that error code. Note that you cannot
    add or delete a subdev while walking the subdevs list. */
-#define v4l2_device_call_until_err(dev, grpid, o, f, args...) 		\
-	__v4l2_device_call_subdevs_until_err(dev,			\
+#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...) 	\
+	__v4l2_device_call_subdevs_until_err(v4l2_dev,			\
 		       !(grpid) || sd->grp_id == (grpid), o, f , ##args)
 
 #endif
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index b01c044..7a4529d 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 #include <linux/compiler.h> /* need __user */
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
+#define __MIN_V4L1
 #include <linux/videodev.h>
 #else
 #include <linux/videodev2.h>
@@ -267,6 +268,7 @@
 
 /*  Video standard functions  */
 extern const char *v4l2_norm_to_name(v4l2_std_id id);
+extern void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod);
 extern int v4l2_video_std_construct(struct v4l2_standard *vs,
 				    int id, const char *name);
 /* Prints the ioctl in a human-readable format */
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 37b09e5..1d181b4 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -78,6 +78,9 @@
 	int (*queryctrl)(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc);
 	int (*g_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
 	int (*s_ctrl)(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+	int (*g_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
+	int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
+	int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
 	int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
 	long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -112,9 +115,17 @@
 	int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
 	int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
 	int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
+	int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
+	int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
 	int (*s_stream)(struct v4l2_subdev *sd, int enable);
-	int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+	int (*enum_fmt)(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmtdesc);
 	int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+	int (*try_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+	int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt);
+	int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
+	int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
+	int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
+	int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
 };
 
 struct v4l2_subdev_ops {
@@ -132,7 +143,7 @@
 struct v4l2_subdev {
 	struct list_head list;
 	struct module *owner;
-	struct v4l2_device *dev;
+	struct v4l2_device *v4l2_dev;
 	const struct v4l2_subdev_ops *ops;
 	/* name must be unique */
 	char name[V4L2_SUBDEV_NAME_SIZE];
@@ -171,7 +182,7 @@
 	/* ops->core MUST be set */
 	BUG_ON(!ops || !ops->core);
 	sd->ops = ops;
-	sd->dev = NULL;
+	sd->v4l2_dev = NULL;
 	sd->name[0] = '\0';
 	sd->grp_id = 0;
 	sd->priv = NULL;
@@ -186,4 +197,9 @@
 	(!(sd) ? -ENODEV : (((sd) && (sd)->ops->o && (sd)->ops->o->f) ?	\
 		(sd)->ops->o->f((sd) , ##args) : -ENOIOCTLCMD))
 
+/* Send a notification to v4l2_device. */
+#define v4l2_subdev_notify(sd, notification, arg)			   \
+	((!(sd) || !(sd)->v4l2_dev || !(sd)->v4l2_dev->notify) ? -ENODEV : \
+	 (sd)->v4l2_dev->notify((sd), (notification), (arg)))
+
 #endif
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h
index 874f134..1c5946c 100644
--- a/include/media/videobuf-core.h
+++ b/include/media/videobuf-core.h
@@ -18,6 +18,7 @@
 
 #include <linux/poll.h>
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
+#define __MIN_V4L1
 #include <linux/videodev.h>
 #endif
 #include <linux/videodev2.h>
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index bedc7f6..abd4436 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -40,6 +40,7 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <net/netlabel.h>
+#include <net/request_sock.h>
 #include <asm/atomic.h>
 
 /* known doi values */
@@ -215,6 +216,10 @@
 			  const struct netlbl_lsm_secattr *secattr);
 void cipso_v4_sock_delattr(struct sock *sk);
 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
+int cipso_v4_req_setattr(struct request_sock *req,
+			 const struct cipso_v4_doi *doi_def,
+			 const struct netlbl_lsm_secattr *secattr);
+void cipso_v4_req_delattr(struct request_sock *req);
 int cipso_v4_skbuff_setattr(struct sk_buff *skb,
 			    const struct cipso_v4_doi *doi_def,
 			    const struct netlbl_lsm_secattr *secattr);
@@ -247,6 +252,18 @@
 	return -ENOSYS;
 }
 
+static inline int cipso_v4_req_setattr(struct request_sock *req,
+				       const struct cipso_v4_doi *doi_def,
+				       const struct netlbl_lsm_secattr *secattr)
+{
+	return -ENOSYS;
+}
+
+static inline void cipso_v4_req_delattr(struct request_sock *req)
+{
+	return;
+}
+
 static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
 				      const struct cipso_v4_doi *doi_def,
 				      const struct netlbl_lsm_secattr *secattr)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 749011e..60ebbc1 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -36,6 +36,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <net/netlink.h>
+#include <net/request_sock.h>
 #include <asm/atomic.h>
 
 struct cipso_v4_doi;
@@ -406,6 +407,7 @@
  */
 int netlbl_enabled(void);
 int netlbl_sock_setattr(struct sock *sk,
+			u16 family,
 			const struct netlbl_lsm_secattr *secattr);
 void netlbl_sock_delattr(struct sock *sk);
 int netlbl_sock_getattr(struct sock *sk,
@@ -413,6 +415,9 @@
 int netlbl_conn_setattr(struct sock *sk,
 			struct sockaddr *addr,
 			const struct netlbl_lsm_secattr *secattr);
+int netlbl_req_setattr(struct request_sock *req,
+		       const struct netlbl_lsm_secattr *secattr);
+void netlbl_req_delattr(struct request_sock *req);
 int netlbl_skbuff_setattr(struct sk_buff *skb,
 			  u16 family,
 			  const struct netlbl_lsm_secattr *secattr);
@@ -519,7 +524,8 @@
 	return 0;
 }
 static inline int netlbl_sock_setattr(struct sock *sk,
-				     const struct netlbl_lsm_secattr *secattr)
+				      u16 family,
+				      const struct netlbl_lsm_secattr *secattr)
 {
 	return -ENOSYS;
 }
@@ -537,6 +543,15 @@
 {
 	return -ENOSYS;
 }
+static inline int netlbl_req_setattr(struct request_sock *req,
+				     const struct netlbl_lsm_secattr *secattr)
+{
+	return -ENOSYS;
+}
+static inline void netlbl_req_delattr(struct request_sock *req)
+{
+	return;
+}
 static inline int netlbl_skbuff_setattr(struct sk_buff *skb,
 				      u16 family,
 				      const struct netlbl_lsm_secattr *secattr)
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index 426899e..5718a02 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -22,8 +22,9 @@
  *
  */
 
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
 
 struct snd_tea575x;
 
@@ -35,11 +36,10 @@
 
 struct snd_tea575x {
 	struct snd_card *card;
-	struct video_device vd;		/* video device */
-	struct v4l2_file_operations fops;
+	struct video_device *vd;	/* video device */
 	int dev_nr;			/* requested device number + 1 */
-	int vd_registered;		/* video device is registered */
 	int tea5759;			/* 5759 chip is present */
+	int mute;			/* Device is muted? */
 	unsigned int freq_fixup;	/* crystal onboard */
 	unsigned int val;		/* hw value */
 	unsigned long freq;		/* frequency */
diff --git a/include/video/broadsheetfb.h b/include/video/broadsheetfb.h
new file mode 100644
index 0000000..a758534
--- /dev/null
+++ b/include/video/broadsheetfb.h
@@ -0,0 +1,59 @@
+/*
+ * broadsheetfb.h - definitions for the broadsheet framebuffer driver
+ *
+ * Copyright (C) 2008 by 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.
+ *
+ */
+
+#ifndef _LINUX_BROADSHEETFB_H_
+#define _LINUX_BROADSHEETFB_H_
+
+/* Broadsheet command defines */
+#define BS_CMD_INIT_SYS_RUN	0x06
+#define BS_CMD_INIT_DSPE_CFG	0x09
+#define BS_CMD_INIT_DSPE_TMG	0x0A
+#define BS_CMD_INIT_ROTMODE	0x0B
+#define BS_CMD_RD_REG		0x10
+#define BS_CMD_WR_REG		0x11
+#define BS_CMD_LD_IMG		0x20
+#define BS_CMD_LD_IMG_AREA	0x22
+#define BS_CMD_LD_IMG_END	0x23
+#define BS_CMD_WAIT_DSPE_TRG	0x28
+#define BS_CMD_WAIT_DSPE_FREND	0x29
+#define BS_CMD_RD_WFM_INFO	0x30
+#define BS_CMD_UPD_INIT		0x32
+#define BS_CMD_UPD_FULL		0x33
+#define BS_CMD_UPD_GDRV_CLR	0x37
+
+/* Broadsheet pin interface specific defines */
+#define BS_CS	0x01
+#define BS_DC 	0x02
+#define BS_WR 	0x03
+
+/* struct used by broadsheet. board specific stuff comes from *board */
+struct broadsheetfb_par {
+	struct fb_info *info;
+	struct broadsheet_board *board;
+	void (*write_reg)(struct broadsheetfb_par *, u16 reg, u16 val);
+	u16 (*read_reg)(struct broadsheetfb_par *, u16 reg);
+	wait_queue_head_t waitq;
+};
+
+/* board specific routines */
+struct broadsheet_board {
+	struct module *owner;
+	int (*init)(struct broadsheetfb_par *);
+	int (*wait_for_rdy)(struct broadsheetfb_par *);
+	void (*set_ctl)(struct broadsheetfb_par *, unsigned char, u8);
+	void (*set_hdb)(struct broadsheetfb_par *, u16);
+	u16 (*get_hdb)(struct broadsheetfb_par *);
+	void (*cleanup)(struct broadsheetfb_par *);
+	int (*get_panel_type)(void);
+	int (*setup_irq)(struct fb_info *);
+};
+
+#endif
diff --git a/init/initramfs.c b/init/initramfs.c
index 7dcde7e..619c1ba 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -5,6 +5,7 @@
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 #include <linux/string.h>
+#include <linux/dirent.h>
 #include <linux/syscalls.h>
 #include <linux/utime.h>
 
@@ -166,8 +167,6 @@
 static __initdata unsigned count;
 static __initdata loff_t this_header, next_header;
 
-static __initdata int dry_run;
-
 static inline void __init eat(unsigned n)
 {
 	victim += n;
@@ -229,10 +228,6 @@
 	parse_header(collected);
 	next_header = this_header + N_ALIGN(name_len) + body_len;
 	next_header = (next_header + 3) & ~3;
-	if (dry_run) {
-		read_into(name_buf, N_ALIGN(name_len), GotName);
-		return 0;
-	}
 	state = SkipIt;
 	if (name_len <= 0 || name_len > PATH_MAX)
 		return 0;
@@ -303,8 +298,6 @@
 		free_hash();
 		return 0;
 	}
-	if (dry_run)
-		return 0;
 	clean_path(collected, mode);
 	if (S_ISREG(mode)) {
 		int ml = maybe_link();
@@ -417,14 +410,13 @@
 
 #include <linux/decompress/generic.h>
 
-static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+static char * __init unpack_to_rootfs(char *buf, unsigned len)
 {
 	int written;
 	decompress_fn decompress;
 	const char *compress_name;
 	static __initdata char msg_buf[64];
 
-	dry_run = check_only;
 	header_buf = kmalloc(110, GFP_KERNEL);
 	symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
 	name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
@@ -523,10 +515,57 @@
 	initrd_end = 0;
 }
 
+#define BUF_SIZE 1024
+static void __init clean_rootfs(void)
+{
+	int fd;
+	void *buf;
+	struct linux_dirent64 *dirp;
+	int count;
+
+	fd = sys_open("/", O_RDONLY, 0);
+	WARN_ON(fd < 0);
+	if (fd < 0)
+		return;
+	buf = kzalloc(BUF_SIZE, GFP_KERNEL);
+	WARN_ON(!buf);
+	if (!buf) {
+		sys_close(fd);
+		return;
+	}
+
+	dirp = buf;
+	count = sys_getdents64(fd, dirp, BUF_SIZE);
+	while (count > 0) {
+		while (count > 0) {
+			struct stat st;
+			int ret;
+
+			ret = sys_newlstat(dirp->d_name, &st);
+			WARN_ON_ONCE(ret);
+			if (!ret) {
+				if (S_ISDIR(st.st_mode))
+					sys_rmdir(dirp->d_name);
+				else
+					sys_unlink(dirp->d_name);
+			}
+
+			count -= dirp->d_reclen;
+			dirp = (void *)dirp + dirp->d_reclen;
+		}
+		dirp = buf;
+		memset(buf, 0, BUF_SIZE);
+		count = sys_getdents64(fd, dirp, BUF_SIZE);
+	}
+
+	sys_close(fd);
+	kfree(buf);
+}
+
 static int __init populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
-			 __initramfs_end - __initramfs_start, 0);
+			 __initramfs_end - __initramfs_start);
 	if (err)
 		panic(err);	/* Failed to decompress INTERNAL initramfs */
 	if (initrd_start) {
@@ -534,13 +573,15 @@
 		int fd;
 		printk(KERN_INFO "checking if image is initramfs...");
 		err = unpack_to_rootfs((char *)initrd_start,
-			initrd_end - initrd_start, 1);
+			initrd_end - initrd_start);
 		if (!err) {
 			printk(" it is\n");
-			unpack_to_rootfs((char *)initrd_start,
-				initrd_end - initrd_start, 0);
 			free_initrd();
 			return 0;
+		} else {
+			clean_rootfs();
+			unpack_to_rootfs(__initramfs_start,
+				 __initramfs_end - __initramfs_start);
 		}
 		printk("it isn't (%s); looks like an initrd\n", err);
 		fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
@@ -553,7 +594,7 @@
 #else
 		printk(KERN_INFO "Unpacking initramfs...");
 		err = unpack_to_rootfs((char *)initrd_start,
-			initrd_end - initrd_start, 0);
+			initrd_end - initrd_start);
 		if (err) {
 			printk(" failed!\n");
 			printk(KERN_EMERG "%s\n", err);
diff --git a/kernel/async.c b/kernel/async.c
index f565891..968ef94 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -49,6 +49,7 @@
 */
 
 #include <linux/async.h>
+#include <linux/bug.h>
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
@@ -387,20 +388,11 @@
 
 static int __init async_init(void)
 {
-	if (async_enabled)
-		if (IS_ERR(kthread_run(async_manager_thread, NULL,
-				       "async/mgr")))
-			async_enabled = 0;
+	async_enabled =
+		!IS_ERR(kthread_run(async_manager_thread, NULL, "async/mgr"));
+
+	WARN_ON(!async_enabled);
 	return 0;
 }
 
-static int __init setup_async(char *str)
-{
-	async_enabled = 1;
-	return 1;
-}
-
-__setup("fastboot", setup_async);
-
-
 core_initcall(async_init);
diff --git a/kernel/futex.c b/kernel/futex.c
index 438701a..6b50a02 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -114,7 +114,9 @@
 };
 
 /*
- * Split the global futex_lock into every hash list lock.
+ * Hash buckets are shared by all the futex_keys that hash to the same
+ * location.  Each key may have multiple futex_q structures, one for each task
+ * waiting on a futex.
  */
 struct futex_hash_bucket {
 	spinlock_t lock;
@@ -189,8 +191,7 @@
 /**
  * get_futex_key - Get parameters which are the keys for a futex.
  * @uaddr: virtual address of the futex
- * @shared: NULL for a PROCESS_PRIVATE futex,
- *	&current->mm->mmap_sem for a PROCESS_SHARED futex
+ * @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
  * @key: address where result is stored.
  *
  * Returns a negative error code or 0
@@ -200,9 +201,7 @@
  * offset_within_page).  For private mappings, it's (uaddr, current->mm).
  * We can usually work out the index without swapping in the page.
  *
- * fshared is NULL for PROCESS_PRIVATE futexes
- * For other futexes, it points to &current->mm->mmap_sem and
- * caller must have taken the reader lock. but NOT any spinlocks.
+ * lock_page() might sleep, the caller should not hold a spinlock.
  */
 static int get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
 {
@@ -299,41 +298,6 @@
 	return ret ? -EFAULT : 0;
 }
 
-/*
- * Fault handling.
- */
-static int futex_handle_fault(unsigned long address, int attempt)
-{
-	struct vm_area_struct * vma;
-	struct mm_struct *mm = current->mm;
-	int ret = -EFAULT;
-
-	if (attempt > 2)
-		return ret;
-
-	down_read(&mm->mmap_sem);
-	vma = find_vma(mm, address);
-	if (vma && address >= vma->vm_start &&
-	    (vma->vm_flags & VM_WRITE)) {
-		int fault;
-		fault = handle_mm_fault(mm, vma, address, 1);
-		if (unlikely((fault & VM_FAULT_ERROR))) {
-#if 0
-			/* XXX: let's do this when we verify it is OK */
-			if (ret & VM_FAULT_OOM)
-				ret = -ENOMEM;
-#endif
-		} else {
-			ret = 0;
-			if (fault & VM_FAULT_MAJOR)
-				current->maj_flt++;
-			else
-				current->min_flt++;
-		}
-	}
-	up_read(&mm->mmap_sem);
-	return ret;
-}
 
 /*
  * PI code:
@@ -589,10 +553,9 @@
 	 * The waiting task can free the futex_q as soon as this is written,
 	 * without taking any locks.  This must come last.
 	 *
-	 * A memory barrier is required here to prevent the following store
-	 * to lock_ptr from getting ahead of the wakeup. Clearing the lock
-	 * at the end of wake_up_all() does not prevent this store from
-	 * moving.
+	 * A memory barrier is required here to prevent the following store to
+	 * lock_ptr from getting ahead of the wakeup. Clearing the lock at the
+	 * end of wake_up() does not prevent this store from moving.
 	 */
 	smp_wmb();
 	q->lock_ptr = NULL;
@@ -692,9 +655,16 @@
 	}
 }
 
+static inline void
+double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
+{
+	spin_unlock(&hb1->lock);
+	if (hb1 != hb2)
+		spin_unlock(&hb2->lock);
+}
+
 /*
- * Wake up all waiters hashed on the physical page that is mapped
- * to this virtual address:
+ * Wake up waiters matching bitset queued on this futex (uaddr).
  */
 static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset)
 {
@@ -750,9 +720,9 @@
 	struct futex_hash_bucket *hb1, *hb2;
 	struct plist_head *head;
 	struct futex_q *this, *next;
-	int ret, op_ret, attempt = 0;
+	int ret, op_ret;
 
-retryfull:
+retry:
 	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
 		goto out;
@@ -763,16 +733,13 @@
 	hb1 = hash_futex(&key1);
 	hb2 = hash_futex(&key2);
 
-retry:
 	double_lock_hb(hb1, hb2);
-
+retry_private:
 	op_ret = futex_atomic_op_inuser(op, uaddr2);
 	if (unlikely(op_ret < 0)) {
 		u32 dummy;
 
-		spin_unlock(&hb1->lock);
-		if (hb1 != hb2)
-			spin_unlock(&hb2->lock);
+		double_unlock_hb(hb1, hb2);
 
 #ifndef CONFIG_MMU
 		/*
@@ -788,26 +755,16 @@
 			goto out_put_keys;
 		}
 
-		/*
-		 * futex_atomic_op_inuser needs to both read and write
-		 * *(int __user *)uaddr2, but we can't modify it
-		 * non-atomically.  Therefore, if get_user below is not
-		 * enough, we need to handle the fault ourselves, while
-		 * still holding the mmap_sem.
-		 */
-		if (attempt++) {
-			ret = futex_handle_fault((unsigned long)uaddr2,
-						 attempt);
-			if (ret)
-				goto out_put_keys;
-			goto retry;
-		}
-
 		ret = get_user(dummy, uaddr2);
 		if (ret)
-			return ret;
+			goto out_put_keys;
 
-		goto retryfull;
+		if (!fshared)
+			goto retry_private;
+
+		put_futex_key(fshared, &key2);
+		put_futex_key(fshared, &key1);
+		goto retry;
 	}
 
 	head = &hb1->chain;
@@ -834,9 +791,7 @@
 		ret += op_ret;
 	}
 
-	spin_unlock(&hb1->lock);
-	if (hb1 != hb2)
-		spin_unlock(&hb2->lock);
+	double_unlock_hb(hb1, hb2);
 out_put_keys:
 	put_futex_key(fshared, &key2);
 out_put_key1:
@@ -869,6 +824,7 @@
 	hb1 = hash_futex(&key1);
 	hb2 = hash_futex(&key2);
 
+retry_private:
 	double_lock_hb(hb1, hb2);
 
 	if (likely(cmpval != NULL)) {
@@ -877,16 +833,18 @@
 		ret = get_futex_value_locked(&curval, uaddr1);
 
 		if (unlikely(ret)) {
-			spin_unlock(&hb1->lock);
-			if (hb1 != hb2)
-				spin_unlock(&hb2->lock);
+			double_unlock_hb(hb1, hb2);
 
 			ret = get_user(curval, uaddr1);
+			if (ret)
+				goto out_put_keys;
 
-			if (!ret)
-				goto retry;
+			if (!fshared)
+				goto retry_private;
 
-			goto out_put_keys;
+			put_futex_key(fshared, &key2);
+			put_futex_key(fshared, &key1);
+			goto retry;
 		}
 		if (curval != *cmpval) {
 			ret = -EAGAIN;
@@ -923,9 +881,7 @@
 	}
 
 out_unlock:
-	spin_unlock(&hb1->lock);
-	if (hb1 != hb2)
-		spin_unlock(&hb2->lock);
+	double_unlock_hb(hb1, hb2);
 
 	/* drop_futex_key_refs() must be called outside the spinlocks. */
 	while (--drop_count >= 0)
@@ -1063,7 +1019,7 @@
 	struct futex_pi_state *pi_state = q->pi_state;
 	struct task_struct *oldowner = pi_state->owner;
 	u32 uval, curval, newval;
-	int ret, attempt = 0;
+	int ret;
 
 	/* Owner died? */
 	if (!pi_state->owner)
@@ -1076,11 +1032,9 @@
 	 * in the user space variable. This must be atomic as we have
 	 * to preserve the owner died bit here.
 	 *
-	 * Note: We write the user space value _before_ changing the
-	 * pi_state because we can fault here. Imagine swapped out
-	 * pages or a fork, which was running right before we acquired
-	 * mmap_sem, that marked all the anonymous memory readonly for
-	 * cow.
+	 * Note: We write the user space value _before_ changing the pi_state
+	 * because we can fault here. Imagine swapped out pages or a fork
+	 * that marked all the anonymous memory readonly for cow.
 	 *
 	 * Modifying pi_state _before_ the user space value would
 	 * leave the pi_state in an inconsistent state when we fault
@@ -1136,7 +1090,7 @@
 handle_fault:
 	spin_unlock(q->lock_ptr);
 
-	ret = futex_handle_fault((unsigned long)uaddr, attempt++);
+	ret = get_user(uval, uaddr);
 
 	spin_lock(q->lock_ptr);
 
@@ -1185,10 +1139,11 @@
 	if (unlikely(ret != 0))
 		goto out;
 
+retry_private:
 	hb = queue_lock(&q);
 
 	/*
-	 * Access the page AFTER the futex is queued.
+	 * Access the page AFTER the hash-bucket is locked.
 	 * Order is important:
 	 *
 	 *   Userspace waiter: val = var; if (cond(val)) futex_wait(&var, val);
@@ -1204,20 +1159,23 @@
 	 * a wakeup when *uaddr != val on entry to the syscall.  This is
 	 * rare, but normal.
 	 *
-	 * for shared futexes, we hold the mmap semaphore, so the mapping
+	 * For shared futexes, we hold the mmap semaphore, so the mapping
 	 * cannot have changed since we looked it up in get_futex_key.
 	 */
 	ret = get_futex_value_locked(&uval, uaddr);
 
 	if (unlikely(ret)) {
 		queue_unlock(&q, hb);
-		put_futex_key(fshared, &q.key);
 
 		ret = get_user(uval, uaddr);
+		if (ret)
+			goto out_put_key;
 
-		if (!ret)
-			goto retry;
-		goto out;
+		if (!fshared)
+			goto retry_private;
+
+		put_futex_key(fshared, &q.key);
+		goto retry;
 	}
 	ret = -EWOULDBLOCK;
 	if (unlikely(uval != val)) {
@@ -1248,16 +1206,13 @@
 		if (!abs_time)
 			schedule();
 		else {
-			unsigned long slack;
-			slack = current->timer_slack_ns;
-			if (rt_task(current))
-				slack = 0;
 			hrtimer_init_on_stack(&t.timer,
 					      clockrt ? CLOCK_REALTIME :
 					      CLOCK_MONOTONIC,
 					      HRTIMER_MODE_ABS);
 			hrtimer_init_sleeper(&t, current);
-			hrtimer_set_expires_range_ns(&t.timer, *abs_time, slack);
+			hrtimer_set_expires_range_ns(&t.timer, *abs_time,
+						     current->timer_slack_ns);
 
 			hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS);
 			if (!hrtimer_active(&t.timer))
@@ -1354,7 +1309,7 @@
 	struct futex_hash_bucket *hb;
 	u32 uval, newval, curval;
 	struct futex_q q;
-	int ret, lock_taken, ownerdied = 0, attempt = 0;
+	int ret, lock_taken, ownerdied = 0;
 
 	if (refill_pi_state_cache())
 		return -ENOMEM;
@@ -1374,7 +1329,7 @@
 	if (unlikely(ret != 0))
 		goto out;
 
-retry_unlocked:
+retry_private:
 	hb = queue_lock(&q);
 
 retry_locked:
@@ -1458,6 +1413,7 @@
 			 * exit to complete.
 			 */
 			queue_unlock(&q, hb);
+			put_futex_key(fshared, &q.key);
 			cond_resched();
 			goto retry;
 
@@ -1564,6 +1520,13 @@
 		}
 	}
 
+	/*
+	 * If fixup_pi_state_owner() faulted and was unable to handle the
+	 * fault, unlock it and return the fault to userspace.
+	 */
+	if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current))
+		rt_mutex_unlock(&q.pi_state->pi_mutex);
+
 	/* Unqueue and drop the lock */
 	unqueue_me_pi(&q);
 
@@ -1591,22 +1554,18 @@
 	 */
 	queue_unlock(&q, hb);
 
-	if (attempt++) {
-		ret = futex_handle_fault((unsigned long)uaddr, attempt);
-		if (ret)
-			goto out_put_key;
-		goto retry_unlocked;
-	}
-
 	ret = get_user(uval, uaddr);
-	if (!ret)
-		goto retry;
+	if (ret)
+		goto out_put_key;
 
-	if (to)
-		destroy_hrtimer_on_stack(&to->timer);
-	return ret;
+	if (!fshared)
+		goto retry_private;
+
+	put_futex_key(fshared, &q.key);
+	goto retry;
 }
 
+
 /*
  * Userspace attempted a TID -> 0 atomic transition, and failed.
  * This is the in-kernel slowpath: we look up the PI state (if any),
@@ -1619,7 +1578,7 @@
 	u32 uval;
 	struct plist_head *head;
 	union futex_key key = FUTEX_KEY_INIT;
-	int ret, attempt = 0;
+	int ret;
 
 retry:
 	if (get_user(uval, uaddr))
@@ -1635,7 +1594,6 @@
 		goto out;
 
 	hb = hash_futex(&key);
-retry_unlocked:
 	spin_lock(&hb->lock);
 
 	/*
@@ -1700,14 +1658,7 @@
 	 * we have to drop the mmap_sem in order to call get_user().
 	 */
 	spin_unlock(&hb->lock);
-
-	if (attempt++) {
-		ret = futex_handle_fault((unsigned long)uaddr, attempt);
-		if (ret)
-			goto out;
-		uval = 0;
-		goto retry_unlocked;
-	}
+	put_futex_key(fshared, &key);
 
 	ret = get_user(uval, uaddr);
 	if (!ret)
diff --git a/kernel/sched.c b/kernel/sched.c
index f4c413b..5757e03 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3190,7 +3190,7 @@
 	return 0;
 }
 /********** Helpers for find_busiest_group ************************/
-/**
+/*
  * sd_lb_stats - Structure to store the statistics of a sched_domain
  * 		during load balancing.
  */
@@ -3222,7 +3222,7 @@
 #endif
 };
 
-/**
+/*
  * sg_lb_stats - stats of a sched_group required for load_balancing
  */
 struct sg_lb_stats {
@@ -3360,16 +3360,17 @@
 }
 
 /**
- * check_power_save_busiest_group - Check if we have potential to perform
- *	some power-savings balance. If yes, set the busiest group to be
- *	the least loaded group in the sched_domain, so that it's CPUs can
- *	be put to idle.
- *
+ * check_power_save_busiest_group - see if there is potential for some power-savings balance
  * @sds: Variable containing the statistics of the sched_domain
  *	under consideration.
  * @this_cpu: Cpu at which we're currently performing load-balancing.
  * @imbalance: Variable to store the imbalance.
  *
+ * Description:
+ * Check if we have potential to perform some power-savings balance.
+ * If yes, set the busiest group to be the least loaded group in the
+ * sched_domain, so that it's CPUs can be put to idle.
+ *
  * Returns 1 if there is potential to perform power-savings balance.
  * Else returns 0.
  */
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 930c08e..dce71a5 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -42,6 +42,81 @@
 /* pid on the last trace processed */
 static pid_t last_pid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 };
 
+/* Add a function return address to the trace stack on thread info.*/
+int
+ftrace_push_return_trace(unsigned long ret, unsigned long long time,
+			 unsigned long func, int *depth)
+{
+	int index;
+
+	if (!current->ret_stack)
+		return -EBUSY;
+
+	/* The return trace stack is full */
+	if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
+		atomic_inc(&current->trace_overrun);
+		return -EBUSY;
+	}
+
+	index = ++current->curr_ret_stack;
+	barrier();
+	current->ret_stack[index].ret = ret;
+	current->ret_stack[index].func = func;
+	current->ret_stack[index].calltime = time;
+	*depth = index;
+
+	return 0;
+}
+
+/* Retrieve a function return address to the trace stack on thread info.*/
+void
+ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
+{
+	int index;
+
+	index = current->curr_ret_stack;
+
+	if (unlikely(index < 0)) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		/* Might as well panic, otherwise we have no where to go */
+		*ret = (unsigned long)panic;
+		return;
+	}
+
+	*ret = current->ret_stack[index].ret;
+	trace->func = current->ret_stack[index].func;
+	trace->calltime = current->ret_stack[index].calltime;
+	trace->overrun = atomic_read(&current->trace_overrun);
+	trace->depth = index;
+	barrier();
+	current->curr_ret_stack--;
+
+}
+
+/*
+ * Send the trace to the ring-buffer.
+ * @return the original return address.
+ */
+unsigned long ftrace_return_to_handler(void)
+{
+	struct ftrace_graph_ret trace;
+	unsigned long ret;
+
+	ftrace_pop_return_trace(&trace, &ret);
+	trace.rettime = cpu_clock(raw_smp_processor_id());
+	ftrace_graph_return(&trace);
+
+	if (unlikely(!ret)) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		/* Might as well panic. What else to do? */
+		ret = (unsigned long)panic;
+	}
+
+	return ret;
+}
+
 static int graph_trace_init(struct trace_array *tr)
 {
 	int cpu, ret;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 251fa7b..58bfe7e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -402,7 +402,7 @@
 	bool
 	depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
 	select STACKTRACE
-	select FRAME_POINTER if !X86 && !MIPS && !PPC
+	select FRAME_POINTER if !X86 && !MIPS && !PPC && !ARM_UNWIND
 	select KALLSYMS
 	select KALLSYMS_ALL
 
diff --git a/lib/lmb.c b/lib/lmb.c
index 97e54703..e4a6482 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -29,33 +29,33 @@
 }
 early_param("lmb", early_lmb);
 
+static void lmb_dump(struct lmb_region *region, char *name)
+{
+	unsigned long long base, size;
+	int i;
+
+	pr_info(" %s.cnt  = 0x%lx\n", name, region->cnt);
+
+	for (i = 0; i < region->cnt; i++) {
+		base = region->region[i].base;
+		size = region->region[i].size;
+
+		pr_info(" %s[0x%x]\t0x%016llx - 0x%016llx, 0x%llx bytes\n",
+		    name, i, base, base + size - 1, size);
+	}
+}
+
 void lmb_dump_all(void)
 {
-	unsigned long i;
-
 	if (!lmb_debug)
 		return;
 
-	pr_info("lmb_dump_all:\n");
-	pr_info("    memory.cnt		  = 0x%lx\n", lmb.memory.cnt);
-	pr_info("    memory.size		  = 0x%llx\n",
-	    (unsigned long long)lmb.memory.size);
-	for (i=0; i < lmb.memory.cnt ;i++) {
-		pr_info("    memory.region[0x%lx].base       = 0x%llx\n",
-		    i, (unsigned long long)lmb.memory.region[i].base);
-		pr_info("		      .size     = 0x%llx\n",
-		    (unsigned long long)lmb.memory.region[i].size);
-	}
+	pr_info("LMB configuration:\n");
+	pr_info(" rmo_size    = 0x%llx\n", (unsigned long long)lmb.rmo_size);
+	pr_info(" memory.size = 0x%llx\n", (unsigned long long)lmb.memory.size);
 
-	pr_info("    reserved.cnt	  = 0x%lx\n", lmb.reserved.cnt);
-	pr_info("    reserved.size	  = 0x%llx\n",
-	    (unsigned long long)lmb.memory.size);
-	for (i=0; i < lmb.reserved.cnt ;i++) {
-		pr_info("    reserved.region[0x%lx].base       = 0x%llx\n",
-		    i, (unsigned long long)lmb.reserved.region[i].base);
-		pr_info("		      .size     = 0x%llx\n",
-		    (unsigned long long)lmb.reserved.region[i].size);
-	}
+	lmb_dump(&lmb.memory, "memory");
+	lmb_dump(&lmb.reserved, "reserved");
 }
 
 static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2,
diff --git a/mm/highmem.c b/mm/highmem.c
index b36b83b..9101980 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -67,6 +67,25 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
 
+/*
+ * Most architectures have no use for kmap_high_get(), so let's abstract
+ * the disabling of IRQ out of the locking in that case to save on a
+ * potential useless overhead.
+ */
+#ifdef ARCH_NEEDS_KMAP_HIGH_GET
+#define lock_kmap()             spin_lock_irq(&kmap_lock)
+#define unlock_kmap()           spin_unlock_irq(&kmap_lock)
+#define lock_kmap_any(flags)    spin_lock_irqsave(&kmap_lock, flags)
+#define unlock_kmap_any(flags)  spin_unlock_irqrestore(&kmap_lock, flags)
+#else
+#define lock_kmap()             spin_lock(&kmap_lock)
+#define unlock_kmap()           spin_unlock(&kmap_lock)
+#define lock_kmap_any(flags)    \
+		do { spin_lock(&kmap_lock); (void)(flags); } while (0)
+#define unlock_kmap_any(flags)  \
+		do { spin_unlock(&kmap_lock); (void)(flags); } while (0)
+#endif
+
 static void flush_all_zero_pkmaps(void)
 {
 	int i;
@@ -113,9 +132,9 @@
  */
 void kmap_flush_unused(void)
 {
-	spin_lock(&kmap_lock);
+	lock_kmap();
 	flush_all_zero_pkmaps();
-	spin_unlock(&kmap_lock);
+	unlock_kmap();
 }
 
 static inline unsigned long map_new_virtual(struct page *page)
@@ -145,10 +164,10 @@
 
 			__set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&pkmap_map_wait, &wait);
-			spin_unlock(&kmap_lock);
+			unlock_kmap();
 			schedule();
 			remove_wait_queue(&pkmap_map_wait, &wait);
-			spin_lock(&kmap_lock);
+			lock_kmap();
 
 			/* Somebody else might have mapped it while we slept */
 			if (page_address(page))
@@ -184,29 +203,59 @@
 	 * For highmem pages, we can't trust "virtual" until
 	 * after we have the lock.
 	 */
-	spin_lock(&kmap_lock);
+	lock_kmap();
 	vaddr = (unsigned long)page_address(page);
 	if (!vaddr)
 		vaddr = map_new_virtual(page);
 	pkmap_count[PKMAP_NR(vaddr)]++;
 	BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2);
-	spin_unlock(&kmap_lock);
+	unlock_kmap();
 	return (void*) vaddr;
 }
 
 EXPORT_SYMBOL(kmap_high);
 
+#ifdef ARCH_NEEDS_KMAP_HIGH_GET
+/**
+ * kmap_high_get - pin a highmem page into memory
+ * @page: &struct page to pin
+ *
+ * Returns the page's current virtual memory address, or NULL if no mapping
+ * exists.  When and only when a non null address is returned then a
+ * matching call to kunmap_high() is necessary.
+ *
+ * This can be called from any context.
+ */
+void *kmap_high_get(struct page *page)
+{
+	unsigned long vaddr, flags;
+
+	lock_kmap_any(flags);
+	vaddr = (unsigned long)page_address(page);
+	if (vaddr) {
+		BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 1);
+		pkmap_count[PKMAP_NR(vaddr)]++;
+	}
+	unlock_kmap_any(flags);
+	return (void*) vaddr;
+}
+#endif
+
 /**
  * kunmap_high - map a highmem page into memory
  * @page: &struct page to unmap
+ *
+ * If ARCH_NEEDS_KMAP_HIGH_GET is not defined then this may be called
+ * only from user context.
  */
 void kunmap_high(struct page *page)
 {
 	unsigned long vaddr;
 	unsigned long nr;
+	unsigned long flags;
 	int need_wakeup;
 
-	spin_lock(&kmap_lock);
+	lock_kmap_any(flags);
 	vaddr = (unsigned long)page_address(page);
 	BUG_ON(!vaddr);
 	nr = PKMAP_NR(vaddr);
@@ -232,7 +281,7 @@
 		 */
 		need_wakeup = waitqueue_active(&pkmap_map_wait);
 	}
-	spin_unlock(&kmap_lock);
+	unlock_kmap_any(flags);
 
 	/* do wake-up, if needed, race-free outside of the spin lock */
 	if (need_wakeup)
diff --git a/mm/memory.c b/mm/memory.c
index baa999e..2032ad2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1665,9 +1665,10 @@
 	 * behaviour that some programs depend on. We mark the "original"
 	 * un-COW'ed pages by matching them up with "vma->vm_pgoff".
 	 */
-	if (addr == vma->vm_start && end == vma->vm_end)
+	if (addr == vma->vm_start && end == vma->vm_end) {
 		vma->vm_pgoff = pfn;
-	else if (is_cow_mapping(vma->vm_flags))
+		vma->vm_flags |= VM_PFN_AT_MMAP;
+	} else if (is_cow_mapping(vma->vm_flags))
 		return -EINVAL;
 
 	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
@@ -1679,6 +1680,7 @@
 		 * needed from higher level routine calling unmap_vmas
 		 */
 		vma->vm_flags &= ~(VM_IO | VM_RESERVED | VM_PFNMAP);
+		vma->vm_flags &= ~VM_PFN_AT_MMAP;
 		return -EINVAL;
 	}
 
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 7bc9929..039cc1f 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1942,23 +1942,85 @@
 }
 
 /**
- * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
- * @sk: the socket
+ * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
+ * @req: the connection request socket
+ * @doi_def: the CIPSO DOI to use
+ * @secattr: the specific security attributes of the socket
  *
  * Description:
- * Removes the CIPSO option from a socket, if present.
+ * Set the CIPSO option on the given socket using the DOI definition and
+ * security attributes passed to the function.  Returns zero on success and
+ * negative values on failure.
  *
  */
-void cipso_v4_sock_delattr(struct sock *sk)
+int cipso_v4_req_setattr(struct request_sock *req,
+			 const struct cipso_v4_doi *doi_def,
+			 const struct netlbl_lsm_secattr *secattr)
 {
-	u8 hdr_delta;
-	struct ip_options *opt;
-	struct inet_sock *sk_inet;
+	int ret_val = -EPERM;
+	unsigned char *buf = NULL;
+	u32 buf_len;
+	u32 opt_len;
+	struct ip_options *opt = NULL;
+	struct inet_request_sock *req_inet;
 
-	sk_inet = inet_sk(sk);
-	opt = sk_inet->opt;
-	if (opt == NULL || opt->cipso == 0)
-		return;
+	/* We allocate the maximum CIPSO option size here so we are probably
+	 * being a little wasteful, but it makes our life _much_ easier later
+	 * on and after all we are only talking about 40 bytes. */
+	buf_len = CIPSO_V4_OPT_LEN_MAX;
+	buf = kmalloc(buf_len, GFP_ATOMIC);
+	if (buf == NULL) {
+		ret_val = -ENOMEM;
+		goto req_setattr_failure;
+	}
+
+	ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
+	if (ret_val < 0)
+		goto req_setattr_failure;
+	buf_len = ret_val;
+
+	/* We can't use ip_options_get() directly because it makes a call to
+	 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
+	 * we won't always have CAP_NET_RAW even though we _always_ want to
+	 * set the IPOPT_CIPSO option. */
+	opt_len = (buf_len + 3) & ~3;
+	opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
+	if (opt == NULL) {
+		ret_val = -ENOMEM;
+		goto req_setattr_failure;
+	}
+	memcpy(opt->__data, buf, buf_len);
+	opt->optlen = opt_len;
+	opt->cipso = sizeof(struct iphdr);
+	kfree(buf);
+	buf = NULL;
+
+	req_inet = inet_rsk(req);
+	opt = xchg(&req_inet->opt, opt);
+	kfree(opt);
+
+	return 0;
+
+req_setattr_failure:
+	kfree(buf);
+	kfree(opt);
+	return ret_val;
+}
+
+/**
+ * cipso_v4_delopt - Delete the CIPSO option from a set of IP options
+ * @opt_ptr: IP option pointer
+ *
+ * Description:
+ * Deletes the CIPSO IP option from a set of IP options and makes the necessary
+ * adjustments to the IP option structure.  Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int cipso_v4_delopt(struct ip_options **opt_ptr)
+{
+	int hdr_delta = 0;
+	struct ip_options *opt = *opt_ptr;
 
 	if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
 		u8 cipso_len;
@@ -2003,11 +2065,34 @@
 	} else {
 		/* only the cipso option was present on the socket so we can
 		 * remove the entire option struct */
-		sk_inet->opt = NULL;
+		*opt_ptr = NULL;
 		hdr_delta = opt->optlen;
 		kfree(opt);
 	}
 
+	return hdr_delta;
+}
+
+/**
+ * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
+ * @sk: the socket
+ *
+ * Description:
+ * Removes the CIPSO option from a socket, if present.
+ *
+ */
+void cipso_v4_sock_delattr(struct sock *sk)
+{
+	int hdr_delta;
+	struct ip_options *opt;
+	struct inet_sock *sk_inet;
+
+	sk_inet = inet_sk(sk);
+	opt = sk_inet->opt;
+	if (opt == NULL || opt->cipso == 0)
+		return;
+
+	hdr_delta = cipso_v4_delopt(&sk_inet->opt);
 	if (sk_inet->is_icsk && hdr_delta > 0) {
 		struct inet_connection_sock *sk_conn = inet_csk(sk);
 		sk_conn->icsk_ext_hdr_len -= hdr_delta;
@@ -2016,6 +2101,27 @@
 }
 
 /**
+ * cipso_v4_req_delattr - Delete the CIPSO option from a request socket
+ * @reg: the request socket
+ *
+ * Description:
+ * Removes the CIPSO option from a request socket, if present.
+ *
+ */
+void cipso_v4_req_delattr(struct request_sock *req)
+{
+	struct ip_options *opt;
+	struct inet_request_sock *req_inet;
+
+	req_inet = inet_rsk(req);
+	opt = req_inet->opt;
+	if (opt == NULL || opt->cipso == 0)
+		return;
+
+	cipso_v4_delopt(&req_inet->opt);
+}
+
+/**
  * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
  * @cipso: the CIPSO v4 option
  * @secattr: the security attributes
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index d346c22..b35a950 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -288,10 +288,6 @@
 	if (!req)
 		goto out;
 
-	if (security_inet_conn_request(sk, skb, req)) {
-		reqsk_free(req);
-		goto out;
-	}
 	ireq = inet_rsk(req);
 	treq = tcp_rsk(req);
 	treq->rcv_isn		= ntohl(th->seq) - 1;
@@ -322,6 +318,11 @@
 		}
 	}
 
+	if (security_inet_conn_request(sk, skb, req)) {
+		reqsk_free(req);
+		goto out;
+	}
+
 	req->expires	= 0UL;
 	req->retrans	= 0;
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d0a3148..5d427f8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1230,14 +1230,15 @@
 
 	tcp_openreq_init(req, &tmp_opt, skb);
 
-	if (security_inet_conn_request(sk, skb, req))
-		goto drop_and_free;
-
 	ireq = inet_rsk(req);
 	ireq->loc_addr = daddr;
 	ireq->rmt_addr = saddr;
 	ireq->no_srccheck = inet_sk(sk)->transparent;
 	ireq->opt = tcp_v4_save_options(sk, skb);
+
+	if (security_inet_conn_request(sk, skb, req))
+		goto drop_and_free;
+
 	if (!want_cookie)
 		TCP_ECN_create_request(req, tcp_hdr(skb));
 
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index fd9229d..b0e582f 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -619,8 +619,9 @@
 }
 
 /**
- * netlbl_socket_setattr - Label a socket using the correct protocol
+ * netlbl_sock_setattr - Label a socket using the correct protocol
  * @sk: the socket to label
+ * @family: protocol family
  * @secattr: the security attributes
  *
  * Description:
@@ -633,29 +634,45 @@
  *
  */
 int netlbl_sock_setattr(struct sock *sk,
+			u16 family,
 			const struct netlbl_lsm_secattr *secattr)
 {
-	int ret_val = -ENOENT;
+	int ret_val;
 	struct netlbl_dom_map *dom_entry;
 
 	rcu_read_lock();
 	dom_entry = netlbl_domhsh_getentry(secattr->domain);
-	if (dom_entry == NULL)
+	if (dom_entry == NULL) {
+		ret_val = -ENOENT;
 		goto socket_setattr_return;
-	switch (dom_entry->type) {
-	case NETLBL_NLTYPE_ADDRSELECT:
-		ret_val = -EDESTADDRREQ;
+	}
+	switch (family) {
+	case AF_INET:
+		switch (dom_entry->type) {
+		case NETLBL_NLTYPE_ADDRSELECT:
+			ret_val = -EDESTADDRREQ;
+			break;
+		case NETLBL_NLTYPE_CIPSOV4:
+			ret_val = cipso_v4_sock_setattr(sk,
+						    dom_entry->type_def.cipsov4,
+						    secattr);
+			break;
+		case NETLBL_NLTYPE_UNLABELED:
+			ret_val = 0;
+			break;
+		default:
+			ret_val = -ENOENT;
+		}
 		break;
-	case NETLBL_NLTYPE_CIPSOV4:
-		ret_val = cipso_v4_sock_setattr(sk,
-						dom_entry->type_def.cipsov4,
-						secattr);
-		break;
-	case NETLBL_NLTYPE_UNLABELED:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		/* since we don't support any IPv6 labeling protocols right
+		 * now we can optimize everything away until we do */
 		ret_val = 0;
 		break;
+#endif /* IPv6 */
 	default:
-		ret_val = -ENOENT;
+		ret_val = -EPROTONOSUPPORT;
 	}
 
 socket_setattr_return:
@@ -689,9 +706,25 @@
  * on failure.
  *
  */
-int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+int netlbl_sock_getattr(struct sock *sk,
+			struct netlbl_lsm_secattr *secattr)
 {
-	return cipso_v4_sock_getattr(sk, secattr);
+	int ret_val;
+
+	switch (sk->sk_family) {
+	case AF_INET:
+		ret_val = cipso_v4_sock_getattr(sk, secattr);
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		ret_val = -ENOMSG;
+		break;
+#endif /* IPv6 */
+	default:
+		ret_val = -EPROTONOSUPPORT;
+	}
+
+	return ret_val;
 }
 
 /**
@@ -748,7 +781,7 @@
 		break;
 #endif /* IPv6 */
 	default:
-		ret_val = 0;
+		ret_val = -EPROTONOSUPPORT;
 	}
 
 conn_setattr_return:
@@ -757,6 +790,90 @@
 }
 
 /**
+ * netlbl_req_setattr - Label a request socket using the correct protocol
+ * @req: the request socket to label
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Attach the correct label to the given socket using the security attributes
+ * specified in @secattr.  Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_req_setattr(struct request_sock *req,
+		       const struct netlbl_lsm_secattr *secattr)
+{
+	int ret_val;
+	struct netlbl_dom_map *dom_entry;
+	struct netlbl_domaddr4_map *af4_entry;
+	u32 proto_type;
+	struct cipso_v4_doi *proto_cv4;
+
+	rcu_read_lock();
+	dom_entry = netlbl_domhsh_getentry(secattr->domain);
+	if (dom_entry == NULL) {
+		ret_val = -ENOENT;
+		goto req_setattr_return;
+	}
+	switch (req->rsk_ops->family) {
+	case AF_INET:
+		if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) {
+			struct inet_request_sock *req_inet = inet_rsk(req);
+			af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
+							    req_inet->rmt_addr);
+			if (af4_entry == NULL) {
+				ret_val = -ENOENT;
+				goto req_setattr_return;
+			}
+			proto_type = af4_entry->type;
+			proto_cv4 = af4_entry->type_def.cipsov4;
+		} else {
+			proto_type = dom_entry->type;
+			proto_cv4 = dom_entry->type_def.cipsov4;
+		}
+		switch (proto_type) {
+		case NETLBL_NLTYPE_CIPSOV4:
+			ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr);
+			break;
+		case NETLBL_NLTYPE_UNLABELED:
+			/* just delete the protocols we support for right now
+			 * but we could remove other protocols if needed */
+			cipso_v4_req_delattr(req);
+			ret_val = 0;
+			break;
+		default:
+			ret_val = -ENOENT;
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		/* since we don't support any IPv6 labeling protocols right
+		 * now we can optimize everything away until we do */
+		ret_val = 0;
+		break;
+#endif /* IPv6 */
+	default:
+		ret_val = -EPROTONOSUPPORT;
+	}
+
+req_setattr_return:
+	rcu_read_unlock();
+	return ret_val;
+}
+
+/**
+* netlbl_req_delattr - Delete all the NetLabel labels on a socket
+* @req: the socket
+*
+* Description:
+* Remove all the NetLabel labeling from @req.
+*
+*/
+void netlbl_req_delattr(struct request_sock *req)
+{
+	cipso_v4_req_delattr(req);
+}
+
+/**
  * netlbl_skbuff_setattr - Label a packet using the correct protocol
  * @skb: the packet
  * @family: protocol family
@@ -808,7 +925,7 @@
 		break;
 #endif /* IPv6 */
 	default:
-		ret_val = 0;
+		ret_val = -EPROTONOSUPPORT;
 	}
 
 skbuff_setattr_return:
@@ -833,9 +950,17 @@
 			  u16 family,
 			  struct netlbl_lsm_secattr *secattr)
 {
-	if (CIPSO_V4_OPTEXIST(skb) &&
-	    cipso_v4_skbuff_getattr(skb, secattr) == 0)
-		return 0;
+	switch (family) {
+	case AF_INET:
+		if (CIPSO_V4_OPTEXIST(skb) &&
+		    cipso_v4_skbuff_getattr(skb, secattr) == 0)
+			return 0;
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		break;
+#endif /* IPv6 */
+	}
 
 	return netlbl_unlabel_getattr(skb, family, secattr);
 }
diff --git a/net/socket.c b/net/socket.c
index 0b14b79..91d0c02 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1536,8 +1536,6 @@
 	fd_install(newfd, newfile);
 	err = newfd;
 
-	security_socket_post_accept(sock, newsock);
-
 out_put:
 	fput_light(sock->file, fput_needed);
 out:
diff --git a/security/capability.c b/security/capability.c
index c545bd1..21b6cea 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -620,10 +620,6 @@
 	return 0;
 }
 
-static void cap_socket_post_accept(struct socket *sock, struct socket *newsock)
-{
-}
-
 static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
 	return 0;
@@ -1014,7 +1010,6 @@
 	set_to_cap_if_null(ops, socket_connect);
 	set_to_cap_if_null(ops, socket_listen);
 	set_to_cap_if_null(ops, socket_accept);
-	set_to_cap_if_null(ops, socket_post_accept);
 	set_to_cap_if_null(ops, socket_sendmsg);
 	set_to_cap_if_null(ops, socket_recvmsg);
 	set_to_cap_if_null(ops, socket_getsockname);
diff --git a/security/security.c b/security/security.c
index c3586c0..206e538 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1007,11 +1007,6 @@
 	return security_ops->socket_accept(sock, newsock);
 }
 
-void security_socket_post_accept(struct socket *sock, struct socket *newsock)
-{
-	security_ops->socket_post_accept(sock, newsock);
-}
-
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
 	return security_ops->socket_sendmsg(sock, msg, size);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7c52ba2..ba808ef 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -93,7 +93,6 @@
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
-extern int selinux_compat_net;
 extern struct security_operations *security_ops;
 
 /* SECMARK reference count */
@@ -311,7 +310,7 @@
 	ssec->sid = SECINITSID_UNLABELED;
 	sk->sk_security = ssec;
 
-	selinux_netlbl_sk_security_reset(ssec, family);
+	selinux_netlbl_sk_security_reset(ssec);
 
 	return 0;
 }
@@ -2945,7 +2944,6 @@
 static int selinux_revalidate_file_permission(struct file *file, int mask)
 {
 	const struct cred *cred = current_cred();
-	int rc;
 	struct inode *inode = file->f_path.dentry->d_inode;
 
 	if (!mask) {
@@ -2957,29 +2955,15 @@
 	if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
 		mask |= MAY_APPEND;
 
-	rc = file_has_perm(cred, file,
-			   file_mask_to_av(inode->i_mode, mask));
-	if (rc)
-		return rc;
-
-	return selinux_netlbl_inode_permission(inode, mask);
+	return file_has_perm(cred, file,
+			     file_mask_to_av(inode->i_mode, mask));
 }
 
 static int selinux_file_permission(struct file *file, int mask)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
-	struct file_security_struct *fsec = file->f_security;
-	struct inode_security_struct *isec = inode->i_security;
-	u32 sid = current_sid();
-
-	if (!mask) {
+	if (!mask)
 		/* No permission to check.  Existence test. */
 		return 0;
-	}
-
-	if (sid == fsec->sid && fsec->isid == isec->sid
-	    && fsec->pseqno == avc_policy_seqno())
-		return selinux_netlbl_inode_permission(inode, mask);
 
 	return selinux_revalidate_file_permission(file, mask);
 }
@@ -3723,7 +3707,7 @@
 		sksec = sock->sk->sk_security;
 		sksec->sid = isec->sid;
 		sksec->sclass = isec->sclass;
-		err = selinux_netlbl_socket_post_create(sock);
+		err = selinux_netlbl_socket_post_create(sock->sk, family);
 	}
 
 	return err;
@@ -3914,13 +3898,7 @@
 static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
 				  int size)
 {
-	int rc;
-
-	rc = socket_has_perm(current, sock, SOCKET__WRITE);
-	if (rc)
-		return rc;
-
-	return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
+	return socket_has_perm(current, sock, SOCKET__WRITE);
 }
 
 static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -4040,72 +4018,6 @@
 			    SECCLASS_NODE, NODE__RECVFROM, ad);
 }
 
-static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
-						struct sk_buff *skb,
-						struct avc_audit_data *ad,
-						u16 family,
-						char *addrp)
-{
-	int err;
-	struct sk_security_struct *sksec = sk->sk_security;
-	u16 sk_class;
-	u32 netif_perm, node_perm, recv_perm;
-	u32 port_sid, node_sid, if_sid, sk_sid;
-
-	sk_sid = sksec->sid;
-	sk_class = sksec->sclass;
-
-	switch (sk_class) {
-	case SECCLASS_UDP_SOCKET:
-		netif_perm = NETIF__UDP_RECV;
-		node_perm = NODE__UDP_RECV;
-		recv_perm = UDP_SOCKET__RECV_MSG;
-		break;
-	case SECCLASS_TCP_SOCKET:
-		netif_perm = NETIF__TCP_RECV;
-		node_perm = NODE__TCP_RECV;
-		recv_perm = TCP_SOCKET__RECV_MSG;
-		break;
-	case SECCLASS_DCCP_SOCKET:
-		netif_perm = NETIF__DCCP_RECV;
-		node_perm = NODE__DCCP_RECV;
-		recv_perm = DCCP_SOCKET__RECV_MSG;
-		break;
-	default:
-		netif_perm = NETIF__RAWIP_RECV;
-		node_perm = NODE__RAWIP_RECV;
-		recv_perm = 0;
-		break;
-	}
-
-	err = sel_netif_sid(skb->iif, &if_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
-	if (err)
-		return err;
-
-	err = sel_netnode_sid(addrp, family, &node_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
-	if (err)
-		return err;
-
-	if (!recv_perm)
-		return 0;
-	err = sel_netport_sid(sk->sk_protocol,
-			      ntohs(ad->u.net.sport), &port_sid);
-	if (unlikely(err)) {
-		printk(KERN_WARNING
-		       "SELinux: failure in"
-		       " selinux_sock_rcv_skb_iptables_compat(),"
-		       " network port label not found\n");
-		return err;
-	}
-	return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
-}
-
 static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 				       u16 family)
 {
@@ -4123,14 +4035,12 @@
 	if (err)
 		return err;
 
-	if (selinux_compat_net)
-		err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
-							   family, addrp);
-	else if (selinux_secmark_enabled())
+	if (selinux_secmark_enabled()) {
 		err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
 				   PACKET__RECV, &ad);
-	if (err)
-		return err;
+		if (err)
+			return err;
+	}
 
 	if (selinux_policycap_netpeer) {
 		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4172,7 +4082,7 @@
 	 * to the selinux_sock_rcv_skb_compat() function to deal with the
 	 * special handling.  We do this in an attempt to keep this function
 	 * as fast and as clean as possible. */
-	if (selinux_compat_net || !selinux_policycap_netpeer)
+	if (!selinux_policycap_netpeer)
 		return selinux_sock_rcv_skb_compat(sk, skb, family);
 
 	secmark_active = selinux_secmark_enabled();
@@ -4304,7 +4214,7 @@
 	newssec->peer_sid = ssec->peer_sid;
 	newssec->sclass = ssec->sclass;
 
-	selinux_netlbl_sk_security_reset(newssec, newsk->sk_family);
+	selinux_netlbl_sk_security_reset(newssec);
 }
 
 static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -4348,16 +4258,15 @@
 	if (peersid == SECSID_NULL) {
 		req->secid = sksec->sid;
 		req->peer_secid = SECSID_NULL;
-		return 0;
+	} else {
+		err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
+		if (err)
+			return err;
+		req->secid = newsid;
+		req->peer_secid = peersid;
 	}
 
-	err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
-	if (err)
-		return err;
-
-	req->secid = newsid;
-	req->peer_secid = peersid;
-	return 0;
+	return selinux_netlbl_inet_conn_request(req, family);
 }
 
 static void selinux_inet_csk_clone(struct sock *newsk,
@@ -4374,7 +4283,7 @@
 
 	/* We don't need to take any sort of lock here as we are the only
 	 * thread with access to newsksec */
-	selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
+	selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
 }
 
 static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
@@ -4387,8 +4296,6 @@
 		family = PF_INET;
 
 	selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
-
-	selinux_netlbl_inet_conn_established(sk, family);
 }
 
 static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4540,71 +4447,6 @@
 	return selinux_ip_output(skb, PF_INET);
 }
 
-static int selinux_ip_postroute_iptables_compat(struct sock *sk,
-						int ifindex,
-						struct avc_audit_data *ad,
-						u16 family, char *addrp)
-{
-	int err;
-	struct sk_security_struct *sksec = sk->sk_security;
-	u16 sk_class;
-	u32 netif_perm, node_perm, send_perm;
-	u32 port_sid, node_sid, if_sid, sk_sid;
-
-	sk_sid = sksec->sid;
-	sk_class = sksec->sclass;
-
-	switch (sk_class) {
-	case SECCLASS_UDP_SOCKET:
-		netif_perm = NETIF__UDP_SEND;
-		node_perm = NODE__UDP_SEND;
-		send_perm = UDP_SOCKET__SEND_MSG;
-		break;
-	case SECCLASS_TCP_SOCKET:
-		netif_perm = NETIF__TCP_SEND;
-		node_perm = NODE__TCP_SEND;
-		send_perm = TCP_SOCKET__SEND_MSG;
-		break;
-	case SECCLASS_DCCP_SOCKET:
-		netif_perm = NETIF__DCCP_SEND;
-		node_perm = NODE__DCCP_SEND;
-		send_perm = DCCP_SOCKET__SEND_MSG;
-		break;
-	default:
-		netif_perm = NETIF__RAWIP_SEND;
-		node_perm = NODE__RAWIP_SEND;
-		send_perm = 0;
-		break;
-	}
-
-	err = sel_netif_sid(ifindex, &if_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
-		return err;
-
-	err = sel_netnode_sid(addrp, family, &node_sid);
-	if (err)
-		return err;
-	err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
-	if (err)
-		return err;
-
-	if (send_perm != 0)
-		return 0;
-
-	err = sel_netport_sid(sk->sk_protocol,
-			      ntohs(ad->u.net.dport), &port_sid);
-	if (unlikely(err)) {
-		printk(KERN_WARNING
-		       "SELinux: failure in"
-		       " selinux_ip_postroute_iptables_compat(),"
-		       " network port label not found\n");
-		return err;
-	}
-	return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
-}
-
 static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 						int ifindex,
 						u16 family)
@@ -4625,15 +4467,10 @@
 	if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
 		return NF_DROP;
 
-	if (selinux_compat_net) {
-		if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
-							 &ad, family, addrp))
-			return NF_DROP;
-	} else if (selinux_secmark_enabled()) {
+	if (selinux_secmark_enabled())
 		if (avc_has_perm(sksec->sid, skb->secmark,
 				 SECCLASS_PACKET, PACKET__SEND, &ad))
 			return NF_DROP;
-	}
 
 	if (selinux_policycap_netpeer)
 		if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
@@ -4657,7 +4494,7 @@
 	 * to the selinux_ip_postroute_compat() function to deal with the
 	 * special handling.  We do this in an attempt to keep this function
 	 * as fast and as clean as possible. */
-	if (selinux_compat_net || !selinux_policycap_netpeer)
+	if (!selinux_policycap_netpeer)
 		return selinux_ip_postroute_compat(skb, ifindex, family);
 #ifdef CONFIG_XFRM
 	/* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index b913c8d..b4b5b9b 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -32,6 +32,7 @@
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
+#include <net/request_sock.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -42,8 +43,7 @@
 void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
 
 void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
-void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
-				      int family);
+void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec);
 
 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
 				 u16 family,
@@ -53,9 +53,9 @@
 				 u16 family,
 				 u32 sid);
 
-void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family);
-int selinux_netlbl_socket_post_create(struct socket *sock);
-int selinux_netlbl_inode_permission(struct inode *inode, int mask);
+int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family);
+void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family);
+int selinux_netlbl_socket_post_create(struct sock *sk, u16 family);
 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
 				struct sk_buff *skb,
 				u16 family,
@@ -85,8 +85,7 @@
 }
 
 static inline void selinux_netlbl_sk_security_reset(
-					       struct sk_security_struct *ssec,
-					       int family)
+					       struct sk_security_struct *ssec)
 {
 	return;
 }
@@ -113,17 +112,17 @@
 	return 0;
 }
 
-static inline void selinux_netlbl_inet_conn_established(struct sock *sk,
-							u16 family)
-{
-	return;
-}
-static inline int selinux_netlbl_socket_post_create(struct socket *sock)
+static inline int selinux_netlbl_inet_conn_request(struct request_sock *req,
+						   u16 family)
 {
 	return 0;
 }
-static inline int selinux_netlbl_inode_permission(struct inode *inode,
-						  int mask)
+static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
+{
+	return;
+}
+static inline int selinux_netlbl_socket_post_create(struct sock *sk,
+						    u16 family)
 {
 	return 0;
 }
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 350794a..2e98441 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -100,41 +100,6 @@
 }
 
 /**
- * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
- * @sk: the socket to label
- *
- * Description:
- * Attempt to label a socket using the NetLabel mechanism.  Returns zero values
- * on success, negative values on failure.
- *
- */
-static int selinux_netlbl_sock_setsid(struct sock *sk)
-{
-	int rc;
-	struct sk_security_struct *sksec = sk->sk_security;
-	struct netlbl_lsm_secattr *secattr;
-
-	if (sksec->nlbl_state != NLBL_REQUIRE)
-		return 0;
-
-	secattr = selinux_netlbl_sock_genattr(sk);
-	if (secattr == NULL)
-		return -ENOMEM;
-	rc = netlbl_sock_setattr(sk, secattr);
-	switch (rc) {
-	case 0:
-		sksec->nlbl_state = NLBL_LABELED;
-		break;
-	case -EDESTADDRREQ:
-		sksec->nlbl_state = NLBL_REQSKB;
-		rc = 0;
-		break;
-	}
-
-	return rc;
-}
-
-/**
  * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
  *
  * Description:
@@ -188,13 +153,9 @@
  * The caller is responsibile for all the NetLabel sk_security_struct locking.
  *
  */
-void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
-				      int family)
+void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec)
 {
-	if (family == PF_INET)
-		ssec->nlbl_state = NLBL_REQUIRE;
-	else
-		ssec->nlbl_state = NLBL_UNSET;
+	ssec->nlbl_state = NLBL_UNSET;
 }
 
 /**
@@ -281,127 +242,86 @@
 }
 
 /**
- * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
- * @sk: the new connection
+ * selinux_netlbl_inet_conn_request - Label an incoming stream connection
+ * @req: incoming connection request socket
  *
  * Description:
- * A new connection has been established on @sk so make sure it is labeled
- * correctly with the NetLabel susbsystem.
+ * A new incoming connection request is represented by @req, we need to label
+ * the new request_sock here and the stack will ensure the on-the-wire label
+ * will get preserved when a full sock is created once the connection handshake
+ * is complete.  Returns zero on success, negative values on failure.
  *
  */
-void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
+int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
 {
 	int rc;
+	struct netlbl_lsm_secattr secattr;
+
+	if (family != PF_INET)
+		return 0;
+
+	netlbl_secattr_init(&secattr);
+	rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
+	if (rc != 0)
+		goto inet_conn_request_return;
+	rc = netlbl_req_setattr(req, &secattr);
+inet_conn_request_return:
+	netlbl_secattr_destroy(&secattr);
+	return rc;
+}
+
+/**
+ * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
+ * @sk: the new sock
+ *
+ * Description:
+ * A new connection has been established using @sk, we've already labeled the
+ * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
+ * we need to set the NetLabel state here since we now have a sock structure.
+ *
+ */
+void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
+{
 	struct sk_security_struct *sksec = sk->sk_security;
-	struct netlbl_lsm_secattr *secattr;
-	struct inet_sock *sk_inet = inet_sk(sk);
-	struct sockaddr_in addr;
 
-	if (sksec->nlbl_state != NLBL_REQUIRE)
-		return;
-
-	secattr = selinux_netlbl_sock_genattr(sk);
-	if (secattr == NULL)
-		return;
-
-	rc = netlbl_sock_setattr(sk, secattr);
-	switch (rc) {
-	case 0:
+	if (family == PF_INET)
 		sksec->nlbl_state = NLBL_LABELED;
-		break;
-	case -EDESTADDRREQ:
-		/* no PF_INET6 support yet because we don't support any IPv6
-		 * labeling protocols */
-		if (family != PF_INET) {
-			sksec->nlbl_state = NLBL_UNSET;
-			return;
-		}
-
-		addr.sin_family = family;
-		addr.sin_addr.s_addr = sk_inet->daddr;
-		if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
-					secattr) != 0) {
-			/* we failed to label the connected socket (could be
-			 * for a variety of reasons, the actual "why" isn't
-			 * important here) so we have to go to our backup plan,
-			 * labeling the packets individually in the netfilter
-			 * local output hook.  this is okay but we need to
-			 * adjust the MSS of the connection to take into
-			 * account any labeling overhead, since we don't know
-			 * the exact overhead at this point we'll use the worst
-			 * case value which is 40 bytes for IPv4 */
-			struct inet_connection_sock *sk_conn = inet_csk(sk);
-			sk_conn->icsk_ext_hdr_len += 40 -
-				      (sk_inet->opt ? sk_inet->opt->optlen : 0);
-			sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
-
-			sksec->nlbl_state = NLBL_REQSKB;
-		} else
-			sksec->nlbl_state = NLBL_CONNLABELED;
-		break;
-	default:
-		/* note that we are failing to label the socket which could be
-		 * a bad thing since it means traffic could leave the system
-		 * without the desired labeling, however, all is not lost as
-		 * we have a check in selinux_netlbl_inode_permission() to
-		 * pick up the pieces that we might drop here because we can't
-		 * return an error code */
-		break;
-	}
+	else
+		sksec->nlbl_state = NLBL_UNSET;
 }
 
 /**
  * selinux_netlbl_socket_post_create - Label a socket using NetLabel
  * @sock: the socket to label
+ * @family: protocol family
  *
  * Description:
  * Attempt to label a socket using the NetLabel mechanism using the given
  * SID.  Returns zero values on success, negative values on failure.
  *
  */
-int selinux_netlbl_socket_post_create(struct socket *sock)
-{
-	return selinux_netlbl_sock_setsid(sock->sk);
-}
-
-/**
- * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
- * @inode: the file descriptor's inode
- * @mask: the permission mask
- *
- * Description:
- * Looks at a file's inode and if it is marked as a socket protected by
- * NetLabel then verify that the socket has been labeled, if not try to label
- * the socket now with the inode's SID.  Returns zero on success, negative
- * values on failure.
- *
- */
-int selinux_netlbl_inode_permission(struct inode *inode, int mask)
+int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
 {
 	int rc;
-	struct sock *sk;
-	struct socket *sock;
-	struct sk_security_struct *sksec;
+	struct sk_security_struct *sksec = sk->sk_security;
+	struct netlbl_lsm_secattr *secattr;
 
-	if (!S_ISSOCK(inode->i_mode) ||
-	    ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
-		return 0;
-	sock = SOCKET_I(inode);
-	sk = sock->sk;
-	if (sk == NULL)
-		return 0;
-	sksec = sk->sk_security;
-	if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE)
+	if (family != PF_INET)
 		return 0;
 
-	local_bh_disable();
-	bh_lock_sock_nested(sk);
-	if (likely(sksec->nlbl_state == NLBL_REQUIRE))
-		rc = selinux_netlbl_sock_setsid(sk);
-	else
+	secattr = selinux_netlbl_sock_genattr(sk);
+	if (secattr == NULL)
+		return -ENOMEM;
+	rc = netlbl_sock_setattr(sk, family, secattr);
+	switch (rc) {
+	case 0:
+		sksec->nlbl_state = NLBL_LABELED;
+		break;
+	case -EDESTADDRREQ:
+		sksec->nlbl_state = NLBL_REQSKB;
 		rc = 0;
-	bh_unlock_sock(sk);
-	local_bh_enable();
+		break;
+	}
 
 	return rc;
 }
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index d3c8b98..2d5136e 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -47,8 +47,6 @@
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
-int selinux_compat_net = 0;
-
 static int __init checkreqprot_setup(char *str)
 {
 	unsigned long checkreqprot;
@@ -58,16 +56,6 @@
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
-static int __init selinux_compat_net_setup(char *str)
-{
-	unsigned long compat_net;
-	if (!strict_strtoul(str, 0, &compat_net))
-		selinux_compat_net = compat_net ? 1 : 0;
-	return 1;
-}
-__setup("selinux_compat_net=", selinux_compat_net_setup);
-
-
 static DEFINE_MUTEX(sel_mutex);
 
 /* global data for booleans */
@@ -450,61 +438,6 @@
 	.write		= sel_write_checkreqprot,
 };
 
-static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	char tmpbuf[TMPBUFLEN];
-	ssize_t length;
-
-	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
-	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
-}
-
-static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
-				    size_t count, loff_t *ppos)
-{
-	char *page;
-	ssize_t length;
-	int new_value;
-
-	length = task_has_security(current, SECURITY__LOAD_POLICY);
-	if (length)
-		return length;
-
-	if (count >= PAGE_SIZE)
-		return -ENOMEM;
-	if (*ppos != 0) {
-		/* No partial writes. */
-		return -EINVAL;
-	}
-	page = (char *)get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-	length = -EFAULT;
-	if (copy_from_user(page, buf, count))
-		goto out;
-
-	length = -EINVAL;
-	if (sscanf(page, "%d", &new_value) != 1)
-		goto out;
-
-	if (new_value) {
-		printk(KERN_NOTICE
-		       "SELinux: compat_net is deprecated, please use secmark"
-		       " instead\n");
-		selinux_compat_net = 1;
-	} else
-		selinux_compat_net = 0;
-	length = count;
-out:
-	free_page((unsigned long) page);
-	return length;
-}
-static const struct file_operations sel_compat_net_ops = {
-	.read		= sel_read_compat_net,
-	.write		= sel_write_compat_net,
-};
-
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1665,7 +1598,6 @@
 		[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
 		[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
-		[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
 		[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
 		[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
 		/* last one */ {""}
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b79582e..42ef313 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -18,6 +18,8 @@
 #include <linux/security.h>
 #include <linux/in.h>
 #include <net/netlabel.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
 
 /*
  * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -40,7 +42,6 @@
 struct socket_smack {
 	char		*smk_out;			/* outbound label */
 	char		*smk_in;			/* inbound label */
-	int		smk_labeled;			/* label scheme */
 	char		smk_packet[SMK_LABELLEN];	/* TCP peer label */
 };
 
@@ -59,17 +60,10 @@
  * A label access rule.
  */
 struct smack_rule {
-	char	*smk_subject;
-	char	*smk_object;
-	int	smk_access;
-};
-
-/*
- * An entry in the table of permitted label accesses.
- */
-struct smk_list_entry {
-	struct smk_list_entry	*smk_next;
-	struct smack_rule	smk_rule;
+	struct list_head	list;
+	char			*smk_subject;
+	char			*smk_object;
+	int			smk_access;
 };
 
 /*
@@ -85,7 +79,7 @@
  * An entry in the table identifying hosts.
  */
 struct smk_netlbladdr {
-	struct smk_netlbladdr	*smk_next;
+	struct list_head	list;
 	struct sockaddr_in	smk_host;	/* network address */
 	struct in_addr		smk_mask;	/* network mask */
 	char			*smk_label;	/* label */
@@ -113,7 +107,7 @@
  * the cipso direct mapping in used internally.
  */
 struct smack_known {
-	struct smack_known	*smk_next;
+	struct list_head	list;
 	char			smk_known[SMK_LABELLEN];
 	u32			smk_secid;
 	struct smack_cipso	*smk_cipso;
@@ -138,6 +132,8 @@
 #define XATTR_NAME_SMACKIPIN	XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
 #define XATTR_NAME_SMACKIPOUT	XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
 
+#define SMACK_CIPSO_OPTION 	"-CIPSO"
+
 /*
  * How communications on this socket are treated.
  * Usually it's determined by the underlying netlabel code
@@ -205,8 +201,8 @@
 extern int smack_cipso_direct;
 extern char *smack_net_ambient;
 extern char *smack_onlycap;
+extern const char *smack_cipso_option;
 
-extern struct smack_known *smack_known;
 extern struct smack_known smack_known_floor;
 extern struct smack_known smack_known_hat;
 extern struct smack_known smack_known_huh;
@@ -214,8 +210,10 @@
 extern struct smack_known smack_known_star;
 extern struct smack_known smack_known_web;
 
-extern struct smk_list_entry *smack_list;
-extern struct smk_netlbladdr *smack_netlbladdrs;
+extern struct list_head smack_known_list;
+extern struct list_head smack_rule_list;
+extern struct list_head smk_netlbladdr_list;
+
 extern struct security_operations smack_ops;
 
 /*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index cfa19ca..ac0a270 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -16,48 +16,42 @@
 #include "smack.h"
 
 struct smack_known smack_known_huh = {
-	.smk_next	= NULL,
 	.smk_known	= "?",
 	.smk_secid	= 2,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_hat = {
-	.smk_next	= &smack_known_huh,
 	.smk_known	= "^",
 	.smk_secid	= 3,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_star = {
-	.smk_next	= &smack_known_hat,
 	.smk_known	= "*",
 	.smk_secid	= 4,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_floor = {
-	.smk_next	= &smack_known_star,
 	.smk_known	= "_",
 	.smk_secid	= 5,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_invalid = {
-	.smk_next	= &smack_known_floor,
 	.smk_known	= "",
 	.smk_secid	= 6,
 	.smk_cipso	= NULL,
 };
 
 struct smack_known smack_known_web = {
-	.smk_next	= &smack_known_invalid,
 	.smk_known	= "@",
 	.smk_secid	= 7,
 	.smk_cipso	= NULL,
 };
 
-struct smack_known *smack_known = &smack_known_web;
+LIST_HEAD(smack_known_list);
 
 /*
  * The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@
 int smk_access(char *subject_label, char *object_label, int request)
 {
 	u32 may = MAY_NOT;
-	struct smk_list_entry *sp;
 	struct smack_rule *srp;
 
 	/*
@@ -139,9 +132,8 @@
 	 * access (e.g. read is included in readwrite) it's
 	 * good.
 	 */
-	for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
-		srp = &sp->smk_rule;
-
+	rcu_read_lock();
+	list_for_each_entry_rcu(srp, &smack_rule_list, list) {
 		if (srp->smk_subject == subject_label ||
 		    strcmp(srp->smk_subject, subject_label) == 0) {
 			if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@
 			}
 		}
 	}
+	rcu_read_unlock();
 	/*
 	 * This is a bit map operation.
 	 */
@@ -228,14 +221,17 @@
 
 	mutex_lock(&smack_known_lock);
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
+	found = 0;
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
+			found = 1;
 			break;
+		}
+	}
 
-	if (skp == NULL) {
+	if (found == 0) {
 		skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
 		if (skp != NULL) {
-			skp->smk_next = smack_known;
 			strncpy(skp->smk_known, smack, SMK_MAXLEN);
 			skp->smk_secid = smack_next_secid++;
 			skp->smk_cipso = NULL;
@@ -244,8 +240,7 @@
 			 * Make sure that the entry is actually
 			 * filled before putting it on the list.
 			 */
-			smp_mb();
-			smack_known = skp;
+			list_add_rcu(&skp->list, &smack_known_list);
 		}
 	}
 
@@ -266,6 +261,9 @@
 {
 	struct smack_known *skp;
 
+	/* labels cannot begin with a '-' */
+	if (string[0] == '-')
+		return NULL;
 	skp = smk_import_entry(string, len);
 	if (skp == NULL)
 		return NULL;
@@ -283,14 +281,19 @@
 {
 	struct smack_known *skp;
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (skp->smk_secid == secid)
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (skp->smk_secid == secid) {
+			rcu_read_unlock();
 			return skp->smk_known;
+		}
+	}
 
 	/*
 	 * If we got this far someone asked for the translation
 	 * of a secid that is not on the list.
 	 */
+	rcu_read_unlock();
 	return smack_known_invalid.smk_known;
 }
 
@@ -305,9 +308,14 @@
 {
 	struct smack_known *skp;
 
-	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
-		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
+	rcu_read_lock();
+	list_for_each_entry_rcu(skp, &smack_known_list, list) {
+		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
+			rcu_read_unlock();
 			return skp->smk_secid;
+		}
+	}
+	rcu_read_unlock();
 	return 0;
 }
 
@@ -332,7 +340,8 @@
 	struct smack_known *kp;
 	char *final = NULL;
 
-	for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) {
+	rcu_read_lock();
+	list_for_each_entry(kp, &smack_known_list, list) {
 		if (kp->smk_cipso == NULL)
 			continue;
 
@@ -344,6 +353,7 @@
 
 		spin_unlock_bh(&kp->smk_cipsolock);
 	}
+	rcu_read_unlock();
 	if (final == NULL)
 		final = smack_known_huh.smk_known;
 	strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +370,19 @@
 int smack_to_cipso(const char *smack, struct smack_cipso *cp)
 {
 	struct smack_known *kp;
+	int found = 0;
 
-	for (kp = smack_known; kp != NULL; kp = kp->smk_next)
+	rcu_read_lock();
+	list_for_each_entry_rcu(kp, &smack_known_list, list) {
 		if (kp->smk_known == smack ||
-		    strcmp(kp->smk_known, smack) == 0)
+		    strcmp(kp->smk_known, smack) == 0) {
+			found = 1;
 			break;
+		}
+	}
+	rcu_read_unlock();
 
-	if (kp == NULL || kp->smk_cipso == NULL)
+	if (found == 0 || kp->smk_cipso == NULL)
 		return -ENOENT;
 
 	memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 84b62b5..9215149 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -7,6 +7,8 @@
  *	Casey Schaufler <casey@schaufler-ca.com>
  *
  *  Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
+ *  Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *                Paul Moore <paul.moore@hp.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,
@@ -20,6 +22,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/kd.h>
 #include <asm/ioctls.h>
+#include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/mutex.h>
@@ -606,6 +609,9 @@
 	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
 		if (!capable(CAP_MAC_ADMIN))
 			rc = -EPERM;
+		/* a label cannot be void and cannot begin with '-' */
+		if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
+			rc = -EINVAL;
 	} else
 		rc = cap_inode_setxattr(dentry, name, value, size, flags);
 
@@ -1275,7 +1281,6 @@
 
 	ssp->smk_in = csp;
 	ssp->smk_out = csp;
-	ssp->smk_labeled = SMACK_CIPSO_SOCKET;
 	ssp->smk_packet[0] = '\0';
 
 	sk->sk_security = ssp;
@@ -1295,6 +1300,43 @@
 }
 
 /**
+* smack_host_label - check host based restrictions
+* @sip: the object end
+*
+* looks for host based access restrictions
+*
+* This version will only be appropriate for really small sets of single label
+* hosts.  The caller is responsible for ensuring that the RCU read lock is
+* taken before calling this function.
+*
+* Returns the label of the far end or NULL if it's not special.
+*/
+static char *smack_host_label(struct sockaddr_in *sip)
+{
+	struct smk_netlbladdr *snp;
+	struct in_addr *siap = &sip->sin_addr;
+
+	if (siap->s_addr == 0)
+		return NULL;
+
+	list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
+		/*
+		* we break after finding the first match because
+		* the list is sorted from longest to shortest mask
+		* so we have found the most specific match
+		*/
+		if ((&snp->smk_host.sin_addr)->s_addr ==
+		    (siap->s_addr & (&snp->smk_mask)->s_addr)) {
+			/* we have found the special CIPSO option */
+			if (snp->smk_label == smack_cipso_option)
+				return NULL;
+			return snp->smk_label;
+		}
+
+	return NULL;
+}
+
+/**
  * smack_set_catset - convert a capset to netlabel mls categories
  * @catset: the Smack categories
  * @sap: where to put the netlabel categories
@@ -1365,11 +1407,10 @@
  */
 static int smack_netlabel(struct sock *sk, int labeled)
 {
-	struct socket_smack *ssp;
+	struct socket_smack *ssp = sk->sk_security;
 	struct netlbl_lsm_secattr secattr;
 	int rc = 0;
 
-	ssp = sk->sk_security;
 	/*
 	 * Usually the netlabel code will handle changing the
 	 * packet labeling based on the label.
@@ -1387,27 +1428,51 @@
 	else {
 		netlbl_secattr_init(&secattr);
 		smack_to_secattr(ssp->smk_out, &secattr);
-		rc = netlbl_sock_setattr(sk, &secattr);
+		rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
 		netlbl_secattr_destroy(&secattr);
 	}
 
 	bh_unlock_sock(sk);
 	local_bh_enable();
-	/*
-	 * Remember the label scheme used so that it is not
-	 * necessary to do the netlabel setting if it has not
-	 * changed the next time through.
-	 *
-	 * The -EDESTADDRREQ case is an indication that there's
-	 * a single level host involved.
-	 */
-	if (rc == 0)
-		ssp->smk_labeled = labeled;
 
 	return rc;
 }
 
 /**
+ * smack_netlbel_send - Set the secattr on a socket and perform access checks
+ * @sk: the socket
+ * @sap: the destination address
+ *
+ * Set the correct secattr for the given socket based on the destination
+ * address and perform any outbound access checks needed.
+ *
+ * Returns 0 on success or an error code.
+ *
+ */
+static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
+{
+	int rc;
+	int sk_lbl;
+	char *hostsp;
+	struct socket_smack *ssp = sk->sk_security;
+
+	rcu_read_lock();
+	hostsp = smack_host_label(sap);
+	if (hostsp != NULL) {
+		sk_lbl = SMACK_UNLABELED_SOCKET;
+		rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
+	} else {
+		sk_lbl = SMACK_CIPSO_SOCKET;
+		rc = 0;
+	}
+	rcu_read_unlock();
+	if (rc != 0)
+		return rc;
+
+	return smack_netlabel(sk, sk_lbl);
+}
+
+/**
  * smack_inode_setsecurity - set smack xattrs
  * @inode: the object
  * @name: attribute name
@@ -1428,7 +1493,7 @@
 	struct socket *sock;
 	int rc = 0;
 
-	if (value == NULL || size > SMK_LABELLEN)
+	if (value == NULL || size > SMK_LABELLEN || size == 0)
 		return -EACCES;
 
 	sp = smk_import(value, size);
@@ -1488,41 +1553,6 @@
 	return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
 }
 
-
-/**
- * smack_host_label - check host based restrictions
- * @sip: the object end
- *
- * looks for host based access restrictions
- *
- * This version will only be appropriate for really small
- * sets of single label hosts.
- *
- * Returns the label of the far end or NULL if it's not special.
- */
-static char *smack_host_label(struct sockaddr_in *sip)
-{
-	struct smk_netlbladdr *snp;
-	struct in_addr *siap = &sip->sin_addr;
-
-	if (siap->s_addr == 0)
-		return NULL;
-
-	for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
-		/*
-		 * we break after finding the first match because
-		 * the list is sorted from longest to shortest mask
-		 * so we have found the most specific match
-		 */
-		if ((&snp->smk_host.sin_addr)->s_addr  ==
-			(siap->s_addr & (&snp->smk_mask)->s_addr)) {
-			return snp->smk_label;
-		}
-	}
-
-	return NULL;
-}
-
 /**
  * smack_socket_connect - connect access check
  * @sock: the socket
@@ -1536,30 +1566,12 @@
 static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
 				int addrlen)
 {
-	struct socket_smack *ssp = sock->sk->sk_security;
-	char *hostsp;
-	int rc;
-
 	if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
 		return 0;
-
 	if (addrlen < sizeof(struct sockaddr_in))
 		return -EINVAL;
 
-	hostsp = smack_host_label((struct sockaddr_in *)sap);
-	if (hostsp == NULL) {
-		if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
-			return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
-		return 0;
-	}
-
-	rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
-	if (rc != 0)
-		return rc;
-
-	if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
-		return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
-	return 0;
+	return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
 }
 
 /**
@@ -2260,9 +2272,6 @@
 				int size)
 {
 	struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
-	struct socket_smack *ssp = sock->sk->sk_security;
-	char *hostsp;
-	int rc;
 
 	/*
 	 * Perfectly reasonable for this to be NULL
@@ -2270,22 +2279,7 @@
 	if (sip == NULL || sip->sin_family != PF_INET)
 		return 0;
 
-	hostsp = smack_host_label(sip);
-	if (hostsp == NULL) {
-		if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
-			return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
-		return 0;
-	}
-
-	rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
-	if (rc != 0)
-		return rc;
-
-	if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
-		return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
-
-	return 0;
-
+	return smack_netlabel_send(sock->sk, sip);
 }
 
 
@@ -2490,31 +2484,24 @@
 }
 
 /**
- * smack_sock_graft - graft access state between two sockets
- * @sk: fresh sock
- * @parent: donor socket
+ * smack_sock_graft - Initialize a newly created socket with an existing sock
+ * @sk: child sock
+ * @parent: parent socket
  *
- * Sets the netlabel socket state on sk from parent
+ * Set the smk_{in,out} state of an existing sock based on the process that
+ * is creating the new socket.
  */
 static void smack_sock_graft(struct sock *sk, struct socket *parent)
 {
 	struct socket_smack *ssp;
-	int rc;
 
-	if (sk == NULL)
-		return;
-
-	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
+	if (sk == NULL ||
+	    (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
 		return;
 
 	ssp = sk->sk_security;
 	ssp->smk_in = ssp->smk_out = current_security();
-	ssp->smk_packet[0] = '\0';
-
-	rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
-	if (rc != 0)
-		printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
-		       __func__, -rc);
+	/* cssp->smk_packet is already set in smack_inet_csk_clone() */
 }
 
 /**
@@ -2529,35 +2516,82 @@
 static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 				   struct request_sock *req)
 {
-	struct netlbl_lsm_secattr skb_secattr;
+	u16 family = sk->sk_family;
 	struct socket_smack *ssp = sk->sk_security;
+	struct netlbl_lsm_secattr secattr;
+	struct sockaddr_in addr;
+	struct iphdr *hdr;
 	char smack[SMK_LABELLEN];
 	int rc;
 
-	if (skb == NULL)
-		return -EACCES;
+	/* handle mapped IPv4 packets arriving via IPv6 sockets */
+	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+		family = PF_INET;
 
-	netlbl_secattr_init(&skb_secattr);
-	rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);
+	netlbl_secattr_init(&secattr);
+	rc = netlbl_skbuff_getattr(skb, family, &secattr);
 	if (rc == 0)
-		smack_from_secattr(&skb_secattr, smack);
+		smack_from_secattr(&secattr, smack);
 	else
 		strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
-	netlbl_secattr_destroy(&skb_secattr);
+	netlbl_secattr_destroy(&secattr);
+
 	/*
-	 * Receiving a packet requires that the other end
-	 * be able to write here. Read access is not required.
-	 *
-	 * If the request is successful save the peer's label
-	 * so that SO_PEERCRED can report it.
+	 * Receiving a packet requires that the other end be able to write
+	 * here. Read access is not required.
 	 */
 	rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
-	if (rc == 0)
-		strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
+	if (rc != 0)
+		return rc;
+
+	/*
+	 * Save the peer's label in the request_sock so we can later setup
+	 * smk_packet in the child socket so that SO_PEERCRED can report it.
+	 */
+	req->peer_secid = smack_to_secid(smack);
+
+	/*
+	 * We need to decide if we want to label the incoming connection here
+	 * if we do we only need to label the request_sock and the stack will
+	 * propogate the wire-label to the sock when it is created.
+	 */
+	hdr = ip_hdr(skb);
+	addr.sin_addr.s_addr = hdr->saddr;
+	rcu_read_lock();
+	if (smack_host_label(&addr) == NULL) {
+		rcu_read_unlock();
+		netlbl_secattr_init(&secattr);
+		smack_to_secattr(smack, &secattr);
+		rc = netlbl_req_setattr(req, &secattr);
+		netlbl_secattr_destroy(&secattr);
+	} else {
+		rcu_read_unlock();
+		netlbl_req_delattr(req);
+	}
 
 	return rc;
 }
 
+/**
+ * smack_inet_csk_clone - Copy the connection information to the new socket
+ * @sk: the new socket
+ * @req: the connection's request_sock
+ *
+ * Transfer the connection's peer label to the newly created socket.
+ */
+static void smack_inet_csk_clone(struct sock *sk,
+				 const struct request_sock *req)
+{
+	struct socket_smack *ssp = sk->sk_security;
+	char *smack;
+
+	if (req->peer_secid != 0) {
+		smack = smack_from_secid(req->peer_secid);
+		strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
+	} else
+		ssp->smk_packet[0] = '\0';
+}
+
 /*
  * Key management security hooks
  *
@@ -2909,6 +2943,7 @@
 	.sk_free_security = 		smack_sk_free_security,
 	.sock_graft = 			smack_sock_graft,
 	.inet_conn_request = 		smack_inet_conn_request,
+	.inet_csk_clone =		smack_inet_csk_clone,
 
  /* key management security hooks */
 #ifdef CONFIG_KEYS
@@ -2930,6 +2965,17 @@
 	.release_secctx = 		smack_release_secctx,
 };
 
+
+static __init void init_smack_know_list(void)
+{
+	list_add(&smack_known_huh.list, &smack_known_list);
+	list_add(&smack_known_hat.list, &smack_known_list);
+	list_add(&smack_known_star.list, &smack_known_list);
+	list_add(&smack_known_floor.list, &smack_known_list);
+	list_add(&smack_known_invalid.list, &smack_known_list);
+	list_add(&smack_known_web.list, &smack_known_list);
+}
+
 /**
  * smack_init - initialize the smack system
  *
@@ -2950,6 +2996,8 @@
 	cred = (struct cred *) current->cred;
 	cred->security = &smack_known_floor.smk_known;
 
+	/* initilize the smack_know_list */
+	init_smack_know_list();
 	/*
 	 * Initialize locks
 	 */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index a1b57e4..e03a7e1 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -80,10 +80,14 @@
  * Packets are sent there unlabeled, but only from tasks that
  * can write to the specified label.
  */
-struct smk_netlbladdr *smack_netlbladdrs;
+
+LIST_HEAD(smk_netlbladdr_list);
+LIST_HEAD(smack_rule_list);
 
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
-struct smk_list_entry *smack_list;
+
+const char *smack_cipso_option = SMACK_CIPSO_OPTION;
+
 
 #define	SEQ_READ_FINISHED	1
 
@@ -134,24 +138,27 @@
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
-
-	return smack_list;
+	if (list_empty(&smack_rule_list))
+		return NULL;
+	return smack_rule_list.next;
 }
 
 static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next;
+	struct list_head *list = v;
 
-	if (skp == NULL)
+	if (list_is_last(list, &smack_rule_list)) {
 		*pos = SEQ_READ_FINISHED;
-
-	return skp;
+		return NULL;
+	}
+	return list->next;
 }
 
 static int load_seq_show(struct seq_file *s, void *v)
 {
-	struct smk_list_entry *slp = (struct smk_list_entry *) v;
-	struct smack_rule *srp = &slp->smk_rule;
+	struct list_head *list = v;
+	struct smack_rule *srp =
+		 list_entry(list, struct smack_rule, list);
 
 	seq_printf(s, "%s %s", (char *)srp->smk_subject,
 		   (char *)srp->smk_object);
@@ -212,32 +219,23 @@
  */
 static int smk_set_access(struct smack_rule *srp)
 {
-	struct smk_list_entry *sp;
-	struct smk_list_entry *newp;
+	struct smack_rule *sp;
 	int ret = 0;
-
+	int found;
 	mutex_lock(&smack_list_lock);
 
-	for (sp = smack_list; sp != NULL; sp = sp->smk_next)
-		if (sp->smk_rule.smk_subject == srp->smk_subject &&
-		    sp->smk_rule.smk_object == srp->smk_object) {
-			sp->smk_rule.smk_access = srp->smk_access;
+	found = 0;
+	list_for_each_entry_rcu(sp, &smack_rule_list, list) {
+		if (sp->smk_subject == srp->smk_subject &&
+		    sp->smk_object == srp->smk_object) {
+			found = 1;
+			sp->smk_access = srp->smk_access;
 			break;
 		}
-
-	if (sp == NULL) {
-		newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
-		if (newp == NULL) {
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		newp->smk_rule = *srp;
-		newp->smk_next = smack_list;
-		smack_list = newp;
 	}
+	if (found == 0)
+		list_add_rcu(&srp->list, &smack_rule_list);
 
-out:
 	mutex_unlock(&smack_list_lock);
 
 	return ret;
@@ -261,7 +259,7 @@
 static ssize_t smk_write_load(struct file *file, const char __user *buf,
 			      size_t count, loff_t *ppos)
 {
-	struct smack_rule rule;
+	struct smack_rule *rule;
 	char *data;
 	int rc = -EINVAL;
 
@@ -272,9 +270,8 @@
 	 */
 	if (!capable(CAP_MAC_ADMIN))
 		return -EPERM;
-	if (*ppos != 0)
-		return -EINVAL;
-	if (count != SMK_LOADLEN)
+
+	if (*ppos != 0 || count != SMK_LOADLEN)
 		return -EINVAL;
 
 	data = kzalloc(count, GFP_KERNEL);
@@ -286,25 +283,31 @@
 		goto out;
 	}
 
-	rule.smk_subject = smk_import(data, 0);
-	if (rule.smk_subject == NULL)
+	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
+	if (rule == NULL) {
+		rc = -ENOMEM;
 		goto out;
+	}
 
-	rule.smk_object = smk_import(data + SMK_LABELLEN, 0);
-	if (rule.smk_object == NULL)
-		goto out;
+	rule->smk_subject = smk_import(data, 0);
+	if (rule->smk_subject == NULL)
+		goto out_free_rule;
 
-	rule.smk_access = 0;
+	rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
+	if (rule->smk_object == NULL)
+		goto out_free_rule;
+
+	rule->smk_access = 0;
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
 	case '-':
 		break;
 	case 'r':
 	case 'R':
-		rule.smk_access |= MAY_READ;
+		rule->smk_access |= MAY_READ;
 		break;
 	default:
-		goto out;
+		goto out_free_rule;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
@@ -312,10 +315,10 @@
 		break;
 	case 'w':
 	case 'W':
-		rule.smk_access |= MAY_WRITE;
+		rule->smk_access |= MAY_WRITE;
 		break;
 	default:
-		goto out;
+		goto out_free_rule;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
@@ -323,10 +326,10 @@
 		break;
 	case 'x':
 	case 'X':
-		rule.smk_access |= MAY_EXEC;
+		rule->smk_access |= MAY_EXEC;
 		break;
 	default:
-		goto out;
+		goto out_free_rule;
 	}
 
 	switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
@@ -334,17 +337,20 @@
 		break;
 	case 'a':
 	case 'A':
-		rule.smk_access |= MAY_APPEND;
+		rule->smk_access |= MAY_APPEND;
 		break;
 	default:
-		goto out;
+		goto out_free_rule;
 	}
 
-	rc = smk_set_access(&rule);
+	rc = smk_set_access(rule);
 
 	if (!rc)
 		rc = count;
+	goto out;
 
+out_free_rule:
+	kfree(rule);
 out:
 	kfree(data);
 	return rc;
@@ -433,24 +439,26 @@
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
+	if (list_empty(&smack_known_list))
+		return NULL;
 
-	return smack_known;
+	return smack_known_list.next;
 }
 
 static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smack_known *skp = ((struct smack_known *) v)->smk_next;
+	struct list_head  *list = v;
 
 	/*
-	 * Omit labels with no associated cipso value
+	 * labels with no associated cipso value wont be printed
+	 * in cipso_seq_show
 	 */
-	while (skp != NULL && !skp->smk_cipso)
-		skp = skp->smk_next;
-
-	if (skp == NULL)
+	if (list_is_last(list, &smack_known_list)) {
 		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
 
-	return skp;
+	return list->next;
 }
 
 /*
@@ -459,7 +467,9 @@
  */
 static int cipso_seq_show(struct seq_file *s, void *v)
 {
-	struct smack_known *skp = (struct smack_known *) v;
+	struct list_head  *list = v;
+	struct smack_known *skp =
+		 list_entry(list, struct smack_known, list);
 	struct smack_cipso *scp = skp->smk_cipso;
 	char *cbp;
 	char sep = '/';
@@ -558,6 +568,11 @@
 		goto unlockedout;
 	}
 
+	/* labels cannot begin with a '-' */
+	if (data[0] == '-') {
+		rc = -EINVAL;
+		goto unlockedout;
+	}
 	data[count] = '\0';
 	rule = data;
 	/*
@@ -638,18 +653,21 @@
 {
 	if (*pos == SEQ_READ_FINISHED)
 		return NULL;
-
-	return smack_netlbladdrs;
+	if (list_empty(&smk_netlbladdr_list))
+		return NULL;
+	return smk_netlbladdr_list.next;
 }
 
 static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
+	struct list_head *list = v;
 
-	if (skp == NULL)
+	if (list_is_last(list, &smk_netlbladdr_list)) {
 		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
 
-	return skp;
+	return list->next;
 }
 #define BEBITS	(sizeof(__be32) * 8)
 
@@ -658,7 +676,9 @@
  */
 static int netlbladdr_seq_show(struct seq_file *s, void *v)
 {
-	struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
+	struct list_head *list = v;
+	struct smk_netlbladdr *skp =
+			 list_entry(list, struct smk_netlbladdr, list);
 	unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
 	int maskn;
 	u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -702,30 +722,36 @@
  *
  * This helper insert netlabel in the smack_netlbladdrs list
  * sorted by netmask length (longest to smallest)
+ * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
+ *
  */
 static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
 {
-	struct smk_netlbladdr *m;
+	struct smk_netlbladdr *m, *m_next;
 
-	if (smack_netlbladdrs == NULL) {
-		smack_netlbladdrs = new;
+	if (list_empty(&smk_netlbladdr_list)) {
+		list_add_rcu(&new->list, &smk_netlbladdr_list);
 		return;
 	}
 
+	m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
+			 struct smk_netlbladdr, list);
+
 	/* the comparison '>' is a bit hacky, but works */
-	if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
-		new->smk_next = smack_netlbladdrs;
-		smack_netlbladdrs = new;
+	if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
+		list_add_rcu(&new->list, &smk_netlbladdr_list);
 		return;
 	}
-	for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
-		if (m->smk_next == NULL) {
-			m->smk_next = new;
+
+	list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
+		if (list_is_last(&m->list, &smk_netlbladdr_list)) {
+			list_add_rcu(&new->list, &m->list);
 			return;
 		}
-		if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
-			new->smk_next = m->smk_next;
-			m->smk_next = new;
+		m_next = list_entry(rcu_dereference(m->list.next),
+				 struct smk_netlbladdr, list);
+		if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
+			list_add_rcu(&new->list, &m->list);
 			return;
 		}
 	}
@@ -755,6 +781,7 @@
 	struct netlbl_audit audit_info;
 	struct in_addr mask;
 	unsigned int m;
+	int found;
 	u32 mask_bits = (1<<31);
 	__be32 nsa;
 	u32 temp_mask;
@@ -789,9 +816,18 @@
 	if (m > BEBITS)
 		return -EINVAL;
 
-	sp = smk_import(smack, 0);
-	if (sp == NULL)
-		return -EINVAL;
+	/* if smack begins with '-', its an option, don't import it */
+	if (smack[0] != '-') {
+		sp = smk_import(smack, 0);
+		if (sp == NULL)
+			return -EINVAL;
+	} else {
+		/* check known options */
+		if (strcmp(smack, smack_cipso_option) == 0)
+			sp = (char *)smack_cipso_option;
+		else
+			return -EINVAL;
+	}
 
 	for (temp_mask = 0; m > 0; m--) {
 		temp_mask |= mask_bits;
@@ -808,14 +844,17 @@
 
 	nsa = newname.sin_addr.s_addr;
 	/* try to find if the prefix is already in the list */
-	for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
+	found = 0;
+	list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
 		if (skp->smk_host.sin_addr.s_addr == nsa &&
-		    skp->smk_mask.s_addr == mask.s_addr)
+		    skp->smk_mask.s_addr == mask.s_addr) {
+			found = 1;
 			break;
-
+		}
+	}
 	smk_netlabel_audit_set(&audit_info);
 
-	if (skp == NULL) {
+	if (found == 0) {
 		skp = kzalloc(sizeof(*skp), GFP_KERNEL);
 		if (skp == NULL)
 			rc = -ENOMEM;
@@ -827,18 +866,23 @@
 			smk_netlbladdr_insert(skp);
 		}
 	} else {
-		rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
-			&skp->smk_host.sin_addr, &skp->smk_mask,
-			PF_INET, &audit_info);
+		/* we delete the unlabeled entry, only if the previous label
+		 * wasnt the special CIPSO option */
+		if (skp->smk_label != smack_cipso_option)
+			rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
+					&skp->smk_host.sin_addr, &skp->smk_mask,
+					PF_INET, &audit_info);
+		else
+			rc = 0;
 		skp->smk_label = sp;
 	}
 
 	/*
 	 * Now tell netlabel about the single label nature of
 	 * this host so that incoming packets get labeled.
+	 * but only if we didn't get the special CIPSO option
 	 */
-
-	if (rc == 0)
+	if (rc == 0 && sp != smack_cipso_option)
 		rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
 			&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
 			smack_to_secid(skp->smk_label), &audit_info);
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 6dcb7cc..26a76d6 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -55,7 +55,7 @@
 struct tomoyo_path_info_with_data {
 	/* Keep "head" first, for this pointer is passed to tomoyo_free(). */
 	struct tomoyo_path_info head;
-	char bariier1[16]; /* Safeguard for overrun. */
+	char barrier1[16]; /* Safeguard for overrun. */
 	char body[TOMOYO_MAX_PATHNAME_LEN];
 	char barrier2[16]; /* Safeguard for overrun. */
 };
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 2e6355f..7793d2a 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -21,7 +21,6 @@
 #include <sound/pxa2xx-lib.h>
 
 #include <asm/irq.h>
-#include <mach/hardware.h>
 #include <mach/regs-ac97.h>
 #include <mach/pxa2xx-gpio.h>
 #include <mach/audio.h>
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 7ed100c..c570ebd 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -20,8 +20,6 @@
 #include <sound/initval.h>
 #include <sound/pxa2xx-lib.h>
 
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/regs-ac97.h>
 #include <mach/audio.h>
 
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c
index 75a0d74..108b643 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -12,8 +12,7 @@
 #include <sound/pcm_params.h>
 #include <sound/pxa2xx-lib.h>
 
-#include <asm/dma.h>
-#include <mach/pxa-regs.h>
+#include <mach/dma.h>
 
 #include "pxa2xx-pcm.h"
 
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 9d98a66..d31c373 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/version.h>
 #include <sound/core.h>
 #include <sound/tea575x-tuner.h>
 
@@ -31,6 +32,13 @@
 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
 MODULE_LICENSE("GPL");
 
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
+#define FREQ_LO		 (87 * 16000)
+#define FREQ_HI		(108 * 16000)
+
 /*
  * definitions
  */
@@ -53,6 +61,17 @@
 #define TEA575X_BIT_DUMMY	(1<<15)		/* buffer */
 #define TEA575X_BIT_FREQ_MASK	0x7fff
 
+static struct v4l2_queryctrl radio_qctrl[] = {
+	{
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.name          = "Mute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	}
+};
+
 /*
  * lowlevel part
  */
@@ -84,94 +103,146 @@
  * Linux Video interface
  */
 
-static long snd_tea575x_ioctl(struct file *file,
-			     unsigned int cmd, unsigned long data)
+static int vidioc_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *v)
 {
 	struct snd_tea575x *tea = video_drvdata(file);
-	void __user *arg = (void __user *)data;
 
-	switch(cmd) {
-		case VIDIOCGCAP:
-		{
-			struct video_capability v;
-			v.type = VID_TYPE_TUNER;
-			v.channels = 1;
-			v.audios = 1;
-			/* No we don't do pictures */
-			v.maxwidth = 0;
-			v.maxheight = 0;
-			v.minwidth = 0;
-			v.minheight = 0;
-			strcpy(v.name, tea->tea5759 ? "TEA5759" : "TEA5757");
-			if (copy_to_user(arg,&v,sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-		case VIDIOCGTUNER:
-		{
-			struct video_tuner v;
-			if (copy_from_user(&v, arg,sizeof(v))!=0)
-				return -EFAULT;
-			if (v.tuner)	/* Only 1 tuner */
-				return -EINVAL;
-			v.rangelow = (87*16000);
-			v.rangehigh = (108*16000);
-			v.flags = VIDEO_TUNER_LOW;
-			v.mode = VIDEO_MODE_AUTO;
-			strcpy(v.name, "FM");
-			v.signal = 0xFFFF;
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-		case VIDIOCSTUNER:
-		{
-			struct video_tuner v;
-			if(copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if(v.tuner!=0)
-				return -EINVAL;
-			/* Only 1 tuner so no setting needed ! */
-			return 0;
-		}
-		case VIDIOCGFREQ:
-			if(copy_to_user(arg, &tea->freq, sizeof(tea->freq)))
-				return -EFAULT;
-			return 0;
-		case VIDIOCSFREQ:
-			if(copy_from_user(&tea->freq, arg, sizeof(tea->freq)))
-				return -EFAULT;
-			snd_tea575x_set_freq(tea);
-			return 0;
-		case VIDIOCGAUDIO:
-		{
-			struct video_audio v;
-			memset(&v, 0, sizeof(v));
-			strcpy(v.name, "Radio");
-			if(copy_to_user(arg,&v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-		case VIDIOCSAUDIO:
-		{
-			struct video_audio v;
-			if(copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (tea->ops->mute)
-				tea->ops->mute(tea,
-					       (v.flags &
-						VIDEO_AUDIO_MUTE) ? 1 : 0);
-			if(v.audio)
-				return -EINVAL;
-			return 0;
-		}
-		default:
-			return -ENOIOCTLCMD;
-	}
+	strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757");
+	strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver));
+	strlcpy(v->card, "Maestro Radio", sizeof(v->card));
+	sprintf(v->bus_info, "PCI");
+	v->version = RADIO_VERSION;
+	v->capabilities = V4L2_CAP_TUNER;
+	return 0;
 }
 
-static void snd_tea575x_release(struct video_device *vfd)
+static int vidioc_g_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *v)
 {
+	if (v->index > 0)
+		return -EINVAL;
+
+	strcpy(v->name, "FM");
+	v->type = V4L2_TUNER_RADIO;
+	v->rangelow = FREQ_LO;
+	v->rangehigh = FREQ_HI;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->capability = V4L2_TUNER_CAP_LOW;
+	v->audmode = V4L2_TUNER_MODE_MONO;
+	v->signal = 0xffff;
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *v)
+{
+	if (v->index > 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = tea->freq;
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
+		return -EINVAL;
+
+	tea->freq = f->frequency;
+
+	snd_tea575x_set_freq(tea);
+
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	if (a->index > 1)
+		return -EINVAL;
+
+	strcpy(a->name, "Radio");
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	if (a->index != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+		if (qc->id && qc->id == radio_qctrl[i].id) {
+			memcpy(qc, &(radio_qctrl[i]),
+						sizeof(*qc));
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+					struct v4l2_control *ctrl)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		if (tea->ops->mute) {
+			ctrl->value = tea->mute;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+					struct v4l2_control *ctrl)
+{
+	struct snd_tea575x *tea = video_drvdata(file);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		if (tea->ops->mute) {
+			tea->ops->mute(tea, ctrl->value);
+			tea->mute = 1;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+	return 0;
 }
 
 static int snd_tea575x_exclusive_open(struct file *file)
@@ -189,50 +260,91 @@
 	return 0;
 }
 
+static const struct v4l2_file_operations tea575x_fops = {
+	.owner		= THIS_MODULE,
+	.open           = snd_tea575x_exclusive_open,
+	.release        = snd_tea575x_exclusive_release,
+	.ioctl		= video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+};
+
+static struct video_device tea575x_radio = {
+	.name           = "tea575x-tuner",
+	.fops           = &tea575x_fops,
+	.ioctl_ops 	= &tea575x_ioctl_ops,
+	.release	= video_device_release,
+};
+
 /*
  * initialize all the tea575x chips
  */
 void snd_tea575x_init(struct snd_tea575x *tea)
 {
+	int retval;
 	unsigned int val;
+	struct video_device *tea575x_radio_inst;
 
 	val = tea->ops->read(tea);
 	if (val == 0x1ffffff || val == 0) {
-		snd_printk(KERN_ERR "Cannot find TEA575x chip\n");
+		snd_printk(KERN_ERR
+			   "tea575x-tuner: Cannot find TEA575x chip\n");
 		return;
 	}
 
-	memset(&tea->vd, 0, sizeof(tea->vd));
-	strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
-	tea->vd.release = snd_tea575x_release;
-	video_set_drvdata(&tea->vd, tea);
-	tea->vd.fops = &tea->fops;
 	tea->in_use = 0;
-	tea->fops.owner = tea->card->module;
-	tea->fops.open = snd_tea575x_exclusive_open;
-	tea->fops.release = snd_tea575x_exclusive_release;
-	tea->fops.ioctl = snd_tea575x_ioctl;
-	if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) {
-		snd_printk(KERN_ERR "unable to register tea575x tuner\n");
-		return;
-	}
-	tea->vd_registered = 1;
-
 	tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
 	tea->freq = 90500 * 16;		/* 90.5Mhz default */
 
+	tea575x_radio_inst = video_device_alloc();
+	if (tea575x_radio_inst == NULL) {
+		printk(KERN_ERR "tea575x-tuner: not enough memory\n");
+		return;
+	}
+
+	memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
+
+	strcpy(tea575x_radio.name, tea->tea5759 ?
+				   "TEA5759 radio" : "TEA5757 radio");
+
+	video_set_drvdata(tea575x_radio_inst, tea);
+
+	retval = video_register_device(tea575x_radio_inst,
+				       VFL_TYPE_RADIO, radio_nr);
+	if (retval) {
+		printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
+		kfree(tea575x_radio_inst);
+		return;
+	}
+
 	snd_tea575x_set_freq(tea);
 
 	/* mute on init */
-	if (tea->ops->mute)
+	if (tea->ops->mute) {
 		tea->ops->mute(tea, 1);
+		tea->mute = 1;
+	}
+	tea->vd = tea575x_radio_inst;
 }
 
 void snd_tea575x_exit(struct snd_tea575x *tea)
 {
-	if (tea->vd_registered) {
-		video_unregister_device(&tea->vd);
-		tea->vd_registered = 0;
+	if (tea->vd) {
+		video_unregister_device(tea->vd);
+		tea->vd = NULL;
 	}
 }
 
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index ca25e61..93422e3 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -507,7 +507,7 @@
 config SND_FM801_TEA575X_BOOL
 	bool "ForteMedia FM801 + TEA5757 tuner"
 	depends on SND_FM801
-	depends on VIDEO_V4L1=y || VIDEO_V4L1=SND_FM801
+	depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
 	help
 	  Say Y here to include support for soundcards based on the ForteMedia
 	  FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 02263e5..d5be2b3 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -26,8 +26,6 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/corgi.h>
 #include <mach/audio.h>
 
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index fe4a729..949be9c 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -29,8 +29,6 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/audio.h>
 
 #include "../codecs/wm9712.h"
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index ef7c6c8..a51058f 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -27,8 +27,6 @@
 
 #include <asm/mach-types.h>
 #include <asm/hardware/locomo.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/poodle.h>
 #include <mach/audio.h>
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index b0bf409..7acd3fe 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -30,7 +30,7 @@
 #include <sound/pxa2xx-lib.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/dma.h>
 #include <mach/regs-ssp.h>
 #include <mach/audio.h>
 #include <mach/ssp.h>
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 01c21c6..d9c94d7 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -20,8 +20,8 @@
 #include <sound/pxa2xx-lib.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
 #include <mach/regs-ac97.h>
+#include <mach/dma.h>
 
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index e6c2440..2f4b6e4 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -24,7 +24,7 @@
 #include <sound/pxa2xx-lib.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa-regs.h>
+#include <mach/dma.h>
 #include <mach/audio.h>
 
 #include "pxa2xx-pcm.h"
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 6ca9f53..c4cd2ac 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -26,8 +26,6 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/spitz.h>
 #include "../codecs/wm8750.h"
 #include "pxa2xx-pcm.h"
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index fc78137..dbbd3e9 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -30,8 +30,6 @@
 
 #include <asm/mach-types.h>
 #include <mach/tosa.h>
-#include <mach/pxa-regs.h>
-#include <mach/hardware.h>
 #include <mach/audio.h>
 
 #include "../codecs/wm9712.h"
diff --git a/usr/Kconfig b/usr/Kconfig
index 43a3a0f..588c588 100644
--- a/usr/Kconfig
+++ b/usr/Kconfig
@@ -46,49 +46,50 @@
 	  If you are not sure, leave it set to "0".
 
 config RD_GZIP
-	bool "Initial ramdisk compressed using gzip"
+	bool "Support initial ramdisks compressed using gzip" if EMBEDDED
 	default y
-	depends on BLK_DEV_INITRD=y
+	depends on BLK_DEV_INITRD
 	select DECOMPRESS_GZIP
 	help
 	  Support loading of a gzip encoded initial ramdisk or cpio buffer.
 	  If unsure, say Y.
 
 config RD_BZIP2
-	bool "Initial ramdisk compressed using bzip2"
-	default n
-	depends on BLK_DEV_INITRD=y
+	bool "Support initial ramdisks compressed using bzip2" if EMBEDDED
+	default !EMBEDDED
+	depends on BLK_DEV_INITRD
 	select DECOMPRESS_BZIP2
 	help
 	  Support loading of a bzip2 encoded initial ramdisk or cpio buffer
 	  If unsure, say N.
 
 config RD_LZMA
-	bool "Initial ramdisk compressed using lzma"
-	default n
-	depends on BLK_DEV_INITRD=y
+	bool "Support initial ramdisks compressed using LZMA" if EMBEDDED
+	default !EMBEDDED
+	depends on BLK_DEV_INITRD
 	select DECOMPRESS_LZMA
 	help
-	  Support loading of a lzma encoded initial ramdisk or cpio buffer
+	  Support loading of a LZMA encoded initial ramdisk or cpio buffer
 	  If unsure, say N.
 
+if INITRAMFS_SOURCE!=""
+
 choice
 	prompt "Built-in initramfs compression mode"
 	help
-	  This setting is only meaningful if the INITRAMFS_SOURCE is
-	  set. It decides by which algorithm the INITRAMFS_SOURCE will
-	  be compressed.
-	  Several compression algorithms are available, which differ
-	  in efficiency, compression and decompression speed.
-	  Compression speed is only relevant when building a kernel.
-	  Decompression speed is relevant at each boot.
+	  This option decides by which algorithm the builtin initramfs
+	  will be compressed.  Several compression algorithms are
+	  available, which differ in efficiency, compression and
+	  decompression speed.  Compression speed is only relevant
+	  when building a kernel.  Decompression speed is relevant at
+	  each boot.
 
-	  If you have any problems with bzip2 or lzma compressed
+	  If you have any problems with bzip2 or LZMA compressed
 	  initramfs, mail me (Alain Knaff) <alain@knaff.lu>.
 
-	  High compression options are mostly useful for users who
-	  are low on disk space (embedded systems), but for whom ram
-	  size matters less.
+	  High compression options are mostly useful for users who are
+	  low on RAM, since it reduces the memory consumption during
+	  boot.
 
 	  If in doubt, select 'gzip'
 
@@ -133,3 +134,14 @@
 	  smaller with LZMA in comparison to gzip.
 
 endchoice
+
+endif
+
+if INITRAMFS_SOURCE=""
+# The builtin initramfs is so small so we don't want to bug the user...
+
+config INITRAMFS_COMPRESSION_NONE
+	bool
+	default y
+
+endif